diff --git a/Multiprotocol/ESky_nrf24l01.ino b/Multiprotocol/ESky_nrf24l01.ino index fdf7613..a7f3f5a 100644 --- a/Multiprotocol/ESky_nrf24l01.ino +++ b/Multiprotocol/ESky_nrf24l01.ino @@ -18,8 +18,13 @@ #include "iface_nrf24l01.h" +//#define ESKY_ET4_FORCE_ID + #define ESKY_BIND_COUNT 1000 -#define ESKY_PACKET_PERIOD 3333 +#define ESKY_STD_PACKET_PERIOD 3333 +#define ESKY_ET4_PACKET_PERIOD 1190 +#define ESKY_ET4_TOTAL_PACKET_PERIOD 20300 +#define ESKY_ET4_BIND_PACKET_PERIOD 5000 #define ESKY_PAYLOAD_SIZE 13 #define ESKY_PACKET_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short) @@ -63,28 +68,37 @@ static void __attribute__((unused)) ESKY_init() static void __attribute__((unused)) ESKY_init2() { NRF24L01_FlushTx(); - hopping_frequency_no = 0; - uint16_t channel_ord = rx_tx_addr[0] % 74; - hopping_frequency[12] = 10 + (uint8_t)channel_ord; //channel_code - uint8_t channel1, channel2; - channel1 = 10 + (uint8_t)((37 + channel_ord*5) % 74); - channel2 = 10 + (uint8_t)(( channel_ord*5) % 74) ; + if(sub_protocol==ESKY_STD) + { + uint16_t channel_ord = rx_tx_addr[0] % 74; + hopping_frequency[12] = 10 + (uint8_t)channel_ord; //channel_code + uint8_t channel1, channel2; + channel1 = 10 + (uint8_t)((37 + channel_ord*5) % 74); + channel2 = 10 + (uint8_t)(( channel_ord*5) % 74) ; - hopping_frequency[0] = channel1; - hopping_frequency[1] = channel1; - hopping_frequency[2] = channel1; - hopping_frequency[3] = channel2; - hopping_frequency[4] = channel2; - hopping_frequency[5] = channel2; - - //end_bytes - hopping_frequency[6] = 6; - hopping_frequency[7] = channel1*2; - hopping_frequency[8] = channel2*2; - hopping_frequency[9] = 6; - hopping_frequency[10] = channel1*2; - hopping_frequency[11] = channel2*2; + hopping_frequency[0] = channel1; + hopping_frequency[1] = channel1; + hopping_frequency[2] = channel1; + hopping_frequency[3] = channel2; + hopping_frequency[4] = channel2; + hopping_frequency[5] = channel2; + //end_bytes + hopping_frequency[6] = 6; + hopping_frequency[7] = channel1*2; + hopping_frequency[8] = channel2*2; + hopping_frequency[9] = 6; + hopping_frequency[10] = channel1*2; + hopping_frequency[11] = channel2*2; + } + else + { // ESKY_ET4 + hopping_frequency[0] = 0x29; //41 + hopping_frequency[1] = 0x12; //18 + hopping_frequency[6] = 0x87; //135 payload end byte + hopping_frequency[12] = 0x84; //132 indicates which channels to use + } + // Turn radio power on NRF24L01_SetTxRxMode(TX_EN); } @@ -111,20 +125,32 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind) } else { - // Regular packet - // Each data packet is repeated 3 times on one channel, and 3 times on another channel - // For arithmetic simplicity, channels are repeated in rf_channels array - if (hopping_frequency_no == 0) + if (packet_count == 0) for (uint8_t i = 0; i < 6; i++) { uint16_t val=convert_channel_ppm(CH_AETR[i]); packet[i*2] = val>>8; //high byte of servo timing(1000-2000us) packet[i*2+1] = val&0xFF; //low byte of servo timing(1000-2000us) } - rf_ch = hopping_frequency[hopping_frequency_no]; - packet[12] = hopping_frequency[hopping_frequency_no+6]; // end_bytes - hopping_frequency_no++; - if (hopping_frequency_no > 6) hopping_frequency_no = 0; + if(sub_protocol==ESKY_STD) + { + // Regular packet + // Each data packet is repeated 3 times on one channel, and 3 times on another channel + // For arithmetic simplicity, channels are repeated in rf_channels array + rf_ch = hopping_frequency[packet_count]; + packet[12] = hopping_frequency[packet_count+6]; // end_bytes + packet_count++; + if (packet_count > 6) packet_count = 0; + } + else + { // ESKY_ET4 + // Regular packet + // Each data packet is repeated 14 times alternating between 2 channels + rf_ch = hopping_frequency[packet_count&1]; + packet_count++; + if(packet_count>14) packet_count=0; + packet[12] = hopping_frequency[6]; // end_byte + } } NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch); NRF24L01_FlushTx(); @@ -137,9 +163,17 @@ uint16_t ESKY_callback() if(IS_BIND_DONE) { #ifdef MULTI_SYNC - telemetry_set_input_sync(ESKY_PACKET_PERIOD); + if(packet_count==0) + telemetry_set_input_sync(sub_protocol==ESKY_STD?ESKY_STD_PACKET_PERIOD*6:ESKY_ET4_TOTAL_PACKET_PERIOD); #endif ESKY_send_packet(0); + if(sub_protocol==ESKY_ET4) + { + if(packet_count==0) + return ESKY_ET4_TOTAL_PACKET_PERIOD-ESKY_ET4_PACKET_PERIOD*13; + else + return ESKY_ET4_PACKET_PERIOD; + } } else { @@ -150,16 +184,25 @@ uint16_t ESKY_callback() BIND_DONE; } } - return ESKY_PACKET_PERIOD; + return ESKY_STD_PACKET_PERIOD; } uint16_t initESKY(void) { bind_counter = ESKY_BIND_COUNT; rx_tx_addr[2] = rx_tx_addr[3]; // Model match + #ifdef ESKY_ET4_FORCE_ID + if(sub_protocol==ESKY_ET4) + { + rx_tx_addr[0]=0x72; + rx_tx_addr[1]=0xBB; + rx_tx_addr[2]=0xCC; + } + #endif rx_tx_addr[3] = 0xBB; ESKY_init(); ESKY_init2(); + packet_count=0; return 50000; } diff --git a/Multiprotocol/FrSkyDVX_common.ino b/Multiprotocol/FrSkyDVX_common.ino index 7bfc346..ec9fbf8 100644 --- a/Multiprotocol/FrSkyDVX_common.ino +++ b/Multiprotocol/FrSkyDVX_common.ino @@ -70,6 +70,41 @@ void Frsky_init_hop(void) hopping_frequency[i]=i>46?0:val; } } + +void FrSkyX2_init_hop(void) +{ + uint16_t id=(rx_tx_addr[2]<<8) + rx_tx_addr[3]; + //Increment + uint8_t inc = (id % 46) + 1; + if( inc == 12 || inc ==35 ) inc++; //Exception list from dumps + //Start offset + uint8_t offset = id % 5; + + debug("hop: "); + uint8_t channel; + for(uint8_t i=0; i<47; i++) + { + channel = 5 * (uint16_t(inc * i) % 47) + offset; + //Exception list from dumps + if(sub_protocol & 2 )// LBT or FCC + { + //LBT + if( channel <=1 || channel == 43 || channel == 44 || channel == 87 || channel == 88 || channel == 129 || channel == 130 || channel == 173 || channel == 174) + channel += 2; + else if( channel == 216 || channel == 217 || channel == 218) + channel += 3; + } + else // FCC + if ( channel == 3 || channel == 4 || channel == 46 || channel == 47 || channel == 90 || channel == 91 || channel == 133 || channel == 134 || channel == 176 || channel == 177 || channel == 220 || channel == 221 ) + channel += 2; + //Store + hopping_frequency[i] = channel; + debug(" %02X",channel); + } + debugln(""); + hopping_frequency[47] = 0; //Bind freq +} + #endif /******************************/ /** FrSky V, D and X routines **/ @@ -142,43 +177,43 @@ void Frsky_init_hop(void) /*15_DEVIATN*/ 0x42 }; #endif - #if defined(FRSKYX_CC2500_INO) || defined(FRSKYX2_CC2500_INO) + #if defined(FRSKYX_CC2500_INO) const PROGMEM uint8_t FRSKYX_cc2500_conf[]= { //FRSKYX - /*02_IOCFG0*/ 0x06 , + /*02_IOCFG0*/ 0x06 , /*00_IOCFG2*/ 0x06 , - /*17_MCSM1*/ 0x0c , + /*17_MCSM1*/ 0x0c , //X2->0x0E -> Go/Stay in RX mode /*18_MCSM0*/ 0x18 , /*06_PKTLEN*/ 0x1E , /*07_PKTCTRL1*/ 0x04 , - /*08_PKTCTRL0*/ 0x01 , + /*08_PKTCTRL0*/ 0x01 , //X2->0x05 -> CRC enabled /*3E_PATABLE*/ 0xff , /*0B_FSCTRL1*/ 0x0A , /*0C_FSCTRL0*/ 0x00 , /*0D_FREQ2*/ 0x5c , /*0E_FREQ1*/ 0x76 , /*0F_FREQ0*/ 0x27 , - /*10_MDMCFG4*/ 0x7B , - /*11_MDMCFG3*/ 0x61 , + /*10_MDMCFG4*/ 0x7B , + /*11_MDMCFG3*/ 0x61 , //X2->0x84 -> bitrate 70K->77K /*12_MDMCFG2*/ 0x13 , /*13_MDMCFG1*/ 0x23 , /*14_MDMCFG0*/ 0x7a , /*15_DEVIATN*/ 0x51 }; const PROGMEM uint8_t FRSKYXEU_cc2500_conf[]= { - /*02_IOCFG0*/ 0x06 , + /*02_IOCFG0*/ 0x06 , /*00_IOCFG2*/ 0x06 , /*17_MCSM1*/ 0x0E , /*18_MCSM0*/ 0x18 , /*06_PKTLEN*/ 0x23 , /*07_PKTCTRL1*/ 0x04 , - /*08_PKTCTRL0*/ 0x01 , + /*08_PKTCTRL0*/ 0x01 , //X2->0x05 -> CRC enabled /*3E_PATABLE*/ 0xff , /*0B_FSCTRL1*/ 0x08 , /*0C_FSCTRL0*/ 0x00 , - /*0D_FREQ2*/ 0x5c , + /*0D_FREQ2*/ 0x5c , /*0E_FREQ1*/ 0x80 , /*0F_FREQ0*/ 0x00 , - /*10_MDMCFG4*/ 0x7B , + /*10_MDMCFG4*/ 0x7B , /*11_MDMCFG3*/ 0xF8 , /*12_MDMCFG2*/ 0x03 , /*13_MDMCFG1*/ 0x23 , @@ -222,8 +257,6 @@ void Frsky_init_hop(void) uint8_t val=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][1]); CC2500_WriteReg(reg,val); } - if(protocol==PROTO_FRSKYX2) - CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // enable CRC CC2500_SetTxRxMode(TX_EN); CC2500_SetPower(); CC2500_Strobe(CC2500_SIDLE); // Go to idle... @@ -257,6 +290,15 @@ static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch ) static void __attribute__((unused)) FrSkyX_init() { FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC + if(protocol==PROTO_FRSKYX2) + { + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC + if(!(sub_protocol&2)) + { // FCC + CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode + CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K + } + } // for(uint8_t c=0;c < 48;c++) {//calibrate hop channels diff --git a/Multiprotocol/FrSkyD_cc2500.ino b/Multiprotocol/FrSkyD_cc2500.ino index 49a5aad..8de5296 100644 --- a/Multiprotocol/FrSkyD_cc2500.ino +++ b/Multiprotocol/FrSkyD_cc2500.ino @@ -21,6 +21,7 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind) { FRSKY_init_cc2500(FRSKYD_cc2500_conf); + CC2500_WriteReg(CC2500_1B_AGCCTRL2, bind ? 0x43 : 0x03); CC2500_WriteReg(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]); CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); CC2500_Strobe(CC2500_SIDLE); // Go to idle... @@ -95,7 +96,17 @@ static void __attribute__((unused)) frsky2way_data_frame() uint16_t initFrSky_2way() { - Frsky_init_hop(); + //FrskyD init hop + for(uint8_t i=0;i<50;i++) + { + uint8_t freq = (i * 0x1e) % 0xeb; + if(i == 3 || i == 23 || i == 47) + freq++; + if(i > 47) + freq=0; + hopping_frequency[i]=freq; + } + packet_count=0; if(IS_BIND_IN_PROGRESS) { diff --git a/Multiprotocol/FrSkyX_cc2500.ino b/Multiprotocol/FrSkyX_cc2500.ino index 0e20dd1..6c00054 100644 --- a/Multiprotocol/FrSkyX_cc2500.ino +++ b/Multiprotocol/FrSkyX_cc2500.ino @@ -21,34 +21,65 @@ static void __attribute__((unused)) FrSkyX_build_bind_packet() { - packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC - packet[1] = 0x03; - packet[2] = 0x01; - // - packet[3] = rx_tx_addr[3]; - packet[4] = rx_tx_addr[2]; - int idx = ((state -FRSKY_BIND) % 10) * 5; - packet[5] = idx; - packet[6] = hopping_frequency[idx++]; - packet[7] = hopping_frequency[idx++]; - packet[8] = hopping_frequency[idx++]; - packet[9] = hopping_frequency[idx++]; - packet[10] = hopping_frequency[idx++]; - packet[11] = 0x02; - packet[12] = RX_num; - // - uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; - memset(&packet[13], 0, limit - 13); - if(binding_idx&0x01) - memcpy(&packet[13],(void *)"\x55\xAA\x5A\xA5",4); // Telem off - if(binding_idx&0x02) - memcpy(&packet[17],(void *)"\x55\xAA\x5A\xA5",4); // CH9-16 - // - uint16_t lcrc = FrSkyX_crc(&packet[3], limit-3); - // - packet[limit++] = lcrc >> 8; - packet[limit] = lcrc; - // + uint8_t packet_size = 0x1D; + if(protocol==PROTO_FRSKYX && (sub_protocol & 2 )) + packet_size=0x20; // FrSkyX V1 LBT + //Header + packet[0] = packet_size; // Number of bytes in the packet (after this one) + packet[1] = 0x03; // Bind packet + packet[2] = 0x01; // Bind packet + + //ID + packet[3] = rx_tx_addr[3]; // ID + packet[4] = rx_tx_addr[2]; // ID + + if(protocol==PROTO_FRSKYX) + { + int idx = ((state -FRSKY_BIND) % 10) * 5; + packet[5] = idx; + packet[6] = hopping_frequency[idx++]; + packet[7] = hopping_frequency[idx++]; + packet[8] = hopping_frequency[idx++]; + packet[9] = hopping_frequency[idx++]; + packet[10] = hopping_frequency[idx++]; + packet[11] = 0x02; // Unknown but constant ID? + packet[12] = RX_num; + // + memset(&packet[13], 0, packet_size - 14); + if(binding_idx&0x01) + memcpy(&packet[13],(void *)"\x55\xAA\x5A\xA5",4); // Telem off + if(binding_idx&0x02) + memcpy(&packet[17],(void *)"\x55\xAA\x5A\xA5",4); // CH9-16 + } + else + { + //packet 1D 03 01 0E 1C 02 00 00 32 0B 00 00 A8 26 28 01 A1 00 00 00 3E F6 87 C7 00 00 00 00 C9 C9 + packet[5] = 0x02; // Unknown but constant ID? + packet[6] = RX_num; + //Bind flags + packet[7]=0; + if(binding_idx&0x01) + packet[7] |= 0x40; // Telem off + if(binding_idx&0x02) + packet[7] |= 0x80; // CH9-16 + //Unknown bytes + memcpy(&packet[8],"\x32\x0B\x00\x00\xA8\x26\x28\x01\xA1\x00\x00\x00\x3E\xF6\x87\xC7",16); + packet[20]^= 0x0E ^ rx_tx_addr[3]; // Update the ID + packet[21]^= 0x1C ^ rx_tx_addr[2]; // Update the ID + //Xor + for(uint8_t i=3; i> 8; + packet[packet_size] = lcrc; + + /*//Debug + debug("Bind:"); + for(uint8_t i=0;i<=packet_size;i++) + debug(" %02X",packet[i]); + debugln("");*/ } #define FrSkyX_FAILSAFE_TIME 1032 @@ -81,10 +112,14 @@ static void __attribute__((unused)) FrSkyX_build_packet() failsafe_count++; #endif - packet[0] = (sub_protocol & 0x02 ) ? 0x20 : 0x1D ; // LBT or FCC - packet[1] = rx_tx_addr[3]; - packet[2] = rx_tx_addr[2]; - packet[3] = 0x02; + uint8_t packet_size = 0x1D; + if(protocol==PROTO_FRSKYX && (sub_protocol & 2 )) + packet_size=0x20; // FrSkyX V1 LBT + //Header + packet[0] = packet_size; // Number of bytes in the packet (after this one) + packet[1] = rx_tx_addr[3]; // ID + packet[2] = rx_tx_addr[2]; // ID + packet[3] = 0x02; // Unknown but constant ID? // packet[4] = (FrSkyX_chanskip<<6)|hopping_frequency_no; packet[5] = FrSkyX_chanskip>>2; @@ -128,8 +163,7 @@ static void __attribute__((unused)) FrSkyX_build_packet() chan_offset^=0x08; //sequence and send SPort - uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; - for (uint8_t i=22;i>8;//high byte - packet[limit]=lcrc;//low byte + //CRC + uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4); + packet[packet_size-1] = lcrc >> 8; + packet[packet_size] = lcrc; + + /*//Debug + debug("Norm:"); + for(uint8_t i=0;i<=packet_size;i++) + debug(" %02X",packet[i]); + debugln("");*/ } uint16_t ReadFrSkyX() { - static bool transmit=true; - #ifdef DEBUG_SERIAL - static uint16_t fr_time=0; - #endif - switch(state) { default: @@ -241,7 +277,61 @@ uint16_t ReadFrSkyX() BIND_DONE; state++; //FRSKY_DATA1 break; - case FRSKY_DATA5: + + case FRSKY_DATA1: + CC2500_Strobe(CC2500_SIDLE); + if ( prev_option != option ) + { + CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack + prev_option = option ; + } + FrSkyX_set_start(hopping_frequency_no); + FrSkyX_build_packet(); + if(sub_protocol & 2) + {// LBT + CC2500_Strobe(CC2500_SRX); //Acquire RSSI + state++; + return 400; // LBT v2.1 + } + case FRSKY_DATA2: + if(sub_protocol & 2) + { + uint16_t rssi=0; + for(uint8_t i=0;i<4;i++) + rssi += CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST); // 0.5 db/count, RSSI value read from the RSSI status register is a 2's complement number + rssi>>=2; + #if 0 + uint8_t rssi_level=convert_channel_8b(CH16)>>1; //CH16 0..127 + if ( rssi > rssi_level && rssi < 128) //test rssi level dynamically + #else + if ( rssi > 72 && rssi < 128) //LBT and RSSI between -36 and -8.5 dBm + #endif + { + POWER_FLAG_off; // Reduce to low power before transmitting + debugln("Busy %d %d",hopping_frequency_no,rssi); + } + } + CC2500_Strobe(CC2500_SIDLE); + CC2500_Strobe(CC2500_SFTX); + CC2500_SetTxRxMode(TX_EN); + CC2500_SetPower(); + hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47; + CC2500_WriteData(packet, packet[0]+1); + state=FRSKY_DATA3; + if(sub_protocol & 2) + return 4000; // LBT v2.1 + else + return 5200; // FCC v2.1 + case FRSKY_DATA3: + CC2500_Strobe(CC2500_SIDLE); + CC2500_SetTxRxMode(RX_EN); + CC2500_Strobe(CC2500_SRX); + state++; + if(sub_protocol & 2) + return 4100; // LBT v2.1 + else + return 3300; // FCC v2.1 + case FRSKY_DATA4: #ifdef MULTI_SYNC telemetry_set_input_sync(9000); #endif @@ -251,11 +341,19 @@ uint16_t ReadFrSkyX() len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (len && (len<=(0x0E + 3))) //Telemetry frame is 17 { + //debug("Telem:"); packet_count=0; CC2500_ReadData(packet_in, len); #if defined TELEMETRY - frsky_check_telemetry(packet_in,len); //Check and parse telemetry packets + if(protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80)) ) + {//with valid crc for FRSKYX2 + //Debug + //for(uint8_t i=0;i 72 && rssi < 128) //LBT and RSSI between -36 and -8.5 dBm - { - transmit=false; - debugln("Busy %d %d",hopping_frequency_no,rssi); - } -#endif - CC2500_Strobe(CC2500_SIDLE); - CC2500_Strobe(CC2500_SFRX); - CC2500_SetTxRxMode(TX_EN); - CC2500_SetPower(); - hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47; - if(transmit) - { - #ifdef DEBUG_SERIAL - uint16_t fr_cur=millis(); - fr_time=fr_cur-fr_time; - if(fr_time!=9) - debugln("Bad timing: %d",fr_time); - fr_time=fr_cur; - #endif - CC2500_WriteData(packet, packet[0]+1); - } - state=FRSKY_DATA3; - return 5200; - case FRSKY_DATA3: - CC2500_SetTxRxMode(RX_EN); - CC2500_Strobe(CC2500_SIDLE); - state++; - return 200; - case FRSKY_DATA4: - CC2500_Strobe(CC2500_SRX); - state++; - return 3100; + return 500; // FCC & LBT v2.1 } return 1; } @@ -340,15 +385,23 @@ uint16_t ReadFrSkyX() uint16_t initFrSkyX() { set_rx_tx_addr(MProtocol_id_master); - Frsky_init_hop(); + + if(protocol==PROTO_FRSKYX) + Frsky_init_hop(); + else + { + #ifdef FRSKYX2_FORCE_ID + rx_tx_addr[3]=0x0E; + rx_tx_addr[2]=0x1C; + FrSkyX_chanskip=18; + #endif + FrSkyX2_init_hop(); + } + packet_count=0; while(!FrSkyX_chanskip) FrSkyX_chanskip=random(0xfefefefe)%47; - //for test*************** - //rx_tx_addr[3]=0xB3; - //rx_tx_addr[2]=0xFD; - //************************ FrSkyX_init(); if(IS_BIND_IN_PROGRESS) diff --git a/Multiprotocol/FrSky_Rx_cc2500.ino b/Multiprotocol/FrSky_Rx_cc2500.ino index f1b7758..9304f33 100644 --- a/Multiprotocol/FrSky_Rx_cc2500.ino +++ b/Multiprotocol/FrSky_Rx_cc2500.ino @@ -19,6 +19,7 @@ #define FRSKY_RX_D16FCC_LENGTH 32 #define FRSKY_RX_D16LBT_LENGTH 35 + #define FRSKY2_RX_D16_LENGTH 32 #define FRSKY_RX_D8_LENGTH 20 #define FRSKY_RX_FORMATS 3 @@ -313,6 +314,7 @@ uint16_t FrSky_Rx_callback() if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc()) { rx_tx_addr[0] = packet[3]; // TXID rx_tx_addr[1] = packet[4]; // TXID + rx_tx_addr[2] = packet[11]; // TXID frsky_rx_finetune = -127; CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); phase = FRSKY_RX_TUNE_LOW; @@ -330,7 +332,7 @@ uint16_t FrSky_Rx_callback() case FRSKY_RX_TUNE_LOW: if (len >= packet_length) { CC2500_ReadData(packet, packet_length); - if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1]) { + if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1] && (frsky_rx_format == FRSKY_RX_D8 || packet[11] == rx_tx_addr[2])) { tune_low = frsky_rx_finetune; frsky_rx_finetune = 127; CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); @@ -347,7 +349,7 @@ uint16_t FrSky_Rx_callback() case FRSKY_RX_TUNE_HIGH: if (len >= packet_length) { CC2500_ReadData(packet, packet_length); - if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1]) { + if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1] && (frsky_rx_format == FRSKY_RX_D8 || packet[11] == rx_tx_addr[2])) { tune_high = frsky_rx_finetune; frsky_rx_finetune = (tune_low + tune_high) / 2; CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frsky_rx_finetune); @@ -367,14 +369,13 @@ uint16_t FrSky_Rx_callback() case FRSKY_RX_BIND: if(len >= packet_length) { CC2500_ReadData(packet, packet_length); - if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1] && packet[5] <= 0x2D) { + if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1] && (frsky_rx_format == FRSKY_RX_D8 || packet[11] == rx_tx_addr[2]) && packet[5] <= 0x2D) { for (ch = 0; ch < 5; ch++) hopping_frequency[packet[5]+ch] = packet[6+ch]; state |= 1 << (packet[5] / 5); if (state == 0x3ff) { debug("Bind complete: "); frsky_rx_calibrate(); - rx_tx_addr[2] = packet[12]; // RX # (D16) CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[0]); // set address CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // check address @@ -389,7 +390,8 @@ uint16_t FrSky_Rx_callback() eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]); debug("addr[1]=%02X, ", rx_tx_addr[1]); eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]); - debug("rx_num=%02X, ", rx_tx_addr[2]); + debug("addr[2]=%02X, ", rx_tx_addr[2]); + debug("rx_num=%02X, ", packet[12]); // RX # (D16) eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune); debugln("tune=%d", (int8_t)frsky_rx_finetune); for (ch = 0; ch < 47; ch++) @@ -408,18 +410,27 @@ uint16_t FrSky_Rx_callback() case FRSKY_RX_DATA: if (len >= packet_length) { CC2500_ReadData(packet, packet_length); - if (packet[1] == rx_tx_addr[0] && packet[2] == rx_tx_addr[1] && frskyx_rx_check_crc() && (frsky_rx_format == FRSKY_RX_D8 || packet[6] == rx_tx_addr[2])) { + if (packet[1] == rx_tx_addr[0] && packet[2] == rx_tx_addr[1] && frskyx_rx_check_crc() && (frsky_rx_format == FRSKY_RX_D8 || (packet[6] == RX_num && packet[3] == rx_tx_addr[2]))) { RX_RSSI = packet[packet_length-2]; if(RX_RSSI >= 128) RX_RSSI -= 128; else RX_RSSI += 128; + bool chanskip_valid=true; // hop to next channel if (frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT) - frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); + { + if(rx_data_started) + { + if(frsky_rx_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2))) + chanskip_valid=false; // chanskip value has changed which surely indicates a bad frame + } + else + frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init + } hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47; frsky_rx_set_channel(hopping_frequency_no); - if (telemetry_link == 0) { // send channels to TX + if (telemetry_link == 0 && chanskip_valid) { // send channels to TX frsky_rx_build_telemetry_packet(); telemetry_link = 1; } diff --git a/Multiprotocol/GD00X_nrf24l01.ino b/Multiprotocol/GD00X_nrf24l01.ino index d4f7f7b..9c8c49d 100644 --- a/Multiprotocol/GD00X_nrf24l01.ino +++ b/Multiprotocol/GD00X_nrf24l01.ino @@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful, #if defined(GD00X_NRF24L01_INO) -#include "iface_xn297l.h" +#include "iface_nrf250k.h" //#define FORCE_GD00X_ORIGINAL_ID diff --git a/Multiprotocol/Hitec_cc2500.ino b/Multiprotocol/Hitec_cc2500.ino index f380074..0f95c77 100644 --- a/Multiprotocol/Hitec_cc2500.ino +++ b/Multiprotocol/Hitec_cc2500.ino @@ -146,6 +146,11 @@ static void __attribute__((unused)) HITEC_build_packet() break; case 0x7B: packet[5]=hopping_frequency[13]>>1; // if not there the Optima link is jerky... + packet[14]=0x2A; + packet[15]=0x46; // unknown but if 0x45 then 17=0x46, if 0x46 then 17=0x46 or 0x47, if 0x47 then 0x45 or 0x46 + packet[16]=0x2A; + packet[17]=0x47; + packet[18]=0x2A; break; } if(sub_protocol==MINIMA) @@ -302,8 +307,8 @@ uint16_t ReadHITEC() { // bind packet: 0A,00,E5,F2,7X,05,06,07,08,09,00 debug(",bind"); boolean check=true; - for(uint8_t i=5;i<=10;i++) - if(packet_in[i]!=i%10) check=false; + for(uint8_t i=5;i<10;i++) + if(packet_in[i]!=i) check=false; if((packet_in[4]&0xF0)==0x70 && check) { bind_phase=packet_in[4]+1; diff --git a/Multiprotocol/KF606_nrf24l01.ino b/Multiprotocol/KF606_nrf24l01.ino index e50d6a4..290f444 100644 --- a/Multiprotocol/KF606_nrf24l01.ino +++ b/Multiprotocol/KF606_nrf24l01.ino @@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful, #if defined(KF606_NRF24L01_INO) -#include "iface_xn297l.h" +#include "iface_nrf250k.h" //#define FORCE_KF606_ORIGINAL_ID diff --git a/Multiprotocol/MJXQ_nrf24l01.ino b/Multiprotocol/MJXQ_nrf24l01.ino index 3db83c0..04c0a07 100644 --- a/Multiprotocol/MJXQ_nrf24l01.ino +++ b/Multiprotocol/MJXQ_nrf24l01.ino @@ -18,7 +18,7 @@ #if defined(MJXQ_NRF24L01_INO) #include "iface_nrf24l01.h" -#include "iface_xn297l.h" +#include "iface_nrf250k.h" #define MJXQ_BIND_COUNT 150 #define MJXQ_PACKET_PERIOD 4000 // Timeout for callback in uSec diff --git a/Multiprotocol/Multi.txt b/Multiprotocol/Multi.txt index 9b72083..59e0da2 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -13,7 +13,7 @@ 13,CG023,CG023,YD829 14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4 15,FrskyX,CH_16,CH_8,EU_16,EU_8 -16,ESky,4CH,7CH +16,ESky,Std,ET4 17,MT99xx,MT,H7,YZ,LS,FY805 18,MJXq,WLH08,X600,X800,H26D,E010,H26WH,PHOENIX 19,Shenqi @@ -32,7 +32,7 @@ 32,GW008 33,DM002 34,CABELL,CAB_V3,C_TELEM,-,-,-,-,F_SAFE,UNBIND -35,ESKY150 +35,ESKY150,4CH,7CH 36,H8_3D,H8_3D,H20H,H20Mini,H30Mini 37,CORONA,COR_V1,COR_V2,FD_V3 38,CFlie @@ -43,7 +43,7 @@ 43,Traxxas,RX6519 44,NCC1701 45,E01X,E012,E015,E016H -46,V911S,Std +46,V911S,V911S,E119 47,GD00X,GD_V1,GD_V2 48,V761 49,KF606 @@ -63,3 +63,4 @@ 63,XN_DUMP,250K,1M,2M,AUTO 64,FrskyX2,CH_16,CH_8,EU_16,EU_8 65,FrSkyR9,915MHz,868MHz,915_8ch,868_8ch +66,PROPEL,74-Z diff --git a/Multiprotocol/Multi_Names.ino b/Multiprotocol/Multi_Names.ino index f5e0fe9..29e7a6b 100644 --- a/Multiprotocol/Multi_Names.ino +++ b/Multiprotocol/Multi_Names.ino @@ -79,6 +79,7 @@ const char STR_TIGER[] ="Tiger"; const char STR_XK[] ="XK"; const char STR_XN297DUMP[] ="XN297DP"; const char STR_FRSKYR9[] ="FrSkyR9"; +const char STR_PROPEL[] ="PROPEL"; const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20"; const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501"; @@ -117,9 +118,11 @@ const char STR_SUBTYPE_FLYZONE[] = "\x05""FZ410"; const char STR_SUBTYPE_FX816[] = "\x03""P38"; const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 "; const char STR_SUBTYPE_ESKY150[] = "\x03""4CH""7CH"; -const char STR_SUBTYPE_V911S[] = "\x04""Std\0""E119"; +const char STR_SUBTYPE_V911S[] = "\x05""V911S""E119\0"; const char STR_SUBTYPE_XK[] = "\x04""X450""X420"; const char STR_SUBTYPE_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch"; +const char STR_SUBTYPE_ESKY[] = "\x03""Std""ET4"; +const char STR_SUBTYPE_PROPEL[] = "\x04""74-Z"; enum { @@ -169,7 +172,7 @@ const mm_protocol_definition multi_protocols[] = { {PROTO_SYMAX, STR_SYMAX, 2, STR_SUBTYPE_SYMAX, OPTION_NONE }, #endif #if defined(SLT_NRF24L01_INO) - {PROTO_SLT, STR_SLT, 5, STR_SUBTYPE_SLT, OPTION_NONE }, + {PROTO_SLT, STR_SLT, 5, STR_SUBTYPE_SLT, OPTION_RFTUNE }, #endif #if defined(CX10_NRF24L01_INO) {PROTO_CX10, STR_CX10, 7, STR_SUBTYPE_CX10, OPTION_NONE }, @@ -182,12 +185,10 @@ const mm_protocol_definition multi_protocols[] = { #endif #if defined(FRSKYX_CC2500_INO) {PROTO_FRSKYX, STR_FRSKYX, 4, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE }, -#endif -#if defined(FRSKYX2_CC2500_INO) {PROTO_FRSKYX2, STR_FRSKYX2, 4, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE }, #endif #if defined(ESKY_NRF24L01_INO) - {PROTO_ESKY, STR_ESKY, 0, NO_SUBTYPE, OPTION_NONE }, + {PROTO_ESKY, STR_ESKY, 2, STR_SUBTYPE_ESKY, OPTION_NONE }, #endif #if defined(MT99XX_NRF24L01_INO) {PROTO_MT99XX, STR_MT99XX, 5, STR_SUBTYPE_MT99, OPTION_NONE }, @@ -274,7 +275,7 @@ const mm_protocol_definition multi_protocols[] = { {PROTO_E01X, STR_E01X, 3, STR_SUBTYPE_E01X, OPTION_OPTION }, #endif #if defined(V911S_NRF24L01_INO) - {PROTO_V911S, STR_V911S, 1, STR_SUBTYPE_V911S, OPTION_RFTUNE }, + {PROTO_V911S, STR_V911S, 2, STR_SUBTYPE_V911S, OPTION_RFTUNE }, #endif #if defined(GD00X_NRF24L01_INO) {PROTO_GD00X, STR_GD00X, 2, STR_SUBTYPE_GD00X, OPTION_RFTUNE }, @@ -328,7 +329,10 @@ const mm_protocol_definition multi_protocols[] = { {PROTO_XN297DUMP, STR_XN297DUMP, 4, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN }, #endif #if defined(FRSKYR9_SX1276_INO) - {PROTO_FRSKY_R9, STR_FRSKYR9, 4, STR_SUBTYPE_FRSKYR9, OPTION_NONE }, + {PROTO_FRSKY_R9, STR_FRSKYR9, 4, STR_SUBTYPE_FRSKYR9, OPTION_NONE }, +#endif +#if defined(PROPEL_NRF24L01_INO) + {PROTO_PROPEL, STR_PROPEL, 4, STR_SUBTYPE_PROPEL, OPTION_NONE }, #endif {0x00, nullptr, 0, nullptr, 0 } }; diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index 6823672..c6cbe87 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 67 +#define VERSION_PATCH_LEVEL 84 //****************** // Protocols @@ -92,6 +92,7 @@ enum PROTOCOLS PROTO_XN297DUMP = 63, // =>NRF24L01 PROTO_FRSKYX2 = 64, // =>CC2500 PROTO_FRSKY_R9 = 65, // =>SX1276 + PROTO_PROPEL = 66, // =>NRF24L01 }; enum Flysky @@ -214,13 +215,6 @@ enum FRSKYX EU_16 = 2, EU_8 = 3, }; -enum FRSKYX2 -{ - FRSKYX2_CH_16 = 0, - FRSKYX2_CH_8 = 1, - FRSKYX2_EU_16 = 2, - FRSKYX2_EU_8 = 3, -}; enum HONTAI { HONTAI = 0, @@ -334,6 +328,11 @@ enum FRSKY_R9 R9_915_8CH = 2, R9_868_8CH = 3, }; +enum ESKY +{ + ESKY_STD = 0, + ESKY_ET4 = 1, +}; #define NONE 0 #define P_HIGH 1 @@ -377,7 +376,7 @@ 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 ) +#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 ) //*************** @@ -729,6 +728,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- XN297DUMP 63 FRSKYX2 64 FRSKY_R9 65 + PROPEL 66 BindBit=> 0x80 1=Bind/0=No AutoBindBit=> 0x40 1=Yes /0=No RangeCheck=> 0x20 1=Yes /0=No @@ -879,14 +879,14 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- sub_protocol==XK X450 0 X420 1 - sub_protocol==V911S - V911S_STD 0 - V911S_E119 1 sub_protocol==FRSKY_R9 R9_915 0 R9_868 1 R9_915_8CH 2 R9_868_8CH 3 + sub_protocol==ESKY + ESKY_STD 0 + ESKY_ET4 1 Power value => 0x80 0=High/1=Low Stream[3] = option_protocol; @@ -909,6 +909,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- Disable_Telemetry => 0x02 0=enable, 1=disable Disable_CH_Mapping => 0x01 0=enable, 1=disable Stream[27.. 35] = between 0 and 9 bytes for additional protocol data + Protocol specific use: + FrSkyX and FrSkyX2: Stream[27] during bind Telem on=0x00,off=0x01 | CH1-8=0x00,CH9-16=0x02 + FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent + HoTT: Stream[27] 1 byte for telemetry type */ /* Multimodule Status diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 233916f..3e8da97 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -514,11 +514,6 @@ void setup() option = FORCE_FRSKYX_TUNING; // Use config-defined tuning value for FrSkyX else #endif - #if defined(FORCE_FRSKYX2_TUNING) && defined(FRSKYX2_CC2500_INO) - if(protocol==PROTO_FRSKYX2) - option = FORCE_FRSKYX2_TUNING; // Use config-defined tuning value for FrSkyX2 - else - #endif #if defined(FORCE_SFHSS_TUNING) && defined(SFHSS_CC2500_INO) if (protocol==PROTO_SFHSS) option = FORCE_SFHSS_TUNING; // Use config-defined tuning value for SFHSS @@ -742,7 +737,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)) + 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)) #endif if(IS_DISABLE_TELEM_off) TelemetryUpdate(); @@ -759,7 +754,7 @@ bool Update_All() BIND_CH_PREV_off; //Request protocol to terminate bind #if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO) - if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A ) + if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A ) BIND_DONE; else #endif @@ -1127,20 +1122,13 @@ static void protocol_init() #endif #if defined(FRSKYX_CC2500_INO) case PROTO_FRSKYX: + case PROTO_FRSKYX2: PE1_off; //antenna RF2 PE2_on; next_callback = initFrSkyX(); remote_callback = ReadFrSkyX; break; #endif - #if defined(FRSKYX2_CC2500_INO) - case PROTO_FRSKYX2: - PE1_off; //antenna RF2 - PE2_on; - next_callback = initFrSkyX2(); - remote_callback = ReadFrSkyX2; - break; - #endif #if defined(SFHSS_CC2500_INO) case PROTO_SFHSS: PE1_off; //antenna RF2 @@ -1497,6 +1485,12 @@ static void protocol_init() remote_callback = XK_callback; break; #endif + #if defined(PROPEL_NRF24L01_INO) + case PROTO_PROPEL: + next_callback=initPROPEL(); + remote_callback = PROPEL_callback; + break; + #endif #if defined(XN297DUMP_NRF24L01_INO) case PROTO_XN297DUMP: next_callback=initXN297Dump(); @@ -1624,11 +1618,6 @@ void update_serial_data() option=FORCE_FRSKYX_TUNING; // Use config-defined tuning value for FrSkyX else #endif - #if defined(FORCE_FRSKYX2_TUNING) && defined(FRSKYX2_CC2500_INO) - if(protocol==PROTO_FRSKYX2) - option=FORCE_FRSKYX2_TUNING; // Use config-defined tuning value for FrSkyX2 - else - #endif #if defined(FORCE_SFHSS_TUNING) && defined(SFHSS_CC2500_INO) if (protocol==PROTO_SFHSS) option=FORCE_SFHSS_TUNING; // Use config-defined tuning value for SFHSS @@ -1732,7 +1721,7 @@ void update_serial_data() if( ((rx_ok_buff[1]&0x80)==0) && ((cur_protocol[1]&0x80)!=0) ) // Bind flag has been reset { // Request protocol to end bind #if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO) || defined(FRSKYR9_SX1276_INO) - if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A || protocol==PROTO_FRSKY_R9 ) + if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A || protocol==PROTO_FRSKY_R9 ) BIND_DONE; else #endif @@ -1791,7 +1780,7 @@ void update_serial_data() #endif if(rx_len>27) { // Data available for the current protocol - #if defined FRSKYX_CC2500_INO || defined FRSKYX2_CC2500_INO + #if defined FRSKYX_CC2500_INO if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2) && rx_len==28) {//Protocol waiting for 1 byte during bind binding_idx=rx_ok_buff[27]; @@ -1803,33 +1792,41 @@ void update_serial_data() #define BYTE_STUFF 0x7D #define STUFF_MASK 0x20 //debug("SPort_in: "); - SportData[SportTail]=0x7E; - SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1); - SportData[SportTail]=rx_ok_buff[27]&0x1F; - SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1); + boolean sport_valid=false; for(uint8_t i=28;i<28+7;i++) + if(rx_ok_buff[i]!=0) sport_valid=true; //Check that the payload is not full of 0 + if((rx_ok_buff[27]&0x1F) > 0x1B) //Check 1st byte validity + sport_valid=false; + if(sport_valid) { - if(rx_ok_buff[i]==BYTE_STUFF) - {//stuff - SportData[SportTail]=BYTE_STUFF; - SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1); - SportData[SportTail]=rx_ok_buff[i]^STUFF_MASK; - } - else - SportData[SportTail]=rx_ok_buff[i]; - //debug("%02X ",SportData[SportTail]); + SportData[SportTail]=0x7E; SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1); - } - uint8_t used = SportTail; - if ( SportHead > SportTail ) - used += MAX_SPORT_BUFFER - SportHead ; - else - used -= SportHead ; - if ( used >= MAX_SPORT_BUFFER-(MAX_SPORT_BUFFER>>2) ) - { - DATA_BUFFER_LOW_on; - SEND_MULTI_STATUS_on; //Send Multi Status ASAP to inform the TX - debugln("Low buf=%d,h=%d,t=%d",used,SportHead,SportTail); + SportData[SportTail]=rx_ok_buff[27]&0x1F; + SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1); + for(uint8_t i=28;i<28+7;i++) + { + if( (rx_ok_buff[i]==BYTE_STUFF) || (rx_ok_buff[i]==0x7E) ) + {//stuff + SportData[SportTail]=BYTE_STUFF; + SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1); + SportData[SportTail]=rx_ok_buff[i]^STUFF_MASK; + } + else + SportData[SportTail]=rx_ok_buff[i]; + //debug("%02X ",SportData[SportTail]); + SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1); + } + uint8_t used = SportTail; + if ( SportHead > SportTail ) + used += MAX_SPORT_BUFFER - SportHead ; + else + used -= SportHead ; + if ( used >= MAX_SPORT_BUFFER-(MAX_SPORT_BUFFER>>2) ) + { + DATA_BUFFER_LOW_on; + SEND_MULTI_STATUS_on; //Send Multi Status ASAP to inform the TX + debugln("Low buf=%d,h=%d,t=%d",used,SportHead,SportTail); + } } } #endif //SPORT_SEND @@ -2084,7 +2081,7 @@ void pollBoot() #if defined(TELEMETRY) void PPM_Telemetry_serial_init() { - if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) + if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) #ifdef TELEMETRY_FRSKYX_TO_FRSKYD || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) #endif diff --git a/Multiprotocol/NRF24l01_SPI.ino b/Multiprotocol/NRF24l01_SPI.ino index 3911a77..df0e31b 100644 --- a/Multiprotocol/NRF24l01_SPI.ino +++ b/Multiprotocol/NRF24l01_SPI.ino @@ -172,6 +172,10 @@ void NRF24L01_SetPower() if(prev_power != power) { rf_setup = (rf_setup & 0xF9) | (power << 1); + if(power==3) + rf_setup |=0x01; // Si24r01 full power, unused bit for NRF + else + rf_setup &=0xFE; NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup); prev_power=power; } diff --git a/Multiprotocol/XN297L_EMU.ino b/Multiprotocol/NRF250K_EMU.ino similarity index 83% rename from Multiprotocol/XN297L_EMU.ino rename to Multiprotocol/NRF250K_EMU.ino index 2f64665..daf959a 100644 --- a/Multiprotocol/XN297L_EMU.ino +++ b/Multiprotocol/NRF250K_EMU.ino @@ -13,7 +13,7 @@ along with Multiprotocol. If not, see . */ #ifdef NRF24L01_INSTALLED -#include "iface_xn297l.h" +#include "iface_nrf250k.h" static void __attribute__((unused)) XN297L_Init() { @@ -233,7 +233,7 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui buf[last] ^= xn297_scramble[scramble_index++] & 0xc0; // crc - if (xn297_crc) + //if (xn297_crc) { uint8_t offset = xn297_addr_len < 4 ? 1 : 0; uint16_t crc = 0xb5d2; @@ -249,11 +249,9 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui buf[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2); buf[last++] = (crc & 0xff) << 6; } - NRF24L01_WritePayload(packet, last); pid++; - if(pid>3) - pid=0; + pid &= 3; // stop TX/RX CC2500_Strobe(CC2500_SIDLE); @@ -262,7 +260,7 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui // packet length CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3); // xn297L preamble - CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0f\x55", 3); + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0F\x55", 3); // xn297 packet CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); // transmit @@ -352,4 +350,89 @@ static void __attribute__((unused)) XN297L_SetFreqOffset() } #endif } + +static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len) +{ + if (len > 5) len = 5; + if (len < 3) len = 3; + #ifdef CC2500_INSTALLED + if(option==0) + #endif + {//NRF + NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2); + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len); + return; + } + //CC2500 + #ifdef CC2500_INSTALLED + xn297_addr_len = len; + memcpy(xn297_tx_addr, addr, len); + #endif +} + +static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len) +{ + #ifdef CC2500_INSTALLED + if(option==0) + #endif + {//NRF + NRF24L01_FlushTx(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT)); + NRF24L01_WritePayload(msg, len); + return; + } + //CC2500 + #ifdef CC2500_INSTALLED + uint8_t buf[35]; + uint8_t last = 0; + uint8_t i; + + //nrf preamble + if(xn297_tx_addr[xn297_addr_len - 1] & 0x80) + buf[0]=0xAA; + else + buf[0]=0x55; + last++; + // address + for (i = 0; i < xn297_addr_len; ++i) + buf[last++] = xn297_tx_addr[xn297_addr_len - i - 1]; + // payload + for (i = 0; i < len; ++i) + buf[last++] = msg[i]; + + // crc + uint16_t crc = 0xffff; + for (uint8_t i = 1; i < last; ++i) + crc = crc16_update(crc, buf[i], 8); + buf[last++] = crc >> 8; + buf[last++] = crc & 0xff; + buf[last++] = 0; + + //for(uint8_t i=0;i. + */ +// Compatible with PROPEL 74-Z Speeder Bike. + +#if defined(PROPEL_NRF24L01_INO) + +#include "iface_nrf24l01.h" + +//#define PROPEL_FORCE_ID + +#define PROPEL_INITIAL_WAIT 500 +#define PROPEL_PACKET_PERIOD 10000 +#define PROPEL_BIND_RF_CHANNEL 0x23 +#define PROPEL_PAYLOAD_SIZE 16 +#define PROPEL_SEARCH_PERIOD 50 //*10ms +#define PROPEL_BIND_PERIOD 1500 +#define PROPEL_PACKET_SIZE 14 +#define PROPEL_RF_NUM_CHANNELS 4 +#define PROPEL_ADDRESS_LENGTH 5 +#define PROPEL_DEFAULT_PERIOD 20 + +enum { + PROPEL_BIND1 = 0, + PROPEL_BIND2, + PROPEL_BIND3, + PROPEL_DATA1, +}; + +static uint16_t __attribute__((unused)) PROPEL_checksum() +{ + typedef union { + struct { + uint8_t h:1; + uint8_t g:1; + uint8_t f:1; + uint8_t e:1; + uint8_t d:1; + uint8_t c:1; + uint8_t b:1; + uint8_t a:1; + } bits; + uint8_t byte:8; + } byte_bits_t; + + uint8_t sum = packet[0]; + for (uint8_t i = 1; i < PROPEL_PACKET_SIZE - 2; i++) + sum += packet[i]; + + byte_bits_t in = { .byte = sum }; + byte_bits_t out = { .byte = sum }; + out.byte ^= 0x0a; + out.bits.d = !(in.bits.d ^ in.bits.h); + out.bits.c = (!in.bits.c && !in.bits.d && in.bits.g) + || (in.bits.c && !in.bits.d && !in.bits.g) + || (!in.bits.c && in.bits.g && !in.bits.h) + || (in.bits.c && !in.bits.g && !in.bits.h) + || (in.bits.c && in.bits.d && in.bits.g && in.bits.h) + || (!in.bits.c && in.bits.d && !in.bits.g && in.bits.h); + out.bits.b = (!in.bits.b && !in.bits.c && !in.bits.d) + || (in.bits.b && in.bits.c && in.bits.g) + || (!in.bits.b && !in.bits.c && !in.bits.g) + || (!in.bits.b && !in.bits.d && !in.bits.g) + || (!in.bits.b && !in.bits.c && !in.bits.h) + || (!in.bits.b && !in.bits.g && !in.bits.h) + || (in.bits.b && in.bits.c && in.bits.d && in.bits.h) + || (in.bits.b && in.bits.d && in.bits.g && in.bits.h); + out.bits.a = (in.bits.a && !in.bits.b) + || (in.bits.a && !in.bits.c && !in.bits.d) + || (in.bits.a && !in.bits.c && !in.bits.g) + || (in.bits.a && !in.bits.d && !in.bits.g) + || (in.bits.a && !in.bits.c && !in.bits.h) + || (in.bits.a && !in.bits.g && !in.bits.h) + || (!in.bits.a && in.bits.b && in.bits.c && in.bits.g) + || (!in.bits.a && in.bits.b && in.bits.c && in.bits.d && in.bits.h) + || (!in.bits.a && in.bits.b && in.bits.d && in.bits.g && in.bits.h); + + return (sum << 8) | (out.byte & 0xff); +} + +static void __attribute__((unused)) PROPEL_bind_packet(bool valid_rx_id) +{ + memset(packet, 0, PROPEL_PACKET_SIZE); + + packet[0] = 0xD0; + memcpy(&packet[1], rx_tx_addr, 4); // only 4 bytes sent of 5-byte address + if (valid_rx_id) memcpy(&packet[5], rx_id, 4); + packet[9] = rf_ch_num; // hopping table to be used when switching to normal mode + packet[11] = 0x05; // unknown, 0x01 on TX2?? + + uint16_t check = PROPEL_checksum(); + packet[12] = check >> 8; + packet[13] = check & 0xff; + + NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))); + NRF24L01_FlushTx(); + NRF24L01_FlushRx(); + NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE); +} + +static void __attribute__((unused)) PROPEL_data_packet() +{ + memset(packet, 0, PROPEL_PACKET_SIZE); + + packet[0] = 0xC0; + packet[1] = convert_channel_16b_limit(THROTTLE, 0x2f, 0xcf); + packet[2] = convert_channel_16b_limit(RUDDER , 0xcf, 0x2f); + packet[3] = convert_channel_16b_limit(ELEVATOR, 0x2f, 0xcf); + packet[4] = convert_channel_16b_limit(AILERON , 0xcf, 0x2f); + packet[5] = 0x40; //might be trims but unsused + packet[6] = 0x40; //might be trims but unsused + packet[7] = 0x40; //might be trims but unsused + packet[8] = 0x40; //might be trims but unsused + if (bind_phase) + {//need to send a couple of default packets after bind + bind_phase--; + packet[10] = 0x80; // LEDs + } + else + { + packet[9] = 0x02 // Always fast speed, slow=0x00, medium=0x01, fast=0x02, 0x03=flight training mode + | GET_FLAG( CH14_SW, 0x03) // Flight training mode + | GET_FLAG( CH10_SW, 0x04) // Calibrate + | GET_FLAG( CH12_SW, 0x08) // Take off + | GET_FLAG( CH8_SW, 0x10) // Fire + | GET_FLAG( CH11_SW, 0x20) // Altitude hold=0x20 + | GET_FLAG( CH6_SW, 0x40) // Roll CW + | GET_FLAG( CH7_SW, 0x80); // Roll CCW + packet[10] = GET_FLAG( CH13_SW, 0x20) // Land + | GET_FLAG( CH9_SW, 0x40) // Weapon system activted=0x40 + | GET_FLAG(!CH5_SW, 0x80); // LEDs + } + packet[11] = 5; // unknown, 0x01 on TX2?? + + uint16_t check = PROPEL_checksum(); + packet[12] = check >> 8; + packet[13] = check & 0xff; + + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]); + hopping_frequency_no &= 0x03; + NRF24L01_SetPower(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))); + NRF24L01_FlushTx(); + NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE); +} + +static void __attribute__((unused)) PROPEL_init() +{ + NRF24L01_Initialize(); + NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f); + NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes + NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address + NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps + NRF24L01_SetPower(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // ?? match protocol capture + NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address + NRF24L01_WriteReg(NRF24L01_05_RF_CH, PROPEL_BIND_RF_CHANNEL); + NRF24L01_Activate(0x73); // Activate feature register + NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length + NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features + // Beken 2425 register bank 1 initialized here in stock tx capture + // Hopefully won't matter for nRF compatibility + NRF24L01_FlushTx(); + NRF24L01_SetTxRxMode(TX_EN); +} + +const uint8_t PROGMEM PROPEL_hopping []= { 0x47,0x36,0x27,0x44,0x33,0x0D,0x3C,0x2E,0x1B,0x39,0x2A,0x18 }; +static void __attribute__((unused)) PROPEL_initialize_txid() +{ + //address last byte + rx_tx_addr[4]=0x11; + + //random hopping channel table + rf_ch_num=random(0xfefefefe)&0x03; + for(uint8_t i=0; i<3; i++) + hopping_frequency[i]=pgm_read_byte_near( &PROPEL_hopping[i + 3*rf_ch_num] ); + hopping_frequency[3]=0x23; + +#ifdef PROPEL_FORCE_ID + if(RX_num&1) + memcpy(rx_tx_addr, (uint8_t *)"\x73\xd3\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX1: 73 d3 31 30 11 + else + memcpy(rx_tx_addr, (uint8_t *)"\x94\xc5\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX2: 94 c5 31 30 11 + rf_ch_num = 0x03; //TX1 + memcpy(hopping_frequency,(uint8_t *)"\x39\x2A\x18\x23",PROPEL_RF_NUM_CHANNELS); //TX1: 57,42,24,35 + rf_ch_num = 0x00; //TX2 + memcpy(hopping_frequency,(uint8_t *)"\x47\x36\x27\x23",PROPEL_RF_NUM_CHANNELS); //TX2: 71,54,39,35 + rf_ch_num = 0x01; // Manual search + memcpy(hopping_frequency,(uint8_t *)"\x44\x33\x0D\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 68,51,13,35 + rf_ch_num = 0x02; // Manual search + memcpy(hopping_frequency,(uint8_t *)"\x3C\x2E\x1B\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 60,46,27,35 +#endif +} + +uint16_t PROPEL_callback() +{ + uint8_t status; + + switch (phase) + { + case PROPEL_BIND1: + PROPEL_bind_packet(false); //rx_id unknown + phase++; //BIND2 + return PROPEL_BIND_PERIOD; + + case PROPEL_BIND2: + status=NRF24L01_ReadReg(NRF24L01_07_STATUS); + if (status & _BV(NRF24L01_07_MAX_RT)) + {// Max retry (6) reached + phase = PROPEL_BIND1; + return PROPEL_BIND_PERIOD; + } + if (!(_BV(NRF24L01_07_RX_DR) & status)) + return PROPEL_BIND_PERIOD; // nothing received + // received frame, got rx_id, save it + NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE); + memcpy(rx_id, &packet_in[1], 4); + PROPEL_bind_packet(true); //send bind packet with rx_id + phase++; //BIND3 + break; + + case PROPEL_BIND3: + if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS)) + { + NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE); + if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,4)==0) + {//confirmation from the model + phase++; //PROPEL_DATA1 + bind_phase=PROPEL_DEFAULT_PERIOD; + packet_count=0; + BIND_DONE; + break; + } + } + NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, PROPEL_ADDRESS_LENGTH); + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, PROPEL_ADDRESS_LENGTH); + PROPEL_bind_packet(true); //send bind packet with rx_id + break; + + case PROPEL_DATA1: + if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS)) + {// data received from the model + NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE); + if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,3)==0) + { + telemetry_counter++; //LQI + v_lipo1=packet[5]; //number of life left? + v_lipo2=packet[4]; //bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed + if(telemetry_lost==0) + telemetry_link=1; + } + } + PROPEL_data_packet(); + packet_count++; + if(packet_count>=100) + {//LQI calculation + packet_count=0; + TX_LQI=telemetry_counter; + RX_RSSI=telemetry_counter; + telemetry_counter = 0; + telemetry_lost=0; + } + break; + } + return PROPEL_PACKET_PERIOD; +} + +uint16_t initPROPEL() +{ + BIND_IN_PROGRESS; // autobind protocol + PROPEL_initialize_txid(); + PROPEL_init(); + hopping_frequency_no = 0; + phase=PROPEL_BIND1; + return PROPEL_INITIAL_WAIT; +} + +#endif +// equations for checksum check byte from truth table +// (1) z = a && !b +// || a && !c && !d +// || a && !c && !g +// || a && !d && !g +// || a && !c && !h +// || a && !g && !h +// || !a && b && c && g +// || !a && b && c && d && h +// || !a && b && d && g && h; +// +// (2) y = !b && !c && !d +// || b && c && g +// || !b && !c && !g +// || !b && !d && !g +// || !b && !c && !h +// || !b && !g && !h +// || b && c && d && h +// || b && d && g && h; +// +// (3) x = !c && !d && g +// || c && !d && !g +// || !c && g && !h +// || c && !g && !h +// || c && d && g && h +// || !c && d && !g && h; +// +// (4) w = d && h +// || !d && !h; +// +// (5) v = !e; +// +// (6) u = f; +// +// (7) t = !g; +// +// (8) s = h; \ No newline at end of file diff --git a/Multiprotocol/Redpine_cc2500.ino b/Multiprotocol/Redpine_cc2500.ino index 6ae5ea7..7f881db 100644 --- a/Multiprotocol/Redpine_cc2500.ino +++ b/Multiprotocol/Redpine_cc2500.ino @@ -17,10 +17,10 @@ #include "iface_cc2500.h" -#define REDPINE_LOOPTIME_FAST 25 //2.5ms -#define REDPINE_LOOPTIME_SLOW 6 //6ms +#define REDPINE_LOOPTIME_FAST 20 //2.0ms +#define REDPINE_LOOPTIME_SLOW 20 //20ms -#define REDPINE_BIND 1000 +#define REDPINE_BIND 2000 #define REDPINE_PACKET_SIZE 11 #define REDPINE_FEC false // from cc2500 datasheet: The convolutional coder is a rate 1/2 code with a constraint length of m=4 #define REDPINE_NUM_HOPS 50 @@ -105,10 +105,9 @@ static uint16_t ReadREDPINE() } if(IS_BIND_IN_PROGRESS) { - if(bind_counter == REDPINE_BIND) - REDPINE_init(0); - if(bind_counter == REDPINE_BIND/2) - REDPINE_init(1); + if (state == REDPINE_BIND) { + REDPINE_init(0); + } REDPINE_set_channel(49); CC2500_SetTxRxMode(TX_EN); CC2500_SetPower(); @@ -121,7 +120,7 @@ static uint16_t ReadREDPINE() BIND_DONE; REDPINE_init(sub_protocol); } - return 9000; + return 4000; } else { @@ -149,23 +148,19 @@ static const uint8_t REDPINE_init_data[][3] = { {CC2500_07_PKTCTRL1, 0x04, 0x04}, {CC2500_08_PKTCTRL0, 0x05, 0x05}, {CC2500_09_ADDR, 0x00, 0x00}, - {CC2500_0B_FSCTRL1, 0x0A, 0x0A}, + {CC2500_0B_FSCTRL1, 0x0A, 0x06}, {CC2500_0C_FSCTRL0, 0x00, 0x00}, - {CC2500_0D_FREQ2, 0x5D, 0x5c}, - {CC2500_0E_FREQ1, 0x93, 0x76}, - {CC2500_0F_FREQ0, 0xB1, 0x27}, - {CC2500_10_MDMCFG4, 0x2D, 0x7B}, - {CC2500_11_MDMCFG3, 0x3B, 0x61}, - {CC2500_12_MDMCFG2, 0x73, 0x13}, - #ifdef REDPINE_FEC - {CC2500_13_MDMCFG1, 0xA3, 0xA3}, - #else - {CC2500_13_MDMCFG1, 0x23, 0x23}, - #endif - {CC2500_14_MDMCFG0, 0x56, 0x7a}, // Chan space - {CC2500_15_DEVIATN, 0x00, 0x51}, + {CC2500_0D_FREQ2, 0x5D, 0x5D}, + {CC2500_0E_FREQ1, 0x93, 0x93}, + {CC2500_0F_FREQ0, 0xB1, 0xB1}, + {CC2500_10_MDMCFG4, 0x2D, 0x78}, + {CC2500_11_MDMCFG3, 0x3B, 0x93}, + {CC2500_12_MDMCFG2, 0x73, 0x03}, + {CC2500_13_MDMCFG1, 0x23, 0x22}, + {CC2500_14_MDMCFG0, 0x56, 0xF8}, // Chan space + {CC2500_15_DEVIATN, 0x00, 0x44}, {CC2500_17_MCSM1, 0x0c, 0x0c}, - {CC2500_18_MCSM0, 0x08, 0x08}, //??? 0x18, 0x18}, + {CC2500_18_MCSM0, 0x18, 0x18}, {CC2500_19_FOCCFG, 0x1D, 0x16}, {CC2500_1A_BSCFG, 0x1C, 0x6c}, {CC2500_1B_AGCCTRL2, 0xC7, 0x43}, @@ -181,7 +176,7 @@ static const uint8_t REDPINE_init_data[][3] = { {CC2500_2C_TEST2, 0x88, 0x88}, {CC2500_2D_TEST1, 0x31, 0x31}, {CC2500_2E_TEST0, 0x0B, 0x0B}, - {CC2500_3E_PATABLE, 0xff, 0xff} + {CC2500_3E_PATABLE, 0xff, 0xff} }; static void REDPINE_init(uint8_t format) @@ -190,8 +185,9 @@ static void REDPINE_init(uint8_t format) CC2500_WriteReg(CC2500_06_PKTLEN, REDPINE_PACKET_SIZE); - for (uint8_t i=0; i < ((sizeof REDPINE_init_data) / (sizeof REDPINE_init_data[0])); i++) + for (uint8_t i=0; i < ((sizeof(REDPINE_init_data)) / (sizeof(REDPINE_init_data[0]))); i++) { CC2500_WriteReg(REDPINE_init_data[i][0], REDPINE_init_data[i][format+1]); + } prev_option = option; CC2500_WriteReg(CC2500_0C_FSCTRL0, option); @@ -215,7 +211,6 @@ static uint16_t initREDPINE() uint32_t idx = 0; uint32_t rnd = MProtocol_id; #define REDPINE_MAX_RF_CHANNEL 255 - hopping_frequency[idx++] = 1; while (idx < REDPINE_NUM_HOPS-1) { uint32_t i; @@ -226,8 +221,9 @@ static uint16_t initREDPINE() for (i = 0; i < idx; i++) { uint8_t ch = hopping_frequency[i]; - if ((ch <= next_ch + 1) && (ch >= next_ch - 1) && (ch > 1)) - break; + if ((ch <= next_ch + 1) && (ch >= next_ch - 1) && (ch >= 1)) { + break; + } } if (i != idx) continue; diff --git a/Multiprotocol/SLT_nrf24l01.ino b/Multiprotocol/SLT_nrf24l01.ino index 924aaaa..b5f62e6 100644 --- a/Multiprotocol/SLT_nrf24l01.ino +++ b/Multiprotocol/SLT_nrf24l01.ino @@ -16,7 +16,7 @@ #if defined(SLT_NRF24L01_INO) -#include "iface_nrf24l01.h" +#include "iface_nrf250k.h" //#define SLT_Q200_FORCE_ID @@ -25,6 +25,7 @@ #define SLT_PAYLOADSIZE_V2 11 #define SLT_NFREQCHANNELS 15 #define SLT_TXID_SIZE 4 +#define SLT_BIND_CHANNEL 0x50 enum{ // flags going to packet[6] (Q200) @@ -48,30 +49,13 @@ enum { SLT_DATA2, SLT_DATA3, SLT_BIND1, - SLT_BIND2 + SLT_BIND2, }; static void __attribute__((unused)) SLT_init() { - NRF24L01_Initialize(); - NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off - NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement - NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 - NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address - NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // Disable auto retransmit - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit - NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 4); // bytes of data payload for pipe 1 - NRF24L01_SetBitrate(NRF24L01_BR_250K); // 256kbps - NRF24L01_SetPower(); - if(sub_protocol==SLT_V1) - NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xC3\xC3\xAA\x55", SLT_TXID_SIZE); - else // V2 - NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE); - NRF24L01_FlushRx(); - NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE); - NRF24L01_FlushTx(); - // Turn radio power on - NRF24L01_SetTxRxMode(TX_EN); + NRF250K_Init(); + NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE); } static void __attribute__((unused)) SLT_set_freq(void) @@ -109,21 +93,25 @@ static void __attribute__((unused)) SLT_set_freq(void) } } } + + //Bind channel + hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL; + + //Calib all channels + NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1); } static void __attribute__((unused)) SLT_wait_radio() { if (packet_sent) - while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS))); + while (!NRF250K_IsPacketSent()); packet_sent = 0; } static void __attribute__((unused)) SLT_send_packet(uint8_t len) { SLT_wait_radio(); - NRF24L01_FlushTx(); - NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT)); - NRF24L01_WritePayload(packet, len); + NRF250K_WritePayload(packet, len); packet_sent = 1; } @@ -132,7 +120,8 @@ static void __attribute__((unused)) SLT_build_packet() static uint8_t calib_counter=0; // Set radio channel - once per packet batch - NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); + NRF250K_SetFreqOffset(); // Set frequency offset + NRF250K_Hopping(hopping_frequency_no); if (++hopping_frequency_no >= SLT_NFREQCHANNELS) hopping_frequency_no = 0; @@ -183,23 +172,16 @@ static void __attribute__((unused)) SLT_build_packet() static void __attribute__((unused)) SLT_send_bind_packet() { SLT_wait_radio(); - BIND_IN_PROGRESS; //Limit TX power to bind level - NRF24L01_SetPower(); + NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel + BIND_IN_PROGRESS; //Limit TX power to bind level + NRF250K_SetPower(); BIND_DONE; - NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE); - - NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x50); + NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE); memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE); if(phase==SLT_BIND2) SLT_send_packet(SLT_TXID_SIZE); else // SLT_BIND1 SLT_send_packet(SLT_PAYLOADSIZE_V2); - - SLT_wait_radio(); //Wait until the packet's sent before changing TX address! - - NRF24L01_SetPower(); //Change power back to normal level - if(phase==SLT_BIND2) // after V1 bind and V2 second bind packet - NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE); } #define SLT_TIMING_BUILD 1000 @@ -217,6 +199,8 @@ uint16_t SLT_callback() telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730); #endif SLT_build_packet(); + NRF250K_SetPower(); //Change power level + NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE); phase++; return SLT_TIMING_BUILD; case SLT_DATA1: @@ -253,7 +237,6 @@ uint16_t SLT_callback() } else {// Continue to send normal packets - NRF24L01_SetPower(); // Set tx_power phase = SLT_BUILD; if(sub_protocol==SLT_V1) return 20000-SLT_TIMING_BUILD; @@ -289,8 +272,8 @@ uint16_t initSLT() /* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/ #endif } - SLT_set_freq(); SLT_init(); + SLT_set_freq(); phase = SLT_BUILD; return 50000; } diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index e458096..3fa4b86 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -379,7 +379,7 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len) #endif #if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO - if (protocol==PROTO_FRSKYX) + if (protocol==PROTO_FRSKYX||protocol==PROTO_FRSKYX2) { /*Telemetry frames(RF) SPORT info 15 bytes payload @@ -514,7 +514,7 @@ void frsky_link_frame() telemetry_link |= 2 ; // Send hub if available } else - {//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX + {//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL frame[1] = v_lipo1; frame[2] = v_lipo2; frame[3] = RX_RSSI; @@ -856,7 +856,7 @@ void TelemetryUpdate() #endif #endif #if defined SPORT_TELEMETRY - if (protocol==PROTO_FRSKYX && telemetry_link + if ((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2) && telemetry_link #ifdef TELEMETRY_FRSKYX_TO_FRSKYD && mode_select==MODE_SERIAL #endif @@ -935,7 +935,7 @@ void TelemetryUpdate() #endif if( telemetry_link & 1 ) - { // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + { // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL // FrSkyX telemetry if in PPM frsky_link_frame(); return; diff --git a/Multiprotocol/V911S_xn297l.ino b/Multiprotocol/V911S_xn297l.ino index 664e240..6df074b 100644 --- a/Multiprotocol/V911S_xn297l.ino +++ b/Multiprotocol/V911S_xn297l.ino @@ -16,7 +16,7 @@ #if defined(V911S_NRF24L01_INO) -#include "iface_xn297l.h" +#include "iface_nrf250k.h" //#define V911S_ORIGINAL_ID @@ -30,6 +30,8 @@ // flags going to packet[1] #define V911S_FLAG_EXPERT 0x04 +#define E119_FLAG_EXPERT 0x08 +#define E119_FLAG_CALIB 0x40 // flags going to packet[2] #define V911S_FLAG_CALIB 0x01 @@ -56,10 +58,21 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind) } if(rf_ch_num&2) channel=7-channel; + XN297L_Hopping(channel); + hopping_frequency_no++; + hopping_frequency_no&=7; // 8 RF channels + packet[ 0]=(rf_ch_num<<3)|channel; - packet[ 1]=V911S_FLAG_EXPERT; // short press on left button - packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button - memset(packet+3, 0x00, V911S_PACKET_SIZE - 3); + memset(packet+1, 0x00, V911S_PACKET_SIZE - 1); + if(sub_protocol==V911S_STD) + { + packet[ 1]=V911S_FLAG_EXPERT; // short press on left button + packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button + } + else + packet[ 1]=E119_FLAG_EXPERT // short press on left button + |GET_FLAG(CH5_SW,E119_FLAG_CALIB); // short press on right button + //packet[3..6]=trims TAER signed uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF); packet[ 7] = ch; @@ -68,25 +81,31 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind) packet[ 8]|= ch<<3; packet[ 9] = ch>>5; ch=convert_channel_16b_limit(ELEVATOR,0,0x7FF); - packet[10] = ch; - packet[11] = ch>>8; - ch=convert_channel_16b_limit(RUDDER ,0x7FF,0); - packet[11]|= ch<<3; - packet[12] = ch>>5; + if(sub_protocol==V911S_STD) + { + packet[10] = ch; + packet[11] = ch>>8; + ch=convert_channel_16b_limit(RUDDER ,0x7FF,0); + packet[11]|= ch<<3; + packet[12] = ch>>5; + } + else + { + ch=0x7FF-ch; + packet[ 9]|= ch<<6; + packet[10] = ch>>2; + packet[11] = ch>>10; + ch=convert_channel_16b_limit(RUDDER ,0x7FF,0); + packet[11]|= ch<<1; + packet[12] = ch>>7; + } } - if (!bind) - { - XN297L_Hopping(channel); - hopping_frequency_no++; - hopping_frequency_no&=7; // 8 RF channels - } - if(sub_protocol==V911S_STD) XN297L_WritePayload(packet, V911S_PACKET_SIZE); else - XN297L_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, bind); - + XN297L_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, bind?0:1); + XN297L_SetPower(); // Set tx_power XN297L_SetFreqOffset(); // Set frequency offset } @@ -95,9 +114,9 @@ static void __attribute__((unused)) V911S_init() { XN297L_Init(); if(sub_protocol==V911S_STD) - XN297L_SetTXAddr((uint8_t *)"KNBND",5); // V911S Bind address + XN297L_SetTXAddr((uint8_t *)"KNBND",5); // V911S Bind address else - XN297L_SetTXAddr((uint8_t *)"XPBND",5); // E119 Bind address + XN297L_SetTXAddr((uint8_t *)"XPBND",5); // E119 Bind address XN297L_HoppingCalib(V911S_NUM_RF_CHANNELS); // Calibrate all channels XN297L_RFChannel(V911S_RF_BIND_CHANNEL); // Set bind channel } diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index 0c554b6..383baec 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -89,11 +89,6 @@ #error "The FrSkyX forced frequency tuning value is outside of the range -127..127." #endif #endif -#ifdef FORCE_FRSKYX2_TUNING - #if ( FORCE_FRSKYX2_TUNING < -127 ) || ( FORCE_FRSKYX2_TUNING > 127 ) - #error "The FrSkyX2 forced frequency tuning value is outside of the range -127..127." - #endif -#endif #ifdef FORCE_HITEC_TUNING #if ( FORCE_HITEC_TUNING < -127 ) || ( FORCE_HITEC_TUNING > 127 ) #error "The HITEC forced frequency tuning value is outside of the range -127..127." @@ -209,7 +204,6 @@ #undef FRSKYD_CC2500_INO #undef FRSKYV_CC2500_INO #undef FRSKYX_CC2500_INO - #undef FRSKYX2_CC2500_INO #undef SFHSS_CC2500_INO #undef CORONA_CC2500_INO #undef REDPINE_CC2500_INO @@ -256,6 +250,7 @@ #undef BAYANG_RX_NRF24L01_INO #undef TIGER_NRF24L01_INO #undef XK_NRF24L01_INO + #undef PROPEL_NRF24L01_INO #endif #if not defined(STM32_BOARD) #undef SX1276_INSTALLED @@ -337,7 +332,7 @@ #if not defined(FRSKYD_CC2500_INO) #undef HUB_TELEMETRY #endif - #if not defined(FRSKYX_CC2500_INO) and not defined(FRSKYX2_CC2500_INO) + #if not defined(FRSKYX_CC2500_INO) #undef SPORT_TELEMETRY #undef SPORT_SEND #endif diff --git a/Multiprotocol/XK_nrf24l01.ino b/Multiprotocol/XK_nrf24l01.ino index 91797d2..d47df04 100644 --- a/Multiprotocol/XK_nrf24l01.ino +++ b/Multiprotocol/XK_nrf24l01.ino @@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful, #if defined(XK_NRF24L01_INO) -#include "iface_xn297l.h" +#include "iface_nrf250k.h" //#define FORCE_XK_ORIGINAL_ID diff --git a/Multiprotocol/XN297Dump_nrf24l01.ino b/Multiprotocol/XN297Dump_nrf24l01.ino index 81aca45..b04c333 100644 --- a/Multiprotocol/XN297Dump_nrf24l01.ino +++ b/Multiprotocol/XN297Dump_nrf24l01.ino @@ -84,6 +84,10 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void) // init crc crc = 0xb5d2; + /*debug("P: 71 0F 55 "); + for(uint8_t i=0; i