From e038c49ae9d78eb49fbc48db28d33a870814dfda Mon Sep 17 00:00:00 2001 From: goebish Date: Mon, 23 Sep 2019 08:11:06 +0200 Subject: [PATCH] Protocol FrskyX D16 RX frequency auto-tune (#270) * Add autotune during bind * Fix data phase --- Multiprotocol/FrSkyX_Rx_cc2500.ino | 114 +++++++++++++++++++++++------ Multiprotocol/Multiprotocol.h | 2 +- 2 files changed, 94 insertions(+), 22 deletions(-) diff --git a/Multiprotocol/FrSkyX_Rx_cc2500.ino b/Multiprotocol/FrSkyX_Rx_cc2500.ino index a83e7e5..958ba93 100644 --- a/Multiprotocol/FrSkyX_Rx_cc2500.ino +++ b/Multiprotocol/FrSkyX_Rx_cc2500.ino @@ -17,10 +17,13 @@ #include "iface_cc2500.h" - #define FRSKYX_FCC_LENGTH 30+2 - #define FRSKYX_LBT_LENGTH 33+2 + #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, }; @@ -28,6 +31,14 @@ 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(); @@ -36,7 +47,7 @@ static void __attribute__((unused)) FrSkyX_Rx_initialise() { CC2500_WriteReg(CC2500_18_MCSM0, 0x18); CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x04); CC2500_WriteReg(CC2500_3E_PATABLE, 0xFF); - CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack + CC2500_WriteReg(CC2500_0C_FSCTRL0, 0); CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); CC2500_WriteReg(CC2500_14_MDMCFG0, 0x7A); @@ -88,9 +99,7 @@ static void __attribute__((unused)) FrSkyX_Rx_initialise() { frskyx_rx_disable_lna = IS_POWER_FLAG_on; CC2500_SetTxRxMode(frskyx_rx_disable_lna ? TXRX_OFF : RX_EN); // lna disable / enable - CC2500_Strobe(CC2500_SIDLE); - CC2500_Strobe(CC2500_SFRX); - CC2500_Strobe(CC2500_SRX); + frskyx_rx_strobe_rx(); CC2500_WriteReg(CC2500_0A_CHANNR, 0); // bind channel delayMicroseconds(1000); // wait for RX to activate } @@ -99,16 +108,12 @@ 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]); - CC2500_Strobe(CC2500_SIDLE); - CC2500_Strobe(CC2500_SFRX); - CC2500_Strobe(CC2500_SRX); + frskyx_rx_strobe_rx(); } static void __attribute__((unused)) frskyx_rx_calibrate() { - CC2500_Strobe(CC2500_SIDLE); - CC2500_Strobe(CC2500_SFRX); - CC2500_Strobe(CC2500_SRX); + frskyx_rx_strobe_rx(); for (unsigned c = 0; c < 47; c++) { CC2500_Strobe(CC2500_SIDLE); @@ -178,21 +183,27 @@ uint16_t initFrSkyX_Rx() 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_BIND; + phase = FRSKYX_RX_TUNE_START; } else { uint16_t temp = FRSKYX_RX_EEPROM_OFFSET; rx_tx_addr[0] = eeprom_read_byte(temp++); rx_tx_addr[1] = eeprom_read_byte(temp++); rx_tx_addr[2] = eeprom_read_byte(temp++); + frskyx_rx_finetune = eeprom_read_byte(temp++); for(uint8_t ch = 0; ch < 47; ch++) hopping_frequency[ch] = eeprom_read_byte(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; } @@ -205,19 +216,81 @@ 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) - { - CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack + + 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: - len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if(len >= packet_length) { CC2500_ReadData(packet, packet_length); if (frskyx_rx_check_crc()) { @@ -243,17 +316,16 @@ uint16_t FrSkyX_Rx_callback() 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; } - CC2500_Strobe(CC2500_SIDLE); - CC2500_Strobe(CC2500_SFRX); - CC2500_Strobe(CC2500_SRX); + frskyx_rx_strobe_rx(); } return 1000; + case FRSKYX_RX_DATA: - len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; 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()) { diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index de95ed5..a3e2614 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -574,7 +574,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 + (47) channels + (1) freq_tune, 51 bytes per model, end is 178+51=229 +#define FRSKYX_RX_EEPROM_OFFSET 178 // (3) TX ID + (1) freq_tune + (47) channels, 51 bytes per model, end is 178+51=229 //#define CONFIG_EEPROM_OFFSET 210 // Current configuration of the multimodule //****************************************