diff --git a/Multiprotocol/FrSkyDVX_common.ino b/Multiprotocol/FrSkyDVX_common.ino index 8f257ed..9293634 100644 --- a/Multiprotocol/FrSkyDVX_common.ino +++ b/Multiprotocol/FrSkyDVX_common.ino @@ -17,7 +17,7 @@ /** 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[]={ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, @@ -74,7 +74,7 @@ void Frsky_init_hop(void) /******************************/ /** FrSky V, D and X routines **/ /******************************/ -#if defined(FRSKYV_CC2500_INO) || defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) +#if defined(FRSKYV_CC2500_INO) || defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) const PROGMEM uint8_t FRSKY_common_startreg_cc2500_conf[]= { CC2500_02_IOCFG0 , CC2500_00_IOCFG2 , @@ -119,7 +119,7 @@ void Frsky_init_hop(void) /*15_DEVIATN*/ 0x41 }; #endif - #if defined(FRSKYD_CC2500_INO) + #if defined(FRSKYD_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) const PROGMEM uint8_t FRSKYD_cc2500_conf[]= { /*02_IOCFG0*/ 0x06 , /*00_IOCFG2*/ 0x06 , @@ -142,7 +142,7 @@ void Frsky_init_hop(void) /*15_DEVIATN*/ 0x42 }; #endif - #if defined(FRSKYX_CC2500_INO) + #if defined(FRSKYX_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) const PROGMEM uint8_t FRSKYX_cc2500_conf[]= { //FRSKYX /*02_IOCFG0*/ 0x06 , diff --git a/Multiprotocol/FrSkyX_Rx_cc2500.ino b/Multiprotocol/FrSkyX_Rx_cc2500.ino deleted file mode 100644 index a14f490..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(&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 - packet_in[idx++] = RX_LQI; - packet_in[idx++] = RX_RSSI; - packet_in[idx++] = 0; // start channel - packet_in[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) { - packet_in[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/FrSky_Rx_cc2500.ino b/Multiprotocol/FrSky_Rx_cc2500.ino new file mode 100644 index 0000000..09e3bbf --- /dev/null +++ b/Multiprotocol/FrSky_Rx_cc2500.ino @@ -0,0 +1,365 @@ +/* + 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 + + enum { + FRSKY_RX_TUNE_START, + FRSKY_RX_TUNE_LOW, + FRSKY_RX_TUNE_HIGH, + FRSKY_RX_BIND, + FRSKY_RX_DATA, + }; + + static uint8_t frsky_rx_chanskip; + static uint8_t frsky_rx_disable_lna; + static uint8_t frsky_rx_data_started; + static int8_t frsky_rx_finetune; + static uint16_t frsky_rx_rc_chan[16]; + +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_Reset(); + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, 0); // bind channel + switch (sub_protocol) { + case FRSKY_RX_D16FCC: + FRSKY_init_cc2500(FRSKYX_cc2500_conf); + break; + case FRSKY_RX_D16LBT: + FRSKY_init_cc2500(FRSKYXEU_cc2500_conf); + break; + case FRSKY_RX_D8: + FRSKY_init_cc2500(FRSKYD_cc2500_conf); + CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // always check address + CC2500_WriteReg(CC2500_09_ADDR, 0x03); // bind address + CC2500_WriteReg(CC2500_23_FSCAL3, 0x89); // fixed FSCAL3 ? + break; + } + frsky_rx_disable_lna = IS_POWER_FLAG_on; + CC2500_SetTxRxMode(frsky_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(sub_protocol == FRSKY_RX_D8) + CC2500_WriteReg(CC2500_23_FSCAL3, 0x89); + else + 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() +{ + if (sub_protocol == FRSKY_RX_D8) + return 1; + 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 (sub_protocol == FRSKY_RX_D16FCC || sub_protocol == 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++) { + uint8_t shifted = (raw_channel[i] & 0x800)>0; + uint16_t channel_value = raw_channel[i] & 0x7FF; + if (channel_value < 64) + frsky_rx_rc_chan[shifted ? i + 8 : i] = 0; + else + frsky_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; + frsky_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++] = sub_protocol == FRSKY_RX_D8 ? 8 : 16; // number of channels in packet + + // pack channels + for (i = 0; i < packet_in[3]; i++) { + bits |= ((uint32_t)frsky_rx_rc_chan[i]) << bitsavailable; + bitsavailable += 11; + while (bitsavailable >= 8) { + packet_in[idx++] = bits & 0xff; + bits >>= 8; + bitsavailable -= 8; + } + } +} + +uint16_t initFrSky_Rx() +{ + const uint8_t frsky_rx_length[] = {FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D8_LENGTH}; + packet_length = frsky_rx_length[sub_protocol]; + frsky_rx_initialise(); + state = 0; + frsky_rx_chanskip = 1; + hopping_frequency_no = 0; + frsky_rx_data_started = 0; + frsky_rx_finetune = 0; + telemetry_link = 0; + for(uint8_t ch=0; ch= 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 (frsky_rx_disable_lna != IS_POWER_FLAG_on) { + frsky_rx_disable_lna = IS_POWER_FLAG_on; + CC2500_SetTxRxMode(frsky_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_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) + if (sub_protocol == FRSKY_RX_D16FCC || sub_protocol == FRSKY_RX_D16LBT) + 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 txid and channel list + uint16_t temp = FRSKY_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++, 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() && (sub_protocol == 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 (sub_protocol == FRSKY_RX_D16FCC || sub_protocol == 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((sub_protocol == FRSKY_RX_D8 || packet[7] == 0) && telemetry_link == 0) { // send channels to TX + frsky_rx_build_telemetry_packet(); + telemetry_link = 1; + } + frsky_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 + frsky_rx_chanskip) % 47; + frsky_rx_set_channel(hopping_frequency_no); + if(frsky_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/Multi.txt b/Multiprotocol/Multi.txt index b866d0b..2542135 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -52,6 +52,6 @@ 52,ZSX,280 53,Flyzone,FZ-410 54,Scanner -55,FrskyX_RX,FCC,EU_LBT +55,Frsky_RX,D16FCC,D16LBT,D8 56,AFHDS2A_RX 63,XN_DUMP,250K,1M,2M diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index dcad97a..e867a25 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -81,7 +81,7 @@ 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_XN297DUMP = 63, // =>NRF24L01 }; @@ -290,10 +290,11 @@ enum TRAXXAS { RX6519 = 0, }; -enum FRSKYX_RX +enum FRSKY_RX { - FRSKYX_FCC = 0, - FRSKYX_LBT + FRSKY_RX_D16FCC= 0, + FRSKY_RX_D16LBT, + FRSKY_RX_D8 }; #define NONE 0 @@ -594,7 +595,7 @@ 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 FRSKY_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 AFHDS2A_EEPROM_OFFSET2 249 // RX ID, 4 bytes per model id, end is 249+192=441 //#define CONFIG_EEPROM_OFFSET 441 // Current configuration of the multimodule @@ -670,7 +671,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- ZSX 52 FLYZONE 53 SCANNER 54 - FRSKYX_RX 55 + FRSKY_RX 55 BindBit=> 0x80 1=Bind/0=No AutoBindBit=> 0x40 1=Yes /0=No RangeCheck=> 0x20 1=Yes /0=No @@ -812,9 +813,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- RED_SLOW 1 sub_protocol==TRAXXAS RX6519 0 - sub_protocol==FRSKYX_RX - FCC 0 - LBT 1 + sub_protocol==FRSKY_RX + FRSKY_RX_D16FCC 0 + FRSKY_RX_D16LBT 1 + FRSKY_RX_D8 2 Power value => 0x80 0=High/1=Low Stream[3] = option_protocol; diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 3494c6f..e65809b 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -668,7 +668,7 @@ 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)) #endif if(IS_DISABLE_TELEM_off && !(protocol==PROTO_XN297DUMP)) TelemetryUpdate(); @@ -1086,12 +1086,12 @@ static void protocol_init() remote_callback = Scanner_callback; break; #endif - #if defined(FRSKYX_RX_CC2500_INO) - case PROTO_FRSKYX_RX: + #if defined(FRSKY_RX_CC2500_INO) + case PROTO_FRSKY_RX: PE1_off; PE2_on; //antenna RF2 - next_callback = initFrSkyX_Rx(); - remote_callback = FrSkyX_Rx_callback; + next_callback = initFrSky_Rx(); + remote_callback = FrSky_Rx_callback; break; #endif #endif diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index 3ae816c..2d19b15 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -226,7 +226,7 @@ static void multi_send_status() } #endif -#if defined (FRSKYX_RX_TELEMETRY) || defined (AFHDS2A_RX_TELEMETRY) +#if defined (FRSKY_RX_TELEMETRY) || defined (AFHDS2A_RX_TELEMETRY) void receiver_channels_frame() { uint16_t len = packet_in[3] * 11; // 11 bit per channel @@ -861,8 +861,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; diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index 51a2116..aa11e91 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -194,7 +194,7 @@ #undef HITEC_CC2500_INO #undef XN297L_CC2500_EMU #undef SCANNER_CC2500_INO - #undef FRSKYX_RX_CC2500_INO + #undef FRSKY_RX_CC2500_INO #endif #ifndef NRF24L01_INSTALLED #undef BAYANG_NRF24L01_INO @@ -253,8 +253,8 @@ #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 #else @@ -265,9 +265,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 @@ -309,7 +309,7 @@ #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(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) #undef TELEMETRY #undef INVERT_TELEMETRY #endif diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index 3efd302..3767a01 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -176,7 +176,7 @@ #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 SCANNER_CC2500_INO #define SFHSS_CC2500_INO @@ -288,7 +288,7 @@ #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 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 /****************************/ @@ -545,7 +545,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { CH_8 EU_16 EU_8 - PROTO_FRSKYX_RX + PROTO_FRSKY_RX FRSKYX_FCC FRSKYX_LBT PROTO_FY326