#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){ 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; iduration1 >= 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, void * arg) { 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, NULL); } void loop() { // printout some of the channels Serial.printf("%04x %04x %04x %04x\n", channels[0], channels[1], channels[2], channels[3]); delay(500); }