forked from espressif/arduino-esp32
Initial version of rmt driver (#1525)
* rmt driver initial version * supporting conti mode plus interrupts * using conitnous mode for sending more data * working continous mode * rmt driver cleanup after conti mode * initial version of rmt driver * adding a simple example * adding channel and block locks * modified of rmt interface for simpler/easier usage * adding header sentinels, split interface to common and additional settings * Fixes per code review + support for rx callback mode * renamed internal structures and enums, fixed formatting * cmake support for rmt * refactored tx-conti interrupts to function to make it more readable * added Tx and Rx examples * added license headers * minor updates per review * used struct access, renamed defines, corrected diagram
This commit is contained in:
61
libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopbakc.ino
Normal file
61
libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopbakc.ino
Normal file
@ -0,0 +1,61 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "esp32-hal.h"
|
||||
|
||||
rmt_data_t my_data[256];
|
||||
rmt_data_t data[256];
|
||||
|
||||
rmt_obj_t* rmt_send = NULL;
|
||||
rmt_obj_t* rmt_recv = NULL;
|
||||
|
||||
static EventGroupHandle_t events;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
if ((rmt_send = rmtInit(18, true, RMT_MEM_64)) == NULL)
|
||||
{
|
||||
Serial.println("init sender failed\n");
|
||||
}
|
||||
if ((rmt_recv = rmtInit(21, false, RMT_MEM_192)) == NULL)
|
||||
{
|
||||
Serial.println("init receiver failed\n");
|
||||
}
|
||||
|
||||
float realTick = rmtSetTick(rmt_send, 100);
|
||||
printf("real tick set to: %fns\n", realTick);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Init data
|
||||
int i;
|
||||
for (i=0; i<255; i++) {
|
||||
data[i].val = 0x80010001 + ((i%13)<<16) + 13-(i%13);
|
||||
}
|
||||
data[255].val = 0;
|
||||
|
||||
// Start receiving
|
||||
rmtReadAsync(rmt_recv, my_data, 100, events, false, 0);
|
||||
|
||||
// Send in continous mode
|
||||
rmtWrite(rmt_send, data, 100);
|
||||
|
||||
// Wait for data
|
||||
xEventGroupWaitBits(events, RMT_FLAG_RX_DONE, 1, 1, portMAX_DELAY);
|
||||
|
||||
// Printout the received data plus the original values
|
||||
for (i=0; i<60; i++)
|
||||
{
|
||||
Serial.printf("%08x=%08x ", my_data[i], data[i] );
|
||||
if (!((i+1)%4)) Serial.println("\n");
|
||||
}
|
||||
Serial.println("\n");
|
||||
|
||||
delay(2000);
|
||||
}
|
204
libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino
Normal file
204
libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino
Normal file
@ -0,0 +1,204 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "esp32-hal.h"
|
||||
|
||||
//
|
||||
// Note: This example uses a FrSKY device communication
|
||||
// using XJT D12 protocol
|
||||
//
|
||||
// ; 0 bit = 6us low/10us high
|
||||
// ; 1 bit = 14us low/10us high
|
||||
// ;
|
||||
// ; --------+ +----------+ +----------+
|
||||
// ; | | | | |
|
||||
// ; | 0 | | 1 | |
|
||||
// ; | | | | |
|
||||
// ; | | | | |
|
||||
// ; +-------+ +-----------------+ +---------
|
||||
// ;
|
||||
// ; | 6us 10us | 14us 10us |
|
||||
// ; |-------|----------|-----------------|----------|--------
|
||||
// ; | 16us | 24us |
|
||||
|
||||
// Typedef of received frame
|
||||
//
|
||||
// ; 0x00 - Sync, 0x7E (sync header ID)
|
||||
// ; 0x01 - Rx ID, 0x?? (receiver ID number, 0x00-0x??)
|
||||
// ; 0x02 - Flags 1, 0x?? (used for failsafe and binding)
|
||||
// ; 0x03 - Flags 2, 0x00 (reserved)
|
||||
// ; 0x04-0x06, Channels 1/9 and 2/10
|
||||
// ; 0x07-0x09, Channels 3/11 and 4/12
|
||||
// ; 0x0A-0x0C, Channels 5/13 and 6/14
|
||||
// ; 0x0D-0x0F, Channels 7/15 and 8/16
|
||||
// ; 0x10 - 0x00, always zero
|
||||
// ; 0x11 - CRC-16 High
|
||||
// ; 0x12 - CRC-16 Low
|
||||
// ; 0x13 - Tail, 0x7E (tail ID)
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t head;//0x7E
|
||||
uint8_t rxid;//Receiver Number
|
||||
uint8_t flags;//Range:0x20, Bind:0x01
|
||||
uint8_t reserved0;//0x00
|
||||
union {
|
||||
struct {
|
||||
uint8_t ch0_l;
|
||||
uint8_t ch0_h:4;
|
||||
uint8_t ch1_l:4;
|
||||
uint8_t ch1_h;
|
||||
};
|
||||
uint8_t bytes[3];
|
||||
} channels[4];
|
||||
uint8_t reserved1;//0x00
|
||||
uint8_t crc_h;
|
||||
uint8_t crc_l;
|
||||
uint8_t tail;//0x7E
|
||||
};
|
||||
uint8_t buffer[20];
|
||||
} xjt_packet_t;
|
||||
|
||||
#define XJT_VALID(i) (i->level0 && !i->level1 && i->duration0 >= 8 && i->duration0 <= 11)
|
||||
|
||||
rmt_obj_t* rmt_recv = NULL;
|
||||
|
||||
static uint32_t *s_channels;
|
||||
static uint32_t channels[16];
|
||||
static uint8_t xjt_flags = 0x0;
|
||||
static uint8_t xjt_rxid = 0x0;
|
||||
|
||||
static bool xjtReceiveBit(size_t index, bool bit){
|
||||
static xjt_packet_t xjt;
|
||||
static uint8_t xjt_bit_index = 8;
|
||||
static uint8_t xht_byte_index = 0;
|
||||
static uint8_t xht_ones = 0;
|
||||
|
||||
if(!index){
|
||||
xjt_bit_index = 8;
|
||||
xht_byte_index = 0;
|
||||
xht_ones = 0;
|
||||
}
|
||||
|
||||
if(xht_byte_index > 19){
|
||||
//fail!
|
||||
return false;
|
||||
}
|
||||
if(bit){
|
||||
xht_ones++;
|
||||
if(xht_ones > 5 && xht_byte_index && xht_byte_index < 19){
|
||||
//fail!
|
||||
return false;
|
||||
}
|
||||
//add bit
|
||||
xjt.buffer[xht_byte_index] |= (1 << --xjt_bit_index);
|
||||
} else if(xht_ones == 5 && xht_byte_index && xht_byte_index < 19){
|
||||
xht_ones = 0;
|
||||
//skip bit
|
||||
return true;
|
||||
} else {
|
||||
xht_ones = 0;
|
||||
//add bit
|
||||
xjt.buffer[xht_byte_index] &= ~(1 << --xjt_bit_index);
|
||||
}
|
||||
if ((!xjt_bit_index) || (xjt_bit_index==1 && xht_byte_index==19) ) {
|
||||
xjt_bit_index = 8;
|
||||
if(!xht_byte_index && xjt.buffer[0] != 0x7E){
|
||||
//fail!
|
||||
return false;
|
||||
}
|
||||
xht_byte_index++;
|
||||
if(xht_byte_index == 20){
|
||||
//done
|
||||
if(xjt.buffer[19] != 0x7E){
|
||||
//fail!
|
||||
return false;
|
||||
}
|
||||
//check crc?
|
||||
|
||||
xjt_flags = xjt.flags;
|
||||
xjt_rxid = xjt.rxid;
|
||||
for(int i=0; i<4; i++){
|
||||
uint16_t ch0 = xjt.channels[i].ch0_l | ((uint16_t)(xjt.channels[i].ch0_h & 0x7) << 8);
|
||||
ch0 = ((ch0 * 2) + 2452) / 3;
|
||||
uint16_t ch1 = xjt.channels[i].ch1_l | ((uint16_t)(xjt.channels[i].ch1_h & 0x7F) << 4);
|
||||
ch1 = ((ch1 * 2) + 2452) / 3;
|
||||
uint8_t c0n = i*2;
|
||||
if(xjt.channels[i].ch0_h & 0x8){
|
||||
c0n += 8;
|
||||
}
|
||||
uint8_t c1n = i*2+1;
|
||||
if(xjt.channels[i].ch1_h & 0x80){
|
||||
c1n += 8;
|
||||
}
|
||||
s_channels[c0n] = ch0;
|
||||
s_channels[c1n] = ch1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void parseRmt(rmt_data_t* items, size_t len, uint32_t* channels){
|
||||
size_t chan = 0;
|
||||
bool valid = true;
|
||||
rmt_data_t* it = NULL;
|
||||
|
||||
if (!channels) {
|
||||
log_e("Please provide data block for storing channel info");
|
||||
return;
|
||||
}
|
||||
s_channels = channels;
|
||||
|
||||
it = &items[0];
|
||||
for(size_t i = 0; i<len; i++){
|
||||
|
||||
if(!valid){
|
||||
break;
|
||||
}
|
||||
it = &items[i];
|
||||
if(XJT_VALID(it)){
|
||||
if(it->duration1 >= 5 && it->duration1 <= 8){
|
||||
valid = xjtReceiveBit(i, false);
|
||||
} else if(it->duration1 >= 13 && it->duration1 <= 16){
|
||||
valid = xjtReceiveBit(i, true);
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
} else if(!it->duration1 && !it->level1 && it->duration0 >= 5 && it->duration0 <= 8) {
|
||||
valid = xjtReceiveBit(i, false);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void receive_data(uint32_t *data, size_t len)
|
||||
{
|
||||
parseRmt((rmt_data_t*) data, len, channels);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
// Initialize the channel to capture up to 192 items
|
||||
if ((rmt_recv = rmtInit(21, false, RMT_MEM_192)) == NULL)
|
||||
{
|
||||
Serial.println("init receiver failed\n");
|
||||
}
|
||||
|
||||
// Setup 1us tick
|
||||
float realTick = rmtSetTick(rmt_recv, 1000);
|
||||
Serial.printf("real tick set to: %fns\n", realTick);
|
||||
|
||||
// Ask to start reading
|
||||
rmtRead(rmt_recv, receive_data);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// printout some of the channels
|
||||
Serial.printf("%04x %04x %04x %04x\n", channels[0], channels[1], channels[2], channels[3]);
|
||||
delay(500);
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "esp32-hal.h"
|
||||
|
||||
#define NR_OF_LEDS 8*4
|
||||
#define NR_OF_ALL_BITS 24*NR_OF_LEDS
|
||||
|
||||
//
|
||||
// Note: This example uses Neopixel LED board, 32 LEDs chained one
|
||||
// after another, each RGB LED has its 24 bit value
|
||||
// for color configuration (8b for each color)
|
||||
//
|
||||
// Bits encoded as pulses as follows:
|
||||
//
|
||||
// "0":
|
||||
// +-------+ +--
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// ---| |--------------|
|
||||
// + + +
|
||||
// | 0.4us | 0.85 0us |
|
||||
//
|
||||
// "1":
|
||||
// +-------------+ +--
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// ---+ +-------+
|
||||
// | 0.8us | 0.4us |
|
||||
|
||||
rmt_data_t led_data[NR_OF_ALL_BITS];
|
||||
|
||||
rmt_obj_t* rmt_send = NULL;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
if ((rmt_send = rmtInit(18, true, RMT_MEM_64)) == NULL)
|
||||
{
|
||||
Serial.println("init sender failed\n");
|
||||
}
|
||||
|
||||
float realTick = rmtSetTick(rmt_send, 100);
|
||||
Serial.printf("real tick set to: %fns\n", realTick);
|
||||
|
||||
}
|
||||
|
||||
int color[] = { 0x55, 0x11, 0x77 }; // RGB value
|
||||
int led_index = 0;
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Init data with only one led ON
|
||||
int led, col, bit;
|
||||
int i=0;
|
||||
for (led=0; led<NR_OF_LEDS; led++) {
|
||||
for (col=0; col<3; col++ ) {
|
||||
for (bit=0; bit<8; bit++){
|
||||
if ( (color[col] & (1<<(8-bit))) && (led == led_index) ) {
|
||||
led_data[i].level0 = 1;
|
||||
led_data[i].duration0 = 8;
|
||||
led_data[i].level1 = 0;
|
||||
led_data[i].duration1 = 4;
|
||||
} else {
|
||||
led_data[i].level0 = 1;
|
||||
led_data[i].duration0 = 4;
|
||||
led_data[i].level1 = 0;
|
||||
led_data[i].duration1 = 8;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// make the led travel in the pannel
|
||||
if ((++led_index)>=NR_OF_LEDS) {
|
||||
led_index = 0;
|
||||
}
|
||||
|
||||
// Send the data
|
||||
rmtWrite(rmt_send, led_data, NR_OF_ALL_BITS);
|
||||
|
||||
delay(100);
|
||||
}
|
Reference in New Issue
Block a user