diff --git a/Multiprotocol/CYRF6936_SPI.ino b/Multiprotocol/CYRF6936_SPI.ino index 693ae8b..53772e8 100644 --- a/Multiprotocol/CYRF6936_SPI.ino +++ b/Multiprotocol/CYRF6936_SPI.ino @@ -313,6 +313,7 @@ const uint8_t PROGMEM DEVO_j6pro_sopcodes[][8] = { #endif }; #endif + static void __attribute__((unused)) CYRF_PROGMEM_ConfigSOPCode(const uint8_t *data) { uint8_t code[8]; diff --git a/Multiprotocol/DSM.ino b/Multiprotocol/DSM.ino new file mode 100644 index 0000000..b12b291 --- /dev/null +++ b/Multiprotocol/DSM.ino @@ -0,0 +1,181 @@ +#if defined(DSM_CYRF6936_INO) || defined(DSM_RX_CYRF6936_INO) + +#include "iface_cyrf6936.h" + +uint8_t sop_col; + +const uint8_t PROGMEM DSM_pncodes[5][9][8] = { + /* Note these are in order transmitted (LSB 1st) */ + { /* Row 0 */ + /* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8}, + /* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6}, + /* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9}, + /* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4}, + /* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0}, + /* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8}, + /* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D}, + /* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1}, + /* Col 8 */ {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86} + }, + { /* Row 1 */ + /* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3}, + /* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9}, + /* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82}, + /* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB}, + /* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7}, + /* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95}, + /* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4}, + /* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF}, + /* Col 8 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97} + }, + { /* Row 2 */ + /* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97}, + /* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA}, + /* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE}, + /* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD}, + /* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD}, + /* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9}, + /* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3}, + /* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0}, + /* Col 8 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E} + }, + { /* Row 3 */ + /* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E}, + /* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7}, + /* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1}, + /* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4}, + /* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6}, + /* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80}, + /* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88}, + /* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88}, + /* Col 8 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93} +// Wrong values used by Orange TX/RX +// /* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40} + }, + { /* Row 4 */ + /* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93}, + /* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C}, + /* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA}, + /* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC}, + /* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84}, + /* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7}, + /* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0}, + /* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1}, + /* Col 8 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8} + }, +}; + +static void __attribute__((unused)) DSM_read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len) +{ + for(uint8_t i=0;i> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3 + if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 ) + continue; + for (i = 0; i < idx; i++) + { + if(hopping_frequency[i] == next_ch) + break; + if(hopping_frequency[i] <= 27) + count_3_27++; + else + if (hopping_frequency[i] <= 51) + count_28_51++; + else + count_52_76++; + } + if (i != idx) + continue; + if ((next_ch < 28 && count_3_27 < 8) + ||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7) + ||(next_ch >= 52 && count_52_76 < 8)) + hopping_frequency[idx++] = next_ch; + } +} + +#endif \ No newline at end of file diff --git a/Multiprotocol/DSM_Rx_cyrf6936.ino b/Multiprotocol/DSM_Rx_cyrf6936.ino new file mode 100644 index 0000000..c60facc --- /dev/null +++ b/Multiprotocol/DSM_Rx_cyrf6936.ino @@ -0,0 +1,466 @@ +/* + This project is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Multiprotocol is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Multiprotocol. If not, see . + */ + +#if defined(DSM_RX_CYRF6936_INO) + +#include "iface_cyrf6936.h" + +//#define DSM_DEBUG_RF + +uint8_t DSM_rx_type; + +enum { + DSM_RX_BIND1 = 0, + DSM_RX_BIND2, + DSM_RX_DATA_PREP, + DSM2_RX_SCAN, + DSM_RX_DATA_CH1, + DSM_RX_DATA_CH2, +}; + +static void __attribute__((unused)) DSM_Rx_init() +{ + DSM_cyrf_config(); + if(IS_BIND_IN_PROGRESS) + { + //64 SDR Mode is configured so only the 8 first values are needed but need to write 16 values... + uint8_t code[16]; + DSM_read_code(code,0,8,8); + CYRF_ConfigDataCode(code, 16); + CYRF_ConfigRFChannel(1); + CYRF_SetTxRxMode(RX_EN); // Force end state read + CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive + } + else + DSM_cyrf_configdata(); + rx_disable_lna = IS_POWER_FLAG_on; + CYRF_WriteRegister(CYRF_06_RX_CFG, rx_disable_lna ? 0x0A:0xCA); // AGC enabled/disabled, LNA enabled/disabled, Attenuator disabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX +} + +uint16_t convert_channel_DSM_nolimit(int32_t val) +{ + val=(val-0x150)*(CHANNEL_MAX_100-CHANNEL_MIN_100)/(0x6B0-0x150)+CHANNEL_MIN_100; + if(val<0) + val=0; + else + if(val>2047) + val=2047; + return (uint16_t)val; +} + +static uint8_t __attribute__((unused)) DSM_Rx_check_packet() +{ + uint8_t rx_status=CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); + if((rx_status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing) + rx_status |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); + if((rx_status & 0x07) == 0x02) + { // data received with no errors + if(CYRF_ReadRegister(CYRF_09_RX_COUNT)==16) + {// 16 bytes + // Read packet + CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read + CYRF_ReadDataPacketLen(packet, 16); + + // Check packet ID + if ((DSM_rx_type&0x80) == 0) + {//DSM2 + packet[0] ^= 0xff; + packet[1] ^= 0xff; + } + if(packet[0] == cyrfmfg_id[2] && packet[1] == cyrfmfg_id[3]) + return 0x02; // Packet ok + } + return 0x00; // Wrong size or ID -> nothing received + } + return rx_status; // Return error code +} + +static void __attribute__((unused)) DSM_Rx_build_telemetry_packet() +{ + uint8_t nbr_bits = 11; + if((DSM_rx_type&0xF0) == 0x00) + nbr_bits=10; // Only DSM_22 is using a resolution of 1024 + + // Extract channels + uint8_t idx; + for (uint8_t i = 0; i < 7; i++) + { + uint16_t value=(packet[i*2+2]<<8) | packet[i*2+3]; + if(value!=0xFFFF) + { + idx=(value&0x7FFF)>>nbr_bits; // retrieve channel index 0..12 + if(idx<13) + { + if(nbr_bits==10) value <<= 1; // switch to 11 bits + value &= 0x7FF; + rx_rc_chan[CH_TAER[idx]]=convert_channel_DSM_nolimit(value); + } + } + } + + // Buid telemetry packet + idx=0; + packet_in[idx++] = RX_LQI; + packet_in[idx++] = RX_LQI; + packet_in[idx++] = 0; // start channel + packet_in[idx++] = 12; // number of channels in packet + + // Pack channels + uint32_t bits = 0; + uint8_t bitsavailable = 0; + for (uint8_t i = 0; i < 12; i++) + { + bits |= ((uint32_t)rx_rc_chan[i]) << bitsavailable; + bitsavailable += 11; + while (bitsavailable >= 8) + { + packet_in[idx++] = bits & 0xff; + bits >>= 8; + bitsavailable -= 8; + } + } + if(bitsavailable) + packet_in[idx++] = bits & 0xff; + // Send telemetry + telemetry_link = 1; +} + +static bool __attribute__((unused)) DSM_Rx_bind_check_validity() +{ + uint16_t sum = 384 - 0x10;// + for(uint8_t i = 0; i < 8; i++) + sum += packet_in[i]; + if( packet_in[8] != (sum>>8) || packet_in[9] != (sum&0xFF)) //Checksum + return false; + for(uint8_t i = 8; i < 14; i++) + sum += packet_in[i]; + if( packet_in[14] != (sum>>8) || packet_in[15] != (sum&0xFF)) //Checksum + return false; + if(memcmp(packet_in,packet_in+4,4)) //Check ID + return false; + return true; +} + +static void __attribute__((unused)) DSM_Rx_build_bind_packet() +{ + uint16_t sum = 384 - 0x10;// + packet[0] = 0xff ^ cyrfmfg_id[0]; // ID + packet[1] = 0xff ^ cyrfmfg_id[1]; + packet[2] = 0xff ^ cyrfmfg_id[2]; + packet[3] = 0xff ^ cyrfmfg_id[3]; + packet[4] = 0x01; // RX version + packet[5] = num_ch; // Number of channels + packet[6] = DSM_rx_type; // DSM type, let's just send back whatever the TX gave us... + packet[7] = 0x00; // Unknown + for(uint8_t i = 0; i < 8; i++) + sum += packet[i]; + packet[8] = sum >> 8; + packet[9] = sum & 0xff; +} + +static void __attribute__((unused)) DSM_abort_channel_rx(uint8_t ch) +{ + CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation + CYRF_SetTxRxMode(IS_POWER_FLAG_on ? TXRX_OFF:RX_EN); // Force end state read + if (rx_disable_lna != IS_POWER_FLAG_on) + { + rx_disable_lna = IS_POWER_FLAG_on; + CYRF_WriteRegister(CYRF_06_RX_CFG, rx_disable_lna ? 0x0A:0xCA); // AGC enabled/disabled, LNA enabled/disabled, Attenuator disabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX + } + if(ch&0x02) DSM_set_sop_data_crc(true ,DSM_rx_type&0x80); // Set sop data,crc seed and rf channel using CH1, DSM2/X + if(ch&0x01) DSM_set_sop_data_crc(false,DSM_rx_type&0x80); // Set sop data,crc seed and rf channel using CH1, DSM2/X + CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation + CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive +} + +uint16_t DSM_Rx_callback() +{ + uint8_t rx_status; + static uint8_t read_retry=10; + static uint16_t pps_counter; + static uint32_t pps_timer = 0; + + switch (phase) + { + case DSM_RX_BIND1: + //Check received data + rx_status = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); + if((rx_status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing) + rx_status |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); + if((rx_status & 0x07) == 0x02 && read_retry) + { // data received with no errors + CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read + rx_status=CYRF_ReadRegister(CYRF_09_RX_COUNT); + debugln("RX:%d",rx_status); + if(rx_status==16) + { + CYRF_ReadDataPacketLen(packet_in, 16); + if(DSM_Rx_bind_check_validity()) + { + // store tx info into eeprom + uint16_t temp = DSM_RX_EEPROM_OFFSET; + debug("ID="); + for(uint8_t i=0;i<4;i++) + { + cyrfmfg_id[i]=packet_in[i]^0xFF; + //eeprom_write_byte((EE_ADDR)temp++, cyrfmfg_id[i]); + debug(" %02X", cyrfmfg_id[i]); + } + // check num_ch + num_ch=packet_in[11]; + if(num_ch>12) num_ch=12; + //check DSM_rx_type + /*packet[12] 1 byte -> max DSM type allowed: + 0x01 => 22ms 1024 DSM2 1 packet => number of channels is <8 and no telemetry + 0x02 => 22ms 1024 DSM2 2 packets => either a number of channel >7 or telemetry enable RX + 0x12 => 11ms 2048 DSM2 2 packets => can be any number of channels with/without telemetry + 0xA2 => 22ms 2048 DSMX 1 packet => number of channels is <8 and no telemetry + 0xB2 => 11ms 2048 DSMX => can be any number of channels with/without telemetry + (0x01 or 0xA2) and num_ch < 7 => 22ms else 11ms + &0x80 => false=DSM2, true=DSMX + &0xF0 => false=1024, true=2048 */ + DSM_rx_type=packet_in[12]; + switch(DSM_rx_type) + { + case 0x01: + if(num_ch>7) DSM_rx_type = 0x02; // Can't be 0x01 with this number of channels + break; + case 0xA2: + if(num_ch>7) DSM_rx_type = 0xB2; // Can't be 0xA2 with this number of channels + break; + case 0x02: + case 0x12: + case 0xB2: + break; + default: // Unknown type, default to DSMX 11ms + DSM_rx_type = 0xB2; + break; + } + // eeprom_write_byte((EE_ADDR)temp, DSM_rx_type); + debugln(", num_ch=%d, type=%02X",num_ch, DSM_rx_type); + CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation + CYRF_SetTxRxMode(TX_EN); // Force end state TX + CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX + DSM_Rx_build_bind_packet(); + bind_counter=500; + phase++; // DSM_RX_BIND2; + } + } + if(read_retry) + read_retry--; + } + else + { + hopping_frequency_no++; // Change channel + hopping_frequency_no %= 0x50; + hopping_frequency_no |= 0x01; // Odd channels only + CYRF_ConfigRFChannel(hopping_frequency_no); + //debugln("ch:%d",hopping_frequency_no); + read_retry = 10; + DSM_abort_channel_rx(0); // Abort RX operation and receive + } + return 12500; + case DSM_RX_BIND2: + //Transmit settings back + CYRF_WriteDataPacketLen(packet,10); // Does not work ?!?!? + if(bind_counter--==0) + { + BIND_DONE; + phase++; // DSM_RX_DATA_PREP + } + break; + case DSM_RX_DATA_PREP: + hopping_frequency_no = 0; + read_retry=0; + rx_data_started = false; + read_retry=0; + pps_counter = 0; + RX_LQI = 100; + DSM_cyrf_configdata(); + pps_timer=millis(); + sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07; + seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1]; + if(DSM_rx_type&0x80) + { // DSMX + DSM_calc_dsmx_channel(); // Build hop table + DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive + phase=DSM_RX_DATA_CH1; + } + else + { // DSM2 + rf_ch_num=0; + hopping_frequency_no = 0; + hopping_frequency[0] = 3; + hopping_frequency[1] = 0; + DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive + phase=DSM2_RX_SCAN; + } + break; + case DSM2_RX_SCAN: // Scan for DSM2 frequencies + //Received something ? + rx_status = DSM_Rx_check_packet(); + if(rx_status == 0x02) + { // data received with no errors + debugln("CH%d:Found %d",rf_ch_num+1,hopping_frequency[rf_ch_num]); + read_retry=0; + if(rf_ch_num) + { // Both CH1 and CH2 found + read_retry=0; + hopping_frequency_no=0; + DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive + pps_timer=millis(); + phase++; // DSM_RX_DATA_CH1 + } + else + { + rf_ch_num++; // CH1 found, scan for CH2 + hopping_frequency_no = 1; + if(hopping_frequency[1] < 3) // If no CH2 keep then restart from current + hopping_frequency[1]=hopping_frequency[0]+1; + DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive + } + } + else + { + read_retry++; + if(read_retry>50) // After 50ms + { // Try next channel + debugln("CH%d:Next channel",rf_ch_num+1); + read_retry=0; + hopping_frequency_no = rf_ch_num; + hopping_frequency[rf_ch_num]++; + if(hopping_frequency[rf_ch_num] > 73) hopping_frequency[rf_ch_num] = 3; + DSM_abort_channel_rx(rf_ch_num+1); // Abort RX operation, set sop&data&seed&rf using CH1/2, DSM2/X and receive + } + else if(rx_status & 0x02) + { // data received with errors + if((rx_status & 0x01) && rf_ch_num==0) + hopping_frequency[1] = hopping_frequency[0];// Might be CH2 since it's a CRC error so keep it + debugln("CH%d:RX error",rf_ch_num+1); + DSM_abort_channel_rx(0); // Abort RX operation and receive + } + } + return 1000; + case DSM_RX_DATA_CH1: + //Packets per second + if (millis() - pps_timer >= 1000) + {//182pps @11ms, 91pps @22ms + pps_timer = millis(); + if(DSM_rx_type!=0xA2 && DSM_rx_type!=0x01) // if 11ms + pps_counter >>=1; // then /2 + debugln("%d pps", pps_counter); + RX_LQI = pps_counter; // max=91pps + pps_counter = 0; + } + //Received something ? + rx_status = DSM_Rx_check_packet(); + if(rx_status == 0x02) + { // data received with no errors + #ifdef DSM_DEBUG_RF + debugln("CH1:RX"); + #endif + DSM_Rx_build_telemetry_packet(); + rx_data_started = true; + pps_counter++; + DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive + phase++; + return 5000; + } + else + { + read_retry++; + if(rx_data_started && read_retry>6) // After 6*500=3ms + { // skip to CH2 + #ifdef DSM_DEBUG_RF + debugln("CH1:Skip to CH2"); + #endif + DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive + phase++; + return 4000; + } + if(rx_data_started && RX_LQI==0) + { // communication lost + #ifdef DSM_DEBUG_RF + debugln("CH1:Restart..."); + #endif + phase=DSM_RX_DATA_PREP; + return 1000; + } + if(read_retry>250) + { // move to next RF channel + #ifdef DSM_DEBUG_RF + debugln("CH1:Scan"); + #endif + DSM_abort_channel_rx(3); // Abort RX operation, set sop&data&seed&rf using CH2 then CH1, DSM2/X and receive + read_retry=0; + } + else if(rx_status & 0x02) + { // data received with errors + #ifdef DSM_DEBUG_RF + debugln("CH1:RX error %02X",rx_status); + #endif + DSM_abort_channel_rx(0); // Abort RX operation and receive + } + } + return 500; + case DSM_RX_DATA_CH2: + rx_status = DSM_Rx_check_packet(); + if(rx_status == 0x02) + { // data received with no errors + #ifdef DSM_DEBUG_RF + debugln("CH2:RX"); + #endif + DSM_Rx_build_telemetry_packet(); + pps_counter++; + } + #ifdef DSM_DEBUG_RF + else + debugln("CH2:No RX"); + #endif + DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive + read_retry=0; + phase=DSM_RX_DATA_CH1; + if(DSM_rx_type==0xA2) //|| DSM_rx_type==0x01 -> not needed for DSM2 since we are ok to listen even if there will be nothing + return 15000; //22ms + else + return 4000; //11ms + } + return 10000; +} + +uint16_t initDSM_Rx() +{ + DSM_Rx_init(); + hopping_frequency_no = 0; + + if (IS_BIND_IN_PROGRESS) + phase = DSM_RX_BIND1; + else + { + uint16_t temp = DSM_RX_EEPROM_OFFSET; + debug("ID="); + for(uint8_t i=0;i<4;i++) + { + cyrfmfg_id[i]=eeprom_read_byte((EE_ADDR)temp++); + debug(" %02X", cyrfmfg_id[i]); + } + DSM_rx_type=0xB2; //eeprom_read_byte((EE_ADDR)temp); + debugln(", type=%02X", DSM_rx_type); + phase = DSM_RX_DATA_PREP; + } + return 1000; +} + +#endif diff --git a/Multiprotocol/DSM_cyrf6936.ino b/Multiprotocol/DSM_cyrf6936.ino index 6293663..14047a4 100644 --- a/Multiprotocol/DSM_cyrf6936.ino +++ b/Multiprotocol/DSM_cyrf6936.ino @@ -41,7 +41,6 @@ enum { }; // -uint8_t sop_col; uint8_t ch_map[14]; const uint8_t PROGMEM DSM_ch_map_progmem[][14] = { //22+11ms for 4..7 channels @@ -61,116 +60,6 @@ const uint8_t PROGMEM DSM_ch_map_progmem[][14] = { {1, 5, 2, 3, 4, 8, 9, 1, 5, 2, 3, 0, 7, 6 }, //10ch - DX18 }; -const uint8_t PROGMEM DSM_pncodes[5][8][8] = { - /* Note these are in order transmitted (LSB 1st) */ - { /* Row 0 */ - /* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8}, - /* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6}, - /* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9}, - /* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4}, - /* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0}, - /* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8}, - /* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D}, - /* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1}, - /* Col 8 {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86}*/ - }, - { /* Row 1 */ - /* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3}, - /* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9}, - /* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82}, - /* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB}, - /* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7}, - /* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95}, - /* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4}, - /* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF}, - /* Col 8 {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97} */ - }, - { /* Row 2 */ - /* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97}, - /* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA}, - /* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE}, - /* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD}, - /* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD}, - /* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9}, - /* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3}, - /* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0}, - /* Col 8 {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E} */ - }, - { /* Row 3 */ - /* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E}, - /* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7}, - /* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1}, - /* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4}, - /* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6}, - /* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80}, - /* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88}, - /* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88}, - /* Col 8 {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93} */ -// Wrong values used by Orange TX/RX -// /* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40} - }, - { /* Row 4 */ - /* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93}, - /* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C}, - /* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA}, - /* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC}, - /* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84}, - /* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7}, - /* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0}, - /* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1}, - /* Col 8 {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8} */ - }, -}; - -static void __attribute__((unused)) DSM_read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len) -{ - for(uint8_t i=0;i 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX + value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX #else if(option & 0x80) value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX @@ -299,66 +184,6 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper) } } -static void __attribute__((unused)) DSM_set_sop_data_crc() -{ - //The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1]) - //The crc for channel '2' is (mfgid[0] << 8 + mfgid[1]) - uint16_t crc = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1]; - if(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B) - CYRF_ConfigCRCSeed(crc); //CH2 - else - CYRF_ConfigCRCSeed(~crc); //CH1 - - uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no]); - uint8_t code[16]; - DSM_read_code(code,pn_row,sop_col,8); // pn_row between 0 and 4, sop_col between 1 and 7 - CYRF_ConfigSOPCode(code); - DSM_read_code(code,pn_row,7 - sop_col,8); // 7-sop_col between 0 and 6 - DSM_read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7 - CYRF_ConfigDataCode(code, 16); - - CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]); - hopping_frequency_no++; - if(sub_protocol == DSMX_11 || sub_protocol == DSMX_22) - hopping_frequency_no %=23; - else - hopping_frequency_no %=2; -} - -static void __attribute__((unused)) DSM_calc_dsmx_channel() -{ - uint8_t idx = 0; - uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0)); - uint32_t id_tmp = id; - while(idx < 23) - { - uint8_t i; - uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0; - id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization - uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3 - if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 ) - continue; - for (i = 0; i < idx; i++) - { - if(hopping_frequency[i] == next_ch) - break; - if(hopping_frequency[i] <= 27) - count_3_27++; - else - if (hopping_frequency[i] <= 51) - count_28_51++; - else - count_52_76++; - } - if (i != idx) - continue; - if ((next_ch < 28 && count_3_27 < 8) - ||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7) - ||(next_ch >= 52 && count_52_76 < 8)) - hopping_frequency[idx++] = next_ch; - } -} - static uint8_t __attribute__((unused)) DSM_Check_RX_packet() { uint8_t result=1; // assume good packet @@ -418,17 +243,17 @@ uint16_t ReadDsm() rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); if((rx_phase & 0x07) == 0x02) { // data received with no errors - CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read - len=CYRF_ReadRegister(CYRF_09_RX_COUNT); - if(len>TELEMETRY_BUFFER_SIZE-2) - len=TELEMETRY_BUFFER_SIZE-2; - CYRF_ReadDataPacketLen(packet_in+1, len); - if(len==10 && DSM_Check_RX_packet()) + CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read + if(CYRF_ReadRegister(CYRF_09_RX_COUNT)==10) // Len { - packet_in[0]=0x80; - telemetry_link=1; // send received data on serial - phase++; - return 2000; + CYRF_ReadDataPacketLen(packet_in+1, 10); + if(DSM_Check_RX_packet()) + { + packet_in[0]=0x80; + telemetry_link=1; // Send received data on serial + phase++; + return 2000; + } } } else @@ -441,7 +266,7 @@ uint16_t ReadDsm() } if( --bind_counter == 0 ) { // Exit if no answer has been received for some time - phase++; // DSM_CHANSEL + phase++; // DSM_CHANSEL return 7000 ; } return 7000; @@ -452,7 +277,7 @@ uint16_t ReadDsm() CYRF_SetTxRxMode(TX_EN); hopping_frequency_no = 0; phase = DSM_CH1_WRITE_A; // in fact phase++ - DSM_set_sop_data_crc(); + DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22); return 10000; case DSM_CH1_WRITE_A: #ifdef MULTI_SYNC @@ -487,7 +312,7 @@ uint16_t ReadDsm() CYRF_SetTxRxMode(TX_EN); } #endif - DSM_set_sop_data_crc(); + DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11 || sub_protocol==DSMX_22); phase++; // change from CH1_CHECK to CH2_WRITE return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY; } @@ -529,11 +354,11 @@ uint16_t ReadDsm() phase = DSM_CH1_WRITE_A; //Transmit lower CYRF_SetTxRxMode(TX_EN); //TX mode CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); //Clear abort RX operation - DSM_set_sop_data_crc(); + DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22); return DSM_READ_DELAY; #else // No telemetry - DSM_set_sop_data_crc(); + DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22); if (phase == DSM_CH2_CHECK_A) { if(num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11) @@ -565,6 +390,8 @@ uint16_t initDsm() cyrfmfg_id[rx_tx_addr[0]%3]^=0x01; //Change a bit so sop_col will be different from 0 sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07; } + //Calc CRC seed + seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1]; //Hopping frequencies if (sub_protocol == DSMX_11 || sub_protocol == DSMX_22) DSM_calc_dsmx_channel(); diff --git a/Multiprotocol/Multi.txt b/Multiprotocol/Multi.txt index ea7834a..5820172 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -67,3 +67,4 @@ 67,LR12,LR12,LR12_6ch 68,Skyartec 69,ESKYv2,150V2 +70,DSM_RX \ No newline at end of file diff --git a/Multiprotocol/Multi_Names.ino b/Multiprotocol/Multi_Names.ino index 64f3e70..b73c4b4 100644 --- a/Multiprotocol/Multi_Names.ino +++ b/Multiprotocol/Multi_Names.ino @@ -21,6 +21,7 @@ const char STR_FRSKYD[] ="FrSky D"; const char STR_HISKY[] ="Hisky"; const char STR_V2X2[] ="V2x2"; const char STR_DSM[] ="DSM"; +const char STR_DSM_RX[] ="DSM_RX"; const char STR_DEVO[] ="Devo"; const char STR_YD717[] ="YD717"; const char STR_KN[] ="KN"; @@ -191,6 +192,9 @@ const mm_protocol_definition multi_protocols[] = { #if defined(DSM_CYRF6936_INO) {PROTO_DSM, STR_DSM, 4, STR_SUBTYPE_DSM, OPTION_MAXTHR }, #endif + #if defined(DSM_RX_CYRF6936_INO) + {PROTO_DSM_RX, STR_DSM_RX, 0, NO_SUBTYPE, OPTION_NONE }, + #endif #if defined(ESKY_NRF24L01_INO) {PROTO_ESKY, STR_ESKY, 2, STR_SUBTYPE_ESKY, OPTION_NONE }, #endif diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index f600ef7..f34a914 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -19,7 +19,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 3 #define VERSION_REVISION 0 -#define VERSION_PATCH_LEVEL 96 +#define VERSION_PATCH_LEVEL 98 //****************** // Protocols @@ -96,6 +96,7 @@ enum PROTOCOLS PROTO_FRSKYL = 67, // =>CC2500 PROTO_SKYARTEC = 68, // =>CC2500 PROTO_ESKY150V2 = 69, // =>CC2500+NRF24L01 + PROTO_DSM_RX = 70, // =>CYRF6936 }; enum Flysky @@ -397,8 +398,8 @@ enum MultiPacketTypes //*************** //*** Tests *** //*************** -#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 ) -#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN || protocol==PROTO_SKYARTEC || protocol==PROTO_ESKY150V2 ) +#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9) +#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN || protocol==PROTO_SKYARTEC || protocol==PROTO_ESKY150V2 || protocol==PROTO_DSM_RX) //*************** //*** Flags *** @@ -674,7 +675,8 @@ enum { #define FRSKYD_CLONE_EEPROM_OFFSET 771 // (1) format + (3) TX ID + (47) channels, 51 bytes, end is 822 #define FRSKYX_CLONE_EEPROM_OFFSET 822 // (1) format + (3) TX ID + (47) channels, 51 bytes, end is 873 #define FRSKYX2_CLONE_EEPROM_OFFSET 873 // (1) format + (3) TX ID, 4 bytes, end is 877 -//#define CONFIG_EEPROM_OFFSET 877 // Current configuration of the multimodule +#define DSM_RX_EEPROM_OFFSET 877 // (4) TX ID + format, 5 bytes, end is 882 +//#define CONFIG_EEPROM_OFFSET 882 // Current configuration of the multimodule //**************************************** //*** MULTI protocol serial definition *** diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 26b2143..1883bca 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -751,7 +751,7 @@ bool Update_All() update_led_status(); #if defined(TELEMETRY) #if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) ) - if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_PROPEL) || (protocol==PROTO_DEVO)) + if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_PROPEL) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX)) #endif if(IS_DISABLE_TELEM_off) TelemetryUpdate(); @@ -1232,6 +1232,13 @@ static void protocol_init() remote_callback = ReadDsm; break; #endif + #if defined(DSM_RX_CYRF6936_INO) + case PROTO_DSM_RX: + PE2_on; //antenna RF4 + next_callback = initDSM_Rx(); + remote_callback = DSM_Rx_callback; + break; + #endif #if defined(WFLY_CYRF6936_INO) case PROTO_WFLY: PE2_on; //antenna RF4 diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index 27104ec..68aeb76 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -267,7 +267,7 @@ static void multi_send_status() } #endif -#if defined (FRSKY_RX_TELEMETRY) || defined (AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY) +#if defined (FRSKY_RX_TELEMETRY) || defined (AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY) || defined (DSM_RX_CYRF6936_INO) void receiver_channels_frame() { uint16_t len = packet_in[3] * 11; // 11 bit per channel @@ -939,8 +939,8 @@ void TelemetryUpdate() } #endif - #if defined (FRSKY_RX_TELEMETRY) || defined(AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY) - if ((telemetry_link & 1) && (protocol == PROTO_FRSKY_RX || protocol == PROTO_AFHDS2A_RX || protocol == PROTO_BAYANG_RX)) + #if defined (FRSKY_RX_TELEMETRY) || defined(AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY) || defined (DSM_RX_CYRF6936_INO) + if ((telemetry_link & 1) && (protocol == PROTO_FRSKY_RX || protocol == PROTO_AFHDS2A_RX || protocol == PROTO_BAYANG_RX || protocol == PROTO_DSM_RX) ) { receiver_channels_frame(); telemetry_link &= ~1; diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index 035cfd0..c2c1cfe 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -204,6 +204,7 @@ #ifndef CYRF6936_INSTALLED #undef DEVO_CYRF6936_INO #undef DSM_CYRF6936_INO + #undef DSM_RX_CYRF6936_INO #undef HOTT_CC2500_INO #undef J6PRO_CYRF6936_INO #undef TRAXXAS_CYRF6936_INO @@ -307,6 +308,7 @@ #undef BAYANG_RX_TELEMETRY #undef BAYANG_RX_NRF24L01_INO #undef DEVO_HUB_TELEMETRY + #undef DSM_RX_CYRF6936_INO #else #if defined(MULTI_TELEMETRY) && defined(MULTI_STATUS) #error You should choose either MULTI_TELEMETRY or MULTI_STATUS but not both. diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index f8e9de8..3db2af6 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -170,6 +170,7 @@ //The protocols below need a CYRF6936 to be installed #define DEVO_CYRF6936_INO #define DSM_CYRF6936_INO +#define DSM_RX_CYRF6936_INO #define J6PRO_CYRF6936_INO #define TRAXXAS_CYRF6936_INO #define WFLY_CYRF6936_INO @@ -231,7 +232,7 @@ #define ZSX_NRF24L01_INO //The protocols below need a SX1276 to be installed -//#define FRSKYR9_SX1276_INO +#define FRSKYR9_SX1276_INO /***************************/ /*** PROTOCOLS SETTINGS ***/ @@ -544,6 +545,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { DSM2_11 DSMX_22 DSMX_11 + PROTO_DSM_RX + NONE PROTO_E01X E012 E015 diff --git a/Protocols_Details.md b/Protocols_Details.md index f2e6cd8..d9b351a 100644 --- a/Protocols_Details.md +++ b/Protocols_Details.md @@ -79,6 +79,7 @@ CFlie|38|CFlie||||||||NRF24L01| [Devo](Protocols_Details.md#DEVO---7)|7|Devo|8CH|10CH|12CH|6CH|7CH|||CYRF6936| [DM002](Protocols_Details.md#DM002---33)|33|DM002||||||||NRF24L01|XN297 [DSM](Protocols_Details.md#DSM---6)|6|DSM2-22|DSM2-11|DSMX-22|DSMX-11|AUTO||||CYRF6936| +[DSM_RX](Protocols_Details.md#DSM_RX---70)|70|||||||||CYRF6936| [E01X](Protocols_Details.md#E01X---45)|45|E012|E015|E016H||||||NRF24L01|XN297/HS6200 [ESky](Protocols_Details.md#ESKY---16)|16|ESky|Std|ET4||||||NRF24L01| [ESky150](Protocols_Details.md#ESKY150---35)|35|ESKY150||||||||NRF24L01| @@ -669,6 +670,20 @@ The current radio firmware which are able to use the "AUTO" feature are erskyTX For these firmwares, you must have a telemetry enabled TX and you have to make sure you set the Telemetry "Usr proto" to "DSMx". Also on er9x you will need to be sure to match the polarity of the telemetry serial (normal or inverted by bitbashing), while on erskyTX you can set "Invert COM1" accordinlgy. +## DSM_RX - *70* +The DSM receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,... + +Notes: + - Automatically support DSM 2/X 11/22 1024/2048 + - Currently the bind response does not work which means that the TX doesn't know what the DSM RX protocol has selected. **You must manually select the right protocol on the TX**. By default the RX will select DSMX/11ms. + - Available in OpenTX 2.3.3, Trainer Mode Master/Multi + - Channels 1..4 are remapped to the module default + - Extended limits supported + +CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 +---|---|---|---|---|---|---|---|---|----|----|---- +A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 + ## J6Pro - *22* CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12