diff --git a/.travis.yml b/.travis.yml index 43492c3..693dc91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ env: - BOARD="multi4in1:avr:multiatmega328p:bootloader=optiboot" - BOARD="multi4in1:avr:multixmega32d4" - BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=none" - - BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=native" + # - BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=native" - BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=ftdi" # notifications: diff --git a/Multiprotocol/AFHDS2A_Rx_a7105.ino b/Multiprotocol/AFHDS2A_Rx_a7105.ino index 33e2aab..992750c 100644 --- a/Multiprotocol/AFHDS2A_Rx_a7105.ino +++ b/Multiprotocol/AFHDS2A_Rx_a7105.ino @@ -21,9 +21,6 @@ #define AFHDS2A_RX_RXPACKET_SIZE 37 #define AFHDS2A_RX_NUMFREQ 16 -static uint8_t afhds2a_rx_data_started; -static uint8_t afhds2a_rx_disable_lna; - enum { AFHDS2A_RX_BIND1, AFHDS2A_RX_BIND2, @@ -36,23 +33,22 @@ static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet() uint8_t bitsavailable = 0; uint8_t idx = 0; - pkt[idx++] = RX_LQI; // 0 - 130 - pkt[idx++] = RX_RSSI; - pkt[idx++] = 0; // start channel - pkt[idx++] = 14; // number of channels in packet + packet_in[idx++] = RX_LQI; // 0 - 130 + packet_in[idx++] = RX_RSSI; + packet_in[idx++] = 0; // start channel + packet_in[idx++] = 14; // number of channels in packet // pack channels for (uint8_t i = 0; i < 14; i++) { - uint16_t val = packet[9+i*2] | (packet[10+i*2] << 8); + uint32_t val = packet[9+i*2] | (packet[10+i*2] << 8); if (val < 860) val = 860; - else if (val > 2140) - val = 2140; - val -= 860; + // convert ppm (860-2140) to Multi (0-2047) + val = min(((val-860)<<3)/5, 2047); - bits |= ((uint32_t)val) << bitsavailable; + bits |= val << bitsavailable; bitsavailable += 11; while (bitsavailable >= 8) { - pkt[idx++] = bits & 0xff; + packet_in[idx++] = bits & 0xff; bits >>= 8; bitsavailable -= 8; } @@ -71,9 +67,9 @@ uint16_t initAFHDS2A_Rx() A7105_Init(); hopping_frequency_no = 0; packet_count = 0; - afhds2a_rx_data_started = 0; - afhds2a_rx_disable_lna = IS_POWER_FLAG_on; - A7105_SetTxRxMode(afhds2a_rx_disable_lna ? TXRX_OFF : RX_EN); + rx_data_started = false; + rx_disable_lna = IS_POWER_FLAG_on; + A7105_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN); A7105_Strobe(A7105_RX); if (IS_BIND_IN_PROGRESS) { @@ -103,9 +99,9 @@ uint16_t AFHDS2A_Rx_callback() #ifndef FORCE_AFHDS2A_TUNING A7105_AdjustLOBaseFreq(1); #endif - if (afhds2a_rx_disable_lna != IS_POWER_FLAG_on) { - afhds2a_rx_disable_lna = IS_POWER_FLAG_on; - A7105_SetTxRxMode(afhds2a_rx_disable_lna ? TXRX_OFF : RX_EN); + if (rx_disable_lna != IS_POWER_FLAG_on) { + rx_disable_lna = IS_POWER_FLAG_on; + A7105_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN); } switch(phase) { @@ -169,11 +165,11 @@ uint16_t AFHDS2A_Rx_callback() if (memcmp(&packet[1], rx_id, 4) == 0 && memcmp(&packet[5], rx_tx_addr, 4) == 0) { if (packet[0] == 0x58 && packet[37] == 0x00 && telemetry_link == 0) { // standard packet, send channels to TX int rssi = min(A7105_ReadReg(A7105_1D_RSSI_THOLD),160); - RX_RSSI = map(rssi, 160, 8, 0, 100); + RX_RSSI = map16b(rssi, 160, 8, 0, 128); AFHDS2A_Rx_build_telemetry_packet(); telemetry_link = 1; } - afhds2a_rx_data_started = 1; + rx_data_started = true; read_retry = 10; // hop to next channel pps_counter++; } @@ -194,7 +190,7 @@ uint16_t AFHDS2A_Rx_callback() hopping_frequency_no = 0; A7105_WriteReg(A7105_0F_PLL_I, hopping_frequency[hopping_frequency_no]); A7105_Strobe(A7105_RX); - if (afhds2a_rx_data_started) + if (rx_data_started) read_retry = 0; else read_retry = -127; // retry longer until first packet is catched diff --git a/Multiprotocol/AFHDS2A_a7105.ino b/Multiprotocol/AFHDS2A_a7105.ino index d0ec349..066de46 100644 --- a/Multiprotocol/AFHDS2A_a7105.ino +++ b/Multiprotocol/AFHDS2A_a7105.ino @@ -90,14 +90,14 @@ static void AFHDS2A_update_telemetry() #ifdef AFHDS2A_FW_TELEMETRY if (option & 0x80) {// forward 0xAA and 0xAC telemetry to TX, skip rx and tx id to save space - pkt[0]= TX_RSSI; + packet_in[0]= TX_RSSI; debug("T(%02X)=",packet[0]); for(uint8_t i=9;i < AFHDS2A_RXPACKET_SIZE; i++) { - pkt[i-8]=packet[i]; + packet_in[i-8]=packet[i]; debug(" %02X",packet[i]); } - pkt[29]=packet[0]; // 0xAA Normal telemetry, 0xAC Extended telemetry + packet_in[29]=packet[0]; // 0xAA Normal telemetry, 0xAC Extended telemetry telemetry_link=2; debugln(""); return; @@ -265,11 +265,15 @@ uint16_t ReadAFHDS2A() A7105_ReadData(AFHDS2A_RXPACKET_SIZE); if(packet[0] == 0xbc && packet[9] == 0x01) { - uint8_t temp=AFHDS2A_EEPROM_OFFSET+RX_num*4; + uint8_t addr; + if(RX_num<16) + addr=AFHDS2A_EEPROM_OFFSET+RX_num*4; + else + addr=AFHDS2A_EEPROM_OFFSET2+(RX_num-16)*4; for(uint8_t i=0; i<4; i++) { rx_id[i] = packet[5+i]; - eeprom_write_byte((EE_ADDR)(temp+i),rx_id[i]); + eeprom_write_byte((EE_ADDR)(addr+i),rx_id[i]); } phase = AFHDS2A_BIND4; packet_count++; @@ -317,6 +321,7 @@ uint16_t ReadAFHDS2A() packet_type = AFHDS2A_PACKET_STICKS; phase = AFHDS2A_DATA; case AFHDS2A_DATA: + telemetry_set_input_sync(3850); AFHDS2A_build_packet(packet_type); if((A7105_ReadReg(A7105_00_MODE) & 0x01)) // Check if something has been received... data_rx=0; @@ -331,7 +336,10 @@ uint16_t ReadAFHDS2A() { #ifdef FAILSAFE_ENABLE if(!(packet_counter % 1569) && IS_FAILSAFE_VALUES_on) + { packet_type = AFHDS2A_PACKET_FAILSAFE; + FAILSAFE_VALUES_off; + } else #endif packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes @@ -345,7 +353,7 @@ uint16_t ReadAFHDS2A() if(packet[0] == 0xAA || packet[0] == 0xAC) { if(!memcmp(&packet[1], rx_tx_addr, 4)) - { // Validate TX address + { // TX address validated #ifdef AFHDS2A_LQI_CH if(packet[0]==0xAA && packet[9]!=0xFD) {// Normal telemetry packet @@ -397,14 +405,15 @@ uint16_t initAFHDS2A() { phase = AFHDS2A_DATA_INIT; //Read RX ID from EEPROM based on RX_num, RX_num must be uniq for each RX - uint8_t temp=AFHDS2A_EEPROM_OFFSET+RX_num*4; + uint8_t addr; + if(RX_num<16) + addr=AFHDS2A_EEPROM_OFFSET+RX_num*4; + else + addr=AFHDS2A_EEPROM_OFFSET2+(RX_num-16)*4; for(uint8_t i=0;i<4;i++) - rx_id[i]=eeprom_read_byte((EE_ADDR)(temp+i)); + rx_id[i]=eeprom_read_byte((EE_ADDR)(addr+i)); } hopping_frequency_no = 0; -#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY) - init_frskyd_link_telemetry(); -#endif return 50000; } #endif diff --git a/Multiprotocol/ASSAN_nrf24l01.ino b/Multiprotocol/ASSAN_nrf24l01.ino index 4504654..ce1648d 100644 --- a/Multiprotocol/ASSAN_nrf24l01.ino +++ b/Multiprotocol/ASSAN_nrf24l01.ino @@ -127,6 +127,7 @@ uint16_t ASSAN_callback() phase=ASSAN_DATA2; return 2000; case ASSAN_DATA2: + telemetry_set_input_sync(12000); case ASSAN_DATA3: ASSAN_send_packet(); phase++; // DATA 3 or 4 diff --git a/Multiprotocol/BUGSMINI_nrf24l01.ino b/Multiprotocol/BUGSMINI_nrf24l01.ino index a52c735..8672a4e 100644 --- a/Multiprotocol/BUGSMINI_nrf24l01.ino +++ b/Multiprotocol/BUGSMINI_nrf24l01.ino @@ -181,7 +181,7 @@ static void __attribute__((unused)) BUGSMINI_make_address() uint8_t start, length, index; //read rxid - uint8_t base_adr=BUGSMINI_EEPROM_OFFSET+RX_num*2; + uint8_t base_adr=BUGSMINI_EEPROM_OFFSET+(RX_num&0x0F)*2; uint8_t rxid_high = eeprom_read_byte((EE_ADDR)(base_adr+0)); uint8_t rxid_low = eeprom_read_byte((EE_ADDR)(base_adr+1)); @@ -272,7 +272,7 @@ uint16_t BUGSMINI_callback() if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) { // RX fifo data ready XN297_ReadPayload(packet, BUGSMINI_RX_PAYLOAD_SIZE); - base_adr=BUGSMINI_EEPROM_OFFSET+RX_num*2; + base_adr=BUGSMINI_EEPROM_OFFSET+(RX_num&0x0F)*2; eeprom_write_byte((EE_ADDR)(base_adr+0),packet[1]); // Save rxid in EEPROM eeprom_write_byte((EE_ADDR)(base_adr+1),packet[2]); // Save rxid in EEPROM NRF24L01_SetTxRxMode(TXRX_OFF); @@ -299,6 +299,7 @@ uint16_t BUGSMINI_callback() phase = BUGSMINI_BIND1; return BUGSMINI_PACKET_INTERVAL - BUGSMINI_WRITE_WAIT; case BUGSMINI_DATA1: + telemetry_set_input_sync(BUGSMINI_PACKET_INTERVAL); if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) { // RX fifo data ready => read only 12 bytes to not overwrite channel change flag XN297_ReadPayload(packet, 12); @@ -375,9 +376,6 @@ uint16_t initBUGSMINI() armed = 0; arm_flags = BUGSMINI_FLAG_DISARM; // initial value from captures arm_channel_previous = BUGSMINI_CH_SW_ARM; - #ifdef BUGS_HUB_TELEMETRY - init_frskyd_link_telemetry(); - #endif return BUGSMINI_INITIAL_WAIT; } diff --git a/Multiprotocol/Bayang_nrf24l01.ino b/Multiprotocol/Bayang_nrf24l01.ino index 089fca9..4d57e1b 100644 --- a/Multiprotocol/Bayang_nrf24l01.ino +++ b/Multiprotocol/Bayang_nrf24l01.ino @@ -283,7 +283,10 @@ uint16_t BAYANG_callback() if(IS_BIND_DONE) { if(packet_count==0) + { + telemetry_set_input_sync((option & BAYANG_OPTION_FLAG_TELEMETRY)?5*BAYANG_PACKET_PERIOD:2*BAYANG_PACKET_PERIOD); BAYANG_send_packet(0); + } packet_count++; #ifdef BAYANG_HUB_TELEMETRY if (option & BAYANG_OPTION_FLAG_TELEMETRY) @@ -349,10 +352,6 @@ uint16_t initBAYANG(void) BAYANG_initialize_txid(); BAYANG_init(); packet_count=0; - #ifdef BAYANG_HUB_TELEMETRY - init_frskyd_link_telemetry(); - telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message... - #endif return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD; } diff --git a/Multiprotocol/Bugs_a7105.ino b/Multiprotocol/Bugs_a7105.ino index feae006..00f667b 100644 --- a/Multiprotocol/Bugs_a7105.ino +++ b/Multiprotocol/Bugs_a7105.ino @@ -284,7 +284,7 @@ static void __attribute__((unused))BUGS_set_radio_data() { offset=BUGS_NUM_RFCHAN; // Read radio_id from EEPROM - uint8_t base_adr=BUGS_EEPROM_OFFSET+RX_num*2; + uint8_t base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2; uint16_t rxid=0; for(uint8_t i=0; i<2; i++) rxid|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8); @@ -374,7 +374,7 @@ uint16_t ReadBUGS(void) BIND_DONE; // set radio_id rxid = (packet[1] << 8) + packet[2]; - base_adr=BUGS_EEPROM_OFFSET+RX_num*2; + base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2; for(uint8_t i=0; i<2; i++) eeprom_write_byte((EE_ADDR)(base_adr+i),rxid>>(i*8)); // Save rxid in EEPROM BUGS_set_radio_data(); @@ -385,6 +385,7 @@ uint16_t ReadBUGS(void) break; case BUGS_DATA_1: + telemetry_set_input_sync(BUGS_PACKET_PERIOD); A7105_SetPower(); BUGS_build_packet(0); A7105_WriteReg(A7105_03_FIFOI, BUGS_FIFO_SIZE_TX); @@ -437,7 +438,7 @@ uint16_t ReadBUGS(void) uint16_t initBUGS(void) { uint16_t rxid=0; - uint8_t base_adr=BUGS_EEPROM_OFFSET+RX_num*2; + uint8_t base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2; for(uint8_t i=0; i<2; i++) rxid|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8); if(rxid==0xffff) @@ -456,9 +457,6 @@ uint16_t initBUGS(void) armed = 0; arm_flags = BUGS_FLAG_DISARM; // initial value from captures arm_channel_previous = BUGS_CH_SW_ARM; - #ifdef BUGS_HUB_TELEMETRY - init_frskyd_link_telemetry(); - #endif return 10000; } diff --git a/Multiprotocol/CABELL_nrf224l01.ino b/Multiprotocol/CABELL_nrf224l01.ino index ce48808..1b7e4bf 100644 --- a/Multiprotocol/CABELL_nrf224l01.ino +++ b/Multiprotocol/CABELL_nrf224l01.ino @@ -406,9 +406,10 @@ uint16_t CABELL_callback() if (IS_BIND_DONE) { CABELL_send_packet(0); // packet_period is set/adjusted in CABELL_send_packet + telemetry_set_input_sync(packet_period); return packet_period; } - if (bind_counter == 0) + else if (bind_counter == 0) { BIND_DONE; CABELL_init(); // non-bind address @@ -429,10 +430,6 @@ uint16_t initCABELL(void) else bind_counter = CABELL_BIND_COUNT; CABELL_init(); - #if defined CABELL_HUB_TELEMETRY - init_frskyd_link_telemetry(); - telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message... - #endif packet_period = CABELL_PACKET_PERIOD; diff --git a/Multiprotocol/CFlie_nrf24l01.ino b/Multiprotocol/CFlie_nrf24l01.ino index b632345..9efa1cb 100644 --- a/Multiprotocol/CFlie_nrf24l01.ino +++ b/Multiprotocol/CFlie_nrf24l01.ino @@ -97,7 +97,7 @@ static inline uint8_t crtp_create_header(uint8_t port, uint8_t channel) #define TX_ADDR_SIZE 5 // Timeout for callback in uSec, 10ms=10000us for Crazyflie -#define PACKET_PERIOD 10000 +#define CFLIE_PACKET_PERIOD 10000 #define MAX_PACKET_SIZE 32 // CRTP is 32 bytes @@ -781,7 +781,8 @@ static uint16_t cflie_callback() break; case CFLIE_DATA: - // if (Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_ON_CRTPLOG) { + telemetry_set_input_sync(CFLIE_PACKET_PERIOD); + // if (Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_ON_CRTPLOG) { // update_telemetry_crtplog(); // } else if (Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_ON_ACKPKT) { // update_telemetry_ackpkt(); @@ -792,7 +793,7 @@ static uint16_t cflie_callback() send_cmd_packet(); break; } - return PACKET_PERIOD; // Packet at standard protocol interval + return CFLIE_PACKET_PERIOD; // Packet at standard protocol interval } // Generate address to use from TX id and manufacturer id (STM32 unique id) diff --git a/Multiprotocol/CG023_nrf24l01.ino b/Multiprotocol/CG023_nrf24l01.ino index 77f4509..beb667c 100644 --- a/Multiprotocol/CG023_nrf24l01.ino +++ b/Multiprotocol/CG023_nrf24l01.ino @@ -138,7 +138,10 @@ static void __attribute__((unused)) CG023_init() uint16_t CG023_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(packet_period); CG023_send_packet(0); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/CX10_nrf24l01.ino b/Multiprotocol/CX10_nrf24l01.ino index 4f98d44..96a7cc2 100644 --- a/Multiprotocol/CX10_nrf24l01.ino +++ b/Multiprotocol/CX10_nrf24l01.ino @@ -229,6 +229,7 @@ uint16_t CX10_callback() } break; case CX10_DATA: + telemetry_set_input_sync(packet_period); CX10_Write_Packet(0); break; } diff --git a/Multiprotocol/Convert.ino b/Multiprotocol/Convert.ino new file mode 100644 index 0000000..edfc26e --- /dev/null +++ b/Multiprotocol/Convert.ino @@ -0,0 +1,142 @@ +/* + 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 . + */ + +/************************/ +/** Convert routines **/ +/************************/ +// Reverse a channel and store it +void reverse_channel(uint8_t num) +{ + uint16_t val=2048-Channel_data[num]; + if(val>=2048) val=2047; + Channel_data[num]=val; +} + +// Channel value is converted to ppm 860<->2140 -125%<->+125% and 988<->2012 -100%<->+100% +uint16_t convert_channel_ppm(uint8_t num) +{ + uint16_t val=Channel_data[num]; + return (((val<<2)+val)>>3)+860; //value range 860<->2140 -125%<->+125% +} + +// Channel value 100% is converted to 10bit values 0<->1023 +uint16_t convert_channel_10b(uint8_t num) +{ + uint16_t val=Channel_data[num]; + val=((val<<2)+val)>>3; + if(val<=128) return 0; + if(val>=1152) return 1023; + return val-128; +} + +// Channel value 100% is converted to 8bit values 0<->255 +uint8_t convert_channel_8b(uint8_t num) +{ + uint16_t val=Channel_data[num]; + val=((val<<2)+val)>>5; + if(val<=32) return 0; + if(val>=288) return 255; + return val-32; +} + +// Channel value 100% is converted to 8b with deadband +uint8_t convert_channel_8b_limit_deadband(uint8_t num,uint8_t min,uint8_t mid, uint8_t max, uint8_t deadband) +{ + uint16_t val=limit_channel_100(num); // 204<->1844 + uint16_t db_low=CHANNEL_MID-deadband, db_high=CHANNEL_MID+deadband; // 1024+-deadband + int32_t calc; + uint8_t out; + if(val>=db_low && val<=db_high) + return mid; + else if(valmin) out++; else out--; + } + return out; +} + +// Channel value 100% is converted to value scaled +int16_t convert_channel_16b_limit(uint8_t num,int16_t min,int16_t max) +{ + int32_t val=limit_channel_100(num); // 204<->1844 + val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min; + return (uint16_t)val; +} + +// Channel value -125%<->125% is scaled to 16bit value with no limit +int16_t convert_channel_16b_nolimit(uint8_t num, int16_t min, int16_t max) +{ + int32_t val=Channel_data[num]; // 0<->2047 + val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min; + return (uint16_t)val; +} + +// Channel value is converted sign + magnitude 8bit values +uint8_t convert_channel_s8b(uint8_t num) +{ + uint8_t ch; + ch = convert_channel_8b(num); + return (ch < 128 ? 127-ch : ch); +} + +// Channel value is limited to 100% +uint16_t limit_channel_100(uint8_t num) +{ + if(Channel_data[num]>=CHANNEL_MAX_100) + return CHANNEL_MAX_100; + if (Channel_data[num]<=CHANNEL_MIN_100) + return CHANNEL_MIN_100; + return Channel_data[num]; +} + +// Channel value is converted for HK310 +void convert_channel_HK310(uint8_t num, uint8_t *low, uint8_t *high) +{ + uint16_t temp=0xFFFF-(3440+((Channel_data[num]*5)>>1))/3; + *low=(uint8_t)(temp&0xFF); + *high=(uint8_t)(temp>>8); +} + +#ifdef FAILSAFE_ENABLE +// Failsafe value is converted for HK310 +void convert_failsafe_HK310(uint8_t num, uint8_t *low, uint8_t *high) +{ + uint16_t temp=0xFFFF-(3440+((Failsafe_data[num]*5)>>1))/3; + *low=(uint8_t)(temp&0xFF); + *high=(uint8_t)(temp>>8); +} +#endif + +// Channel value for FrSky (PPM is multiplied by 1.5) +uint16_t convert_channel_frsky(uint8_t num) +{ + uint16_t val=Channel_data[num]; + return ((val*15)>>4)+1290; +} diff --git a/Multiprotocol/Corona_cc2500.ino b/Multiprotocol/Corona_cc2500.ino index c254b8f..aba0446 100644 --- a/Multiprotocol/Corona_cc2500.ino +++ b/Multiprotocol/Corona_cc2500.ino @@ -258,6 +258,7 @@ static uint16_t __attribute__((unused)) CORONA_build_packet() uint16_t ReadCORONA() { + telemetry_set_input_sync(22000); // Tune frequency if it has been changed if ( prev_option != option ) { diff --git a/Multiprotocol/DM002_nrf24l01.ino b/Multiprotocol/DM002_nrf24l01.ino index c87d89d..f319397 100644 --- a/Multiprotocol/DM002_nrf24l01.ino +++ b/Multiprotocol/DM002_nrf24l01.ino @@ -113,7 +113,10 @@ static void __attribute__((unused)) DM002_init() uint16_t DM002_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(DM002_PACKET_PERIOD); DM002_send_packet(0); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/DSM_cyrf6936.ino b/Multiprotocol/DSM_cyrf6936.ino index faea637..0fb52b9 100644 --- a/Multiprotocol/DSM_cyrf6936.ino +++ b/Multiprotocol/DSM_cyrf6936.ino @@ -230,7 +230,7 @@ static void __attribute__((unused)) DSM_update_channels() if(sub_protocol==DSM_AUTO) num_ch=12; // Force 12 channels in mode Auto else - num_ch=option; + num_ch=option & 0x7F; // Remove the Max Throw flag if(num_ch<4 || num_ch>12) num_ch=6; // Default to 6 channels if invalid choice... @@ -273,8 +273,8 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper) /* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to select the transmitter mode (e.g. computer vs non-computer radio), so always send normal output */ #ifdef DSM_THROTTLE_KILL_CH - if(CH_TAER[idx]==THROTTLE && kill_ch<=604) - {//Activate throttle kill only if DSM_THROTTLE_KILL_CH below -50% + if(idx==CH1 && kill_ch<=604) + {//Activate throttle kill only if channel is throttle and DSM_THROTTLE_KILL_CH below -50% if(kill_ch 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX #else - value=convert_channel_16b_nolimit(CH_TAER[idx],0x150,0x6B0); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on Redcon 6 channel DSM2 RX + 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 + else + value=convert_channel_16b_nolimit(CH_TAER[idx],0x150,0x6B0); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on Redcon 6 channel DSM2 RX #endif if(bits==10) value>>=1; value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits); @@ -363,12 +366,12 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet() uint16_t sum = 384 - 0x10; for(uint8_t i = 1; i < 9; i++) { - sum += pkt[i]; + sum += packet_in[i]; if(i<5) - if(pkt[i] != (0xff ^ cyrfmfg_id[i-1])) + if(packet_in[i] != (0xff ^ cyrfmfg_id[i-1])) result=0; // bad packet } - if( pkt[9] != (sum>>8) && pkt[10] != (uint8_t)sum ) + if( packet_in[9] != (sum>>8) && packet_in[10] != (uint8_t)sum ) result=0; return result; } @@ -417,12 +420,12 @@ uint16_t ReadDsm() { // 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>MAX_PKT-2) - len=MAX_PKT-2; - CYRF_ReadDataPacketLen(pkt+1, len); + if(len>TELEMETRY_BUFFER_SIZE-2) + len=TELEMETRY_BUFFER_SIZE-2; + CYRF_ReadDataPacketLen(packet_in+1, len); if(len==10 && DSM_Check_RX_packet()) { - pkt[0]=0x80; + packet_in[0]=0x80; telemetry_link=1; // send received data on serial phase++; return 2000; @@ -452,6 +455,7 @@ uint16_t ReadDsm() DSM_set_sop_data_crc(); return 10000; case DSM_CH1_WRITE_A: + telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode case DSM_CH1_WRITE_B: case DSM_CH2_WRITE_A: case DSM_CH2_WRITE_B: @@ -502,10 +506,10 @@ uint16_t ReadDsm() { // good data (complete 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>MAX_PKT-2) - len=MAX_PKT-2; - CYRF_ReadDataPacketLen(pkt+1, len); - pkt[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal + if(len>TELEMETRY_BUFFER_SIZE-2) + len=TELEMETRY_BUFFER_SIZE-2; + CYRF_ReadDataPacketLen(packet_in+1, len); + packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal telemetry_link=1; } CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation diff --git a/Multiprotocol/Devo_cyrf6936.ino b/Multiprotocol/Devo_cyrf6936.ino index cc5de95..60ec4cf 100644 --- a/Multiprotocol/Devo_cyrf6936.ino +++ b/Multiprotocol/Devo_cyrf6936.ino @@ -272,6 +272,7 @@ uint16_t devo_callback() static uint8_t txState=0; if (txState == 0) { + telemetry_set_input_sync(2400); txState = 1; DEVO_BuildPacket(); CYRF_WriteDataPacket(packet); diff --git a/Multiprotocol/E01X_nrf24l01.ino b/Multiprotocol/E01X_nrf24l01.ino index 8c9c455..7a37daf 100644 --- a/Multiprotocol/E01X_nrf24l01.ino +++ b/Multiprotocol/E01X_nrf24l01.ino @@ -287,7 +287,10 @@ uint16_t E01X_callback() } } else + { + telemetry_set_input_sync(packet_period); E01X_send_packet(0); + } return packet_period; } diff --git a/Multiprotocol/ESky150_nrf24l01.ino b/Multiprotocol/ESky150_nrf24l01.ino index bbc88c5..fe4da38 100644 --- a/Multiprotocol/ESky150_nrf24l01.ino +++ b/Multiprotocol/ESky150_nrf24l01.ino @@ -151,7 +151,10 @@ uint8_t ESKY150_convert_2bit_channel(uint8_t num) uint16_t ESKY150_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(ESKY150_SENDING_PACKET_PERIOD); ESKY150_send_packet(); + } else { NRF24L01_WritePayload(packet, ESKY150_PAYLOADSIZE); diff --git a/Multiprotocol/ESky_nrf24l01.ino b/Multiprotocol/ESky_nrf24l01.ino index 82cbda2..672ad96 100644 --- a/Multiprotocol/ESky_nrf24l01.ino +++ b/Multiprotocol/ESky_nrf24l01.ino @@ -135,7 +135,10 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind) uint16_t ESKY_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(ESKY_PACKET_PERIOD); ESKY_send_packet(0); + } else { ESKY_send_packet(1); diff --git a/Multiprotocol/FQ777_nrf24l01.ino b/Multiprotocol/FQ777_nrf24l01.ino index a40c4e5..86a5dfe 100644 --- a/Multiprotocol/FQ777_nrf24l01.ino +++ b/Multiprotocol/FQ777_nrf24l01.ino @@ -188,7 +188,10 @@ uint16_t FQ777_callback() } } else + { + telemetry_set_input_sync(FQ777_PACKET_PERIOD); FQ777_send_packet(0); + } return FQ777_PACKET_PERIOD; } diff --git a/Multiprotocol/FY326_nrf24l01.ino b/Multiprotocol/FY326_nrf24l01.ino index 117c7fe..eb98853 100644 --- a/Multiprotocol/FY326_nrf24l01.ino +++ b/Multiprotocol/FY326_nrf24l01.ino @@ -188,6 +188,7 @@ uint16_t FY326_callback() return FY326_PACKET_CHKTIME; break; case FY326_DATA: + telemetry_set_input_sync(FY326_PACKET_PERIOD); FY326_send_packet(0); break; } diff --git a/Multiprotocol/FlySky_a7105.ino b/Multiprotocol/FlySky_a7105.ino index 3aa6269..657734a 100644 --- a/Multiprotocol/FlySky_a7105.ino +++ b/Multiprotocol/FlySky_a7105.ino @@ -145,7 +145,7 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init) for(i = 0; i < 8; i++) { uint16_t temp=convert_channel_ppm(CH_AETR[i]); - if(sub_protocol == CX20 && CH_AETR[i]==ELEVATOR) + if(sub_protocol == CX20 && i==CH2) //ELEVATOR temp=3000-temp; packet[5 + i*2]=temp&0xFF; //low byte of servo timing(1000-2000us) packet[6 + i*2]=(temp>>8)&0xFF; //high byte of servo timing(1000-2000us) @@ -168,16 +168,13 @@ uint16_t ReadFlySky() } else { + telemetry_set_input_sync(packet_period); flysky_build_packet(0); A7105_WriteData(21, hopping_frequency[hopping_frequency_no & 0x0F]); A7105_SetPower(); } hopping_frequency_no++; - - if(sub_protocol==CX20) - return 3984; - else - return 1510; //1460 on deviation but not working with the latest V911 bricks... Turnigy 9X v2 is 1533, Flysky TX for 9XR/9XR Pro is 1510, V911 TX is 1490. + return packet_period; } const uint8_t PROGMEM tx_channels[8][4] = { @@ -235,6 +232,10 @@ uint16_t initFlySky() } hopping_frequency_no=0; packet_count=0; + if(sub_protocol==CX20) + packet_period=3984; + else + packet_period=1510; //1460 on deviation but not working with the latest V911 bricks... Turnigy 9X v2 is 1533, Flysky TX for 9XR/9XR Pro is 1510, V911 TX is 1490. if(IS_BIND_IN_PROGRESS) bind_counter = FLYSKY_BIND_COUNT; else diff --git a/Multiprotocol/Flyzone_a7105.ino b/Multiprotocol/Flyzone_a7105.ino index 24c69ee..063d41b 100644 --- a/Multiprotocol/Flyzone_a7105.ino +++ b/Multiprotocol/Flyzone_a7105.ino @@ -55,6 +55,7 @@ uint16_t ReadFlyzone() if(phase>19) { phase=0; + telemetry_set_input_sync(20*1500); flyzone_build_packet(); A7105_WriteData(8, hopping_frequency[0]); A7105_SetPower(); diff --git a/Multiprotocol/Common.ino b/Multiprotocol/FrSkyDVX_common.ino similarity index 60% rename from Multiprotocol/Common.ino rename to Multiprotocol/FrSkyDVX_common.ino index 14c05af..a827f87 100644 --- a/Multiprotocol/Common.ino +++ b/Multiprotocol/FrSkyDVX_common.ino @@ -13,169 +13,27 @@ along with Multiprotocol. If not, see . */ -#ifdef ENABLE_PPM -void InitPPM() -{ - for(uint8_t i=0;i1844 - uint16_t db_low=CHANNEL_MID-deadband, db_high=CHANNEL_MID+deadband; // 1024+-deadband - int32_t calc; - uint8_t out; - if(val>=db_low && val<=db_high) - return mid; - else if(valmin) out++; else out--; - } - return out; -} - -// Reverse a channel and store it -void reverse_channel(uint8_t num) -{ - uint16_t val=2048-Channel_data[num]; - if(val>=2048) val=2047; - Channel_data[num]=val; -} -// Channel value is converted to ppm 860<->2140 -125%<->+125% and 988<->2012 -100%<->+100% -uint16_t convert_channel_ppm(uint8_t num) -{ - uint16_t val=Channel_data[num]; - return (((val<<2)+val)>>3)+860; //value range 860<->2140 -125%<->+125% -} -// Channel value 100% is converted to 10bit values 0<->1023 -uint16_t convert_channel_10b(uint8_t num) -{ - uint16_t val=Channel_data[num]; - val=((val<<2)+val)>>3; - if(val<=128) return 0; - if(val>=1152) return 1023; - return val-128; -} -// Channel value 100% is converted to 8bit values 0<->255 -uint8_t convert_channel_8b(uint8_t num) -{ - uint16_t val=Channel_data[num]; - val=((val<<2)+val)>>5; - if(val<=32) return 0; - if(val>=288) return 255; - return val-32; -} - -// Channel value 100% is converted to value scaled -int16_t convert_channel_16b_limit(uint8_t num,int16_t min,int16_t max) -{ - int32_t val=limit_channel_100(num); // 204<->1844 - val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min; - return (uint16_t)val; -} - -// Channel value -125%<->125% is scaled to 16bit value with no limit -int16_t convert_channel_16b_nolimit(uint8_t num, int16_t min, int16_t max) -{ - int32_t val=Channel_data[num]; // 0<->2047 - val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min; - return (uint16_t)val; -} - -// Channel value is converted sign + magnitude 8bit values -uint8_t convert_channel_s8b(uint8_t num) -{ - uint8_t ch; - ch = convert_channel_8b(num); - return (ch < 128 ? 127-ch : ch); -} - -// Channel value is limited to 100% -uint16_t limit_channel_100(uint8_t num) -{ - if(Channel_data[num]>=CHANNEL_MAX_100) - return CHANNEL_MAX_100; - if (Channel_data[num]<=CHANNEL_MIN_100) - return CHANNEL_MIN_100; - return Channel_data[num]; -} - -// Channel value is converted for HK310 -void convert_channel_HK310(uint8_t num, uint8_t *low, uint8_t *high) -{ - uint16_t temp=0xFFFF-(3440+((Channel_data[num]*5)>>1))/3; - *low=(uint8_t)(temp&0xFF); - *high=(uint8_t)(temp>>8); -} -#ifdef FAILSAFE_ENABLE -// Failsafe value is converted for HK310 -void convert_failsafe_HK310(uint8_t num, uint8_t *low, uint8_t *high) -{ - uint16_t temp=0xFFFF-(3440+((Failsafe_data[num]*5)>>1))/3; - *low=(uint8_t)(temp&0xFF); - *high=(uint8_t)(temp>>8); -} -#endif - -// Channel value for FrSky (PPM is multiplied by 1.5) -uint16_t convert_channel_frsky(uint8_t num) -{ - uint16_t val=Channel_data[num]; - return ((val*15)>>4)+1290; -} - /******************************/ /** FrSky D and X routines **/ /******************************/ -#if defined(FRSKYX_CC2500_INO) || defined(FRSKYX_RX_CC2500_INO) +#if defined(FRSKYX_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) //**CRC** -const uint16_t PROGMEM frskyX_CRC_Short[]={ +const uint16_t PROGMEM FrSkyX_CRC_Short[]={ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7 }; -static uint16_t __attribute__((unused)) frskyX_CRCTable(uint8_t val) +static uint16_t __attribute__((unused)) FrSkyX_CRCTable(uint8_t val) { uint16_t word ; - word = pgm_read_word(&frskyX_CRC_Short[val&0x0F]) ; + word = pgm_read_word(&FrSkyX_CRC_Short[val&0x0F]) ; val /= 16 ; return word ^ (0x1081 * val) ; } -uint16_t frskyX_crc_x(uint8_t *data, uint8_t len) +uint16_t FrSkyX_crc(uint8_t *data, uint8_t len) { uint16_t crc = 0; for(uint8_t i=0; i < len; i++) - crc = (crc<<8) ^ frskyX_CRCTable((uint8_t)(crc>>8) ^ *data++); + crc = (crc<<8) ^ FrSkyX_CRCTable((uint8_t)(crc>>8) ^ *data++); return crc; } #endif @@ -189,7 +47,7 @@ enum { FRSKY_DATA2, FRSKY_DATA3, FRSKY_DATA4, - FRSKY_DATA5 + FRSKY_DATA5, }; void Frsky_init_hop(void) diff --git a/Multiprotocol/FrSkyD_cc2500.ino b/Multiprotocol/FrSkyD_cc2500.ino index 9cfabf0..ceb415f 100644 --- a/Multiprotocol/FrSkyD_cc2500.ino +++ b/Multiprotocol/FrSkyD_cc2500.ino @@ -97,9 +97,6 @@ uint16_t initFrSky_2way() { Frsky_init_hop(); packet_count=0; - #if defined TELEMETRY - init_frskyd_link_telemetry(); - #endif if(IS_BIND_IN_PROGRESS) { frsky2way_init(1); @@ -156,15 +153,16 @@ uint16_t ReadFrSky_2way() { if (state == FRSKY_DATA1) { + telemetry_set_input_sync(9000); len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (len && len<=(0x11+3))// 20bytes { - CC2500_ReadData(pkt, len); //received telemetry packets + CC2500_ReadData(packet_in, len); //received telemetry packets #if defined(TELEMETRY) - if(pkt[len-1] & 0x80) + if(packet_in[len-1] & 0x80) {//with valid crc packet_count=0; - frsky_check_telemetry(pkt,len); //check if valid telemetry packets and buffer them. + frsky_check_telemetry(packet_in,len); //check if valid telemetry packets and buffer them. } #endif } @@ -177,7 +175,7 @@ uint16_t ReadFrSky_2way() packet_count=0; #if defined TELEMETRY telemetry_link=0;//no link frames - pkt[6]=0;//no user frames. + packet_in[6]=0;//no user frames. #endif } } diff --git a/Multiprotocol/FrSkyV_cc2500.ino b/Multiprotocol/FrSkyV_cc2500.ino index f277b2c..2d19030 100644 --- a/Multiprotocol/FrSkyV_cc2500.ino +++ b/Multiprotocol/FrSkyV_cc2500.ino @@ -117,6 +117,7 @@ uint16_t ReadFRSKYV() { if(IS_BIND_DONE) { // Normal operation + telemetry_set_input_sync(9006); uint8_t chan = FRSKYV_calc_channel(); CC2500_Strobe(CC2500_SIDLE); if (option != prev_option) diff --git a/Multiprotocol/FrSkyX_Rx_cc2500.ino b/Multiprotocol/FrSkyX_Rx_cc2500.ino deleted file mode 100644 index ec56a4f..0000000 --- a/Multiprotocol/FrSkyX_Rx_cc2500.ino +++ /dev/null @@ -1,373 +0,0 @@ -/* - 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(FRSKYX_RX_CC2500_INO) - -#include "iface_cc2500.h" - - #define FRSKYX_FCC_LENGTH (30+2) - #define FRSKYX_LBT_LENGTH (33+2) - - enum { - FRSKYX_RX_TUNE_START, - FRSKYX_RX_TUNE_LOW, - FRSKYX_RX_TUNE_HIGH, - FRSKYX_RX_BIND, - FRSKYX_RX_DATA, - }; - - static uint8_t frskyx_rx_chanskip; - static uint8_t frskyx_rx_disable_lna; - static uint8_t frskyx_rx_data_started; - static int8_t frskyx_rx_finetune; - -static void __attribute__((unused)) frskyx_rx_strobe_rx() -{ - CC2500_Strobe(CC2500_SIDLE); - CC2500_Strobe(CC2500_SFRX); - CC2500_Strobe(CC2500_SRX); -} - -static void __attribute__((unused)) FrSkyX_Rx_initialise() { - CC2500_Reset(); - - CC2500_WriteReg(CC2500_02_IOCFG0, 0x01); - CC2500_WriteReg(CC2500_18_MCSM0, 0x18); - CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x04); - CC2500_WriteReg(CC2500_3E_PATABLE, 0xFF); - CC2500_WriteReg(CC2500_0C_FSCTRL0, 0); - CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); - CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); - CC2500_WriteReg(CC2500_14_MDMCFG0, 0x7A); - CC2500_WriteReg(CC2500_19_FOCCFG, 0x16); - CC2500_WriteReg(CC2500_1A_BSCFG, 0x6C); - CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0x03); - CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x40); - CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0x91); - CC2500_WriteReg(CC2500_21_FREND1, 0x56); - CC2500_WriteReg(CC2500_22_FREND0, 0x10); - CC2500_WriteReg(CC2500_23_FSCAL3, 0xA9); - CC2500_WriteReg(CC2500_24_FSCAL2, 0x0A); - CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); - CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); - CC2500_WriteReg(CC2500_29_FSTEST, 0x59); - CC2500_WriteReg(CC2500_2C_TEST2, 0x88); - CC2500_WriteReg(CC2500_2D_TEST1, 0x31); - CC2500_WriteReg(CC2500_2E_TEST0, 0x0B); - CC2500_WriteReg(CC2500_03_FIFOTHR, 0x07); - CC2500_WriteReg(CC2500_09_ADDR, 0x00); - - switch (sub_protocol) { - case FRSKYX_FCC: - CC2500_WriteReg(CC2500_17_MCSM1, 0x0C); - CC2500_WriteReg(CC2500_0E_FREQ1, 0x76); - CC2500_WriteReg(CC2500_0F_FREQ0, 0x27); - CC2500_WriteReg(CC2500_06_PKTLEN, 0x1E); - CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); - CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); - CC2500_WriteReg(CC2500_10_MDMCFG4, 0x7B); - CC2500_WriteReg(CC2500_11_MDMCFG3, 0x61); - CC2500_WriteReg(CC2500_12_MDMCFG2, 0x13); - CC2500_WriteReg(CC2500_15_DEVIATN, 0x51); - break; - case FRSKYX_LBT: - CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); - CC2500_WriteReg(CC2500_0E_FREQ1, 0x80); - CC2500_WriteReg(CC2500_0F_FREQ0, 0x00); - CC2500_WriteReg(CC2500_06_PKTLEN, 0x23); - CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); - CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x08); - CC2500_WriteReg(CC2500_10_MDMCFG4, 0x7B); - CC2500_WriteReg(CC2500_11_MDMCFG3, 0xF8); - CC2500_WriteReg(CC2500_12_MDMCFG2, 0x03); - CC2500_WriteReg(CC2500_15_DEVIATN, 0x53); - break; - } - - frskyx_rx_disable_lna = IS_POWER_FLAG_on; - CC2500_SetTxRxMode(frskyx_rx_disable_lna ? TXRX_OFF : RX_EN); // lna disable / enable - - frskyx_rx_strobe_rx(); - CC2500_WriteReg(CC2500_0A_CHANNR, 0); // bind channel - delayMicroseconds(1000); // wait for RX to activate -} - -static void __attribute__((unused)) frskyx_rx_set_channel(uint8_t channel) -{ - CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[channel]); - CC2500_WriteReg(CC2500_25_FSCAL1, calData[channel]); - frskyx_rx_strobe_rx(); -} - -static void __attribute__((unused)) frskyx_rx_calibrate() -{ - frskyx_rx_strobe_rx(); - for (unsigned c = 0; c < 47; c++) - { - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[c]); - CC2500_Strobe(CC2500_SCAL); - delayMicroseconds(900); - calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1); - } -} - -static uint8_t __attribute__((unused)) frskyx_rx_check_crc() -{ - uint8_t limit = packet_length - 4; - uint16_t lcrc = frskyX_crc_x(&packet[3], limit - 3); // computed crc - uint16_t rcrc = (packet[limit] << 8) | (packet[limit + 1] & 0xff); // received crc - return lcrc == rcrc; -} - -static void __attribute__((unused)) frskyx_rx_build_telemetry_packet() -{ - static uint16_t frskyx_rx_rc_chan[16]; - uint16_t pxx_channel[8]; - uint32_t bits = 0; - uint8_t bitsavailable = 0; - uint8_t idx = 0; - - // decode PXX channels - pxx_channel[0] = ((packet[10] << 8) & 0xF00) | packet[9]; - pxx_channel[1] = ((packet[11] << 4) & 0xFF0) | (packet[10] >> 4); - pxx_channel[2] = ((packet[13] << 8) & 0xF00) | packet[12]; - pxx_channel[3] = ((packet[14] << 4) & 0xFF0) | (packet[13] >> 4); - pxx_channel[4] = ((packet[16] << 8) & 0xF00) | packet[15]; - pxx_channel[5] = ((packet[17] << 4) & 0xFF0) | (packet[16] >> 4); - pxx_channel[6] = ((packet[19] << 8) & 0xF00) | packet[18]; - pxx_channel[7] = ((packet[20] << 4) & 0xFF0) | (packet[19] >> 4); - for (unsigned i = 0; i < 8; i++) { - uint8_t shifted = (pxx_channel[i] & 0x800)>0; - uint16_t channel_value = pxx_channel[i] & 0x7FF; - if (channel_value < 64) - frskyx_rx_rc_chan[shifted ? i + 8 : i] = 0; - else - frskyx_rx_rc_chan[shifted ? i + 8 : i] = min(((channel_value - 64) << 4) / 15, 2047); - } - - // buid telemetry packet - pkt[idx++] = RX_LQI; - pkt[idx++] = RX_RSSI; - pkt[idx++] = 0; // start channel - pkt[idx++] = 16; // number of channels in packet - - // pack channels - for (int i = 0; i < 16; i++) { - bits |= ((uint32_t)frskyx_rx_rc_chan[i]) << bitsavailable; - bitsavailable += 11; - while (bitsavailable >= 8) { - pkt[idx++] = bits & 0xff; - bits >>= 8; - bitsavailable -= 8; - } - } -} - -uint16_t initFrSkyX_Rx() -{ - FrSkyX_Rx_initialise(); - state = 0; - frskyx_rx_chanskip = 1; - hopping_frequency_no = 0; - frskyx_rx_data_started = 0; - frskyx_rx_finetune = 0; - telemetry_link = 0; - if (IS_BIND_IN_PROGRESS) { - phase = FRSKYX_RX_TUNE_START; - } - else { - uint16_t temp = FRSKYX_RX_EEPROM_OFFSET; - rx_tx_addr[0] = eeprom_read_byte((EE_ADDR)temp++); - rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++); - rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++); - frskyx_rx_finetune = eeprom_read_byte((EE_ADDR)temp++); - for(uint8_t ch = 0; ch < 47; ch++) - hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++); - frskyx_rx_calibrate(); - 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 - if (option == 0) - CC2500_WriteReg(CC2500_0C_FSCTRL0, frskyx_rx_finetune); - else - CC2500_WriteReg(CC2500_0C_FSCTRL0, option); - frskyx_rx_set_channel(hopping_frequency_no); - phase = FRSKYX_RX_DATA; - } - packet_length = (sub_protocol == FRSKYX_LBT) ? FRSKYX_LBT_LENGTH : FRSKYX_FCC_LENGTH; - return 1000; -} - -uint16_t FrSkyX_Rx_callback() -{ - static uint32_t pps_timer=0; - static uint8_t pps_counter=0; - static int8_t read_retry = 0; - static int8_t tune_low, tune_high; - uint8_t len, ch; - - if ((prev_option != option) && (phase >= FRSKYX_RX_DATA)) { - if (option == 0) - CC2500_WriteReg(CC2500_0C_FSCTRL0, frskyx_rx_finetune); - else - CC2500_WriteReg(CC2500_0C_FSCTRL0, option); - prev_option = option; - } - - if (frskyx_rx_disable_lna != IS_POWER_FLAG_on) { - frskyx_rx_disable_lna = IS_POWER_FLAG_on; - CC2500_SetTxRxMode(frskyx_rx_disable_lna ? TXRX_OFF : RX_EN); - } - - len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; - - switch(phase) { - case FRSKYX_RX_TUNE_START: - if (len >= packet_length) { - CC2500_ReadData(packet, packet_length); - if(packet[1] == 0x03 && packet[2] == 0x01) { - if(frskyx_rx_check_crc()) { - frskyx_rx_finetune = -127; - CC2500_WriteReg(CC2500_0C_FSCTRL0, frskyx_rx_finetune); - phase = FRSKYX_RX_TUNE_LOW; - frskyx_rx_strobe_rx(); - return 1000; - } - } - } - frskyx_rx_finetune += 10; - CC2500_WriteReg(CC2500_0C_FSCTRL0, frskyx_rx_finetune); - frskyx_rx_strobe_rx(); - return 18000; - - case FRSKYX_RX_TUNE_LOW: - if (len >= packet_length) { - CC2500_ReadData(packet, packet_length); - if (frskyx_rx_check_crc()) { - tune_low = frskyx_rx_finetune; - frskyx_rx_finetune = 127; - CC2500_WriteReg(CC2500_0C_FSCTRL0, frskyx_rx_finetune); - phase = FRSKYX_RX_TUNE_HIGH; - frskyx_rx_strobe_rx(); - return 1000; - } - } - frskyx_rx_finetune += 1; - CC2500_WriteReg(CC2500_0C_FSCTRL0, frskyx_rx_finetune); - frskyx_rx_strobe_rx(); - return 18000; - - case FRSKYX_RX_TUNE_HIGH: - if (len >= packet_length) { - CC2500_ReadData(packet, packet_length); - if (frskyx_rx_check_crc()) { - tune_high = frskyx_rx_finetune; - frskyx_rx_finetune = (tune_low + tune_high) / 2; - CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frskyx_rx_finetune); - if(tune_low < tune_high) - phase = FRSKYX_RX_BIND; - else - phase = FRSKYX_RX_TUNE_START; - frskyx_rx_strobe_rx(); - return 1000; - } - } - frskyx_rx_finetune -= 1; - CC2500_WriteReg(CC2500_0C_FSCTRL0, frskyx_rx_finetune); - frskyx_rx_strobe_rx(); - return 18000; - - case FRSKYX_RX_BIND: - if(len >= packet_length) { - CC2500_ReadData(packet, packet_length); - if (frskyx_rx_check_crc()) { - if (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) { - debugln("bind complete"); - frskyx_rx_calibrate(); - rx_tx_addr[0] = packet[3]; // TXID - rx_tx_addr[1] = packet[4]; // TXID - rx_tx_addr[2] = packet[12]; // RX # - 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 - phase = FRSKYX_RX_DATA; - frskyx_rx_set_channel(hopping_frequency_no); - // store txid and channel list - uint16_t temp = FRSKYX_RX_EEPROM_OFFSET; - eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[0]); - eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]); - eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]); - eeprom_write_byte((EE_ADDR)temp++, frskyx_rx_finetune); - for (ch = 0; ch < 47; ch++) - eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]); - BIND_DONE; - } - frskyx_rx_strobe_rx(); - } - return 1000; - - case FRSKYX_RX_DATA: - if (len >= packet_length) { - CC2500_ReadData(packet, packet_length); - if (packet[1] == rx_tx_addr[0] && packet[2] == rx_tx_addr[1] && packet[6] == rx_tx_addr[2] && frskyx_rx_check_crc()) { - RX_RSSI = packet[packet_length-2]; - if(RX_RSSI >= 128) - RX_RSSI -= 128; - else - RX_RSSI += 128; - // hop to next channel - frskyx_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); - hopping_frequency_no = (hopping_frequency_no + frskyx_rx_chanskip) % 47; - frskyx_rx_set_channel(hopping_frequency_no); - if(packet[7] == 0 && telemetry_link == 0) { // standard packet, send channels to TX - frskyx_rx_build_telemetry_packet(); - telemetry_link = 1; - } - frskyx_rx_data_started = 1; - read_retry = 0; - pps_counter++; - } - } - - // packets per second - if (millis() - pps_timer >= 1000) { - pps_timer = millis(); - debugln("%d pps", pps_counter); - RX_LQI = pps_counter; - pps_counter = 0; - } - - // skip channel if no packet received in time - if (read_retry++ >= 9) { - hopping_frequency_no = (hopping_frequency_no + frskyx_rx_chanskip) % 47; - frskyx_rx_set_channel(hopping_frequency_no); - if(frskyx_rx_data_started) - read_retry = 0; - else - read_retry = -50; // retry longer until first packet is catched - } - break; - } - return 1000; -} - -#endif diff --git a/Multiprotocol/FrSkyX_cc2500.ino b/Multiprotocol/FrSkyX_cc2500.ino index 7fa5de1..754b29d 100644 --- a/Multiprotocol/FrSkyX_cc2500.ino +++ b/Multiprotocol/FrSkyX_cc2500.ino @@ -19,20 +19,30 @@ #include "iface_cc2500.h" -uint8_t FrX_chanskip; -uint8_t FrX_send_seq ; -uint8_t FrX_receive_seq ; +uint8_t FrSkyX_chanskip; +uint8_t FrSkyX_TX_Seq, FrSkyX_TX_IN_Seq; +uint8_t FrSkyX_RX_Seq ; -#define FRX_FAILSAFE_TIMEOUT 1032 +#ifdef SPORT_SEND + struct t_FrSkyX_TX_Frame + { + uint8_t count; + uint8_t payload[8]; + } ; + // Store FrskyX telemetry + struct t_FrSkyX_TX_Frame FrSkyX_TX_Frames[4] ; +#endif -static void __attribute__((unused)) frskyX_set_start(uint8_t ch ) +#define FrSkyX_FAILSAFE_TIMEOUT 1032 + +static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch ) { CC2500_Strobe(CC2500_SIDLE); CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]); CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]); } -static void __attribute__((unused)) frskyX_init() +static void __attribute__((unused)) FrSkyX_init() { FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC // @@ -47,7 +57,7 @@ static void __attribute__((unused)) frskyX_init() //#######END INIT######## } -static void __attribute__((unused)) frskyX_initialize_data(uint8_t adr) +static void __attribute__((unused)) FrSkyX_initialize_data(uint8_t adr) { CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack CC2500_WriteReg(CC2500_18_MCSM0, 0x8); @@ -55,7 +65,7 @@ static void __attribute__((unused)) frskyX_initialize_data(uint8_t adr) CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05); } -static void __attribute__((unused)) frskyX_build_bind_packet() +static void __attribute__((unused)) FrSkyX_build_bind_packet() { packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC packet[1] = 0x03; @@ -75,7 +85,7 @@ static void __attribute__((unused)) frskyX_build_bind_packet() // uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; memset(&packet[13], 0, limit - 13); - uint16_t lcrc = frskyX_crc_x(&packet[3], limit-3); + uint16_t lcrc = FrSkyX_crc(&packet[3], limit-3); // packet[limit++] = lcrc >> 8; packet[limit] = lcrc; @@ -84,14 +94,14 @@ static void __attribute__((unused)) frskyX_build_bind_packet() // 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182 //64=860,1024=1500,1984=2140//Taranis 125% -static uint16_t __attribute__((unused)) frskyX_scaleForPXX( uint8_t i ) +static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX( uint8_t i ) { //mapped 860,2140(125%) range to 64,1984(PXX values); uint16_t chan_val=convert_channel_frsky(i)-1226; if(i>7) chan_val|=2048; // upper channels offset return chan_val; } #ifdef FAILSAFE_ENABLE -static uint16_t __attribute__((unused)) frskyX_scaleForPXX_FS( uint8_t i ) +static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i ) { //mapped 1,2046(125%) range to 64,1984(PXX values); uint16_t chan_val=((Failsafe_data[i]*15)>>4)+64; if(Failsafe_data[i]==FAILSAFE_CHANNEL_NOPULSES) @@ -103,8 +113,8 @@ static uint16_t __attribute__((unused)) frskyX_scaleForPXX_FS( uint8_t i ) } #endif -#define FRX_FAILSAFE_TIME 1032 -static void __attribute__((unused)) frskyX_data_frame() +#define FrSkyX_FAILSAFE_TIME 1032 +static void __attribute__((unused)) FrSkyX_build_packet() { //0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12 // @@ -116,29 +126,30 @@ static void __attribute__((unused)) frskyX_data_frame() #ifdef FAILSAFE_ENABLE static uint16_t failsafe_count=0; static uint8_t FS_flag=0,failsafe_chan=0; - if (FS_flag == 0 && failsafe_count > FRX_FAILSAFE_TIME && chan_offset == 0 && IS_FAILSAFE_VALUES_on) + if (FS_flag == 0 && failsafe_count > FrSkyX_FAILSAFE_TIME && chan_offset == 0 && IS_FAILSAFE_VALUES_on) { FS_flag = 0x10; failsafe_chan = 0; } else if (FS_flag & 0x10 && failsafe_chan < (sub_protocol & 0x01 ? 8-1:16-1)) { - FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet + FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet failsafe_chan ++; } else if (FS_flag & 0x10) { FS_flag = 0; failsafe_count = 0; + FAILSAFE_VALUES_off; } failsafe_count++; #endif - packet[0] = (sub_protocol & 0x02 ) ? 0x20 : 0x1D ; // LBT or FCC + 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; // - packet[4] = (FrX_chanskip<<6)|hopping_frequency_no; - packet[5] = FrX_chanskip>>2; + packet[4] = (FrSkyX_chanskip<<6)|hopping_frequency_no; + packet[5] = FrSkyX_chanskip>>2; packet[6] = RX_num; //packet[7] = FLAGS 00 - standard packet //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet @@ -150,78 +161,135 @@ static void __attribute__((unused)) frskyX_data_frame() #endif packet[8] = 0; // - uint8_t startChan = chan_offset; for(uint8_t i = 0; i <12 ; i+=3) + uint8_t startChan = chan_offset; + for(uint8_t i = 0; i <12 ; i+=3) {//12 bytes of channel data #ifdef FAILSAFE_ENABLE if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) ) - chan_0 = frskyX_scaleForPXX_FS(failsafe_chan); + chan_0 = FrSkyX_scaleForPXX_FS(failsafe_chan); else #endif - chan_0 = frskyX_scaleForPXX(startChan); + chan_0 = FrSkyX_scaleForPXX(startChan); startChan++; // #ifdef FAILSAFE_ENABLE if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) ) - chan_1 = frskyX_scaleForPXX_FS(failsafe_chan); + chan_1 = FrSkyX_scaleForPXX_FS(failsafe_chan); else #endif - chan_1 = frskyX_scaleForPXX(startChan); + chan_1 = FrSkyX_scaleForPXX(startChan); startChan++; // - packet[9+i] = lowByte(chan_0); //3 bytes*4 + packet[9+i] = lowByte(chan_0); //3 bytes*4 packet[9+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4)); packet[9+i+2]=chan_1>>4; } - packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start - - if(sub_protocol & 0x01 ) // in X8 mode send only 8ch every 9ms + if(sub_protocol & 0x01 ) //In X8 mode send only 8ch every 9ms chan_offset = 0 ; else chan_offset^=0x08; + //sequence and send SPort uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; for (uint8_t i=22;i SportTail ) + used += MAX_SPORT_BUFFER - SportHead ; + else + used -= SportHead ; + if ( used < (MAX_SPORT_BUFFER>>1) ) + { + DATA_BUFFER_LOW_off; + debugln("Ok buf:%d",used); + } + } + FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; //Next iteration send next packet + } + else + {//Not in sequence somehow, transmit what the receiver wants but why not asking for retransmit... + //debugln("RX_Seq:%d,TX:%d",FrSkyX_TX_IN_Seq,FrSkyX_TX_Seq); + packet[21] |= FrSkyX_TX_IN_Seq; + packet[22] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count; + for (uint8_t i=23;i<23+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;i++) + packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].payload[i-23]; + } + } + else + packet[21] |= 0x08 ; //FrSkyX_TX_Seq=8 at startup + } + if(packet[22]) + {//Debug + debug("SP: "); + for(uint8_t i=0;i>8;//high byte packet[limit]=lcrc;//low byte } uint16_t ReadFrSkyX() { + static bool transmit=true; + #ifdef DEBUG_SERIAL + static uint16_t fr_time=0; + #endif + switch(state) { default: - frskyX_set_start(47); + FrSkyX_set_start(47); CC2500_SetPower(); CC2500_Strobe(CC2500_SFRX); // - frskyX_build_bind_packet(); + FrSkyX_build_bind_packet(); CC2500_Strobe(CC2500_SIDLE); CC2500_WriteData(packet, packet[0]+1); if(IS_BIND_DONE) @@ -230,73 +298,101 @@ uint16_t ReadFrSkyX() state++; return 9000; case FRSKY_BIND_DONE: - frskyX_initialize_data(0); + FrSkyX_initialize_data(0); hopping_frequency_no=0; BIND_DONE; - state++; - break; + state++; //FRSKY_DATA1 + break; + case FRSKY_DATA5: + telemetry_set_input_sync(9000); + #if defined TELEMETRY + telemetry_link=1; //Send telemetry out anyway + #endif + len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; + if (len && (len<=(0x0E + 3))) //Telemetry frame is 17 + { + packet_count=0; + CC2500_ReadData(packet_in, len); + #if defined TELEMETRY + frsky_check_telemetry(packet_in,len); //Check and parse telemetry packets + #endif + } + else + { + packet_count++; + //debugln("M %d",packet_count); + // restart sequence on missed packet - might need count or timeout instead of one missed + if(packet_count>100) + {//~1sec + FrSkyX_TX_Seq = 0x08 ; //Request init + FrSkyX_TX_IN_Seq = 0xFF ; //No sequence received yet + #ifdef SPORT_SEND + for(uint8_t i=0;i<4;i++) + FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer + #endif + packet_count=0; + #if defined TELEMETRY + telemetry_lost=1; + telemetry_link=0; //Stop sending telemetry + #endif + } + CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO + } + FrSkyX_build_packet(); + state = FRSKY_DATA1; +#if not defined(FRSKYX_LBT) + return 500; +#endif // for LBT just continue to DATA1 right away case FRSKY_DATA1: if ( prev_option != option ) { - CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack + CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack prev_option = option ; } - CC2500_SetTxRxMode(TX_EN); - frskyX_set_start(hopping_frequency_no); - CC2500_SetPower(); - CC2500_Strobe(CC2500_SFRX); - hopping_frequency_no = (hopping_frequency_no+FrX_chanskip)%47; - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteData(packet, packet[0]+1); - // -// frskyX_data_frame(); + FrSkyX_set_start(hopping_frequency_no); + transmit=true; +#ifdef FRSKYX_LBT + CC2500_Strobe(CC2500_SIDLE); + delayMicroseconds(90); //Wait for the freq to stabilize + CC2500_Strobe(CC2500_SRX); //Acquire RSSI state++; - return 5200; + return 500; case FRSKY_DATA2: + uint8_t rssi; + 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 + if ((sub_protocol & 2) && rssi > 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_DATA3: + case FRSKY_DATA4: CC2500_Strobe(CC2500_SRX); state++; return 3100; - case FRSKY_DATA4: - len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; - if (len && (len<=(0x0E + 3))) //Telemetry frame is 17 - { - packet_count=0; - CC2500_ReadData(pkt, len); - #if defined TELEMETRY - frsky_check_telemetry(pkt,len); //check if valid telemetry packets - //parse telemetry packets here - //The same telemetry function used by FrSky(D8). - #endif - } - else - { - packet_count++; - // restart sequence on missed packet - might need count or timeout instead of one missed - if(packet_count>100) - {//~1sec -// seq_last_sent = 0; -// seq_last_rcvd = 8; - FrX_send_seq = 0x08 ; -// FrX_receive_seq = 0 ; - packet_count=0; - #if defined TELEMETRY - telemetry_lost=1; - #endif - } - CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO - } - frskyX_data_frame(); - if ( FrX_send_seq != 0x08 ) - { - FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ; - } - state = FRSKY_DATA1; - return 500; } return 1; } @@ -306,34 +402,33 @@ uint16_t initFrSkyX() set_rx_tx_addr(MProtocol_id_master); Frsky_init_hop(); packet_count=0; - while(!FrX_chanskip) - FrX_chanskip=random(0xfefefefe)%47; + while(!FrSkyX_chanskip) + FrSkyX_chanskip=random(0xfefefefe)%47; //for test*************** //rx_tx_addr[3]=0xB3; //rx_tx_addr[2]=0xFD; //************************ - frskyX_init(); -#if defined SPORT_POLLING -#ifdef INVERT_SERIAL - start_timer4() ; -#endif -#endif - // + FrSkyX_init(); + if(IS_BIND_IN_PROGRESS) { state = FRSKY_BIND; - frskyX_initialize_data(1); + FrSkyX_initialize_data(1); } else { state = FRSKY_DATA1; - frskyX_initialize_data(0); + FrSkyX_initialize_data(0); } -// seq_last_sent = 0; -// seq_last_rcvd = 8; - FrX_send_seq = 0x08 ; - FrX_receive_seq = 0 ; + FrSkyX_TX_Seq = 0x08 ; // Request init + FrSkyX_TX_IN_Seq = 0xFF ; // No sequence received yet + #ifdef SPORT_SEND + for(uint8_t i=0;i<4;i++) + FrSkyX_TX_Frames[i].count=0; // discard frames in current output buffer + SportHead=SportTail=0; // empty data buffer + #endif + FrSkyX_RX_Seq = 0 ; // Seq 0 to start with return 10000; } #endif \ No newline at end of file diff --git a/Multiprotocol/FrSky_Rx_cc2500.ino b/Multiprotocol/FrSky_Rx_cc2500.ino new file mode 100644 index 0000000..a284e2a --- /dev/null +++ b/Multiprotocol/FrSky_Rx_cc2500.ino @@ -0,0 +1,449 @@ +/* + 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(FRSKY_RX_CC2500_INO) + +#include "iface_cc2500.h" + + #define FRSKY_RX_D16FCC_LENGTH 32 + #define FRSKY_RX_D16LBT_LENGTH 35 + #define FRSKY_RX_D8_LENGTH 20 + #define FRSKY_RX_FORMATS 3 + +enum +{ + FRSKY_RX_D16FCC = 0, + FRSKY_RX_D16LBT, + FRSKY_RX_D8 +}; + +enum { + FRSKY_RX_TUNE_START, + FRSKY_RX_TUNE_LOW, + FRSKY_RX_TUNE_HIGH, + FRSKY_RX_BIND, + FRSKY_RX_DATA, +}; + +const PROGMEM uint8_t frsky_rx_common_reg[][2] = { + {CC2500_02_IOCFG0, 0x01}, + {CC2500_18_MCSM0, 0x18}, + {CC2500_07_PKTCTRL1, 0x04}, + {CC2500_3E_PATABLE, 0xFF}, + {CC2500_0C_FSCTRL0, 0}, + {CC2500_0D_FREQ2, 0x5C}, + {CC2500_13_MDMCFG1, 0x23}, + {CC2500_14_MDMCFG0, 0x7A}, + {CC2500_19_FOCCFG, 0x16}, + {CC2500_1A_BSCFG, 0x6C}, + {CC2500_1B_AGCCTRL2, 0x03}, + {CC2500_1C_AGCCTRL1, 0x40}, + {CC2500_1D_AGCCTRL0, 0x91}, + {CC2500_21_FREND1, 0x56}, + {CC2500_22_FREND0, 0x10}, + {CC2500_23_FSCAL3, 0xA9}, + {CC2500_24_FSCAL2, 0x0A}, + {CC2500_25_FSCAL1, 0x00}, + {CC2500_26_FSCAL0, 0x11}, + {CC2500_29_FSTEST, 0x59}, + {CC2500_2C_TEST2, 0x88}, + {CC2500_2D_TEST1, 0x31}, + {CC2500_2E_TEST0, 0x0B}, + {CC2500_03_FIFOTHR, 0x07}, + {CC2500_09_ADDR, 0x00}, +}; + +const PROGMEM uint8_t frsky_rx_d16fcc_reg[][2] = { + {CC2500_17_MCSM1, 0x0C}, + {CC2500_0E_FREQ1, 0x76}, + {CC2500_0F_FREQ0, 0x27}, + {CC2500_06_PKTLEN, 0x1E}, + {CC2500_08_PKTCTRL0, 0x01}, + {CC2500_0B_FSCTRL1, 0x0A}, + {CC2500_10_MDMCFG4, 0x7B}, + {CC2500_11_MDMCFG3, 0x61}, + {CC2500_12_MDMCFG2, 0x13}, + {CC2500_15_DEVIATN, 0x51}, +}; + +const PROGMEM uint8_t frsky_rx_d16lbt_reg[][2] = { + {CC2500_17_MCSM1, 0x0E}, + {CC2500_0E_FREQ1, 0x80}, + {CC2500_0F_FREQ0, 0x00}, + {CC2500_06_PKTLEN, 0x23}, + {CC2500_08_PKTCTRL0, 0x01}, + {CC2500_0B_FSCTRL1, 0x08}, + {CC2500_10_MDMCFG4, 0x7B}, + {CC2500_11_MDMCFG3, 0xF8}, + {CC2500_12_MDMCFG2, 0x03}, + {CC2500_15_DEVIATN, 0x53}, +}; + +const PROGMEM uint8_t frsky_rx_d8_reg[][2] = { + {CC2500_17_MCSM1, 0x0C}, + {CC2500_0E_FREQ1, 0x76}, + {CC2500_0F_FREQ0, 0x27}, + {CC2500_06_PKTLEN, 0x19}, + {CC2500_08_PKTCTRL0, 0x05}, + {CC2500_0B_FSCTRL1, 0x08}, + {CC2500_10_MDMCFG4, 0xAA}, + {CC2500_11_MDMCFG3, 0x39}, + {CC2500_12_MDMCFG2, 0x11}, + {CC2500_15_DEVIATN, 0x42}, +}; + +static uint8_t frsky_rx_chanskip; +static int8_t frsky_rx_finetune; +static uint8_t frsky_rx_format; + +static void __attribute__((unused)) frsky_rx_strobe_rx() +{ + CC2500_Strobe(CC2500_SIDLE); + CC2500_Strobe(CC2500_SFRX); + CC2500_Strobe(CC2500_SRX); +} + +static void __attribute__((unused)) frsky_rx_initialise_cc2500() { + const uint8_t frsky_rx_length[] = { FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D8_LENGTH }; + packet_length = frsky_rx_length[frsky_rx_format]; + CC2500_Reset(); + CC2500_Strobe(CC2500_SIDLE); + for (uint8_t i = 0; i < sizeof(frsky_rx_common_reg) / 2; i++) + CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_common_reg[i][0]), pgm_read_byte_near(&frsky_rx_common_reg[i][1])); + + switch (frsky_rx_format) { + case FRSKY_RX_D16FCC: + for (uint8_t i = 0; i < sizeof(frsky_rx_d16fcc_reg) / 2; i++) + CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][1])); + break; + case FRSKY_RX_D16LBT: + for (uint8_t i = 0; i < sizeof(frsky_rx_d16lbt_reg) / 2; i++) + CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][1])); + break; + case FRSKY_RX_D8: + for (uint8_t i = 0; i < sizeof(frsky_rx_d8_reg) / 2; i++) + CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d8_reg[i][0]), pgm_read_byte_near(&frsky_rx_d8_reg[i][1])); + CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // always check address + CC2500_WriteReg(CC2500_09_ADDR, 0x03); // bind address + CC2500_WriteReg(CC2500_23_FSCAL3, 0x89); + break; + } + CC2500_WriteReg(CC2500_0A_CHANNR, 0); // bind channel + rx_disable_lna = IS_POWER_FLAG_on; + CC2500_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN); // lna disable / enable + frsky_rx_strobe_rx(); + delayMicroseconds(1000); // wait for RX to activate +} + +static void __attribute__((unused)) frsky_rx_set_channel(uint8_t channel) +{ + CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[channel]); + if(frsky_rx_format == FRSKY_RX_D8) + CC2500_WriteReg(CC2500_23_FSCAL3, 0x89); + CC2500_WriteReg(CC2500_25_FSCAL1, calData[channel]); + frsky_rx_strobe_rx(); +} + +static void __attribute__((unused)) frsky_rx_calibrate() +{ + frsky_rx_strobe_rx(); + for (unsigned c = 0; c < 47; c++) + { + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[c]); + CC2500_Strobe(CC2500_SCAL); + delayMicroseconds(900); + calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1); + } +} + +static uint8_t __attribute__((unused)) frskyx_rx_check_crc() +{ + // check D8 checksum + if (frsky_rx_format == FRSKY_RX_D8) + return (packet[packet_length-1] & 0x80) == 0x80; // check CRC_OK flag in status byte 2 + // check D16 checksum + uint8_t limit = packet_length - 4; + uint16_t lcrc = FrSkyX_crc(&packet[3], limit - 3); // computed crc + uint16_t rcrc = (packet[limit] << 8) | (packet[limit + 1] & 0xff); // received crc + return lcrc == rcrc; +} + +static void __attribute__((unused)) frsky_rx_build_telemetry_packet() +{ + uint16_t raw_channel[8]; + uint32_t bits = 0; + uint8_t bitsavailable = 0; + uint8_t idx = 0; + uint8_t i; + + if (frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT) { + // decode D16 channels + raw_channel[0] = ((packet[10] << 8) & 0xF00) | packet[9]; + raw_channel[1] = ((packet[11] << 4) & 0xFF0) | (packet[10] >> 4); + raw_channel[2] = ((packet[13] << 8) & 0xF00) | packet[12]; + raw_channel[3] = ((packet[14] << 4) & 0xFF0) | (packet[13] >> 4); + raw_channel[4] = ((packet[16] << 8) & 0xF00) | packet[15]; + raw_channel[5] = ((packet[17] << 4) & 0xFF0) | (packet[16] >> 4); + raw_channel[6] = ((packet[19] << 8) & 0xF00) | packet[18]; + raw_channel[7] = ((packet[20] << 4) & 0xFF0) | (packet[19] >> 4); + for (i = 0; i < 8; i++) { + // ignore failsafe channels + if(packet[7] != 0x10+(i<<1)) { + uint8_t shifted = (raw_channel[i] & 0x800)>0; + uint16_t channel_value = raw_channel[i] & 0x7FF; + if (channel_value < 64) + rx_rc_chan[shifted ? i + 8 : i] = 0; + else + rx_rc_chan[shifted ? i + 8 : i] = min(((channel_value - 64) << 4) / 15, 2047); + } + } + } + else { + // decode D8 channels + raw_channel[0] = ((packet[10] & 0x0F) << 8 | packet[6]); + raw_channel[1] = ((packet[10] & 0xF0) << 4 | packet[7]); + raw_channel[2] = ((packet[11] & 0x0F) << 8 | packet[8]); + raw_channel[3] = ((packet[11] & 0xF0) << 4 | packet[9]); + raw_channel[4] = ((packet[16] & 0x0F) << 8 | packet[12]); + raw_channel[5] = ((packet[16] & 0xF0) << 4 | packet[13]); + raw_channel[6] = ((packet[17] & 0x0F) << 8 | packet[14]); + raw_channel[7] = ((packet[17] & 0xF0) << 4 | packet[15]); + for (i = 0; i < 8; i++) { + if (raw_channel[i] < 1290) + raw_channel[i] = 1290; + rx_rc_chan[i] = min(((raw_channel[i] - 1290) << 4) / 15, 2047); + } + } + + // buid telemetry packet + packet_in[idx++] = RX_LQI; + packet_in[idx++] = RX_RSSI; + packet_in[idx++] = 0; // start channel + packet_in[idx++] = frsky_rx_format == FRSKY_RX_D8 ? 8 : 16; // number of channels in packet + + // pack channels + for (i = 0; i < packet_in[3]; i++) { + bits |= ((uint32_t)rx_rc_chan[i]) << bitsavailable; + bitsavailable += 11; + while (bitsavailable >= 8) { + packet_in[idx++] = bits & 0xff; + bits >>= 8; + bitsavailable -= 8; + } + } +} + +uint16_t initFrSky_Rx() +{ + state = 0; + frsky_rx_chanskip = 1; + hopping_frequency_no = 0; + rx_data_started = false; + frsky_rx_finetune = 0; + telemetry_link = 0; + if (IS_BIND_IN_PROGRESS) { + frsky_rx_format = FRSKY_RX_D8; + frsky_rx_initialise_cc2500(); + phase = FRSKY_RX_TUNE_START; + } + else { + uint16_t temp = FRSKY_RX_EEPROM_OFFSET; + frsky_rx_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS; + rx_tx_addr[0] = eeprom_read_byte((EE_ADDR)temp++); + rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++); + rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++); + frsky_rx_finetune = eeprom_read_byte((EE_ADDR)temp++); + for (uint8_t ch = 0; ch < 47; ch++) + hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++); + frsky_rx_initialise_cc2500(); + frsky_rx_calibrate(); + 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 + if (option == 0) + CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); + else + CC2500_WriteReg(CC2500_0C_FSCTRL0, option); + frsky_rx_set_channel(hopping_frequency_no); + phase = FRSKY_RX_DATA; + } + return 1000; +} + +uint16_t FrSky_Rx_callback() +{ + static uint32_t pps_timer=0; + static uint8_t pps_counter=0; + static int8_t read_retry = 0; + static int8_t tune_low, tune_high; + uint8_t len, ch; + + if ((prev_option != option) && (phase >= FRSKY_RX_DATA)) { + if (option == 0) + CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); + else + CC2500_WriteReg(CC2500_0C_FSCTRL0, option); + prev_option = option; + } + + if (rx_disable_lna != IS_POWER_FLAG_on) { + rx_disable_lna = IS_POWER_FLAG_on; + CC2500_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN); + } + + len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; + + switch(phase) { + case FRSKY_RX_TUNE_START: + if (len >= packet_length) { + CC2500_ReadData(packet, packet_length); + if(packet[1] == 0x03 && packet[2] == 0x01) { + if(frskyx_rx_check_crc()) { + frsky_rx_finetune = -127; + CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); + phase = FRSKY_RX_TUNE_LOW; + frsky_rx_strobe_rx(); + return 1000; + } + } + } + frsky_rx_format = (frsky_rx_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D16FCC, D16LBT, D8) + frsky_rx_initialise_cc2500(); + frsky_rx_finetune += 10; + CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); + frsky_rx_strobe_rx(); + return 18000; + + case FRSKY_RX_TUNE_LOW: + if (len >= packet_length) { + CC2500_ReadData(packet, packet_length); + if (frskyx_rx_check_crc()) { + tune_low = frsky_rx_finetune; + frsky_rx_finetune = 127; + CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); + phase = FRSKY_RX_TUNE_HIGH; + frsky_rx_strobe_rx(); + return 1000; + } + } + frsky_rx_finetune += 1; + CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); + frsky_rx_strobe_rx(); + return 18000; + + case FRSKY_RX_TUNE_HIGH: + if (len >= packet_length) { + CC2500_ReadData(packet, packet_length); + if (frskyx_rx_check_crc()) { + tune_high = frsky_rx_finetune; + frsky_rx_finetune = (tune_low + tune_high) / 2; + CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frsky_rx_finetune); + if(tune_low < tune_high) + phase = FRSKY_RX_BIND; + else + phase = FRSKY_RX_TUNE_START; + frsky_rx_strobe_rx(); + return 1000; + } + } + frsky_rx_finetune -= 1; + CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune); + frsky_rx_strobe_rx(); + return 18000; + + case FRSKY_RX_BIND: + if(len >= packet_length) { + CC2500_ReadData(packet, packet_length); + if (frskyx_rx_check_crc()) { + if (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) { + debugln("bind complete"); + frsky_rx_calibrate(); + rx_tx_addr[0] = packet[3]; // TXID + rx_tx_addr[1] = packet[4]; // TXID + 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 + phase = FRSKY_RX_DATA; + frsky_rx_set_channel(hopping_frequency_no); + // store format, finetune setting, txid, channel list + uint16_t temp = FRSKY_RX_EEPROM_OFFSET; + eeprom_write_byte((EE_ADDR)temp++, frsky_rx_format); + eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[0]); + eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]); + eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]); + eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune); + for (ch = 0; ch < 47; ch++) + eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]); + BIND_DONE; + } + frsky_rx_strobe_rx(); + } + return 1000; + + 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])) { + RX_RSSI = packet[packet_length-2]; + if(RX_RSSI >= 128) + RX_RSSI -= 128; + else + RX_RSSI += 128; + // 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); + 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 + frsky_rx_build_telemetry_packet(); + telemetry_link = 1; + } + rx_data_started = true; + read_retry = 0; + pps_counter++; + } + } + + // packets per second + if (millis() - pps_timer >= 1000) { + pps_timer = millis(); + debugln("%d pps", pps_counter); + RX_LQI = pps_counter; + pps_counter = 0; + } + + // skip channel if no packet received in time + if (read_retry++ >= 9) { + hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47; + frsky_rx_set_channel(hopping_frequency_no); + if(rx_data_started) + read_retry = 0; + else + read_retry = -50; // retry longer until first packet is catched + } + break; + } + return 1000; +} + +#endif diff --git a/Multiprotocol/GD00X_nrf24l01.ino b/Multiprotocol/GD00X_nrf24l01.ino index 7a1b32b..ca1a64d 100644 --- a/Multiprotocol/GD00X_nrf24l01.ino +++ b/Multiprotocol/GD00X_nrf24l01.ino @@ -208,6 +208,7 @@ uint16_t GD00X_callback() if(--bind_counter==0) BIND_DONE; GD00X_send_packet(); + telemetry_set_input_sync(packet_period); return packet_period; } diff --git a/Multiprotocol/GW008_nrf24l01.ino b/Multiprotocol/GW008_nrf24l01.ino index 3bcae2e..84669eb 100644 --- a/Multiprotocol/GW008_nrf24l01.ino +++ b/Multiprotocol/GW008_nrf24l01.ino @@ -139,6 +139,7 @@ uint16_t GW008_callback() return 5000; break; case GW008_DATA: + telemetry_set_input_sync(GW008_PACKET_PERIOD); GW008_send_packet(0); break; } diff --git a/Multiprotocol/H8_3D_nrf24l01.ino b/Multiprotocol/H8_3D_nrf24l01.ino index 8fe92f5..14f9fe5 100644 --- a/Multiprotocol/H8_3D_nrf24l01.ino +++ b/Multiprotocol/H8_3D_nrf24l01.ino @@ -177,7 +177,10 @@ static void __attribute__((unused)) H8_3D_init() uint16_t H8_3D_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(packet_period); H8_3D_send_packet(0); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/HOTT_cc2500.ino b/Multiprotocol/HOTT_cc2500.ino new file mode 100644 index 0000000..0d7498f --- /dev/null +++ b/Multiprotocol/HOTT_cc2500.ino @@ -0,0 +1,385 @@ +/* + 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(HOTT_CC2500_INO) + +#include "iface_cc2500.h" + +//#define HOTT_FORCE_ID // Force ID of original dump + +#define HOTT_TX_PACKET_LEN 50 +#define HOTT_RX_PACKET_LEN 22 +#define HOTT_PACKET_PERIOD 10000 +#define HOTT_NUM_RF_CHANNELS 75 +#define HOTT_COARSE 0 + +enum { + HOTT_START = 0x00, + HOTT_CAL = 0x01, + HOTT_DATA1 = 0x02, + HOTT_RX1 = 0x03, + HOTT_RX2 = 0x04, +}; + +#define HOTT_FREQ0_VAL 0x6E + +// Some important initialization parameters, all others are either default, +// or not important in the context of transmitter +// FIFOTHR 00 +// SYNC1 D3 +// SYNC0 91 +// PKTLEN 32 - Packet length, 50 bytes +// PKTCTRL1 04 - APPEND_STATUS on=RSSI+LQI, all other are receive parameters - irrelevant +// PKTCTRL0 44 - whitening, use FIFO, use CRC, fixed packet length +// ADDR 00 +// CHANNR 10 +// FSCTRL1 09 - IF +// FSCTRL0 00 - zero freq offset +// FREQ2 5C - synthesizer frequencyfor 26MHz crystal +// FREQ1 6C +// FREQ0 B9 +// MDMCFG4 2D - +// MDMCFG3 3B - +// MDMCFG2 73 - disable DC blocking, MSK, no Manchester code, 32 bits sync word +// MDMCFG1 A3 - FEC enable, 4 preamble bytes, CHANSPC_E - 03 +// MDMCFG0 AA - CHANSPC_M - AA +// DEVIATN 47 - +// MCSM2 07 - +// MCSM1 00 - always use CCA, go to IDLE when done +// MCSM0 08 - disable autocalibration, PO_TIMEOUT - 64, no pin radio control, no forcing XTAL to stay in SLEEP +// FOCCFG 1D +const PROGMEM uint8_t HOTT_init_values[] = { + /* 00 */ 0x2F, 0x2E, 0x2F, 0x00, 0xD3, 0x91, 0x32, 0x04, + /* 08 */ 0x44, 0x00, 0x00, 0x09, 0x00, 0x5C, 0x6C, HOTT_FREQ0_VAL + HOTT_COARSE, + /* 10 */ 0x2D, 0x3B, 0x73, 0xA3, 0xAA, 0x47, 0x07, 0x00, + /* 18 */ 0x08, 0x1D, 0x1C, 0xC7, 0x09, 0xF0, 0x87, 0x6B, + /* 20 */ 0xF0, 0xB6, 0x10, 0xEA, 0x0A, 0x00, 0x11 +}; + +static void __attribute__((unused)) HOTT_rf_init() +{ + CC2500_Strobe(CC2500_SIDLE); + + for (uint8_t i = 0; i < 39; ++i) + CC2500_WriteReg(i, pgm_read_byte_near(&HOTT_init_values[i])); + + prev_option = option; + CC2500_WriteReg(CC2500_0C_FSCTRL0, option); + + CC2500_SetTxRxMode(TX_EN); + CC2500_SetPower(); +} + +static void __attribute__((unused)) HOTT_tune_chan() +{ + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, (rf_ch_num+1)*3); + CC2500_Strobe(CC2500_SCAL); +} + +static void __attribute__((unused)) HOTT_tune_chan_fast() +{ + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, (rf_ch_num+1)*3); + CC2500_WriteReg(CC2500_25_FSCAL1, calData[rf_ch_num]); +} + +static void __attribute__((unused)) HOTT_tune_freq() +{ + if ( prev_option != option ) + { + CC2500_WriteReg(CC2500_0C_FSCTRL0, option); + CC2500_WriteReg(CC2500_0F_FREQ0, HOTT_FREQ0_VAL + HOTT_COARSE); + prev_option = option ; + phase = HOTT_START; // Restart the tune process if option is changed to get good tuned values + } +} + +const uint8_t PROGMEM HOTT_hop[][HOTT_NUM_RF_CHANNELS]= + { { 48, 37, 16, 62, 9, 50, 42, 22, 68, 0, 55, 35, 21, 74, 1, 56, 31, 20, 70, 11, 45, 32, 24, 71, 8, 54, 38, 26, 61, 13, 53, 30, 15, 65, 7, 52, 34, 28, 60, 3, 47, 39, 18, 69, 2, 49, 44, 23, 72, 5, 51, 43, 19, 64, 12, 46, 33, 17, 67, 6, 58, 36, 29, 73, 14, 57, 41, 25, 63, 4, 59, 40, 27, 66, 10 }, + { 50, 23, 5, 34, 67, 53, 22, 12, 39, 62, 51, 21, 10, 33, 63, 59, 16, 1, 43, 66, 49, 19, 8, 30, 71, 47, 24, 2, 35, 68, 45, 25, 14, 41, 74, 55, 18, 4, 32, 61, 54, 17, 11, 31, 72, 52, 28, 6, 38, 65, 46, 15, 9, 40, 60, 48, 26, 3, 37, 70, 58, 29, 0, 36, 64, 56, 20, 7, 42, 69, 57, 27, 13, 44, 73 }, + { 73, 51, 39, 18, 9, 64, 56, 34, 16, 12, 66, 58, 36, 25, 11, 61, 47, 40, 15, 8, 71, 50, 43, 20, 6, 62, 54, 42, 19, 3, 63, 46, 44, 29, 14, 72, 49, 33, 22, 5, 69, 57, 30, 21, 10, 70, 45, 35, 26, 7, 65, 59, 31, 28, 1, 67, 48, 32, 24, 0, 60, 55, 41, 17, 2, 74, 52, 38, 27, 4, 68, 53, 37, 23, 13 }, + { 52, 60, 40, 21, 14, 50, 72, 41, 23, 13, 59, 61, 39, 16, 6, 58, 66, 33, 17, 5, 55, 64, 43, 20, 12, 54, 74, 35, 29, 3, 46, 63, 37, 22, 10, 48, 65, 31, 27, 9, 49, 73, 38, 24, 11, 56, 70, 32, 15, 1, 51, 71, 44, 18, 8, 45, 67, 36, 25, 7, 57, 62, 34, 28, 2, 53, 69, 42, 19, 4, 47, 68, 30, 26, 0 }, + { 50, 16, 34, 6, 71, 51, 24, 40, 7, 68, 57, 27, 33, 14, 70, 55, 26, 30, 5, 74, 47, 28, 44, 11, 67, 49, 15, 32, 9, 61, 52, 22, 37, 13, 66, 59, 18, 42, 3, 62, 46, 29, 31, 12, 60, 48, 19, 38, 1, 72, 58, 17, 36, 4, 64, 53, 21, 39, 0, 63, 56, 20, 41, 2, 65, 45, 25, 35, 10, 69, 54, 23, 43, 8, 73 }, + { 55, 38, 12, 62, 23, 52, 44, 3, 66, 18, 54, 36, 10, 74, 16, 56, 42, 9, 70, 17, 58, 33, 5, 69, 20, 50, 40, 1, 63, 24, 53, 37, 13, 65, 15, 48, 34, 4, 61, 22, 57, 31, 6, 64, 26, 46, 35, 11, 72, 21, 47, 30, 7, 68, 29, 45, 32, 8, 60, 19, 49, 43, 2, 67, 27, 51, 39, 0, 71, 28, 59, 41, 14, 73, 25 }, + { 70, 32, 18, 10, 58, 69, 38, 22, 2, 54, 67, 36, 19, 12, 57, 62, 34, 20, 14, 52, 63, 41, 15, 3, 51, 73, 42, 28, 6, 48, 60, 43, 29, 5, 45, 64, 31, 17, 4, 56, 65, 35, 26, 13, 53, 61, 37, 23, 1, 49, 68, 40, 16, 9, 47, 71, 39, 25, 7, 50, 66, 33, 24, 8, 59, 72, 44, 27, 11, 46, 74, 30, 21, 0, 55 }, + { 6, 45, 71, 27, 44, 10, 46, 74, 22, 32, 0, 55, 69, 21, 33, 4, 50, 66, 18, 38, 7, 57, 62, 19, 36, 1, 48, 70, 20, 40, 8, 47, 68, 15, 43, 2, 58, 61, 26, 42, 3, 56, 72, 23, 34, 14, 54, 67, 16, 37, 5, 59, 64, 24, 30, 12, 52, 65, 25, 39, 13, 49, 73, 17, 31, 9, 53, 60, 28, 35, 11, 51, 63, 29, 41 }, + { 31, 65, 50, 20, 13, 37, 66, 45, 23, 5, 32, 69, 54, 19, 7, 39, 74, 52, 27, 1, 42, 64, 53, 22, 4, 43, 70, 58, 16, 3, 40, 71, 57, 17, 0, 35, 63, 56, 18, 9, 44, 72, 51, 21, 6, 33, 67, 46, 25, 11, 30, 73, 55, 15, 8, 36, 62, 48, 24, 10, 41, 60, 49, 29, 14, 34, 61, 47, 26, 2, 38, 68, 59, 28, 12 }, + { 67, 22, 49, 36, 13, 64, 28, 57, 37, 6, 65, 29, 46, 39, 3, 70, 26, 45, 35, 1, 62, 24, 58, 34, 10, 68, 19, 53, 33, 4, 66, 21, 52, 31, 7, 74, 18, 47, 32, 5, 61, 16, 51, 38, 8, 72, 23, 55, 30, 12, 73, 17, 59, 44, 0, 60, 15, 50, 43, 14, 63, 27, 48, 42, 11, 71, 20, 54, 41, 9, 69, 25, 56, 40, 2 }, + { 19, 38, 14, 66, 57, 18, 44, 7, 74, 48, 23, 30, 6, 71, 58, 26, 32, 5, 61, 46, 20, 34, 0, 68, 45, 24, 36, 1, 70, 50, 27, 33, 10, 63, 52, 16, 42, 9, 65, 51, 15, 41, 11, 64, 53, 22, 37, 3, 60, 56, 28, 35, 4, 67, 49, 17, 39, 13, 69, 54, 25, 43, 2, 73, 55, 21, 31, 8, 62, 47, 29, 40, 12, 72, 59 }, + { 4, 52, 64, 28, 44, 14, 46, 74, 16, 32, 11, 50, 68, 27, 36, 0, 47, 70, 26, 34, 13, 57, 61, 18, 38, 6, 56, 62, 19, 40, 5, 58, 67, 17, 31, 12, 54, 63, 22, 33, 3, 53, 72, 21, 41, 10, 48, 66, 15, 35, 7, 45, 60, 20, 37, 9, 51, 69, 25, 42, 2, 59, 71, 24, 39, 1, 55, 65, 23, 30, 8, 49, 73, 29, 43 }, + { 44, 66, 19, 1, 56, 35, 62, 20, 4, 54, 39, 70, 24, 5, 55, 31, 74, 26, 12, 58, 32, 60, 17, 10, 45, 37, 63, 22, 3, 50, 33, 64, 16, 7, 51, 34, 61, 21, 8, 48, 38, 68, 29, 0, 46, 36, 72, 28, 14, 49, 42, 69, 25, 6, 57, 43, 65, 18, 2, 52, 30, 71, 23, 13, 47, 41, 67, 15, 9, 53, 40, 73, 27, 11, 59 }, + { 12, 16, 36, 46, 69, 6, 20, 44, 58, 62, 11, 19, 34, 48, 71, 1, 18, 42, 50, 74, 3, 25, 31, 47, 65, 0, 24, 33, 45, 72, 2, 23, 35, 56, 64, 10, 22, 38, 49, 63, 7, 26, 37, 51, 70, 14, 21, 30, 53, 67, 5, 15, 40, 52, 66, 9, 17, 39, 55, 60, 13, 27, 41, 54, 73, 4, 28, 32, 57, 61, 8, 29, 43, 59, 68 }, + { 63, 42, 18, 2, 57, 71, 34, 22, 10, 48, 67, 36, 25, 4, 46, 60, 31, 28, 6, 47, 74, 37, 15, 0, 55, 65, 32, 24, 12, 56, 66, 40, 27, 14, 52, 62, 38, 19, 3, 50, 73, 33, 29, 11, 53, 61, 35, 16, 7, 58, 72, 41, 26, 5, 59, 69, 30, 20, 9, 51, 68, 44, 23, 1, 49, 70, 39, 17, 8, 54, 64, 43, 21, 13, 45 }, + { 52, 1, 71, 17, 36, 47, 7, 64, 26, 32, 53, 5, 60, 20, 42, 57, 2, 66, 18, 34, 56, 4, 63, 24, 35, 46, 13, 72, 22, 30, 48, 0, 67, 21, 39, 50, 3, 74, 16, 31, 59, 14, 61, 23, 37, 45, 6, 65, 19, 44, 51, 11, 62, 27, 41, 55, 9, 68, 15, 38, 58, 8, 70, 29, 40, 54, 10, 69, 28, 33, 49, 12, 73, 25, 43 } + }; +const uint16_t PROGMEM HOTT_hop_val[] = { 0xC06B, 0xC34A, 0xDB24, 0x8E09, 0x272E, 0x217F, 0x155B, 0xEDE8, 0x1D31, 0x0986, 0x56F7, 0x6454, 0xC42D, 0x01D2, 0xC253, 0x1180 }; + +static void __attribute__((unused)) HOTT_init() +{ + packet[0] = pgm_read_word_near( &HOTT_hop_val[num_ch] ); + packet[1] = pgm_read_word_near( &HOTT_hop_val[num_ch] )>>8; + + for(uint8_t i=0; iconfig menu + packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->config menu, 0x0A->no more RX telemetry + memcpy(&packet[40],rx_tx_addr,5); + + uint8_t addr=HOTT_EEPROM_OFFSET+RX_num*5; + for(uint8_t i=0;i<5;i++) + packet[45+i]=eeprom_read_byte((EE_ADDR)(addr+i)); + } +} + +static void __attribute__((unused)) HOTT_data_packet() +{ + packet[2] = hopping_frequency_no; + + packet[3] = 0x00; // used for failsafe but may also be used for additional channels + #ifdef FAILSAFE_ENABLE + static uint8_t failsafe_count=0; + if(IS_FAILSAFE_VALUES_on && IS_BIND_DONE) + { + failsafe_count++; + if(failsafe_count>=3) + { + FAILSAFE_VALUES_off; + failsafe_count=0; + } + } + else + failsafe_count=0; + #endif + + // Channels value are PPM*2, -100%=1100µs, +100%=1900µs, order TAER + uint16_t val; + for(uint8_t i=4;i<28;i+=2) + { + val=Channel_data[(i-4)>>1]; + val=(((val<<2)+val)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125% + #ifdef FAILSAFE_ENABLE + if(failsafe_count==1) + { // first failsafe packet + packet[3]=0x40; + uint16_t fs=Failsafe_data[(i-4)>>1]; + if( fs == FAILSAFE_CHANNEL_HOLD || fs == FAILSAFE_CHANNEL_NOPULSES) + val|=0x8000; // channel hold flag + else + { + val=(((fs<<2)+fs)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125% + val|=0x4000; // channel specific position flag + } + } + else if(failsafe_count==2) + { // second failsafe packet=timing? + packet[3]=0x50; + if(i==4) + val=2; + else + val=0; + } + #endif + packet[i] = val; + packet[i+1] = val>>8; + } + + #ifdef HOTT_FW_TELEMETRY + static uint8_t prev_SerialRX_val=0; + if(HoTT_SerialRX && HoTT_SerialRX_val >= 0xD7 && HoTT_SerialRX_val <= 0xDF) + { + if(prev_SerialRX_val!=HoTT_SerialRX_val) + { + prev_SerialRX_val=HoTT_SerialRX_val; + packet[28] = HoTT_SerialRX_val; // send the touch being pressed only once + } + else + packet[28] = 0xDF; // no touch pressed + packet[29] = 0x01; // 0x01->config menu + } + else + { + packet[28] = 0x8C; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets, 0x0F->config menu + packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->config menu, 0x0A->no more RX telemetry + } + #endif + + CC2500_SetTxRxMode(TX_EN); + CC2500_SetPower(); + CC2500_WriteReg(CC2500_06_PKTLEN, 0x32); + CC2500_WriteData(packet, HOTT_TX_PACKET_LEN); + #if 0 + debug("RF:%02X P:",rf_ch_num); + for(uint8_t i=0;ino key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0 or D + // packet[29]= 0xX1/0xX9 with X=0 or X counting 0,1,1,2,2,..,9,9 + TX_RSSI = packet_in[22]; + if(TX_RSSI >=128) + TX_RSSI -= 128; + else + TX_RSSI += 128; + // Reduce telemetry to 14 bytes + packet_in[0]= TX_RSSI; + packet_in[1]= TX_LQI; + debug("T="); + for(uint8_t i=10;i < HOTT_RX_PACKET_LEN; i++) + { + packet_in[i-8]=packet_in[i]; + debug(" %02X",packet_in[i]); + } + debugln(""); + telemetry_link=2; + } + pps_counter++; + #endif + } + } + #ifdef HOTT_FW_TELEMETRY + packet_count++; + if(packet_count>=100) + { + TX_LQI=pps_counter; + pps_counter=packet_count=0; + } + #endif + CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO + phase=HOTT_DATA1; + return 1000; + } + return 0; +} + +uint16_t initHOTT() +{ + num_ch=random(0xfefefefe)%16; + HOTT_init(); + HOTT_rf_init(); + packet_count=0; + #ifdef HOTT_FW_TELEMETRY + HoTT_SerialRX_val=0; + HoTT_SerialRX=false; + #endif + phase = HOTT_START; + return 10000; +} + +#endif \ No newline at end of file diff --git a/Multiprotocol/Hisky_nrf24l01.ino b/Multiprotocol/Hisky_nrf24l01.ino index 2596c9a..504842b 100644 --- a/Multiprotocol/Hisky_nrf24l01.ino +++ b/Multiprotocol/Hisky_nrf24l01.ino @@ -123,8 +123,8 @@ static void __attribute__((unused)) build_ch_data() for (i = 0; i< 8; i++) { j=CH_AETR[i]; temp=convert_channel_16b_limit(j,0,1000); - if (j == THROTTLE) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose - temp = 1000 -temp; + if (j == CH3) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose + temp = 1000 - temp; if (j == CH7) temp = temp < 400 ? 0 : 3; // Gyro mode, 0 - 6 axis, 3 - 3 axis packet[i] = (uint8_t)(temp&0xFF); @@ -151,6 +151,7 @@ uint16_t hisky_cb() phase=6; break; case 7: // build packet + telemetry_set_input_sync(5000); #ifdef FAILSAFE_ENABLE if(IS_FAILSAFE_VALUES_on && hopping_frequency_no==0) { // send failsafe every 100ms @@ -159,6 +160,7 @@ uint16_t hisky_cb() convert_failsafe_HK310(CH5, &packet[4],&packet[5]); packet[7]=0xAA; packet[8]=0x5A; + FAILSAFE_VALUES_off; } else #endif @@ -216,6 +218,7 @@ uint16_t hisky_cb() break; case 7: //Build normal packet + telemetry_set_input_sync(9000); build_ch_data(); break; case 8: diff --git a/Multiprotocol/Hitec_cc2500.ino b/Multiprotocol/Hitec_cc2500.ino index 760e61d..f28f5f6 100644 --- a/Multiprotocol/Hitec_cc2500.ino +++ b/Multiprotocol/Hitec_cc2500.ino @@ -259,6 +259,7 @@ uint16_t ReadHITEC() case HITEC_PREP: if ( prev_option == option ) { // No user frequency change + telemetry_set_input_sync(HITEC_PACKET_PERIOD); HITEC_change_chan_fast(); hopping_frequency_no++; if(hopping_frequency_no>=rf_ch_num) @@ -285,14 +286,14 @@ uint16_t ReadHITEC() return HITEC_RX1_TIMING; case HITEC_RX2: uint8_t len=CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; - if(len && len 00 8D=>RX battery voltage 0x008D/28=5.03V @@ -323,40 +324,40 @@ uint16_t ReadHITEC() // 0C,1C,A1,2B,00,16,00,00,00,00,00,16,00,2C,8E // 0C,1C,A1,2B,00,17,00,00,00,42,44,17,00,48,8D -> 42=>temperature3 0x42-0x28=26°C,44=>temperature4 0x44-0x28=28°C // 0C,1C,A1,2B,00,18,00,00,00,00,00,18,00,50,92 - debug(",telem,%02x",pkt[14]&0x7F); + debug(",telem,%02x",packet_in[14]&0x7F); #if defined(HITEC_FW_TELEMETRY) || defined(HITEC_HUB_TELEMETRY) - TX_RSSI = pkt[13]; + TX_RSSI = packet_in[13]; if(TX_RSSI >=128) TX_RSSI -= 128; else TX_RSSI += 128; - TX_LQI = pkt[14]&0x7F; + TX_LQI = packet_in[14]&0x7F; #endif #if defined(HITEC_FW_TELEMETRY) if(sub_protocol==OPT_FW) { // 8 bytes telemetry packets => see at the end of this file how to fully decode it - pkt[0]=TX_RSSI; // TX RSSI - pkt[1]=TX_LQI; // TX LQI - uint8_t offset=pkt[5]==0?1:0; + packet_in[0]=TX_RSSI; // TX RSSI + packet_in[1]=TX_LQI; // TX LQI + uint8_t offset=packet_in[5]==0?1:0; for(uint8_t i=5;i < 11; i++) - pkt[i-3]=pkt[i+offset]; // frame number followed by 5 bytes of data + packet_in[i-3]=packet_in[i+offset]; // frame number followed by 5 bytes of data telemetry_link=2; // telemetry forward available } #endif #if defined(HITEC_HUB_TELEMETRY) if(sub_protocol==OPT_HUB) { - switch(pkt[5]) // telemetry frame number + switch(packet_in[5]) // telemetry frame number { case 0x00: - v_lipo1 = (pkt[10])<<5 | (pkt[11])>>3; // calculation in float is volt=(pkt[10]<<8+pkt[11])/28 + v_lipo1 = (packet_in[10])<<5 | (packet_in[11])>>3; // calculation in float is volt=(packet_in[10]<<8+packet_in[11])/28 break; case 0x11: - v_lipo1 = (pkt[9])<<5 | (pkt[10])>>3; // calculation in float is volt=(pkt[9]<<8+pkt[10])/28 + v_lipo1 = (packet_in[9])<<5 | (packet_in[10])>>3; // calculation in float is volt=(packet_in[9]<<8+packet_in[10])/28 break; case 0x18: - v_lipo2 = (pkt[6])<<5 | (pkt[7])>>3; // calculation in float is volt=(pkt[6]<<8+pkt[7])/10 + v_lipo2 = (packet_in[6])<<5 | (packet_in[7])>>3; // calculation in float is volt=(packet_in[6]<<8+packet_in[7])/10 break; } telemetry_link=1; // telemetry hub available @@ -391,10 +392,6 @@ uint16_t initHITEC() rx_tx_addr[3]=0x6A; memcpy((void *)hopping_frequency,(void *)"\x00\x3A\x4A\x32\x0C\x58\x2A\x10\x26\x20\x08\x60\x68\x70\x78\x80\x88\x56\x5E\x66\x6E",HITEC_NUM_FREQUENCE); #endif - #if defined(HITEC_HUB_TELEMETRY) - if(sub_protocol==OPT_HUB) - init_frskyd_link_telemetry(); - #endif phase = HITEC_START; return 10000; } diff --git a/Multiprotocol/Hontai_nrf24l01.ino b/Multiprotocol/Hontai_nrf24l01.ino index 03d3f1c..d7ab693 100644 --- a/Multiprotocol/Hontai_nrf24l01.ino +++ b/Multiprotocol/Hontai_nrf24l01.ino @@ -242,9 +242,12 @@ uint16_t HONTAI_callback() } } else + { + telemetry_set_input_sync(packet_period); HONTAI_send_packet(0); + } - return sub_protocol == FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD; + return packet_period; } uint16_t initHONTAI() @@ -253,6 +256,7 @@ uint16_t initHONTAI() bind_counter = HONTAI_BIND_COUNT; HONTAI_initialize_txid(); HONTAI_init(); + packet_period = sub_protocol == FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD; return HONTAI_INITIAL_WAIT; } #endif diff --git a/Multiprotocol/Hubsan_a7105.ino b/Multiprotocol/Hubsan_a7105.ino index d454076..014871f 100644 --- a/Multiprotocol/Hubsan_a7105.ino +++ b/Multiprotocol/Hubsan_a7105.ino @@ -376,6 +376,7 @@ uint16_t ReadHubsan() case DATA_4: case DATA_5: if( txState == 0) { // send packet + telemetry_set_input_sync(10000); #ifdef HUBSAN_HUB_TELEMETRY rfMode = A7105_TX; #endif @@ -464,9 +465,6 @@ uint16_t initHubsan() } packet_count=0; bind_phase=0; - #ifdef HUBSAN_HUB_TELEMETRY - init_frskyd_link_telemetry(); - #endif return 10000; } diff --git a/Multiprotocol/J6Pro_cyrf6936.ino b/Multiprotocol/J6Pro_cyrf6936.ino index 454739a..d6871f5 100644 --- a/Multiprotocol/J6Pro_cyrf6936.ino +++ b/Multiprotocol/J6Pro_cyrf6936.ino @@ -201,7 +201,8 @@ uint16_t ReadJ6Pro() cyrf_datainit(); phase = J6PRO_CHAN_1; case J6PRO_CHAN_1: - //Keep transmit power updated + telemetry_set_input_sync(24550); + //Keep transmit power updated CYRF_SetPower(0x28); j6pro_build_data_packet(); //return 3400; diff --git a/Multiprotocol/KF606_nrf24l01.ino b/Multiprotocol/KF606_nrf24l01.ino index f086091..9f8a7e1 100644 --- a/Multiprotocol/KF606_nrf24l01.ino +++ b/Multiprotocol/KF606_nrf24l01.ino @@ -86,6 +86,7 @@ static void __attribute__((unused)) KF606_init() uint16_t KF606_callback() { + telemetry_set_input_sync(KF606_PACKET_PERIOD); if(IS_BIND_IN_PROGRESS) if(--bind_counter==0) { diff --git a/Multiprotocol/KN_nrf24l01.ino b/Multiprotocol/KN_nrf24l01.ino index 40c8f92..64cdbc5 100644 --- a/Multiprotocol/KN_nrf24l01.ino +++ b/Multiprotocol/KN_nrf24l01.ino @@ -279,12 +279,14 @@ uint16_t initKN() packet_period = KN_WL_SENDING_PACKET_PERIOD; bind_counter = KN_WL_BIND_COUNT; packet_count = KN_WL_PACKET_SEND_COUNT; + seed = KN_WL_PACKET_SEND_COUNT * KN_WL_SENDING_PACKET_PERIOD; } else { packet_period = KN_FX_SENDING_PACKET_PERIOD; bind_counter = KN_FX_BIND_COUNT; packet_count = KN_FX_PACKET_SEND_COUNT; + seed = KN_FX_PACKET_SEND_COUNT * KN_FX_SENDING_PACKET_PERIOD; } kn_init(); phase = IS_BIND_IN_PROGRESS ? KN_PHASE_PRE_BIND : KN_PHASE_PRE_SEND; @@ -318,6 +320,7 @@ uint16_t kn_callback() case KN_PHASE_SENDING: if(packet_sent >= packet_count) { + telemetry_set_input_sync(seed); packet_sent = 0; hopping_frequency_no++; if(hopping_frequency_no >= KN_RF_CH_COUNT) hopping_frequency_no = 0; diff --git a/Multiprotocol/MJXQ_nrf24l01.ino b/Multiprotocol/MJXQ_nrf24l01.ino index a08624a..9140f6d 100644 --- a/Multiprotocol/MJXQ_nrf24l01.ino +++ b/Multiprotocol/MJXQ_nrf24l01.ino @@ -327,7 +327,10 @@ static void __attribute__((unused)) MJXQ_initialize_txid() uint16_t MJXQ_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(MJXQ_PACKET_PERIOD); MJXQ_send_packet(0); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/MT99xx_nrf24l01.ino b/Multiprotocol/MT99xx_nrf24l01.ino index 1d7e1b3..cb38aa8 100644 --- a/Multiprotocol/MT99xx_nrf24l01.ino +++ b/Multiprotocol/MT99xx_nrf24l01.ino @@ -222,7 +222,10 @@ static void __attribute__((unused)) MT99XX_initialize_txid() uint16_t MT99XX_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(packet_period); MT99XX_send_packet(); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/Multi.txt b/Multiprotocol/Multi.txt index b866d0b..f99ea1c 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -52,6 +52,7 @@ 52,ZSX,280 53,Flyzone,FZ-410 54,Scanner -55,FrskyX_RX,FCC,EU_LBT +55,Frsky_RX 56,AFHDS2A_RX +57,HoTT 63,XN_DUMP,250K,1M,2M diff --git a/Multiprotocol/Multi_Names.ino b/Multiprotocol/Multi_Names.ino new file mode 100644 index 0000000..98b3573 --- /dev/null +++ b/Multiprotocol/Multi_Names.ino @@ -0,0 +1,303 @@ +/* + 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(MULTI_NAMES) + +const char STR_FLYSKY[] ="FlySky"; +const char STR_HUBSAN[] ="Hubsan"; +const char STR_FRSKYD[] ="FrSky D"; +const char STR_HISKY[] ="Hisky"; +const char STR_V2X2[] ="V2x2"; +const char STR_DSM[] ="DSM"; +const char STR_DEVO[] ="Devo"; +const char STR_YD717[] ="YD717"; +const char STR_KN[] ="KN"; +const char STR_SYMAX[] ="SymaX"; +const char STR_SLT[] ="SLT"; +const char STR_CX10[] ="CX10"; +const char STR_CG023[] ="CG023"; +const char STR_BAYANG[] ="Bayang"; +const char STR_FRSKYX[] ="FrSky X"; +const char STR_ESKY[] ="ESky"; +const char STR_MT99XX[] ="MT99XX"; +const char STR_MJXQ[] ="MJXq"; +const char STR_SHENQI[] ="Shenqi"; +const char STR_FY326[] ="FY326"; +const char STR_SFHSS[] ="SFHSS"; +const char STR_J6PRO[] ="J6 Pro"; +const char STR_FQ777[] ="FQ777"; +const char STR_ASSAN[] ="Assan"; +const char STR_FRSKYV[] ="FrSky V"; +const char STR_HONTAI[] ="Hontai"; +const char STR_AFHDS2A[] ="FSky 2A"; +const char STR_Q2X2[] ="Q2x2"; +const char STR_WK2x01[] ="Walkera"; +const char STR_Q303[] ="Q303"; +const char STR_GW008[] ="GW008"; +const char STR_DM002[] ="DM002"; +const char STR_CABELL[] ="Cabell"; +const char STR_ESKY150[] ="Esky150"; +const char STR_H8_3D[] ="H8 3D"; +const char STR_CORONA[] ="Corona"; +const char STR_CFLIE[] ="CFlie"; +const char STR_HITEC[] ="Hitec"; +const char STR_WFLY[] ="WFly"; +const char STR_BUGS[] ="Bugs"; +const char STR_BUGSMINI[] ="BugMini"; +const char STR_TRAXXAS[] ="Traxxas"; +const char STR_NCC1701[] ="NCC1701"; +const char STR_E01X[] ="E01X"; +const char STR_V911S[] ="V911S"; +const char STR_GD00X[] ="GD00X"; +const char STR_V761[] ="V761"; +const char STR_KF606[] ="KF606"; +const char STR_REDPINE[] ="Redpine"; +const char STR_POTENSIC[] ="Potensi"; +const char STR_ZSX[] ="ZSX"; +const char STR_FLYZONE[] ="FlyZone"; +const char STR_SCANNER[] ="Scanner"; +const char STR_FRSKY_RX[] ="FrSkyRX"; +const char STR_AFHDS2A_RX[] ="FS2A_RX"; +const char STR_HOTT[] ="HoTT"; +const char STR_XN297DUMP[] ="XN297DP"; + +const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20"; +const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501"; +const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch"; +const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310"; +const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506"; +const char STR_SUBTYPE_DSM[] = "\x06""2 22ms""2 11ms""X 22ms""X 11ms"; +const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0"; +const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 "; +const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun"; +const char STR_SUBTYPE_SYMAX[] = "\x03""Std""X5C"; +const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0"; +const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041"; +const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829"; +const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4"; +const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805"; +const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix"; +const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319"; +const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951"; +const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS"; +const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282"; +const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI"; +const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD"; +const char STR_SUBTYPE_CABELL[] = "\x07""V3\0 ""V3 Telm""-\0 ""-\0 ""-\0 ""-\0 ""F-Safe\0""Unbind\0"; +const char STR_SUBTYPE_H83D[] = "\x07""Std\0 ""H20H\0 ""H20Mini""H30Mini"; +const char STR_SUBTYPE_CORONA[] = "\x05""V1\0 ""V2\0 ""FD V3"; +const char STR_SUBTYPE_HITEC[] = "\x07""Optima\0""Opt Hub""Minima\0"; +const char STR_SUBTYPE_BUGS_MINI[] = "\x06""Std\0 ""Bugs3H"; +const char STR_SUBTYPE_TRAXXAS[] = "\x04""6519"; +const char STR_SUBTYPE_E01X[] = "\x05""E012\0""E015\0""E016H"; +const char STR_SUBTYPE_GD00X[] = "\x05""GD_V1""GD_V2"; +const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow"; +const char STR_SUBTYPE_POTENSIC[] = "\x03""A20"; +const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC"; +const char STR_SUBTYPE_FLYZONE[] = "\x05""FZ410"; +const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 "; + +enum +{ + OPTION_NONE, + OPTION_OPTION, + OPTION_RFTUNE, + OPTION_VIDFREQ, + OPTION_FIXEDID, + OPTION_TELEM, + OPTION_SRVFREQ, + OPTION_MAXTHR, + OPTION_RFCHAN +}; + +#define NO_SUBTYPE nullptr + +const mm_protocol_definition multi_protocols[] = { +// Protocol number, Protocol String, Number of sub_protocols, Sub_protocol strings, Option type +#if defined(FLYSKY_A7105_INO) + {PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE }, +#endif +#if defined(HUBSAN_A7105_INO) + {PROTO_HUBSAN, STR_HUBSAN, 3, STR_SUBTYPE_HUBSAN, OPTION_VIDFREQ }, +#endif +#if defined(FRSKYD_CC2500_INO) + {PROTO_FRSKYD, STR_FRSKYD, 0, NO_SUBTYPE, OPTION_RFTUNE }, +#endif +#if defined(HISKY_NRF24L01_INO) + {PROTO_HISKY, STR_HISKY, 2, STR_SUBTYPE_HISKY, OPTION_NONE }, +#endif +#if defined(V2X2_NRF24L01_INO) + {PROTO_V2X2, STR_V2X2, 2, STR_SUBTYPE_V2X2, OPTION_NONE }, +#endif +#if defined(DSM_CYRF6936_INO) + {PROTO_DSM, STR_DSM, 4, STR_SUBTYPE_DSM, OPTION_MAXTHR }, +#endif +#if defined(DEVO_CYRF6936_INO) + {PROTO_DEVO, STR_DEVO, 5, STR_SUBTYPE_DEVO, OPTION_FIXEDID }, +#endif +#if defined(YD717_NRF24L01_INO) + {PROTO_YD717, STR_YD717, 5, STR_SUBTYPE_YD717, OPTION_NONE }, +#endif +#if defined(KN_NRF24L01_INO) + {PROTO_KN, STR_KN, 2, STR_SUBTYPE_KN, OPTION_NONE }, +#endif +#if defined(SYMAX_NRF24L01_INO) + {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 }, +#endif +#if defined(CX10_NRF24L01_INO) + {PROTO_CX10, STR_CX10, 7, STR_SUBTYPE_CX10, OPTION_NONE }, +#endif +#if defined(CG023_NRF24L01_INO) + {PROTO_CG023, STR_CG023, 2, STR_SUBTYPE_CG023, OPTION_NONE }, +#endif +#if defined(BAYANG_NRF24L01_INO) + {PROTO_BAYANG, STR_BAYANG, 5, STR_SUBTYPE_BAYANG, OPTION_TELEM }, +#endif +#if defined(FRSKYX_CC2500_INO) + {PROTO_FRSKYX, STR_FRSKYX, 4, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE }, +#endif +#if defined(ESKY_NRF24L01_INO) + {PROTO_ESKY, STR_ESKY, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(MT99XX_NRF24L01_INO) + {PROTO_MT99XX, STR_MT99XX, 5, STR_SUBTYPE_MT99, OPTION_NONE }, +#endif +#if defined(MJXQ_NRF24L01_INO) + {PROTO_MJXQ, STR_MJXQ, 7, STR_SUBTYPE_MJXQ, OPTION_RFTUNE }, +#endif +#if defined(SHENQI_NRF24L01_INO) + {PROTO_SHENQI, STR_SHENQI, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(FY326_NRF24L01_INO) + {PROTO_FY326, STR_FY326, 2, STR_SUBTYPE_FY326, OPTION_NONE }, +#endif +#if defined(SFHSS_CC2500_INO) + {PROTO_SFHSS, STR_SFHSS, 0, NO_SUBTYPE, OPTION_RFTUNE }, +#endif +#if defined(J6PRO_CYRF6936_INO) + {PROTO_J6PRO, STR_J6PRO, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(FQ777_NRF24L01_INO) + {PROTO_FQ777, STR_FQ777, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(ASSAN_NRF24L01_INO) + {PROTO_ASSAN, STR_ASSAN, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(FRSKYV_CC2500_INO) + {PROTO_FRSKYV, STR_FRSKYV, 0, NO_SUBTYPE, OPTION_RFTUNE }, +#endif +#if defined(HONTAI_NRF24L01_INO) + {PROTO_HONTAI, STR_HONTAI, 4, STR_SUBTYPE_HONTAI, OPTION_NONE }, +#endif +#if defined(AFHDS2A_A7105_INO) + {PROTO_AFHDS2A, STR_AFHDS2A, 4, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ }, +#endif +#if defined(CX10_NRF24L01_INO) + {PROTO_Q2X2, STR_Q2X2, 3, STR_SUBTYPE_Q2X2, OPTION_NONE }, +#endif +#if defined(WK2x01_CYRF6936_INO) + {PROTO_WK2x01, STR_WK2x01, 6, STR_SUBTYPE_WK2x01, OPTION_NONE }, +#endif +#if defined(Q303_NRF24L01_INO) + {PROTO_Q303, STR_Q303, 4, STR_SUBTYPE_Q303, OPTION_NONE }, +#endif +#if defined(GW008_NRF24L01_INO) + {PROTO_GW008, STR_GW008, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(DM002_NRF24L01_INO) + {PROTO_DM002, STR_DM002, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(CABELL_NRF24L01_INO) + {PROTO_CABELL, STR_CABELL, 8, STR_SUBTYPE_CABELL, OPTION_OPTION }, +#endif +#if defined(ESKY150_NRF24L01_INO) + {PROTO_ESKY150, STR_ESKY150, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(H8_3D_NRF24L01_INO) + {PROTO_H8_3D, STR_H8_3D, 4, STR_SUBTYPE_H83D, OPTION_NONE }, +#endif +#if defined(CORONA_CC2500_INO) + {PROTO_CORONA, STR_CORONA, 3, STR_SUBTYPE_CORONA, OPTION_RFTUNE }, +#endif +#if defined(CFLIE_NRF24L01_INO) + {PROTO_CFLIE, STR_CFLIE, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(HITEC_CC2500_INO) + {PROTO_HITEC, STR_HITEC, 3, STR_SUBTYPE_HITEC, OPTION_RFTUNE }, +#endif +#if defined(WFLY_CYRF6936_INO) + {PROTO_WFLY, STR_WFLY, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(BUGS_A7105_INO) + {PROTO_BUGS, STR_BUGS, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(BUGSMINI_NRF24L01_INO) + {PROTO_BUGSMINI, STR_BUGSMINI, 2, STR_SUBTYPE_BUGS_MINI, OPTION_NONE }, +#endif +#if defined(TRAXXAS_CYRF6936_INO) + {PROTO_TRAXXAS, STR_TRAXXAS, 1, STR_SUBTYPE_TRAXXAS, OPTION_NONE }, +#endif +#if defined(NCC1701_NRF24L01_INO) + {PROTO_NCC1701, STR_NCC1701, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(E01X_NRF24L01_INO) + {PROTO_E01X, STR_E01X, 3, STR_SUBTYPE_E01X, OPTION_OPTION }, +#endif +#if defined(V911S_NRF24L01_INO) + {PROTO_V911S, STR_V911S, 0, NO_SUBTYPE, OPTION_RFTUNE }, +#endif +#if defined(GD00X_NRF24L01_INO) + {PROTO_GD00X, STR_GD00X, 2, STR_SUBTYPE_GD00X, OPTION_RFTUNE }, +#endif +#if defined(V761_NRF24L01_INO) + {PROTO_V761, STR_V761, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(KF606_NRF24L01_INO) + {PROTO_KF606, STR_KF606, 0, NO_SUBTYPE, OPTION_RFTUNE }, +#endif +#if defined(REDPINE_CC2500_INO) + {PROTO_REDPINE, STR_REDPINE, 2, STR_SUBTYPE_REDPINE, OPTION_RFTUNE }, +#endif +#if defined(POTENSIC_NRF24L01_INO) + {PROTO_POTENSIC, STR_POTENSIC, 1, STR_SUBTYPE_POTENSIC, OPTION_NONE }, +#endif +#if defined(ZSX_NRF24L01_INO) + {PROTO_ZSX, STR_ZSX, 1, STR_SUBTYPE_ZSX, OPTION_NONE }, +#endif +#if defined(FLYZONE_A7105_INO) + {PROTO_FLYZONE, STR_FLYZONE, 1, STR_SUBTYPE_FLYZONE, OPTION_NONE }, +#endif +#if defined(SCANNER_CC2500_INO) + {PROTO_SCANNER, STR_SCANNER, 0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(FRSKY_RX_CC2500_INO) + {PROTO_FRSKY_RX, STR_FRSKY_RX, 0, NO_SUBTYPE, OPTION_RFTUNE }, +#endif +#if defined(AFHDS2A_RX_A7105_INO) + {PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,0, NO_SUBTYPE, OPTION_NONE }, +#endif +#if defined(HOTT_CC2500_INO) + {PROTO_HOTT, STR_HOTT, 0, NO_SUBTYPE, OPTION_RFTUNE }, +#endif +#if defined(XN297DUMP_NRF24L01_INO) + {PROTO_XN297DUMP, STR_XN297DUMP, 3, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN }, +#endif + {0x00, nullptr, 0, nullptr, 0 } +}; + +#endif \ No newline at end of file diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index d3cc7a0..15a1152 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -17,9 +17,9 @@ // Version //****************** #define VERSION_MAJOR 1 -#define VERSION_MINOR 2 -#define VERSION_REVISION 1 -#define VERSION_PATCH_LEVEL 86 +#define VERSION_MINOR 3 +#define VERSION_REVISION 0 +#define VERSION_PATCH_LEVEL 43 //****************** // Protocols @@ -81,8 +81,9 @@ enum PROTOCOLS PROTO_ZSX = 52, // =>NRF24L01 PROTO_FLYZONE = 53, // =>A7105 PROTO_SCANNER = 54, // =>CC2500 - PROTO_FRSKYX_RX = 55, // =>CC2500 + PROTO_FRSKY_RX = 55, // =>CC2500 PROTO_AFHDS2A_RX= 56, // =>A7105 + PROTO_HOTT = 57, // =>CC2500 PROTO_XN297DUMP = 63, // =>NRF24L01 }; @@ -290,11 +291,6 @@ enum TRAXXAS { RX6519 = 0, }; -enum FRSKYX_RX -{ - FRSKYX_FCC = 0, - FRSKYX_LBT -}; #define NONE 0 #define P_HIGH 1 @@ -304,17 +300,16 @@ enum FRSKYX_RX struct PPM_Parameters { - uint8_t protocol : 6; - uint8_t sub_proto : 3; - uint8_t rx_num : 4; - uint8_t power : 1; - uint8_t autobind : 1; + uint8_t protocol; + uint8_t sub_proto : 3; + uint8_t rx_num : 6; + uint8_t power : 1; + uint8_t autobind : 1; int8_t option; uint32_t chan_order; }; // Telemetry - enum MultiPacketTypes { MULTI_TELEMETRY_STATUS = 1, @@ -323,13 +318,14 @@ enum MultiPacketTypes MULTI_TELEMETRY_DSM = 4, MULTI_TELEMETRY_DSMBIND = 5, MULTI_TELEMETRY_AFHDS2A = 6, - MULTI_TELEMETRY_CONFIG = 7, + MULTI_TELEMETRY_REUSE_1 = 7, MULTI_TELEMETRY_SYNC = 8, - MULTI_TELEMETRY_SPORT_POLLING = 9, + MULTI_TELEMETRY_REUSE_2 = 9, MULTI_TELEMETRY_HITEC = 10, MULTI_TELEMETRY_SCANNER = 11, MULTI_TELEMETRY_AFHDS2A_AC = 12, MULTI_TELEMETRY_RX_CHANNELS = 13, + MULTI_TELEMETRY_HOTT = 14, }; // Macros @@ -390,6 +386,7 @@ enum MultiPacketTypes #define TX_RX_PAUSE_on protocol_flags2 |= _BV(4) #define IS_TX_RX_PAUSE_on ( ( protocol_flags2 & _BV(4) ) !=0 ) #define IS_TX_PAUSE_on ( ( protocol_flags2 & (_BV(4)|_BV(3)) ) !=0 ) +#define IS_TX_PAUSE_off ( ( protocol_flags2 & (_BV(4)|_BV(3)) ) ==0 ) //Signal OK #define INPUT_SIGNAL_off protocol_flags2 &= ~_BV(5) #define INPUT_SIGNAL_on protocol_flags2 |= _BV(5) @@ -405,6 +402,24 @@ enum MultiPacketTypes #define WAIT_BIND_on protocol_flags2 |= _BV(7) #define IS_WAIT_BIND_on ( ( protocol_flags2 & _BV(7) ) !=0 ) #define IS_WAIT_BIND_off ( ( protocol_flags2 & _BV(7) ) ==0 ) +//Incoming telemetry data buffer +#define DATA_BUFFER_LOW_off protocol_flags3 &= ~_BV(0) +#define DATA_BUFFER_LOW_on protocol_flags3 |= _BV(0) +#define IS_DATA_BUFFER_LOW_on ( ( protocol_flags3 & _BV(0) ) !=0 ) +#define IS_DATA_BUFFER_LOW_off ( ( protocol_flags3 & _BV(0) ) ==0 ) +#define SEND_MULTI_STATUS_off protocol_flags3 &= ~_BV(1) +#define SEND_MULTI_STATUS_on protocol_flags3 |= _BV(1) +#define IS_SEND_MULTI_STATUS_on ( ( protocol_flags3 & _BV(1) ) !=0 ) +#define IS_SEND_MULTI_STATUS_off ( ( protocol_flags3 & _BV(1) ) ==0 ) +#define DISABLE_CH_MAP_off protocol_flags3 &= ~_BV(2) +#define DISABLE_CH_MAP_on protocol_flags3 |= _BV(2) +#define IS_DISABLE_CH_MAP_on ( ( protocol_flags3 & _BV(2) ) !=0 ) +#define IS_DISABLE_CH_MAP_off ( ( protocol_flags3 & _BV(2) ) ==0 ) +#define DISABLE_TELEM_off protocol_flags3 &= ~_BV(3) +#define DISABLE_TELEM_on protocol_flags3 |= _BV(3) +#define IS_DISABLE_TELEM_on ( ( protocol_flags3 & _BV(3) ) !=0 ) +#define IS_DISABLE_TELEM_off ( ( protocol_flags3 & _BV(3) ) ==0 ) + // Failsafe #define FAILSAFE_CHANNEL_HOLD 2047 @@ -576,82 +591,86 @@ enum { #define AFHDS2A_EEPROM_OFFSET 50 // RX ID, 4 bytes per model id, end is 50+64=114 #define BUGS_EEPROM_OFFSET 114 // RX ID, 2 bytes per model id, end is 114+32=146 #define BUGSMINI_EEPROM_OFFSET 146 // RX ID, 2 bytes per model id, end is 146+32=178 -#define FRSKYX_RX_EEPROM_OFFSET 178 // (3) TX ID + (1) freq_tune + (47) channels, 51 bytes, end is 178+51=229 -#define AFHDS2A_RX_EEPROM_OFFSET 229 // (4) TX ID + (16) channels, 20 bytes, end is 229+20=249 -//#define CONFIG_EEPROM_OFFSET 210 // Current configuration of the multimodule +#define FRSKY_RX_EEPROM_OFFSET 178 // (1) format + (3) TX ID + (1) freq_tune + (47) channels, 52 bytes, end is 178+52=230 +#define AFHDS2A_RX_EEPROM_OFFSET 230 // (4) TX ID + (16) channels, 20 bytes, end is 230+20=250 +#define AFHDS2A_EEPROM_OFFSET2 250 // RX ID, 4 bytes per model id, end is 250+192=442 +#define HOTT_EEPROM_OFFSET 442 // RX ID, 5 bytes per model id, end is 320+442=762 +//#define CONFIG_EEPROM_OFFSET 762 // Current configuration of the multimodule //**************************************** //*** MULTI protocol serial definition *** //**************************************** /* -************************** +*************************** 16 channels serial protocol -************************** +*************************** Serial: 100000 Baud 8e2 _ xxxx xxxx p -- - Total of 26 bytes - Stream[0] = 0x55 sub_protocol values are 0..31 Stream contains channels - Stream[0] = 0x54 sub_protocol values are 32..63 Stream contains channels - Stream[0] = 0x57 sub_protocol values are 0..31 Stream contains failsafe - Stream[0] = 0x56 sub_protocol values are 32..63 Stream contains failsafe - header + Total of 26 bytes for protocol V1, variable length 27..36 for protocol V2 + Stream[0] = header + 0x55 sub_protocol values are 0..31 Stream contains channels + 0x54 sub_protocol values are 32..63 Stream contains channels + 0x57 sub_protocol values are 0..31 Stream contains failsafe + 0x56 sub_protocol values are 32..63 Stream contains failsafe Stream[1] = sub_protocol|BindBit|RangeCheckBit|AutoBindBit; - sub_protocol is 0..31 (bits 0..4), value should be added with 32 if Stream[0] = 0x54 - => Reserved 0 - Flysky 1 - Hubsan 2 - FrskyD 3 - Hisky 4 - V2x2 5 - DSM 6 - Devo 7 - YD717 8 - KN 9 - SymaX 10 - SLT 11 - CX10 12 - CG023 13 - Bayang 14 - FrskyX 15 - ESky 16 - MT99XX 17 - MJXQ 18 - SHENQI 19 - FY326 20 - SFHSS 21 - J6PRO 22 - FQ777 23 - ASSAN 24 - FrskyV 25 - HONTAI 26 - OpenLRS 27 - AFHDS2A 28 - Q2X2 29 - WK2x01 30 - Q303 31 - GW008 32 - DM002 33 - CABELL 34 - ESKY150 35 - H8_3D 36 - CORONA 37 - CFlie 38 - Hitec 39 - WFLY 40 - BUGS 41 - BUGSMINI 42 - TRAXXAS 43 - NCC1701 44 - E01X 45 - V911S 46 - GD00X 47 - V761 48 - KF606 49 - REDPINE 50 - POTENSIC 51 - ZSX 52 - FLYZONE 53 - SCANNER 54 - FRSKYX_RX 55 + sub_protocol is 0..31 (bits 0..4), value should be added with 32 if Stream[0] = 0x54 | 0x56 + Reserved 0 + Flysky 1 + Hubsan 2 + FrskyD 3 + Hisky 4 + V2x2 5 + DSM 6 + Devo 7 + YD717 8 + KN 9 + SymaX 10 + SLT 11 + CX10 12 + CG023 13 + Bayang 14 + FrskyX 15 + ESky 16 + MT99XX 17 + MJXQ 18 + SHENQI 19 + FY326 20 + SFHSS 21 + J6PRO 22 + FQ777 23 + ASSAN 24 + FrskyV 25 + HONTAI 26 + OpenLRS 27 + AFHDS2A 28 + Q2X2 29 + WK2x01 30 + Q303 31 + GW008 32 + DM002 33 + CABELL 34 + ESKY150 35 + H8_3D 36 + CORONA 37 + CFlie 38 + Hitec 39 + WFLY 40 + BUGS 41 + BUGSMINI 42 + TRAXXAS 43 + NCC1701 44 + E01X 45 + V911S 46 + GD00X 47 + V761 48 + KF606 49 + REDPINE 50 + POTENSIC 51 + ZSX 52 + FLYZONE 53 + SCANNER 54 + FRSKY_RX 55 + AFHDS2A_RX 56 + HOTT 57 BindBit=> 0x80 1=Bind/0=No AutoBindBit=> 0x40 1=Yes /0=No RangeCheck=> 0x20 1=Yes /0=No @@ -793,9 +812,6 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- RED_SLOW 1 sub_protocol==TRAXXAS RX6519 0 - sub_protocol==FRSKYX_RX - FCC 0 - LBT 1 Power value => 0x80 0=High/1=Low Stream[3] = option_protocol; @@ -810,6 +826,14 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- Values are concatenated to fit in 22 bytes like in SBUS protocol. Failsafe values have exactly the same range/values than normal channels except the extremes where 0=no pulse, 2047=hold. If failsafe is not set or RX then failsafe packets should not be sent. + Stream[26] = sub_protocol bits 6 & 7|RxNum bits 4 & 5|Telemetry_Invert 3|Future_Use 2|Disable_Telemetry 1|Disable_CH_Mapping 0 + sub_protocol is 0..255 (bits 0..5 + bits 6..7) + RxNum value is 0..63 (bits 0..3 + bits 4..5) + Telemetry_Invert => 0x08 0=normal, 1=invert + Future_Use => 0x04 0= , 1= + 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 */ /* Multimodule Status @@ -829,7 +853,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- 0x04 = Protocol is valid 0x08 = Module is in binding mode 0x10 = Module waits a bind event to load the protocol - 0x20 = Failsafe supported by currently running protocol + 0x20 = Current protocol supports failsafe + 0x40 = Current protocol supports disable channel mapping + 0x80 = Data buffer is almost full [3] major [4] minor [5] revision @@ -863,19 +889,36 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- [4] Flags 0x01 = Input signal detected 0x02 = Serial mode enabled - 0x04 = protocol is valid - 0x08 = module is in binding mode - 0x10 = module waits a bind event to load the protocol - 0x20 = current protocol supports failsafe + 0x04 = Protocol is valid + 0x08 = Module is in binding mode + 0x10 = Module waits a bind event to load the protocol + 0x20 = Current protocol supports failsafe + 0x40 = Current protocol supports disable channel mapping + 0x80 = Data buffer is almost full [5] major [6] minor [7] revision - [8] patchlevel, - version of multi code, should be displayed as major.minor.revision.patchlevel + [8] patchlevel + version of multi code, should be displayed as major.minor.revision.patchlevel + [9] channel order: CH4|CH3|CH2|CH1 with CHx value A=0,E=1,T=2,R=3 + [10] Next valid protocol number, can be used to skip invalid protocols + [11] Prev valid protocol number, can be used to skip invalid protocols + [12..18] Protocol name [7], not null terminated if prototcol len == 7 + [19>>4] Option text to be displayed: + OPTION_NONE 0 + OPTION_OPTION 1 + OPTION_RFTUNE 2 + OPTION_VIDFREQ 3 + OPTION_FIXEDID 4 + OPTION_TELEM 5 + OPTION_SRVFREQ 6 + OPTION_MAXTHR 7 + OPTION_RFCHAN 8 + [19&0x0F] Number of sub protocols + [20..27] Sub protocol name [8], not null terminated if sub prototcol len == 8 more information can be added by specifing a longer length of the type, the TX will just ignore these bytes - Type 0x02 Frksy S.port telemetry Type 0x03 Frsky Hub telemetry @@ -896,6 +939,19 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- data[0] = RSSI value data[1-28] telemetry data + Type 0x08 Input synchronisation + Informs the TX about desired rate and current delay + length: 4 + data[0-1] Desired refresh rate in ??s + data[2-3] Time (??s) between last serial servo input received and servo input needed (lateness), TX should adjust its + sending time to minimise this value. + data[4] Interval of this message in ms + data[5] Input delay target in 10??s + Note that there are protocols (AFHDS2A) that have a refresh rate that is smaller than the maximum achievable + refresh rate via the serial protocol, in this case, the TX should double the rate and also subract this + refresh rate from the input lag if the input lag is more than the desired refresh rate. + The remote should try to get to zero of (inputdelay+target*10). + Type 0x0A Hitec telemetry data length: 8 data[0] = TX RSSI value @@ -922,4 +978,12 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- data[3] = number of channels to follow data[4-]= packed channels data, 11 bit per channel + Type 0x0E HoTT telemetry + length: 14 + data[0] = TX_RSSI + data[1] = TX_LQI + data[2] = type + data[3] = page + data[4-13] = data + */ diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 389d578..789292b 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -55,11 +55,8 @@ #include #include HardwareTimer HWTimer2(2); -#if defined SPORT_POLLING -#ifdef INVERT_TELEMETRY - HardwareTimer HWTimer4(4); -#endif -#endif + HardwareTimer HWTimer3(3); + void PPM_decode(); void ISR_COMPB(); extern "C" @@ -76,7 +73,7 @@ uint32_t blink=0,last_signal=0; // uint16_t counter; uint8_t channel; -uint8_t packet[40]; +uint8_t packet[50]; #define NUM_CHN 16 // Servo data @@ -98,7 +95,11 @@ uint16_t packet_period; uint8_t packet_count; uint8_t packet_sent; uint8_t packet_length; -uint8_t hopping_frequency[50]; +#ifdef HOTT_CC2500_INO + uint8_t hopping_frequency[75]; +#else + uint8_t hopping_frequency[50]; +#endif uint8_t *hopping_frequency_ptr; uint8_t hopping_frequency_no=0; uint8_t rf_ch_num; @@ -116,6 +117,8 @@ uint8_t num_ch; #ifdef CC2500_INSTALLED #ifdef SCANNER_CC2500_INO uint8_t calData[255]; + #elif defined(HOTT_CC2500_INO) + uint8_t calData[75]; #else uint8_t calData[50]; #endif @@ -134,14 +137,14 @@ uint8_t num_ch; #endif //Channel mapping for protocols -const uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; -const uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; -const uint8_t CH_RETA[]={RUDDER, ELEVATOR, THROTTLE, AILERON, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; -const uint8_t CH_EATR[]={ELEVATOR, AILERON, THROTTLE, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; +uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; +uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; +//uint8_t CH_RETA[]={RUDDER, ELEVATOR, THROTTLE, AILERON, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; +uint8_t CH_EATR[]={ELEVATOR, AILERON, THROTTLE, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; // Mode_select variables uint8_t mode_select; -uint8_t protocol_flags=0,protocol_flags2=0; +uint8_t protocol_flags=0,protocol_flags2=0,protocol_flags3=0; #ifdef ENABLE_PPM // PPM variable @@ -166,15 +169,21 @@ uint8_t RX_num; //Serial RX variables #define BAUD 100000 -#define RXBUFFER_SIZE 26 +#define RXBUFFER_SIZE 36 // 26+1+9 volatile uint8_t rx_buff[RXBUFFER_SIZE]; volatile uint8_t rx_ok_buff[RXBUFFER_SIZE]; -volatile uint8_t discard_frame = 0; +volatile bool discard_frame = false; +volatile uint8_t rx_idx=0, rx_len=0; + // Telemetry -#define MAX_PKT 30 -uint8_t pkt[MAX_PKT];//telemetry receiving packets +#define TELEMETRY_BUFFER_SIZE 30 +uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets #if defined(TELEMETRY) + #ifdef MULTI_SYNC + uint16_t last_serial_input=0; + uint16_t inputRefreshRate=0; + #endif #ifdef INVERT_TELEMETRY #if not defined(ORANGE_TX) && not defined(STM32_BOARD) // enable bit bash for serial @@ -182,8 +191,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets #endif #define INVERT_SERIAL 1 #endif - uint8_t pass = 0; - uint8_t pktt[MAX_PKT];//telemetry receiving packets + uint8_t telemetry_in_buffer[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets #ifdef BASH_SERIAL // For bit-bashed serial output #define TXBUFFER_SIZE 192 @@ -210,12 +218,34 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets uint8_t telemetry_link=0; uint8_t telemetry_counter=0; uint8_t telemetry_lost; - #ifdef SPORT_POLLING + #ifdef SPORT_SEND #define MAX_SPORT_BUFFER 64 uint8_t SportData[MAX_SPORT_BUFFER]; - bool ok_to_send = false; - uint8_t sport_idx = 0; - uint8_t sport_index = 0; + uint8_t SportHead=0, SportTail=0; + #endif + + //RX protocols + #if defined(AFHDS2A_RX_A7105_INO) || defined(FRSKY_RX_CC2500_INO) + bool rx_data_started; + bool rx_disable_lna; + uint16_t rx_rc_chan[16]; + #endif + + //Multi names + #ifdef MULTI_NAMES + struct mm_protocol_definition { + uint8_t protocol; + const char *ProtoString; + uint8_t nbrSubProto; + const char *SubProtoString; + uint8_t optionType; + }; + extern const mm_protocol_definition multi_protocols[]; + uint8_t multi_protocols_index=0xFF; + #endif + #ifdef HOTT_FW_TELEMETRY + uint8_t HoTT_SerialRX_val=0; + bool HoTT_SerialRX=false; #endif #endif // TELEMETRY @@ -300,7 +330,6 @@ void setup() pinMode(S4_pin,INPUT_PULLUP); //Random pins pinMode(PB0, INPUT_ANALOG); // set up pin for analog input - pinMode(PB1, INPUT_ANALOG); // set up pin for analog input //Timers init_HWTimer(); //0.5us @@ -399,9 +428,15 @@ void setup() #endif // Set default channels' value - InitChannel(); + for(uint8_t i=0;ioption; // Use radio-defined option value @@ -529,88 +572,78 @@ void setup() // Protocol scheduler void loop() { - uint16_t next_callback,diff=0xFFFF; + uint16_t next_callback, diff; + uint8_t count=0; while(1) { - if(remote_callback==0 || IS_WAIT_BIND_on || diff>2*200) - { - do + while(remote_callback==0 || IS_WAIT_BIND_on || IS_INPUT_SIGNAL_off) + if(!Update_All()) { - Update_All(); - } - while(remote_callback==0 || IS_WAIT_BIND_on); - } - #ifndef STM32_BOARD - if( (TIFR1 & OCF1A_bm) != 0) - { - cli(); // Disable global int due to RW of 16 bits registers - OCR1A=TCNT1; // Callback should already have been called... Use "now" as new sync point. - sei(); // Enable global int - } - else - while((TIFR1 & OCF1A_bm) == 0); // Wait before callback - #else - if((TIMER2_BASE->SR & TIMER_SR_CC1IF)!=0) - { - debugln("Callback miss"); - cli(); - OCR1A = TCNT1; - sei(); - } - else - while((TIMER2_BASE->SR & TIMER_SR_CC1IF )==0); // Wait before callback - #endif - do - { - TX_MAIN_PAUSE_on; - tx_pause(); - if(IS_INPUT_SIGNAL_on && remote_callback!=0) - next_callback=remote_callback(); - else - next_callback=2000; // No PPM/serial signal check again in 2ms... - TX_MAIN_PAUSE_off; - tx_resume(); - while(next_callback>4000) - { // start to wait here as much as we can... - next_callback-=2000; // We will wait below for 2ms cli(); // Disable global int due to RW of 16 bits registers - OCR1A += 2000*2 ; // set compare A for callback - #ifndef STM32_BOARD - TIFR1=OCF1A_bm; // clear compare A=callback flag - #else - TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC1IF; // Clear Timer2/Comp1 interrupt flag - #endif - sei(); // enable global int - if(Update_All()) // Protocol changed? - { - next_callback=0; // Launch new protocol ASAP - break; - } - #ifndef STM32_BOARD - while((TIFR1 & OCF1A_bm) == 0); // wait 2ms... - #else - while((TIMER2_BASE->SR & TIMER_SR_CC1IF)==0);//2ms wait - #endif + OCR1A=TCNT1; // Callback should already have been called... Use "now" as new sync point. + sei(); // Enable global int } - // at this point we have a maximum of 4ms in next_callback - next_callback *= 2 ; - cli(); // Disable global int due to RW of 16 bits registers - OCR1A+= next_callback ; // set compare A for callback - #ifndef STM32_BOARD - TIFR1=OCF1A_bm; // clear compare A=callback flag - #else - TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC1IF; // Clear Timer2/Comp1 interrupt flag - #endif - diff=OCR1A-TCNT1; // compare timer and comparator - sei(); // enable global int + TX_MAIN_PAUSE_on; + tx_pause(); + next_callback=remote_callback()<<1; + TX_MAIN_PAUSE_off; + tx_resume(); + cli(); // Disable global int due to RW of 16 bits registers + OCR1A+=next_callback; // Calc when next_callback should happen + #ifndef STM32_BOARD + TIFR1=OCF1A_bm; // Clear compare A=callback flag + #else + TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC1IF; // Clear Timer2/Comp1 interrupt flag + #endif + diff=OCR1A-TCNT1; // Calc the time difference + sei(); // Enable global int + if((diff&0x8000) && !(next_callback&0x8000)) + { // Negative result=callback should already have been called... + debugln("Short CB:%d",next_callback); } - while(diff&0x8000); // Callback did not took more than requested time for next callback - // so we can launch Update_All before next callback + else + { + if(IS_RX_FLAG_on || IS_PPM_FLAG_on) + { // Serial or PPM is waiting... + if(++count>10) + { //The protocol does not leave enough time for an update so forcing it + count=0; + debugln("Force update"); + Update_All(); + } + } + #ifndef STM32_BOARD + while((TIFR1 & OCF1A_bm) == 0) + #else + while((TIMER2_BASE->SR & TIMER_SR_CC1IF )==0) + #endif + { + if(diff>900*2) + { //If at least 1ms is available update values + if((diff&0x8000) && !(next_callback&0x8000)) + {//Should never get here... + debugln("!!!BUG!!!"); + break; + } + count=0; + Update_All(); + #ifdef DEBUG_SERIAL + if(TIMER2_BASE->SR & TIMER_SR_CC1IF ) + debugln("Long update"); + #endif + if(remote_callback==0) + break; + cli(); // Disable global int due to RW of 16 bits registers + diff=OCR1A-TCNT1; // Calc the time difference + sei(); // Enable global int + } + } + } } } -uint8_t Update_All() +bool Update_All() { #ifdef ENABLE_SERIAL #ifdef CHECK_FOR_BOOTLOADER @@ -664,13 +697,14 @@ uint8_t Update_All() update_led_status(); #if defined(TELEMETRY) #if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) ) - if( (protocol == PROTO_FRSKYX_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)) + if( (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)) #endif - TelemetryUpdate(); + if(IS_DISABLE_TELEM_off) + TelemetryUpdate(); #endif #ifdef ENABLE_BIND_CH - if(IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && Channel_data[BIND_CH-1]>CHANNEL_MAX_COMMAND && Channel_data[THROTTLE]<(CHANNEL_MIN_100+50)) - { // Autobind is on and BIND_CH went up and Throttle is low + if(IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && Channel_data[BIND_CH-1]>CHANNEL_MAX_COMMAND) + { // Autobind is on and BIND_CH went up CHANGE_PROTOCOL_FLAG_on; //reload protocol BIND_IN_PROGRESS; //enable bind BIND_CH_PREV_on; @@ -691,9 +725,9 @@ uint8_t Update_All() if(IS_CHANGE_PROTOCOL_FLAG_on) { // Protocol needs to be changed or relaunched for bind protocol_init(); //init new protocol - return 1; + return true; } - return 0; + return false; } #if defined(FAILSAFE_ENABLE) && defined(ENABLE_PPM) @@ -751,7 +785,10 @@ static void update_led_status(void) { if(IS_INPUT_SIGNAL_on) if(millis()-last_signal>70) + { INPUT_SIGNAL_off; //no valid signal (PPM or Serial) received for 70ms + debugln("No input signal"); + } if(blink26) + {//Additional flag received at the end + rx_ok_buff[0]=(rx_ok_buff[26]&0xF0) | (rx_ok_buff[0]&0x0F); // Additional protocol numbers and RX_Num available -> store them in rx_ok_buff[0] + if(rx_ok_buff[26]&0x02) + DISABLE_TELEM_on; + if(rx_ok_buff[26]&0x01) + DISABLE_CH_MAP_on; + #if defined(TELEMETRY) && defined(INVERT_TELEMETRY_TX) + if(((rx_ok_buff[26]&0x08)!=0) ^ prev_inv_telem) + { //value changed + if(rx_ok_buff[26]&0x08) + { // Invert telemetry + debugln("Invert telem %d,%d",rx_ok_buff[26]&0x01,prev_inv_telem); + #if defined (ORANGE_TX) + PORTC.PIN3CTRL |= 0x40 ; + #elif defined (STM32_BOARD) + TX_INV_on; + RX_INV_on; + #endif + } + else + { // Normal telemetry + debugln("Normal telem %d,%d",rx_ok_buff[26]&0x01,prev_inv_telem); + #if defined (ORANGE_TX) + PORTC.PIN3CTRL &= 0xBF ; + #elif defined (STM32_BOARD) + TX_INV_off; + RX_INV_off; + #endif + } + prev_inv_telem=rx_ok_buff[26]&0x08; + } + #endif + } + + if(prev_ch_mapping!=IS_DISABLE_CH_MAP_on) + { + prev_ch_mapping=IS_DISABLE_CH_MAP_on; + if(IS_DISABLE_CH_MAP_on) + { + for(uint8_t i=0;i<4;i++) + CH_AETR[i]=CH_TAER[i]=CH_EATR[i]=i; + debugln("DISABLE_CH_MAP_on"); + } + else + { + CH_AETR[0]=AILERON;CH_AETR[1]=ELEVATOR;CH_AETR[2]=THROTTLE;CH_AETR[3]=RUDDER; + CH_TAER[0]=THROTTLE;CH_TAER[1]=AILERON;CH_TAER[2]=ELEVATOR;CH_TAER[3]=RUDDER; + CH_EATR[0]=ELEVATOR;CH_EATR[1]=AILERON;CH_EATR[2]=THROTTLE;CH_EATR[3]=RUDDER; + debugln("DISABLE_CH_MAP_off"); + } + } + if( (rx_ok_buff[0] != cur_protocol[0]) || ((rx_ok_buff[1]&0x5F) != (cur_protocol[1]&0x5F)) || ( (rx_ok_buff[2]&0x7F) != (cur_protocol[2]&0x7F) ) ) { // New model has been selected CHANGE_PROTOCOL_FLAG_on; //change protocol @@ -1482,9 +1633,15 @@ void update_serial_data() BIND_IN_PROGRESS; //launch bind right away if in autobind mode or bind is set else BIND_DONE; - protocol=(rx_ok_buff[0]==0x55?0:32) + (rx_ok_buff[1]&0x1F); //protocol no (0-63) bits 4-6 of buff[1] and bit 0 of buf[0] + protocol=rx_ok_buff[1]&0x1F; //protocol no (0-31) + if(!(rx_ok_buff[0]&1)) + protocol+=32; //protocol no (0-63) + if(rx_len>26) + protocol|=rx_ok_buff[26]&0xC0; //protocol no (0-255) sub_protocol=(rx_ok_buff[2]>>4)& 0x07; //subprotocol no (0-7) bits 4-6 - RX_num=rx_ok_buff[2]& 0x0F; // rx_num bits 0---3 + RX_num=rx_ok_buff[2]& 0x0F; //rx_num no (0-15) + if(rx_len>26) + RX_num|=rx_ok_buff[26]&0x30; //rx_num no (0-63) } else if( ((rx_ok_buff[1]&0x80)!=0) && ((cur_protocol[1]&0x80)==0) ) // Bind flag has been set @@ -1528,6 +1685,57 @@ void update_serial_data() #endif Channel_data[i]=temp; //value range 0..2047, 0=-125%, 2047=+125% } + + #ifdef HOTT_FW_TELEMETRY + HoTT_SerialRX=false; + #endif + if(rx_len>27) + { // Data available for the current protocol + #ifdef SPORT_SEND + if(protocol==PROTO_FRSKYX && rx_len==35) + {//Protocol waiting for 8 bytes + #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); + for(uint8_t i=28;i<28+7;i++) + { + 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]); + 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 + #ifdef HOTT_FW_TELEMETRY + if(protocol==PROTO_HOTT && rx_len==28) + {//Protocol waiting for 1 byte + HoTT_SerialRX_val=rx_ok_buff[27]; + HoTT_SerialRX=true; + } + #endif + } + RX_DONOTUPDATE_off; #ifdef ORANGE_TX cli(); @@ -1535,8 +1743,13 @@ void update_serial_data() UCSR0B &= ~_BV(RXCIE0); // RX interrupt disable #endif if(IS_RX_MISSED_BUFF_on) // If the buffer is still valid - { memcpy((void*)rx_ok_buff,(const void*)rx_buff,RXBUFFER_SIZE);// Duplicate the buffer - RX_FLAG_on; // data to be processed next time... + { + if(rx_idx>=26 && rx_idxCR1 |= USART_CR1_PCE_BIT; } usart3_begin(100000,SERIAL_8E2); - #ifndef SPORT_POLLING - USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable receive - #endif + USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable receive USART2_BASE->CR1 &= ~ USART_CR1_TE; //disable transmit #else //ATMEGA328p @@ -1674,14 +1881,24 @@ void modules_reset() TIMER2_BASE->ARR = 0xFFFF; // Count until 0xFFFF HWTimer2.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE); // Main scheduler - HWTimer2.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE); // Serial check + //HWTimer2.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE); // Serial check TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC2IF; // Clear Timer2/Comp2 interrupt flag - HWTimer2.attachInterrupt(TIMER_CH2,ISR_COMPB); // Assign function to Timer2/Comp2 interrupt + //HWTimer2.attachInterrupt(TIMER_CH2,ISR_COMPB); // Assign function to Timer2/Comp2 interrupt TIMER2_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer2/Comp2 interrupt HWTimer2.refresh(); // Refresh the timer's count, prescale, and overflow HWTimer2.resume(); + + HWTimer3.pause(); // Pause the timer3 while we're configuring it + TIMER3_BASE->PSC = 35; // 36-1;for 72 MHZ /0.5sec/(35+1) + TIMER3_BASE->ARR = 0xFFFF; // Count until 0xFFFF + HWTimer3.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE); // Serial check + TIMER3_BASE->SR = 0x1E5F & ~TIMER_SR_CC2IF; // Clear Timer3/Comp2 interrupt flag + HWTimer3.attachInterrupt(TIMER_CH2,ISR_COMPB); // Assign function to Timer3/Comp2 interrupt + TIMER3_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer3/Comp2 interrupt + HWTimer3.refresh(); // Refresh the timer's count, prescale, and overflow + HWTimer3.resume(); } #endif @@ -1762,10 +1979,16 @@ 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) + #ifdef TELEMETRY_FRSKYX_TO_FRSKYD + || (protocol==PROTO_FRSKYX) + #endif + ) initTXSerial( SPEED_9600 ) ; - if(protocol==PROTO_FRSKYX) - initTXSerial( SPEED_57600 ) ; + #ifndef TELEMETRY_FRSKYX_TO_FRSKYD + if(protocol==PROTO_FRSKYX) + initTXSerial( SPEED_57600 ) ; + #endif if(protocol==PROTO_DSM) initTXSerial( SPEED_125K ) ; } @@ -1885,77 +2108,83 @@ static uint32_t random_id(uint16_t address, uint8_t create_new) ISR(USART_RX_vect) #endif { // RX interrupt - static uint8_t idx=0; #ifdef ORANGE_TX - if((USARTC0.STATUS & 0x1C)==0) // Check frame error, data overrun and parity error + if((USARTC0.STATUS & 0x1C)==0) // Check frame error, data overrun and parity error #elif defined STM32_BOARD if((USART2_BASE->SR & USART_SR_RXNE) && (USART2_BASE->SR &0x0F)==0) #else - UCSR0B &= ~_BV(RXCIE0) ; // RX interrupt disable + UCSR0B &= ~_BV(RXCIE0) ; // RX interrupt disable sei() ; - if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error + if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error #endif { // received byte is ok to process - if(idx==0||discard_frame==1) + if(rx_idx==0||discard_frame==true) { // Let's try to sync at this point - idx=0;discard_frame=0; - RX_MISSED_BUFF_off; // If rx_buff was good it's not anymore... + RX_MISSED_BUFF_off; // If rx_buff was good it's not anymore... + rx_idx=0;discard_frame=false; rx_buff[0]=UDR0; #ifdef FAILSAFE_ENABLE - if((rx_buff[0]&0xFC)==0x54) // If 1st byte is 0x54, 0x55, 0x56 or 0x57 it looks ok + if((rx_buff[0]&0xFC)==0x54) // If 1st byte is 0x54, 0x55, 0x56 or 0x57 it looks ok #else - if((rx_buff[0]&0xFE)==0x54) // If 1st byte is 0x54 or 0x55 it looks ok + if((rx_buff[0]&0xFE)==0x54) // If 1st byte is 0x54 or 0x55 it looks ok #endif { - TX_RX_PAUSE_on; - tx_pause(); #if defined STM32_BOARD - TIMER2_BASE->CCR2=TIMER2_BASE->CNT+(6500L); // Full message should be received within timer of 3250us - TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC2IF; // Clear Timer2/Comp2 interrupt flag - TIMER2_BASE->DIER |= TIMER_DIER_CC2IE; // Enable Timer2/Comp2 interrupt + TIMER3_BASE->CCR2=TIMER3_BASE->CNT + 500; // Next byte should show up within 250us (1 byte = 120us) + TIMER3_BASE->SR = 0x1E5F & ~TIMER_SR_CC2IF; // Clear Timer3/Comp2 interrupt flag + TIMER3_BASE->DIER |= TIMER_DIER_CC2IE; // Enable Timer3/Comp2 interrupt #else - OCR1B = TCNT1+(6500L) ; // Full message should be received within timer of 3250us - TIFR1 = OCF1B_bm ; // clear OCR1B match flag - SET_TIMSK1_OCIE1B ; // enable interrupt on compare B match + TX_RX_PAUSE_on; + tx_pause(); + cli(); // Disable global int due to RW of 16 bits registers + OCR1B = TCNT1 + 500; // Next byte should show up within 250us (1 byte = 120us) + sei(); // Enable global int + TIFR1 = OCF1B_bm ; // clear OCR1B match flag + SET_TIMSK1_OCIE1B ; // enable interrupt on compare B match #endif - idx++; + rx_idx++; } } else { - rx_buff[idx++]=UDR0; // Store received byte - if(idx>=RXBUFFER_SIZE) - { // A full frame has been received - if(!IS_RX_DONOTUPDATE_on) - { //Good frame received and main is not working on the buffer - memcpy((void*)rx_ok_buff,(const void*)rx_buff,RXBUFFER_SIZE);// Duplicate the buffer - RX_FLAG_on; // flag for main to process servo data - } - else - RX_MISSED_BUFF_on; // notify that rx_buff is good - discard_frame=1; // start again + if(rx_idx>=RXBUFFER_SIZE) + { + discard_frame=true; // Too many bytes being received... + debugln("RX frame too long"); + } + else + { + rx_buff[rx_idx++]=UDR0; // Store received byte + #if defined STM32_BOARD + TIMER3_BASE->CCR2=TIMER3_BASE->CNT + 500; // Next byte should show up within 250us (1 byte = 120us) + #else + cli(); // Disable global int due to RW of 16 bits registers + OCR1B = TCNT1 + 500; // Next byte should show up within 250us (1 byte = 120us) + sei(); // Enable global int + #endif } } } else { - idx=UDR0; // Dummy read - discard_frame=1; // Error encountered discard full frame... + rx_idx=UDR0; // Dummy read + rx_idx=0; + discard_frame=true; // Error encountered discard full frame... debugln("Bad frame RX"); } - if(discard_frame==1) + if(discard_frame==true) { #ifdef STM32_BOARD - TIMER2_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer2/Comp2 interrupt + TIMER3_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer3/Comp2 interrupt #else - CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match + CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match + TX_RX_PAUSE_off; + tx_resume(); #endif - TX_RX_PAUSE_off; - tx_resume(); } #if not defined (ORANGE_TX) && not defined (STM32_BOARD) cli() ; - UCSR0B |= _BV(RXCIE0) ; // RX interrupt enable + UCSR0B |= _BV(RXCIE0) ; // RX interrupt enable #endif } @@ -1965,17 +2194,38 @@ static uint32_t random_id(uint16_t address, uint8_t create_new) #elif defined STM32_BOARD void ISR_COMPB() #else - ISR(TIMER1_COMPB_vect, ISR_NOBLOCK ) + ISR(TIMER1_COMPB_vect) #endif { // Timer1 compare B interrupt - discard_frame=1; - #ifdef STM32_BOARD - TIMER2_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer2/Comp2 interrupt - debugln("Bad frame timer"); - #else - CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match + if(rx_idx>=26 && rx_idxDIER &= ~TIMER_DIER_CC2IE; // Disable Timer3/Comp2 interrupt + #else + CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match + TX_RX_PAUSE_off; + tx_resume(); #endif - tx_resume(); } #endif //ENABLE_SERIAL diff --git a/Multiprotocol/NCC1701_nrf24l01.ino b/Multiprotocol/NCC1701_nrf24l01.ino index 814bb99..dff58ab 100644 --- a/Multiprotocol/NCC1701_nrf24l01.ino +++ b/Multiprotocol/NCC1701_nrf24l01.ino @@ -197,6 +197,7 @@ uint16_t NCC_callback() phase = NCC_BIND_TX2; return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT; case NCC_TX3: + telemetry_set_input_sync(NCC_PACKET_INTERVAL); if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) { // RX fifo data ready NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN); @@ -268,9 +269,6 @@ uint16_t initNCC(void) hopping_frequency_no=4; // start with bind NCC_init(); phase=NCC_BIND_TX1; - #ifdef NCC1701_HUB_TELEMETRY - init_frskyd_link_telemetry(); - #endif return 10000; } diff --git a/Multiprotocol/POTENSIC_nrf24l01.ino b/Multiprotocol/POTENSIC_nrf24l01.ino index 5851887..06577ab 100644 --- a/Multiprotocol/POTENSIC_nrf24l01.ino +++ b/Multiprotocol/POTENSIC_nrf24l01.ino @@ -109,6 +109,7 @@ uint16_t POTENSIC_callback() BIND_DONE; XN297_SetTXAddr(rx_tx_addr,5); } + telemetry_set_input_sync(POTENSIC_PACKET_PERIOD); POTENSIC_send_packet(); return POTENSIC_PACKET_PERIOD; } diff --git a/Multiprotocol/Q303_nrf24l01.ino b/Multiprotocol/Q303_nrf24l01.ino index 9eee446..93ed15a 100644 --- a/Multiprotocol/Q303_nrf24l01.ino +++ b/Multiprotocol/Q303_nrf24l01.ino @@ -354,7 +354,10 @@ static void __attribute__((unused)) Q303_initialize_txid() uint16_t Q303_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(packet_period); Q303_send_packet(0); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/Redpine_cc2500.ino b/Multiprotocol/Redpine_cc2500.ino index df18f9b..463c314 100644 --- a/Multiprotocol/Redpine_cc2500.ino +++ b/Multiprotocol/Redpine_cc2500.ino @@ -125,6 +125,7 @@ static uint16_t ReadREDPINE() } else { + telemetry_set_input_sync(packet_period); CC2500_SetTxRxMode(TX_EN); REDPINE_set_channel(hopping_frequency_no); CC2500_SetPower(); @@ -133,10 +134,7 @@ static uint16_t ReadREDPINE() CC2500_Strobe(CC2500_SIDLE); hopping_frequency_no = (hopping_frequency_no + 1) % 49; CC2500_WriteData(packet, REDPINE_PACKET_SIZE); - if (sub_protocol==0) - return REDPINE_LOOPTIME_FAST*100; - else - return REDPINE_LOOPTIME_SLOW*1000; + return packet_period; } return 1; } @@ -235,6 +233,11 @@ static uint16_t initREDPINE() } hopping_frequency[49] = 0; // Last channel is the bind channel at hop 0 + if (sub_protocol==0) + packet_period = REDPINE_LOOPTIME_FAST*100; + else + packet_period = REDPINE_LOOPTIME_SLOW*1000; + bind_counter=REDPINE_BIND; REDPINE_init(sub_protocol); CC2500_SetTxRxMode(TX_EN); // enable PA diff --git a/Multiprotocol/SFHSS_cc2500.ino b/Multiprotocol/SFHSS_cc2500.ino index 7f9dbd9..95d7066 100644 --- a/Multiprotocol/SFHSS_cc2500.ino +++ b/Multiprotocol/SFHSS_cc2500.ino @@ -173,8 +173,8 @@ static void __attribute__((unused)) SFHSS_build_data_packet() else { //Use channel value ch[i]=(ch[i]>>1)+2560; - if(CH_AETR[ch_offset+i]==THROTTLE && ch[i]<3072) // Throttle - ch[i]+=1024; + //if(IS_DISABLE_CH_MAP_off && ch_offset+i==CH3 && ch[i]<3072) // Throttle + // ch[i]+=1024; } } } @@ -235,6 +235,7 @@ uint16_t ReadSFHSS() #define SFHSS_PACKET_PERIOD 6800 #define SFHSS_DATA2_TIMING 1625 // Adjust this value between 1600 and 1650 if your RX(s) are not operating properly case SFHSS_DATA1: + telemetry_set_input_sync(6800); SFHSS_build_data_packet(); SFHSS_send_packet(); phase = SFHSS_DATA2; diff --git a/Multiprotocol/SHENQI_nrf24l01.ino b/Multiprotocol/SHENQI_nrf24l01.ino index ca3d873..745ce9b 100644 --- a/Multiprotocol/SHENQI_nrf24l01.ino +++ b/Multiprotocol/SHENQI_nrf24l01.ino @@ -63,6 +63,8 @@ void SHENQI_send_packet() } else { + if(packet_count==1) + telemetry_set_input_sync(3000+2508+6*1750); LT8900_SetAddress(rx_tx_addr,4); packet[1]=255-convert_channel_8b(RUDDER); packet[2]=255-convert_channel_16b_limit(THROTTLE,0x60,0xA0); @@ -91,7 +93,9 @@ void SHENQI_send_packet() uint16_t SHENQI_callback() { if(IS_BIND_DONE) + { SHENQI_send_packet(); + } else { if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) diff --git a/Multiprotocol/SLT_nrf24l01.ino b/Multiprotocol/SLT_nrf24l01.ino index 3ce909f..693014a 100644 --- a/Multiprotocol/SLT_nrf24l01.ino +++ b/Multiprotocol/SLT_nrf24l01.ino @@ -141,7 +141,7 @@ static void __attribute__((unused)) SLT_build_packet() for (uint8_t i = 0; i < 4; ++i) { uint16_t v = convert_channel_10b(CH_AETR[i]); - if(sub_protocol>SLT_V2 && (CH_AETR[i]==THROTTLE || CH_AETR[i]==ELEVATOR) ) + if(sub_protocol>SLT_V2 && (i==CH2 || i==CH3) ) v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols packet[i] = v; e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0); @@ -213,6 +213,7 @@ uint16_t SLT_callback() switch (phase) { case SLT_BUILD: + telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730); SLT_build_packet(); phase++; return SLT_TIMING_BUILD; diff --git a/Multiprotocol/Scanner_cc2500.ino b/Multiprotocol/Scanner_cc2500.ino index 6b09b21..fa7c416 100644 --- a/Multiprotocol/Scanner_cc2500.ino +++ b/Multiprotocol/Scanner_cc2500.ino @@ -18,13 +18,11 @@ #include "iface_cc2500.h" #define SCAN_MAX_RADIOCHANNEL 249 // 2483 MHz -#define SCAN_CHANNEL_LOCK_TIME 210 // with precalibration, channel requires only 90 usec for synthesizer to settle +#define SCAN_CHANNEL_LOCK_TIME 90 // with precalibration, channel requires only 90 usec for synthesizer to settle #define SCAN_AVERAGE_INTVL 20 -#define SCAN_MAX_COUNT 5 +#define SCAN_MAX_COUNT 10 #define SCAN_CHANS_PER_PACKET 5 -static uint8_t scan_tlm_index; - enum ScanStates { SCAN_CHANNEL_CHANGE = 0, SCAN_GET_RSSI = 1, @@ -90,56 +88,53 @@ static int __attribute__((unused)) Scanner_scan_rssi() rssi_rel = rssi - 128; // relative power levels 0-127 (equals -137 to -72 dBm) } else { - rssi_rel = rssi + 128; // relativ power levels 128-255 (equals -73 to -10 dBm) + rssi_rel = rssi + 128; // relative power levels 128-255 (equals -73 to -10 dBm) } return rssi_rel; } uint16_t Scanner_callback() { - static uint8_t max_count, max_rssi; - uint8_t rssi; - switch (phase) - { - case SCAN_CHANNEL_CHANGE: - if(telemetry_link == 0) { - max_count = 0; - max_rssi = 0; - rf_ch_num++; - if (rf_ch_num >= (SCAN_MAX_RADIOCHANNEL + 1)) - rf_ch_num = 0; - if (scan_tlm_index++ == 0) - pkt[0] = rf_ch_num; // start channel for telemetry packet - Scanner_scan_next(); - phase = SCAN_GET_RSSI; - } - return SCAN_CHANNEL_LOCK_TIME; - case SCAN_GET_RSSI: - rssi = Scanner_scan_rssi(); - if(rssi >= max_rssi) { - max_rssi = rssi; - pkt[scan_tlm_index] = rssi; - } - max_count++; - if(max_count > SCAN_MAX_COUNT) { - phase = SCAN_CHANNEL_CHANGE; - if (scan_tlm_index == SCAN_CHANS_PER_PACKET) - { - // send data to TX - telemetry_link = 1; - scan_tlm_index = 0; - } + uint8_t rssi,max_rssi; + + //!!!Blocking mode protocol!!! + TX_MAIN_PAUSE_off; + tx_resume(); + while(1) + { //Start + packet_in[0] = rf_ch_num; // start channel for telemetry packet + for(uint8_t i=0;i= max_rssi) max_rssi = rssi; + delayMicroseconds(SCAN_AVERAGE_INTVL); // wait before next read } + packet_in[i+1] = max_rssi; + //next channel + rf_ch_num++; + if (rf_ch_num >= (SCAN_MAX_RADIOCHANNEL + 1)) + rf_ch_num = 0; + } + telemetry_link = 1; + do + { + if(Update_All()) + return 1000; // protocol has changed, give back the control to main + } + while(telemetry_link == 1); } - return SCAN_AVERAGE_INTVL; + return 0; } uint16_t initScanner(void) { - rf_ch_num = SCAN_MAX_RADIOCHANNEL; - scan_tlm_index = 0; + rf_ch_num = 0; telemetry_link = 0; - phase = SCAN_CHANNEL_CHANGE; Scanner_cc2500_init(); CC2500_Strobe(CC2500_SRX); Scanner_calibrate(); diff --git a/Multiprotocol/Symax_nrf24l01.ino b/Multiprotocol/Symax_nrf24l01.ino index f33a344..029e388 100644 --- a/Multiprotocol/Symax_nrf24l01.ino +++ b/Multiprotocol/Symax_nrf24l01.ino @@ -359,6 +359,7 @@ uint16_t symax_callback() } break; case SYMAX_DATA: + telemetry_set_input_sync(SYMAX_PACKET_PERIOD); SYMAX_send_packet(0); break; } diff --git a/Multiprotocol/TRAXXAS_cyrf6936.ino b/Multiprotocol/TRAXXAS_cyrf6936.ino index 4de89c6..5ed502a 100644 --- a/Multiprotocol/TRAXXAS_cyrf6936.ino +++ b/Multiprotocol/TRAXXAS_cyrf6936.ino @@ -162,6 +162,7 @@ uint16_t ReadTRAXXAS() TRAXXAS_cyrf_data_config(); phase++; case TRAXXAS_DATA: + telemetry_set_input_sync(13940); TRAXXAS_send_data_packet(); break; } diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index 40e83d7..edc6511 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -20,46 +20,35 @@ uint8_t RetrySequence ; #if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) - #define MULTI_TIME 500 //in ms - #define INPUT_SYNC_TIME 100 //in ms - #define INPUT_ADDITIONAL_DELAY 100 // in 10µs, 100 => 1000 µs uint32_t lastMulti = 0; + #define MULTI_TIME 500 //in ms + #ifdef MULTI_SYNC + #define INPUT_SYNC_TIME 100 //in ms + #define INPUT_ADDITIONAL_DELAY 100 // in 10µs, 100 => 1000 µs + uint32_t lastInputSync = 0; + uint16_t inputDelay = 0; + #endif // MULTI_SYNC #endif // MULTI_TELEMETRY/MULTI_STATUS #if defined SPORT_TELEMETRY - #define SPORT_TIME 12000 //12ms #define FRSKY_SPORT_PACKET_SIZE 8 #define FX_BUFFERS 4 - uint32_t last = 0; - uint8_t sport_counter=0; uint8_t RxBt = 0; - uint8_t sport = 0; + uint8_t Sport_Data = 0; uint8_t pktx1[FRSKY_SPORT_PACKET_SIZE*FX_BUFFERS]; // Store for out of sequence packet - uint8_t FrskyxRxTelemetryValidSequence ; - struct t_fx_rx_frame + uint8_t FrSkyX_RX_ValidSeq ; + struct t_FrSkyX_RX_Frame { - uint8_t valid ; - uint8_t count ; - uint8_t payload[6] ; + boolean valid; + uint8_t count; + uint8_t payload[6]; } ; // Store for FrskyX telemetry - struct t_fx_rx_frame FrskyxRxFrames[4] ; - uint8_t NextFxFrameToForward ; - #ifdef SPORT_POLLING - uint8_t sport_rx_index[28] ; - uint8_t ukindex ; - uint8_t kindex ; - uint8_t TxData[2]; - uint8_t SportIndexPolling; - uint8_t RxData[16] ; - volatile uint8_t RxIndex=0 ; - uint8_t sport_bytes=0; - uint8_t skipped_id; - uint8_t rx_counter=0; - #endif + struct t_FrSkyX_RX_Frame FrSkyX_RX_Frames[4] ; + uint8_t FrSkyX_RX_NextFrame=0; #endif // SPORT_TELEMETRY #if defined HUB_TELEMETRY @@ -72,7 +61,6 @@ uint8_t RetrySequence ; #define STUFF_MASK 0x20 #define MAX_PKTX 10 uint8_t pktx[MAX_PKTX]; -uint8_t indx; uint8_t frame[18]; #if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) @@ -88,17 +76,58 @@ static void multi_send_header(uint8_t type, uint8_t len) Serial_write(len); } +static void telemetry_set_input_sync(uint16_t refreshRate) +{ + #ifdef MULTI_SYNC + #if defined(STM32_BOARD) && defined(DEBUG_PIN) + static uint8_t c=0; + if (c++%2==0) + { DEBUG_PIN_on; } + else + { DEBUG_PIN_off; } + #endif + // Only record input Delay after a frame has really been received + // Otherwise protocols with faster refresh rates then the TX sends (e.g. 3ms vs 6ms) will screw up the calcualtion + inputRefreshRate = refreshRate; + if (last_serial_input != 0) + { + cli(); // Disable global int due to RW of 16 bits registers + inputDelay = TCNT1; + sei(); // Enable global int + //inputDelay = (inputDelay - last_serial_input)>>1; + inputDelay -= last_serial_input; + //if(inputDelay & 0x8000) + // inputDelay = inputDelay - 0x8000; + last_serial_input=0; + } + #else + (void)refreshRate; + #endif +} + +#ifdef MULTI_SYNC + static void mult_send_inputsync() + { + multi_send_header(MULTI_TELEMETRY_SYNC, 6); + Serial_write(inputRefreshRate >> 8); + Serial_write(inputRefreshRate & 0xff); +// Serial_write(inputDelay >> 8); +// Serial_write(inputDelay & 0xff); + Serial_write(inputDelay >> 9); + Serial_write(inputDelay >> 1); + Serial_write(INPUT_SYNC_TIME); + Serial_write(INPUT_ADDITIONAL_DELAY); + } +#endif //MULTI_SYNC + static void multi_send_status() { - #ifdef SPORT_POLLING - #ifdef INVERT_SERIAL - USART3_BASE->CR1 &= ~USART_CR1_TE ; - TX_INV_on; //activate inverter for both serial TX and RX signals - USART3_BASE->CR1 |= USART_CR1_TE ; + #ifdef MULTI_NAMES + if(multi_protocols_index != 0xFF) + multi_send_header(MULTI_TELEMETRY_STATUS, 24); + else #endif - rx_pause(); - #endif - multi_send_header(MULTI_TELEMETRY_STATUS, 5); + multi_send_header(MULTI_TELEMETRY_STATUS, 6); // Build flags uint8_t flags=0; @@ -114,23 +143,34 @@ static void multi_send_status() else if (IS_BIND_IN_PROGRESS) flags |= 0x08; - #ifdef FAILSAFE_ENABLE - //Is failsafe supported? - switch (protocol) - { - case PROTO_HISKY: - if(sub_protocol!=HK310) - break; - case PROTO_AFHDS2A: - case PROTO_DEVO: - case PROTO_SFHSS: - case PROTO_WK2x01: - case PROTO_FRSKYX: - flags |= 0x20; //Yes - default: + switch (protocol) + { + case PROTO_HISKY: + if(sub_protocol!=HK310) break; - } - #endif + case PROTO_AFHDS2A: + case PROTO_DEVO: + case PROTO_SFHSS: + case PROTO_WK2x01: + #ifdef FAILSAFE_ENABLE + flags |= 0x20; //Failsafe supported + #endif + case PROTO_DSM: + case PROTO_SLT: + case PROTO_FLYSKY: + case PROTO_ESKY: + case PROTO_J6PRO: + flags |= 0x40; //Disable_ch_mapping supported + break; + #ifdef FAILSAFE_ENABLE + case PROTO_HOTT: + case PROTO_FRSKYX: + flags |= 0x20; //Failsafe supported + break; + #endif + } + if(IS_DATA_BUFFER_LOW_on) + flags |= 0x80; } Serial_write(flags); @@ -139,6 +179,42 @@ static void multi_send_status() Serial_write(VERSION_MINOR); Serial_write(VERSION_REVISION); Serial_write(VERSION_PATCH_LEVEL); + + // Channel order + Serial_write(RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON); + + #ifdef MULTI_NAMES + if(multi_protocols_index != 0xFF) + { + // Protocol next/prev + if(multi_protocols[multi_protocols_index+1].protocol != 0) + Serial_write(multi_protocols[multi_protocols_index+1].protocol); // next protocol number + else + Serial_write(protocol); // end of list + if(multi_protocols_index>0) + Serial_write(multi_protocols[multi_protocols_index-1].protocol); // prev protocol number + else + Serial_write(protocol); // begining of list + // Protocol + for(uint8_t i=0;i<7;i++) + Serial_write(multi_protocols[multi_protocols_index].ProtoString[i]); // protocol name + // Sub-protocol + uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto | (multi_protocols[multi_protocols_index].optionType<<4); // add option display type + Serial_write(nbr); // number of sub protocols + uint8_t j=0; + if(nbr && (sub_protocol&0x07)=128) + TX_RSSI -= 128; + else + TX_RSSI += 128; + TX_LQI = packet_in[len-1]&0x7F; + +#if defined FRSKYD_CC2500_INO + if (protocol==PROTO_FRSKYD) { - telemetry_link|=1; // Telemetry data is available - TX_RSSI = pkt[len-2]; - if(TX_RSSI >=128) - TX_RSSI -= 128; - else - TX_RSSI += 128; - TX_LQI = pkt[len-1]&0x7F; + //Save current buffer for (uint8_t i=3;i0 && pktt[6]<=10) - { - if (protocol==PROTO_FRSKYD) - { - if ( ( pktt[7] & 0x1F ) == (telemetry_counter & 0x1F) ) - { - uint8_t topBit = 0 ; - if ( telemetry_counter & 0x80 ) - if ( ( telemetry_counter & 0x1F ) != RetrySequence ) - topBit = 0x80 ; - telemetry_counter = ( (telemetry_counter+1)%32 ) | topBit ; // Request next telemetry frame - } - else - { - // incorrect sequence - RetrySequence = pktt[7] & 0x1F ; - telemetry_counter |= 0x80 ; - pktt[6]=0 ; // Discard current packet and wait for retransmit - } + telemetry_in_buffer[i]=packet_in[i]; // Buffer telemetry values to be sent + + //Check incoming telemetry sequence + if(telemetry_in_buffer[6]>0 && telemetry_in_buffer[6]<=10) + { //Telemetry length ok + if ( ( telemetry_in_buffer[7] & 0x1F ) == (telemetry_counter & 0x1F) ) + {//Sequence is ok + uint8_t topBit = 0 ; + if ( telemetry_counter & 0x80 ) + if ( ( telemetry_counter & 0x1F ) != RetrySequence ) + topBit = 0x80 ; + telemetry_counter = ( (telemetry_counter+1)%32 ) | topBit ; // Request next telemetry frame + } + else + {//Incorrect sequence + RetrySequence = telemetry_in_buffer[7] & 0x1F ; + telemetry_counter |= 0x80 ; + telemetry_in_buffer[6]=0 ; // Discard current packet and wait for retransmit } } else - pktt[6]=0; // Discard packet - // + telemetry_in_buffer[6]=0; // Discard packet + } +#endif + #if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO + if (protocol==PROTO_FRSKYX) + { + /*Telemetry frames(RF) SPORT info + 15 bytes payload + SPORT frame valid 6+3 bytes + [00] PKLEN 0E 0E 0E 0E + [01] TXID1 DD DD DD DD + [02] TXID2 6D 6D 6D 6D + [03] CONST 02 02 02 02 + [04] RS/RB 2C D0 2C CE //D0;CE=2*RSSI;....2C = RX battery voltage(5V from Bec) + [05] HD-SK 03 10 21 32 //TX/RX telemetry hand-shake bytes + [06] NO.BT 00 00 06 03 //No.of valid SPORT frame bytes in the frame + [07] STRM1 00 00 7E 00 + [08] STRM2 00 00 1A 00 + [09] STRM3 00 00 10 00 + [10] STRM4 03 03 03 03 + [11] STRM5 F1 F1 F1 F1 + [12] STRM6 D1 D1 D0 D0 + [13] CHKSUM1 --|2 CRC bytes sent by RX (calculated on RX side crc16/table) + [14] CHKSUM2 --|*/ telemetry_lost=0; - if (protocol==PROTO_FRSKYX) - { - uint16_t lcrc = frskyX_crc_x(&pkt[3], len-7 ) ; - if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) ) - { - // Check if in sequence - if ( (pkt[5] & 0x0F) == 0x08 ) - { - FrX_receive_seq = 0x08 ; - NextFxFrameToForward = 0 ; - FrskyxRxFrames[0].valid = 0 ; - FrskyxRxFrames[1].valid = 0 ; - FrskyxRxFrames[2].valid = 0 ; - FrskyxRxFrames[3].valid = 0 ; - } - else if ( (pkt[5] & 0x03) == (FrX_receive_seq & 0x03 ) ) - { - // OK to process - struct t_fx_rx_frame *p ; - uint8_t count ; - p = &FrskyxRxFrames[FrX_receive_seq & 3] ; - count = pkt[6] ; - if ( count <= 6 ) - { - p->count = count ; - for ( uint8_t i = 0 ; i < count ; i += 1 ) - p->payload[i] = pkt[i+7] ; - } - else - p->count = 0 ; - p->valid = 1 ; + uint16_t lcrc = FrSkyX_crc(&packet_in[3], len-7 ) ; + if ( ( (lcrc >> 8) != packet_in[len-4]) || ( (lcrc & 0x00FF ) != packet_in[len-3]) ) + return; // Bad CRC - FrX_receive_seq = ( FrX_receive_seq + 1 ) & 0x03 ; + if(packet_in[4] & 0x80) + RX_RSSI=packet_in[4] & 0x7F ; + else + RxBt = (packet_in[4]<<1) + 1 ; + #if defined(TELEMETRY_FRSKYX_TO_FRSKYD) && defined(ENABLE_PPM) + if(mode_select != MODE_SERIAL) + {//PPM + v_lipo1=RxBt; + return; + } + #endif + //Save outgoing telemetry sequence + FrSkyX_TX_IN_Seq=packet_in[5] >> 4; - if ( FrskyxRxTelemetryValidSequence & 0x80 ) - { - FrX_receive_seq = ( FrskyxRxTelemetryValidSequence + 1 ) & 3 ; - FrskyxRxTelemetryValidSequence &= 0x7F ; - } + //Check incoming telemetry sequence + uint8_t packet_seq=packet_in[5] & 0x03; + if ( packet_in[5] & 0x08 ) + {//Request init + FrSkyX_RX_Seq = 0x08 ; + FrSkyX_RX_NextFrame = 0x00 ; + FrSkyX_RX_Frames[0].valid = false ; + FrSkyX_RX_Frames[1].valid = false ; + FrSkyX_RX_Frames[2].valid = false ; + FrSkyX_RX_Frames[3].valid = false ; + } + else if ( packet_seq == (FrSkyX_RX_Seq & 0x03 ) ) + {//In sequence + struct t_FrSkyX_RX_Frame *p ; + uint8_t count ; + // packet_in[4] RSSI + // packet_in[5] sequence control + // packet_in[6] payload count + // packet_in[7-12] payload + p = &FrSkyX_RX_Frames[packet_seq] ; + count = packet_in[6]; // Payload length + if ( count <= 6 ) + {//Store payload + p->count = count ; + for ( uint8_t i = 0 ; i < count ; i++ ) + p->payload[i] = packet_in[i+7] ; + } + else + p->count = 0 ; // Discard + p->valid = true ; + FrSkyX_RX_Seq = ( FrSkyX_RX_Seq + 1 ) & 0x03 ; // Move to next sequence + + if ( FrSkyX_RX_ValidSeq & 0x80 ) + { + FrSkyX_RX_Seq = ( FrSkyX_RX_ValidSeq + 1 ) & 3 ; + FrSkyX_RX_ValidSeq &= 0x7F ; + } + + } + else + {//Not in sequence + struct t_FrSkyX_RX_Frame *q ; + uint8_t count ; + // packet_in[4] RSSI + // packet_in[5] sequence control + // packet_in[6] payload count + // packet_in[7-12] payload + if ( packet_seq == ( ( FrSkyX_RX_Seq +1 ) & 3 ) ) + {//Received next sequence -> save it + q = &FrSkyX_RX_Frames[packet_seq] ; + count = packet_in[6]; // Payload length + if ( count <= 6 ) + {//Store payload + q->count = count ; + for ( uint8_t i = 0 ; i < count ; i++ ) + q->payload[i] = packet_in[i+7] ; } else - { - // Save and request correct packet - struct t_fx_rx_frame *q ; - uint8_t count ; - // pkt[4] RSSI - // pkt[5] sequence control - // pkt[6] payload count - // pkt[7-12] payload - pktt[6] = 0 ; // Don't process - if ( (pkt[5] & 0x03) == ( ( FrX_receive_seq +1 ) & 3 ) ) - { - q = &FrskyxRxFrames[(pkt[5] & 0x03)] ; - count = pkt[6] ; - if ( count <= 6 ) - { - q->count = count ; - for ( uint8_t i = 0 ; i < count ; i += 1 ) - { - q->payload[i] = pkt[i+7] ; - } - } - else - q->count = 0 ; - q->valid = 1 ; - - FrskyxRxTelemetryValidSequence = 0x80 | ( pkt[5] & 0x03 ) ; - } - - FrX_receive_seq = ( FrX_receive_seq & 0x03 ) | 0x04 ; // Request re-transmission - } - - if (((pktt[5] >> 4) & 0x0f) == 0x08) - FrX_send_seq = 0 ; + q->count = 0 ; + q->valid = true ; + + FrSkyX_RX_ValidSeq = 0x80 | packet_seq ; } + FrSkyX_RX_Seq = ( FrSkyX_RX_Seq & 0x03 ) | 0x04 ; // Request re-transmission of original sequence } -#endif } +#endif } void init_frskyd_link_telemetry() { telemetry_link=0; telemetry_counter=0; + telemetry_lost=1; v_lipo1=0; v_lipo2=0; RX_RSSI=0; @@ -392,20 +514,19 @@ void frsky_link_frame() frame[0] = 0xFE; // Link frame if (protocol==PROTO_FRSKYD) { - frame[1] = pktt[3]; // A1 - frame[2] = pktt[4]; // A2 - frame[3] = pktt[5]; // RX_RSSI + frame[1] = telemetry_in_buffer[3]; // A1 + frame[2] = telemetry_in_buffer[4]; // A2 + frame[3] = telemetry_in_buffer[5]; // RX_RSSI telemetry_link &= ~1 ; // Sent telemetry_link |= 2 ; // Send hub if available } else - if (protocol==PROTO_HUBSAN||protocol==PROTO_AFHDS2A||protocol==PROTO_BAYANG||protocol==PROTO_NCC1701||protocol==PROTO_CABELL||protocol==PROTO_HITEC||protocol==PROTO_BUGS||protocol==PROTO_BUGSMINI) - { - frame[1] = v_lipo1; - frame[2] = v_lipo2; - frame[3] = RX_RSSI; - telemetry_link=0; - } + {//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX + frame[1] = v_lipo1; + frame[2] = v_lipo2; + frame[3] = RX_RSSI; + telemetry_link=0; + } frame[4] = TX_RSSI; frame[5] = RX_LQI; frame[6] = TX_LQI; @@ -420,26 +541,26 @@ void frsky_link_frame() #if defined HUB_TELEMETRY void frsky_user_frame() { - if(pktt[6]) + if(telemetry_in_buffer[6]) {//only send valid hub frames frame[0] = 0xFD; // user frame - if(pktt[6]>USER_MAX_BYTES) + if(telemetry_in_buffer[6]>USER_MAX_BYTES) { frame[1]=USER_MAX_BYTES; // packet size - pktt[6]-=USER_MAX_BYTES; + telemetry_in_buffer[6]-=USER_MAX_BYTES; telemetry_link |= 2 ; // 2 packets need to be sent } else { - frame[1]=pktt[6]; // packet size + frame[1]=telemetry_in_buffer[6]; // packet size telemetry_link=0; // only 1 packet or processing second packet } - frame[2] = pktt[7]; + frame[2] = telemetry_in_buffer[7]; for(uint8_t i=0;iCR1 &= ~USART_CR1_TE ; - TX_INV_on; //activate inverter for both serial TX and RX signals - USART3_BASE->CR1 |= USART_CR1_TE ; - #endif - #endif multi_send_header(MULTI_TELEMETRY_SPORT, 9); uint16_t crc_s = 0; uint8_t x = p[0] ; if ( x <= 0x1B ) x = pgm_read_byte_near( &Indices[x] ) ; Serial_write(x) ; - for (uint8_t i = 1; i < 9; i++) + for (uint8_t i = 1; i < 8; i++) { - if (i == 8) - p[i] = 0xff - crc_s; - Serial_write(p[i]); - - if (i>0) - { - crc_s += p[i]; //0-1FF - crc_s += crc_s >> 8; //0-100 - crc_s &= 0x00ff; - } + Serial_write(p[i]); + crc_s += p[i]; //0-1FF + crc_s += crc_s >> 8; //0-100 + crc_s &= 0x00ff; } + Serial_write(0xff - crc_s); } #else void sportSend(uint8_t *p) { uint16_t crc_s = 0; - #ifdef SPORT_POLLING - #ifdef INVERT_SERIAL - USART3_BASE->CR1 &= ~USART_CR1_TE ; - TX_INV_on; //activate inverter for both serial TX and RX signals - USART3_BASE->CR1 |= USART_CR1_TE ; - #endif - #endif Serial_write(START_STOP);//+9 Serial_write(p[0]) ; for (uint8_t i = 1; i < 9; i++) @@ -579,210 +681,13 @@ const uint8_t PROGMEM Indices[] = { 0x00, 0xA1, 0x22, 0x83, 0xE4, 0x45, else Serial_write(p[i]); - if (i>0) - { - crc_s += p[i]; //0-1FF - crc_s += crc_s >> 8; //0-100 - crc_s &= 0x00ff; - } + crc_s += p[i]; //0-1FF + crc_s += crc_s >> 8; //0-100 + crc_s &= 0x00ff; } - } - + } #endif -#if defined SPORT_POLLING -uint8_t nextID() -{ - uint8_t i ; - uint8_t poll_idx ; - if (phase) - { - poll_idx = 99 ; - for ( i = 0 ; i < 28 ; i++ ) - { - if ( sport_rx_index[kindex] ) - { - poll_idx = kindex ; - } - kindex++ ; - if ( kindex>= 28 ) - { - kindex = 0 ; - phase = 0 ; - break ; - } - if ( poll_idx != 99 ) - { - break ; - } - } - if ( poll_idx != 99 ) - { - return poll_idx ; - } - } - if ( phase == 0 ) - { - for ( i = 0 ; i < 28 ; i++ ) - { - if ( sport_rx_index[ukindex] == 0 ) - { - poll_idx = ukindex ; - phase = 1 ; - } - ukindex++; - if (ukindex >= 28 ) - { - ukindex = 0 ; - } - if ( poll_idx != 99 ) - { - return poll_idx ; - } - } - if ( poll_idx == 99 ) - { - phase = 1 ; - return 0 ; - } - } - return poll_idx ; -} - -#ifdef INVERT_SERIAL -void start_timer4() -{ - TIMER4_BASE->PSC = 71; // 72-1;for 72 MHZ / 1.0sec/(71+1) - TIMER4_BASE->CCER = 0 ; - TIMER4_BASE->DIER = 0 ; - TIMER4_BASE->CCMR1 = 0 ; - TIMER4_BASE->CCMR1 = TIMER_CCMR1_OC1M ; - HWTimer4.attachInterrupt(TIMER_CH1, __irq_timer4); // Assign function to Timer2/Comp2 interrupt - nvic_irq_set_priority( NVIC_TIMER4, 14 ) ; -} - -void stop_timer4() -{ - TIMER5_BASE->CR1 = 0 ; - nvic_irq_disable( NVIC_TIMER4 ) ; -} - -void __irq_timer4(void) -{ - TIMER4_BASE->DIER = 0 ; - TIMER4_BASE->CR1 = 0 ; - TX_INV_on; //activate inverter for both serial TX and RX signals -} - -#endif - -void pollSport() -{ - uint8_t pindex = nextID() ; - TxData[0] = START_STOP; - TxData[1] = pgm_read_byte_near(&Indices[pindex]) ; - if(!telemetry_lost && ((TxData[1] &0x1F)== skipped_id ||TxData[1]==0x98)) - {//98 ID(RSSI/RxBat and SWR ) and ID's from sport telemetry - pindex = nextID() ; - TxData[1] = pgm_read_byte_near(&Indices[pindex]); - } - SportIndexPolling = pindex ; - RxIndex = 0; - #ifdef INVERT_SERIAL - USART3_BASE->CR1 &= ~USART_CR1_TE ; - TX_INV_on; //activate inverter for both serial TX and RX signals - USART3_BASE->CR1 |= USART_CR1_TE ; - #endif -#ifdef MULTI_TELEMETRY - multi_send_header(MULTI_TELEMETRY_SPORT_POLLING, 1); -#else - Serial_write(TxData[0]); -#endif - RxIndex=0; - Serial_write(TxData[1]); - USART3_BASE->CR1 |= USART_CR1_TCIE ; -#ifdef INVERT_SERIAL - TIMER4_BASE->CNT = 0 ; - TIMER4_BASE->CCR1 = 3000 ; - TIMER4_BASE->DIER = TIMER_DIER_CC1IE ; - TIMER4_BASE->CR1 = TIMER_CR1_CEN ; -#endif -} - -bool checkSportPacket() -{ - uint8_t *packet = RxData ; - uint16_t crc = 0 ; - if ( RxIndex < 8 ) - return 0 ; - for ( uint8_t i = 0 ; i<8 ; i += 1 ) - { - crc += packet[i]; - crc += crc >> 8; - crc &= 0x00ff; - } - return (crc == 0x00ff) ; -} - -uint8_t unstuff() -{ - uint8_t i ; - uint8_t j ; - j = 0 ; - for ( i = 0 ; i < RxIndex ; i += 1 ) - { - if ( RxData[i] == BYTESTUFF ) - { - i += 1 ; - RxData[j] = RxData[i] ^ STUFF_MASK ; ; - } - else - RxData[j] = RxData[i] ; - j += 1 ; - } - return j ; -} - -void processSportData(uint8_t *p) -{ - - RxIndex = unstuff() ; - uint8_t x=checkSportPacket() ; - if (x) - { - SportData[sport_idx]=0x7E; - sport_idx =(sport_idx+1) & (MAX_SPORT_BUFFER-1); - SportData[sport_idx]=TxData[1]&0x1F; - sport_idx =(sport_idx+1) & (MAX_SPORT_BUFFER-1); - - for(uint8_t i=0;i<(RxIndex-1);i++) - {//no crc - if(p[i]==START_STOP || p[i]==BYTESTUFF) - {//stuff back - SportData[sport_idx]=BYTESTUFF; - sport_idx =(sport_idx+1) & (MAX_SPORT_BUFFER-1); - SportData[sport_idx]=p[i]^STUFF_MASK; - } - else - SportData[sport_idx]=p[i]; - sport_idx =(sport_idx+1) & (MAX_SPORT_BUFFER-1); - } - sport_rx_index[SportIndexPolling] = 1 ; - ok_to_send=true; - RxIndex =0 ; - } -} - -inline void rx_pause() -{ - USART3_BASE->CR1 &= ~ USART_CR1_RXNEIE; //disable rx interrupt on USART3 -} -inline void rx_resume() -{ - USART3_BASE->CR1 |= USART_CR1_RXNEIE; //enable rx interrupt on USART3 -} -#endif//end SPORT_POLLING - void sportIdle() { #if !defined MULTI_TELEMETRY @@ -792,18 +697,13 @@ void sportIdle() void sportSendFrame() { - #if defined SPORT_POLLING - rx_pause(); - #endif + static uint8_t sport_counter=0; uint8_t i; + sport_counter = (sport_counter + 1) %36; if(telemetry_lost) { - #ifdef SPORT_POLLING - pollSport(); - #else - sportIdle(); - #endif + sportIdle(); return; } if(sport_counter<6) @@ -836,29 +736,22 @@ void sportSendFrame() frame[4] = RxBt;//a1; break; default: - if(sport) + if(Sport_Data) { for (i=0;i= FRSKY_SPORT_PACKET_SIZE) {//8 bytes no crc - if ( sport < FX_BUFFERS ) + if ( Sport_Data < FX_BUFFERS ) { - uint8_t dest = sport * FRSKY_SPORT_PACKET_SIZE ; + uint8_t dest = Sport_Data * FRSKY_SPORT_PACKET_SIZE ; uint8_t i ; - for ( i = 0 ; i < FRSKY_SPORT_PACKET_SIZE ; i += 1 ) + for ( i = 0 ; i < FRSKY_SPORT_PACKET_SIZE ; i++ ) pktx1[dest++] = pktx[i] ; // Triple buffer - sport += 1 ;//ok to send + Sport_Data += 1 ;//ok to send } // else // { @@ -942,64 +836,57 @@ void TelemetryUpdate() t -= h ; if ( t < 32 ) { + debugln("TEL_BUF_FULL %d",t); return ; } +/* else + if(t!=96) + debugln("TEL_BUF %d",t); +*/ #endif - #if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) + #if defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) + uint32_t now = millis(); + if ((IS_SEND_MULTI_STATUS_on || ((now - lastMulti) > MULTI_TIME))&& protocol != PROTO_SCANNER) { - uint32_t now = millis(); - if ((now - lastMulti) > MULTI_TIME) + multi_send_status(); + SEND_MULTI_STATUS_off; + lastMulti = now; + return; + } + #ifdef MULTI_SYNC + if ( inputRefreshRate && (now - lastInputSync) > INPUT_SYNC_TIME ) { - multi_send_status(); - lastMulti = now; + mult_send_inputsync(); + lastInputSync = now; return; } - } + #endif #endif - #if defined SPORT_TELEMETRY - if (protocol==PROTO_FRSKYX) + if (protocol==PROTO_FRSKYX && telemetry_link + #ifdef TELEMETRY_FRSKYX_TO_FRSKYD + && mode_select==MODE_SERIAL + #endif + ) { // FrSkyX for(;;) - { - struct t_fx_rx_frame *p ; + { //Empty buffer + struct t_FrSkyX_RX_Frame *p ; uint8_t count ; - p = &FrskyxRxFrames[NextFxFrameToForward] ; + p = &FrSkyX_RX_Frames[FrSkyX_RX_NextFrame] ; if ( p->valid ) { count = p->count ; for (uint8_t i=0; i < count ; i++) proces_sport_data(p->payload[i]) ; - p->valid = 0 ; // Sent on - NextFxFrameToForward = ( NextFxFrameToForward + 1 ) & 3 ; + p->valid = false ; // Sent + FrSkyX_RX_NextFrame = ( FrSkyX_RX_NextFrame + 1 ) & 3 ; } else - { break ; - } - } - - if(telemetry_link) - { - if(pktt[4] & 0x80) - RX_RSSI=pktt[4] & 0x7F ; - else - RxBt = (pktt[4]<<1) + 1 ; - telemetry_link=0; - } - uint32_t now = micros(); - if ((now - last) > SPORT_TIME) - { - #if defined SPORT_POLLING - processSportData(RxData); //process arrived data before polling - #endif - sportSendFrame(); - #ifdef STM32_BOARD - last=now; - #else - last += SPORT_TIME ; - #endif } + telemetry_link=0; + sportSendFrame(); } #endif // SPORT_TELEMETRY @@ -1027,6 +914,14 @@ void TelemetryUpdate() return; } #endif + #if defined HOTT_FW_TELEMETRY + if(telemetry_link == 2 && protocol == PROTO_HOTT) + { + HOTT_short_frame(); + telemetry_link=0; + return; + } + #endif #if defined SCANNER_TELEMETRY if (telemetry_link && protocol == PROTO_SCANNER) @@ -1037,8 +932,8 @@ void TelemetryUpdate() } #endif - #if defined (FRSKYX_RX_TELEMETRY) || defined(AFHDS2A_RX_TELEMETRY) - if (telemetry_link && (protocol == PROTO_FRSKYX_RX || protocol == PROTO_AFHDS2A_RX)) + #if defined (FRSKY_RX_TELEMETRY) || defined(AFHDS2A_RX_TELEMETRY) + if (telemetry_link && (protocol == PROTO_FRSKY_RX || protocol == PROTO_AFHDS2A_RX)) { receiver_channels_frame(); telemetry_link = 0; @@ -1046,8 +941,9 @@ void TelemetryUpdate() } #endif - if((telemetry_link & 1 )&& protocol != PROTO_FRSKYX) + if( telemetry_link & 1 ) { // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + // FrSkyX telemetry if in PPM frsky_link_frame(); return; } @@ -1168,27 +1064,6 @@ void TelemetryUpdate() #endif { // Transmit interrupt #ifdef STM32_BOARD - #ifdef SPORT_POLLING - if(USART3_BASE->SR & USART_SR_TC) - { - if ( USART3_BASE->CR1 & USART_CR1_TCIE ) - { - USART3_BASE->CR1 &= ~USART_CR1_TCIE ; - TX_INV_off; - } - } - - if(USART3_BASE->SR & USART_SR_RXNE) - { - USART3_BASE->SR &= ~USART_SR_RXNE; - if (RxIndex < 16 ) - { - if(RxData[0]==TxData[0] && RxData[1]==TxData[1]) - RxIndex=0; - RxData[RxIndex++] = USART3_BASE->DR & 0xFF ; - } - } - #endif if(USART3_BASE->SR & USART_SR_TXE) { #endif @@ -1204,10 +1079,7 @@ void TelemetryUpdate() } if (tx_tail == tx_head) { - tx_pause(); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt - #ifdef SPORT_POLLING - rx_resume(); - #endif + tx_pause(); // Check if all data is transmitted. If yes disable transmitter UDRE interrupt. } #ifdef STM32_BOARD } @@ -1439,4 +1311,9 @@ ISR(TIMER0_OVF_vect) #endif // BASH_SERIAL +#else +void telemetry_set_input_sync(uint16_t refreshRate) +{ + (void)refreshRate; +} #endif // TELEMETRY diff --git a/Multiprotocol/V2X2_nrf24l01.ino b/Multiprotocol/V2X2_nrf24l01.ino index 9a34185..bce24bd 100644 --- a/Multiprotocol/V2X2_nrf24l01.ino +++ b/Multiprotocol/V2X2_nrf24l01.ino @@ -264,6 +264,7 @@ uint16_t ReadV2x2() case V202_DATA: if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) return V2X2_PACKET_CHKTIME; + telemetry_set_input_sync(V2X2_PACKET_PERIOD); V2X2_send_packet(0); break; } diff --git a/Multiprotocol/V761_nrf24l01.ino b/Multiprotocol/V761_nrf24l01.ino index b9eac9f..4a8e81d 100644 --- a/Multiprotocol/V761_nrf24l01.ino +++ b/Multiprotocol/V761_nrf24l01.ino @@ -174,6 +174,7 @@ uint16_t V761_callback() } return 15730; case V761_DATA: + telemetry_set_input_sync(V761_PACKET_PERIOD); V761_send_packet(); break; } diff --git a/Multiprotocol/V911S_nrf24l01.ino b/Multiprotocol/V911S_nrf24l01.ino index 13a47dc..2747c9f 100644 --- a/Multiprotocol/V911S_nrf24l01.ino +++ b/Multiprotocol/V911S_nrf24l01.ino @@ -111,7 +111,10 @@ static void __attribute__((unused)) V911S_initialize_txid() uint16_t V911S_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(V911S_PACKET_PERIOD); V911S_send_packet(0); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index ea713e8..ea6efe1 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -104,6 +104,11 @@ #error "The SFHSS forced frequency tuning value is outside of the range -127..127." #endif #endif +#ifdef FORCE_HOTT_TUNING + #if ( FORCE_HOTT_TUNING < -127 ) || ( FORCE_HOTT_TUNING > 127 ) + #error "The HOTT forced frequency tuning value is outside of the range -127..127." + #endif +#endif //A7105 #ifdef FORCE_AFHDS2A_TUNING #if ( FORCE_AFHDS2A_TUNING < -300 ) || ( FORCE_AFHDS2A_TUNING > 300 ) @@ -179,6 +184,7 @@ #ifndef CYRF6936_INSTALLED #undef DEVO_CYRF6936_INO #undef DSM_CYRF6936_INO + #undef HOTT_CC2500_INO #undef J6PRO_CYRF6936_INO #undef WFLY_CYRF6936_INO #undef WK2x01_CYRF6936_INO @@ -194,7 +200,8 @@ #undef HITEC_CC2500_INO #undef XN297L_CC2500_EMU #undef SCANNER_CC2500_INO - #undef FRSKYX_RX_CC2500_INO + #undef FRSKY_RX_CC2500_INO + #undef HOTT_CC2500_INO #endif #ifndef NRF24L01_INSTALLED #undef BAYANG_NRF24L01_INO @@ -247,16 +254,17 @@ #undef NCC1701_HUB_TELEMETRY #undef HUB_TELEMETRY #undef SPORT_TELEMETRY - #undef SPORT_POLLING + #undef SPORT_SEND #undef DSM_TELEMETRY #undef MULTI_STATUS #undef MULTI_TELEMETRY #undef SCANNER_TELEMETRY #undef SCANNER_CC2500_INO - #undef FRSKYX_RX_TELEMETRY - #undef FRSKYX_RX_CC2500_INO + #undef FRSKY_RX_TELEMETRY + #undef FRSKY_RX_CC2500_INO #undef AFHDS2A_RX_TELEMETRY #undef AFHDS2A_RX_A7105_INO + #undef HOTT_FW_TELEMETRY #else #if defined(MULTI_TELEMETRY) && defined(MULTI_STATUS) #error You should choose either MULTI_TELEMETRY or MULTI_STATUS but not both. @@ -265,9 +273,9 @@ #undef SCANNER_TELEMETRY #undef SCANNER_CC2500_INO #endif - #if not defined(FRSKYX_RX_CC2500_INO) || not defined(FRSKYX_RX_TELEMETRY) - #undef FRSKYX_RX_TELEMETRY - #undef FRSKYX_RX_CC2500_INO + #if not defined(FRSKY_RX_CC2500_INO) || not defined(FRSKY_RX_TELEMETRY) + #undef FRSKY_RX_TELEMETRY + #undef FRSKY_RX_CC2500_INO #endif #if not defined(AFHDS2A_RX_A7105_INO) || not defined(AFHDS2A_RX_TELEMETRY) #undef AFHDS2A_RX_TELEMETRY @@ -301,24 +309,34 @@ #endif #if not defined(FRSKYX_CC2500_INO) #undef SPORT_TELEMETRY - #undef SPORT_POLLING + #undef SPORT_SEND #endif - #if not defined (SPORT_TELEMETRY) || not defined (STM32_BOARD) - #undef SPORT_POLLING - #endif - #if defined SPORT_POLLING && not defined INVERT_TELEMETRY - #error SPORT_POLLING has been defined but not INVERT_TELEMETRY. They should be both enabled to work. + #if not defined (SPORT_TELEMETRY) + #undef SPORT_SEND #endif #if not defined(DSM_CYRF6936_INO) #undef DSM_TELEMETRY #endif - #if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKYX_RX_TELEMETRY) + #if not defined(HOTT_CC2500_INO) + #undef HOTT_FW_TELEMETRY + #endif + #if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) #undef TELEMETRY #undef INVERT_TELEMETRY - #undef SPORT_POLLING #endif #endif +#ifdef SPORT_TELEMETRY + #define SPORT_SEND +#endif + +#if not defined(MULTI_TELEMETRY) + #if not defined(STM32_BOARD) + #undef MULTI_SYNC + #endif + #undef MULTI_NAMES +#endif + //Make sure TX is defined correctly #ifndef AILERON #error You must select a correct channel order. diff --git a/Multiprotocol/WFLY_cyrf6936.ino b/Multiprotocol/WFLY_cyrf6936.ino index baacbcd..62fd66e 100644 --- a/Multiprotocol/WFLY_cyrf6936.ino +++ b/Multiprotocol/WFLY_cyrf6936.ino @@ -194,25 +194,25 @@ uint16_t ReadWFLY() debugln("L=%02X",len) if(len==0x10) { - CYRF_ReadDataPacketLen(pkt, len); + CYRF_ReadDataPacketLen(packet_in, len); debug("RX="); for(uint8_t i=0;i<0x0F;i++) { - debug(" %02X",pkt[i]); - if(pkt[i]==packet[i]) + debug(" %02X",packet_in[i]); + if(packet_in[i]==packet[i]) check++; // Verify quickly the content - sum+=pkt[i]; + sum+=packet_in[i]; } - debugln(" %02X",pkt[15]); - if(sum==pkt[15] && check>=10) + debugln(" %02X",packet_in[15]); + if(sum==packet_in[15] && check>=10) { // Good packet received - if(pkt[2]==0x64) + if(packet_in[2]==0x64) { // Switch to normal mode BIND_DONE; phase=WFLY_PREP_DATA; return 10000; } - memcpy((void *)packet,(void *)pkt,0x10); // Send back to the RX what we've just received with no modifications + memcpy((void *)packet,(void *)packet_in,0x10); // Send back to the RX what we've just received with no modifications } phase=WFLY_BIND_TX; return 200; @@ -232,6 +232,7 @@ uint16_t ReadWFLY() packet_count=0; phase++; case WFLY_DATA: + telemetry_set_input_sync(5371); start=micros(); while ((uint8_t)((uint8_t)micros()-(uint8_t)start) < 200) if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00) diff --git a/Multiprotocol/WK2x01_cyrf6936.ino b/Multiprotocol/WK2x01_cyrf6936.ino index 2924f13..748ee8d 100644 --- a/Multiprotocol/WK2x01_cyrf6936.ino +++ b/Multiprotocol/WK2x01_cyrf6936.ino @@ -435,6 +435,7 @@ uint16_t WK_cb() { if (packet_sent == 0) { + telemetry_set_input_sync(2800); packet_sent = 1; if(sub_protocol == WK2801) WK_BuildPacket_2801(); diff --git a/Multiprotocol/XN297Dump_nrf24l01.ino b/Multiprotocol/XN297Dump_nrf24l01.ino index 2ff6033..7c07918 100644 --- a/Multiprotocol/XN297Dump_nrf24l01.ino +++ b/Multiprotocol/XN297Dump_nrf24l01.ino @@ -176,6 +176,10 @@ static void __attribute__((unused)) XN297Dump_overflow() static uint16_t XN297Dump_callback() { static uint32_t time=0; + + //!!!Blocking mode protocol!!! + TX_MAIN_PAUSE_off; + tx_resume(); while(1) { if(option==0xFF && bind_counter>XN297DUMP_PERIOD_SCAN) diff --git a/Multiprotocol/YD717_nrf24l01.ino b/Multiprotocol/YD717_nrf24l01.ino index 2fdeda4..1fcac90 100644 --- a/Multiprotocol/YD717_nrf24l01.ino +++ b/Multiprotocol/YD717_nrf24l01.ino @@ -155,7 +155,10 @@ static void __attribute__((unused)) yd717_init() uint16_t yd717_callback() { if(IS_BIND_DONE) + { + telemetry_set_input_sync(YD717_PACKET_PERIOD); yd717_send_packet(0); + } else { if (bind_counter == 0) diff --git a/Multiprotocol/ZSX_nrf24l01.ino b/Multiprotocol/ZSX_nrf24l01.ino index 3e8f6be..eedd6a1 100644 --- a/Multiprotocol/ZSX_nrf24l01.ino +++ b/Multiprotocol/ZSX_nrf24l01.ino @@ -80,6 +80,7 @@ static void __attribute__((unused)) ZSX_init() uint16_t ZSX_callback() { + telemetry_set_input_sync(ZSX_PACKET_PERIOD); if(IS_BIND_IN_PROGRESS) if(--bind_counter==0) { diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index 8c4b757..360c658 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -54,7 +54,7 @@ /*** AUTO BIND ***/ // Also referred as "Bind on powerup" /*****************/ //Bind from channel enables you to bind when a specified channel is going from low to high. This feature is only active -// if you specify AUTOBIND in PPM mode or set AutoBind to YES for serial mode. It also requires that the throttle channel is low. +// if you specify AUTOBIND in PPM mode or set AutoBind to YES for serial mode. //Comment to globaly disable the bind feature from a channel. #define ENABLE_BIND_CH //Set the channel number used for bind. Default is 16. @@ -87,17 +87,18 @@ //#define ORANGE_TX_BLUE /** CC2500 Fine Frequency Tuning **/ -//For optimal performance the CC2500 RF module used by the FrSkyD, FrSkyV, FrSkyX, SFHSS, CORONA, Redpine and Hitec protocols needs to be tuned for each protocol. -//Initial tuning should be done via the radio menu with a genuine FrSky/Futaba/CORONA/Hitec/Redpine receiver. +//For optimal performance the CC2500 RF module used by the CORONA, FrSkyD, FrSkyV, FrSkyX, Hitec, HoTT, SFHSS and Redpine protocols needs to be tuned for each protocol. +//Initial tuning should be done via the radio menu with a genuine CORONA/FrSky/Hitec/HoTT/Futaba/Redpine receiver. //Once a good tuning value is found it can be set here and will override the radio's 'option' setting for all existing and new models which use that protocol. //For more information: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/tree/master/docs/Frequency_Tuning.md //Uncomment the lines below (remove the "//") and set an appropriate value (replace the "0") to enable. Valid range is -127 to +127. +//#define FORCE_CORONA_TUNING 0 //#define FORCE_FRSKYD_TUNING 0 //#define FORCE_FRSKYV_TUNING 0 //#define FORCE_FRSKYX_TUNING 0 //#define FORCE_SFHSS_TUNING 0 -//#define FORCE_CORONA_TUNING 0 //#define FORCE_HITEC_TUNING 0 +//#define FORCE_HOTT_TUNING 0 //#define FORCE_REDPINE_TUNING 0 /** A7105 Fine Frequency Tuning **/ @@ -176,8 +177,9 @@ #define FRSKYD_CC2500_INO #define FRSKYV_CC2500_INO #define FRSKYX_CC2500_INO -#define FRSKYX_RX_CC2500_INO +#define FRSKY_RX_CC2500_INO #define HITEC_CC2500_INO +#define HOTT_CC2500_INO #define SCANNER_CC2500_INO #define SFHSS_CC2500_INO #define REDPINE_CC2500_INO @@ -222,6 +224,12 @@ /*** PROTOCOLS SETTINGS ***/ /***************************/ +//FrSkyX specific setting +//----------------------- +//EU LBT setting: if commented the TX will not check if a channel is busy before transmitting. +//!!! Work in progress !!! it's currently known to cause telemerty issues. Enable only if you know what you are doing. +//#define FRSKYX_LBT + //DSM specific settings //--------------------- //The DSM protocol is using by default the Spektrum throw of 1100..1900us @100% and 1000..2000us @125%. @@ -258,24 +266,31 @@ //Comment to invert the polarity of the output telemetry serial signal. //This function takes quite some flash space and processor power on an atmega. -//For OpenTX it must be uncommented. -//On a 9XR_PRO running ersky9x both commented and uncommented will work depending on the radio setting Invert COM1 under the Telemetry menu. -//On other addon/replacement boards like the 9xtreme board or the Ar9x board running ersky9x, you need to uncomment the line below. +//For a Taranis/T16 with an external module it must be uncommented. For a T16 internal module it must be commented. +//A 9XR_PRO running erskyTX will work with both commented and uncommented depending on the radio setting Invert COM1 under the Telemetry menu. +//On other addon/replacement boards like the 9xtreme board or the Ar9x board running erskyTX, you need to uncomment the line below. //For er9x it depends if you have an inveter mod or not on the telemetry pin. If you don't have an inverter comment this line. +//=>OpenTX 2.3.2 with a STM32 or OrangeRX module this setting can be ignored. #define INVERT_TELEMETRY +//For STM32 and OrangeRX modules, comment to prevent the TX from forcing the serial telemetry polarity normal/invert. +#define INVERT_TELEMETRY_TX -//Comment if you don't want to send Multi status telemetry frames (Protocol available, Bind in progress, version...) -//Use with er9x/erksy9x, for OpenTX MULTI_TELEMETRY below is preferred instead +//Uncomment if you want to send Multi status telemetry frames (Protocol available, Bind in progress, version...) +//Use with er9x/erskyTX, for OpenTX you must select MULTI_TELEMETRY below //#define MULTI_STATUS -//Uncomment to send Multi status and allow OpenTX to autodetect the telemetry format -//Supported by OpenTX version 2.2 RC9 and newer. NOT supported by er9x/ersky9x use MULTI_STATUS instead. +//Sends Multi status and allow OpenTX to autodetect the telemetry format. Comment to disable. +//Supported by OpenTX version 2.2 RC9 and newer. NOT supported by er9x/erskyTX use MULTI_STATUS instead. #define MULTI_TELEMETRY +//Send to OpenTX the current protocol and subprotocol names. Comment to disable. +#define MULTI_NAMES +//Work in progress: Sync OpenTX frames with the current protocol timing. This feature is only available on the STM32 module. Uncomment to enable. +//#define MULTI_SYNC //Comment a line to disable a specific protocol telemetry -#define DSM_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by er9x, ersky9x and OpenTX -#define SPORT_TELEMETRY // Use FrSkyX SPORT format to send telemetry to TX -#define AFHDS2A_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by ersky9x and OpenTX +#define DSM_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by er9x, erskyTX and OpenTX +#define SPORT_TELEMETRY // Use FrSkyX format to send/receive telemetry +#define AFHDS2A_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by erskyTX and OpenTX #define AFHDS2A_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to TX like er9x #define HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define BAYANG_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX @@ -283,18 +298,12 @@ #define HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX -#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, ersky9x and OpenTX -#define HITEC_FW_TELEMETRY // Under development: Forward received telemetry packets to be decoded by ersky9x and OpenTX +#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, erskyTX and OpenTX +#define HITEC_FW_TELEMETRY // Forward received telemetry packets to be decoded by erskyTX and OpenTX #define SCANNER_TELEMETRY // Forward spectrum scanner data to TX -#define FRSKYX_RX_TELEMETRY // Forward channels data to TX +#define FRSKY_RX_TELEMETRY // Forward channels data to TX #define AFHDS2A_RX_TELEMETRY // Forward channels data to TX - -//SPORT_POLLING is an implementation of the same polling routine as XJT module for sport telemetry bidirectional communication. -//This is useful for passing sport control frames from TX to RX(ex: changing Betaflight PID or VTX channels on the fly using LUA scripts with OpentX). -//Using this feature requires to uncomment INVERT_TELEMETRY as this TX output on telemetry pin only inverted signal. -//!!!! This is a work in progress!!! Do not enable unless you want to test and report -//#define SPORT_POLLING - +#define HOTT_FW_TELEMETRY // Forward received telemetry packets to be decoded by erskyTX and OpenTX /****************************/ /*** SERIAL MODE SETTINGS ***/ @@ -345,6 +354,10 @@ // The default value is 16 to receive all possible channels but you might want to filter some "bad" channels from the PPM frame like the ones above 6 on the Walkera PL0811. #define MAX_PPM_CHANNELS 16 +/** Telemetry **/ +//Send simple FrSkyX telemetry using the FrSkyD telemetry format +#define TELEMETRY_FRSKYX_TO_FRSKYD + /** Rotary Switch Protocol Selector Settings **/ //The table below indicates which protocol to run when a specific position on the rotary switch has been selected. //All fields and values are explained below. Everything is configurable from here like in the Serial mode. @@ -550,9 +563,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { CH_8 EU_16 EU_8 - PROTO_FRSKYX_RX - FRSKYX_FCC - FRSKYX_LBT + PROTO_FRSKY_RX + NONE PROTO_FY326 FY326 FY319 @@ -578,6 +590,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { JJRCX1 X5C1 FQ777_951 + PROTO_HOTT + NONE PROTO_HUBSAN H107 H301 diff --git a/Protocols_Details.md b/Protocols_Details.md index ae677cc..c859a38 100644 --- a/Protocols_Details.md +++ b/Protocols_Details.md @@ -29,7 +29,7 @@ Here are detailed descriptions of every supported protocols (sorted by RF module ## Protocol selection in PPM mode The protocol selection is based on 2 parameters: * selection switch: this is the rotary switch on the module numbered from 0 to 15 - - switch position 0 is to select the Serial mode for er9x/ersky9x/OpenTX radio + - switch position 0 is to select the Serial mode for er9x/erskyTX/OpenTX radio - switch position 15 is to select the bank - switch position 1..14 will select the protocol 1..14 in the bank *X* * banks are used to increase the amount of accessible protocols by the switch. There are up to 5 banks giving acces to up to 70 protocol entries (5 * 14). To modify or verify which bank is currenlty active do the following: @@ -56,7 +56,7 @@ Notes: Serial mode is selected by placing the rotary switch to position 0 before power on of the radio. You've upgraded the module but the radio does not display the name of the protocol you are loking for: - * ersky9x: + * erskyTX: - Place the file [Multi.txt](https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module/master/Multiprotocol/Multi.txt) (which is part of the MPM source files) on the root of your SD card. - If the entry still does not appear or is broken, [upgrade](https://openrcforums.com/forum/viewtopic.php?f=7&t=4676) to version R222d2 or newer. * OpenTX: @@ -84,6 +84,7 @@ CFlie|38|CFlie||||||||NRF24L01| [ESky150](Protocols_Details.md#ESKY150---35)|35|ESKY150||||||||NRF24L01| [Flysky](Protocols_Details.md#FLYSKY---1)|1|Flysky|V9x9|V6x6|V912|CX20||||A7105| [Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)|28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|||||A7105| +[Flysky AFHDS2A RX](Protocols_Details.md#FLYSKY-AFHDS2A-RX---56)|56|||||||||A7105| [Flyzone](Protocols_Details.md#FLYZONE---53)|53|FZ410||||||||A7105| [FQ777](Protocols_Details.md#FQ777---23)|23|FQ777||||||||NRF24L01|SSV7241 [FrskyD](Protocols_Details.md#FRSKYD---3)|3|FrskyD||||||||CC2500| @@ -97,6 +98,7 @@ CFlie|38|CFlie||||||||NRF24L01| [Hisky](Protocols_Details.md#HISKY---4)|4|Hisky|HK310|||||||NRF24L01| [Hitec](Protocols_Details.md#HITEC---39)|39|OPT_FW|OPT_HUB|MINIMA||||||CC2500| [Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|||||NRF24L01|XN297 +[HoTT](Protocols_Details.md#HoTT---57)|57|||||||||CC2500| [Hubsan](Protocols_Details.md#HUBSAN---2)|2|H107|H301|H501||||||A7105| [J6Pro](Protocols_Details.md#J6Pro---22)|22|J6PRO||||||||CYRF6936| [KF606](Protocols_Details.md#KF606---49)|49|KF606*||||||||NRF24L01|XN297 @@ -165,11 +167,11 @@ Extended limits and failsafe supported Telemetry enabled protocol: - by defaut using FrSky Hub protocol (for example er9x): RX(A1), battery voltage FS-CVT01(A2) and RX&TX RSSI - - if using ersky9x and OpenTX: full telemetry information available + - if using erskyTX and OpenTX: full telemetry information available Option is used to change the servo refresh rate. A value of 0 gives 50Hz (min), 70 gives 400Hz (max). Specific refresh rate value can be calculated like this option=(refresh_rate-50)/5. -**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 16 AFHDS2A RXs are supported.** +**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 64 AFHDS2A RXs are supported.** OpenTX suggested RSSI alarm threshold settings (Telemetry tab): Low=15, Critical=12. @@ -188,6 +190,15 @@ Note that the RX ouput will be AETR whatever the input channel order is. ### Sub_protocol PWM_SBUS - *2* ### Sub_protocol PPM_SBUS - *3* +## FLYSKY AFHDS2A RX - *56* +The Flysky AFHDS2A receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,... + +Available in OpenTX 2.3.2, Trainer Mode Master/Multi + +Extended limits supported + +Low power: enable/disable the LNA stage on the RF component to use depending on the distance with the TX. + ## FLYZONE - *53* Models using the Flyzone FZ-410 TX: Fokker D.VII Micro EP RTF @@ -345,6 +356,8 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8 ## FRSKYX_RX - *55* The FrSkyX receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,... +Available in OpenTX 2.3.2, Trainer Mode Master/Multi + Extended limits supported Option for this protocol corresponds to fine frequency tuning. @@ -383,20 +396,40 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9 ### Sub_protocol OPT_FW - *0* OPTIMA RXs -Full telemetry available on ersky9x and OpenTX. This is still a WIP. +Full telemetry available on OpenTX 2.3.2+, still in progress for erskyTx. **The TX must be close to the RX for the bind negotiation to complete successfully** ### Sub_protocol OPT_HUB - *1* OPTIMA RXs -Basic telemetry using FrSky Hub on er9x, ersky9x, OpenTX and any radio with FrSky telemetry support with RX voltage, VOLT2 voltage, TX RSSI and TX LQI. +Basic telemetry using FrSky Hub on er9x, erskyTX, OpenTX and any radio with FrSky telemetry support with RX voltage, VOLT2 voltage, TX RSSI and TX LQI. **The TX must be close to the RX for the bind negotiation to complete successfully** ### Sub_protocol MINIMA - *2* MINIMA, MICRO and RED receivers +## HoTT - *57* +Models: Graupner HoTT receivers (tested on GR-12L and GR-16L). + +Extended limits and failsafe supported + +**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 64 HoTT RXs are supported.** + +**Failsafe MUST be configured once with the desired channel values (hold or position) while the RX is up (wait 10+sec for the RX to learn the config) and then failsafe MUST be set to RX/Receiver otherwise the servos will jitter!!!** + +The RX features configuration are done using the OpenTX script "Graupner HoTT.lua" . + +Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable. +Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it. + +CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 +---|---|---|---|---|---|---|---|---|----|----|---- +CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 + +Basic telemetry is available on OpenTX 2.3.2+ with RX voltage, Rx temperature, RX RSSI, RX LQI, TX RSSI and TX LQI. + ## SFHSS - *21* Models: Futaba RXs and XK models. @@ -550,9 +583,9 @@ DSMX, Resolution 2048, refresh rate 11ms ### Sub_protocol AUTO - *4* The "AUTO" feature enables the TX to automatically choose what are the best settings for your DSM RX and update your model protocol settings accordingly. -The current radio firmware which are able to use the "AUTO" feature are ersky9x (9XR Pro, 9Xtreme, Taranis, ...), er9x for M128(9XR)&M2561 and OpenTX (mostly Taranis). +The current radio firmware which are able to use the "AUTO" feature are erskyTX (9XR Pro, 9Xtreme, Taranis, ...), er9x for M128(9XR)&M2561 and OpenTX (mostly Taranis). 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 ersky9x you can set "Invert COM1" accordinlgy. +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. ## J6Pro - *22* diff --git a/docs/Frequency_Tuning.md b/docs/Frequency_Tuning.md index 590296f..1294505 100644 --- a/docs/Frequency_Tuning.md +++ b/docs/Frequency_Tuning.md @@ -8,16 +8,17 @@ The protocols which require frequency tuning are: * **S-FHSS** (e.g. Futaba S-FHSS receivers) * **Corona** (e.g. Corona V1 FSS, Corona V2 DSSS CR8D/CR6D/CR4D and FlyDream IS-4R/IS-4R0 receivers) * **Hitec** (e.g. Optima, Minima, Micro and RED receivers) +* **HoTT** (e.g. Graupner receivers) There is a [video](#video) at the end of this page which gives an example of the tuning process. ## More information -Original FrSky, Futaba, Corona and Hitec receivers have been frequency-tuned by the manufacturer at the factory. Because of variations in the oscillator crystals used in multiprotocol modules it is necessary to fine-tune the module to match the manufacturer frequencies. +Original FrSky, Futaba, Corona Hitec and HoTT receivers have been frequency-tuned by the manufacturer at the factory. Because of variations in the oscillator crystals used in multiprotocol modules it is necessary to fine-tune the module to match the manufacturer frequencies. 'Compatible' receivers suffer the same variation in crystal oscillators as multiprotocol modules, but have to be compatible with genuine (manufacturer-tuned) transmitters so they will typically have auto-tuning built in, and will self-tune to the radio's frequency when they are bound. ## Fine-tuning procedure -**Note:** For best results, the fine-tuning procedure should be carried out with a genuine FrSky/Futaba/Corona/Hitec receiver. +**Note:** For best results, the fine-tuning procedure should be carried out with a genuine FrSky/Futaba/Corona/Hitec/HoTT receiver. The procedure can be performed in serial or PPM mode, but is easier with in serial mode where the effect of the change can be seen in real-time. @@ -49,7 +50,7 @@ Connection is lost at -73 and +35; the median is -19: ### Finally Once the **Freq** value is known it should be applied to all other models which use this protocol and, if they were previously bound, the receivers must be re-bound. -For convenience this can be done in the `_Config.h` (or `_MyConfig.h`) configuration file. +For convenience this can be applied once for all per protocol using the FORCE commands described below in `_Config.h` (or `_MyConfig.h`) configuration file. #### Forced tuning values Once known-good tuning values have been determined, they can be stored in the configuration file to be automatically applied to all models which use the given protocol. @@ -73,6 +74,7 @@ These settings can also be used to force different tuning values for different m //#define FORCE_SFHSS_TUNING 0 //#define FORCE_CORONA_TUNING 0 //#define FORCE_HITEC_TUNING 0 +//#define FORCE_HOTT_TUNING 0 ``` ## Video