mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-02-04 20:58:10 +00:00
618 lines
18 KiB
C++
618 lines
18 KiB
C++
/*
|
|
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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#if defined(FRSKY_RX_CC2500_INO)
|
|
|
|
#include "iface_cc2500.h"
|
|
|
|
#define FRSKY_RX_D16FCC_LENGTH 0x1D+1
|
|
#define FRSKY_RX_D16LBT_LENGTH 0x20+1
|
|
#define FRSKY_RX_D16v2_LENGTH 0x1D+1
|
|
#define FRSKY_RX_D8_LENGTH 0x11+1
|
|
#define FRSKY_RX_FORMATS 5
|
|
|
|
enum
|
|
{
|
|
FRSKY_RX_D8 =0,
|
|
FRSKY_RX_D16FCC =1,
|
|
FRSKY_RX_D16LBT =2,
|
|
FRSKY_RX_D16v2FCC =3,
|
|
FRSKY_RX_D16v2LBT =4,
|
|
};
|
|
|
|
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, 0x05},
|
|
{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, 0x03},
|
|
};
|
|
|
|
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_D8_LENGTH, FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D16v2_LENGTH, FRSKY_RX_D16v2_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_D16v2FCC:
|
|
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]));
|
|
if(FRSKY_RX_format==FRSKY_RX_D16v2FCC)
|
|
{
|
|
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
|
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode
|
|
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K
|
|
}
|
|
break;
|
|
case FRSKY_RX_D16v2LBT:
|
|
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]));
|
|
if(FRSKY_RX_format==FRSKY_RX_D16v2LBT)
|
|
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
|
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_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_id(bool bind,bool init)
|
|
{
|
|
/*debugln("RX");
|
|
for(uint8_t i=0; i<packet_length;i++)
|
|
debug(" %02X",packet[i]);
|
|
debugln("");*/
|
|
|
|
if(bind && packet[0]!=packet_length-1 && packet[1] !=0x03 && packet[2] != 0x01)
|
|
return false;
|
|
uint8_t offset=bind?3:1;
|
|
|
|
// Check D8 checksum
|
|
if (FRSKY_RX_format == FRSKY_RX_D8)
|
|
{
|
|
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
|
|
return false; // Bad CRC
|
|
if(init)
|
|
{//Save TXID
|
|
rx_tx_addr[3] = packet[3];
|
|
rx_tx_addr[2] = packet[4];
|
|
rx_tx_addr[1] = packet[17];
|
|
}
|
|
else
|
|
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1] || rx_tx_addr[1] != packet[bind?17:5])
|
|
return false; // Bad address
|
|
return true; // Full match
|
|
}
|
|
|
|
// Check D16v2 checksum
|
|
if (FRSKY_RX_format == FRSKY_RX_D16v2LBT || FRSKY_RX_format == FRSKY_RX_D16v2FCC)
|
|
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
|
|
return false;
|
|
//debugln("HW Checksum ok");
|
|
|
|
// Check D16 checksum
|
|
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length - 5); // Compute crc
|
|
uint16_t rcrc = (packet[packet_length-2] << 8) | (packet[packet_length-1] & 0xff); // Received crc
|
|
if(lcrc != rcrc)
|
|
return false; // Bad CRC
|
|
//debugln("Checksum ok");
|
|
|
|
if (bind && (FRSKY_RX_format == FRSKY_RX_D16v2LBT || FRSKY_RX_format == FRSKY_RX_D16v2FCC))
|
|
for(uint8_t i=3; i<packet_length-2; i++) //unXOR bind packet
|
|
packet[i] ^= 0xA7;
|
|
|
|
uint8_t offset2=0;
|
|
if (bind && (FRSKY_RX_format == FRSKY_RX_D16LBT || FRSKY_RX_format == FRSKY_RX_D16FCC))
|
|
offset2=6;
|
|
if(init)
|
|
{//Save TXID
|
|
rx_tx_addr[3] = packet[3];
|
|
rx_tx_addr[2] = packet[4];
|
|
rx_tx_addr[1] = packet[5+offset2];
|
|
rx_tx_addr[0] = packet[6+offset2]; // RXnum
|
|
}
|
|
else
|
|
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1] || rx_tx_addr[1] != packet[offset+2+offset2])
|
|
return false; // Bad address
|
|
//debugln("Address ok");
|
|
|
|
if(!bind && rx_tx_addr[0] != packet[6])
|
|
return false; // Bad RX num
|
|
|
|
//debugln("Match");
|
|
return true; // Full match
|
|
}
|
|
|
|
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_D8)
|
|
{// 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);
|
|
}
|
|
}
|
|
else
|
|
{// 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void __attribute__((unused)) FRSKY_RX_data()
|
|
{
|
|
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
|
|
FRSKY_RX_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS;
|
|
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
|
|
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
|
|
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
|
|
rx_tx_addr[0] = RX_num;
|
|
FRSKY_RX_finetune = eeprom_read_byte((EE_ADDR)temp++);
|
|
debug("format=%d, ", FRSKY_RX_format);
|
|
debug("addr[3]=%02X, ", rx_tx_addr[3]);
|
|
debug("addr[2]=%02X, ", rx_tx_addr[2]);
|
|
debug("addr[1]=%02X, ", rx_tx_addr[1]);
|
|
debug("rx_num=%02X, ", rx_tx_addr[0]);
|
|
debugln("tune=%d", (int8_t)FRSKY_RX_finetune);
|
|
if(FRSKY_RX_format != FRSKY_RX_D16v2LBT && FRSKY_RX_format != FRSKY_RX_D16v2FCC)
|
|
{//D8 & D16v1
|
|
for (uint8_t ch = 0; ch < 47; ch++)
|
|
hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++);
|
|
}
|
|
else
|
|
{
|
|
FrSkyFormat=FRSKY_RX_format == FRSKY_RX_D16v2FCC?0:2;
|
|
FrSkyX2_init_hop();
|
|
}
|
|
debug("ch:");
|
|
for (uint8_t ch = 0; ch < 47; ch++)
|
|
debug(" %02X", hopping_frequency[ch]);
|
|
debugln("");
|
|
|
|
FRSKY_RX_initialise_cc2500();
|
|
FRSKY_RX_calibrate();
|
|
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
|
|
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[3]); // 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;
|
|
}
|
|
|
|
void FRSKY_RX_init()
|
|
{
|
|
if(sub_protocol == FRSKY_ERASE)
|
|
{
|
|
if(IS_BIND_IN_PROGRESS)
|
|
{// Clear all cloned addresses
|
|
uint16_t addr[]={ FRSKYD_CLONE_EEPROM_OFFSET+1, FRSKYX_CLONE_EEPROM_OFFSET+1, FRSKYX2_CLONE_EEPROM_OFFSET+1 };
|
|
for(uint8_t i=0; i<3;i++)
|
|
for(uint8_t j=0; j<3;j++)
|
|
eeprom_write_byte((EE_ADDR)(addr[i]+j), 0xFF);
|
|
packet_count = 100;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FRSKY_RX_chanskip = 1;
|
|
hopping_frequency_no = 0;
|
|
rx_data_started = false;
|
|
FRSKY_RX_finetune = 0;
|
|
telemetry_link = 0;
|
|
packet_count = 0;
|
|
if (IS_BIND_IN_PROGRESS)
|
|
{
|
|
FRSKY_RX_format = FRSKY_RX_D8;
|
|
FRSKY_RX_initialise_cc2500();
|
|
phase = FRSKY_RX_TUNE_START;
|
|
debugln("FRSKY_RX_TUNE_START");
|
|
}
|
|
else
|
|
FRSKY_RX_data();
|
|
}
|
|
}
|
|
|
|
uint16_t FRSKY_RX_callback()
|
|
{
|
|
static int8_t read_retry = 0;
|
|
static int8_t tune_low, tune_high;
|
|
uint8_t len, ch;
|
|
|
|
if(sub_protocol == FRSKY_ERASE)
|
|
{
|
|
if(packet_count)
|
|
packet_count--;
|
|
else
|
|
BIND_DONE;
|
|
return 10000; // Nothing to do...
|
|
}
|
|
|
|
if(IS_BIND_DONE && phase != FRSKY_RX_DATA)
|
|
FRSKY_RX_init(); // Abort bind
|
|
|
|
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 + 2) //+2=RSSI+LQI+CRC
|
|
{
|
|
CC2500_ReadData(packet, len);
|
|
if(frskyx_rx_check_crc_id(true,true))
|
|
{
|
|
FRSKY_RX_finetune = -127;
|
|
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
|
phase = FRSKY_RX_TUNE_LOW;
|
|
debugln("FRSKY_RX_TUNE_LOW");
|
|
FRSKY_RX_strobe_rx();
|
|
state = 0;
|
|
return 1000;
|
|
}
|
|
}
|
|
FRSKY_RX_format = (FRSKY_RX_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D8, D16FCC, D16LBT, D16v2FCC, D16v2LBT)
|
|
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 + 2) //+2=RSSI+LQI+CRC
|
|
{
|
|
CC2500_ReadData(packet, len);
|
|
if(frskyx_rx_check_crc_id(true,false)) {
|
|
tune_low = FRSKY_RX_finetune;
|
|
FRSKY_RX_finetune = 127;
|
|
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
|
phase = FRSKY_RX_TUNE_HIGH;
|
|
debugln("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 + 2) //+2=RSSI+LQI+CRC
|
|
{
|
|
CC2500_ReadData(packet, len);
|
|
if(frskyx_rx_check_crc_id(true,false)) {
|
|
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;
|
|
debugln("FRSKY_RX_TUNE_HIGH");
|
|
}
|
|
else
|
|
{
|
|
phase = FRSKY_RX_TUNE_START;
|
|
debugln("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 + 2) //+2=RSSI+LQI+CRC
|
|
{
|
|
CC2500_ReadData(packet, len);
|
|
if(frskyx_rx_check_crc_id(true,false)) {
|
|
if(FRSKY_RX_format != FRSKY_RX_D16v2LBT && FRSKY_RX_format != FRSKY_RX_D16v2FCC)
|
|
{// D8 & D16v1
|
|
if(packet[5] <= 0x2D)
|
|
{
|
|
for (ch = 0; ch < 5; ch++)
|
|
hopping_frequency[packet[5]+ch] = packet[6+ch];
|
|
state |= 1 << (packet[5] / 5);
|
|
}
|
|
}
|
|
else
|
|
state = 0x3FF; //No hop table for D16v2
|
|
if (state == 0x3FF)
|
|
{
|
|
debugln("Bind complete");
|
|
BIND_DONE;
|
|
// store format, finetune setting, txid, channel list
|
|
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
|
|
if(sub_protocol==FRSKY_CLONE)
|
|
{
|
|
if(FRSKY_RX_format==FRSKY_RX_D8)
|
|
temp=FRSKYD_CLONE_EEPROM_OFFSET;
|
|
else if(FRSKY_RX_format == FRSKY_RX_D16FCC || FRSKY_RX_format == FRSKY_RX_D16LBT)
|
|
temp=FRSKYX_CLONE_EEPROM_OFFSET;
|
|
else
|
|
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
|
|
}
|
|
eeprom_write_byte((EE_ADDR)temp++, FRSKY_RX_format);
|
|
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[3]);
|
|
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]);
|
|
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
|
|
if(sub_protocol==FRSKY_RX)
|
|
eeprom_write_byte((EE_ADDR)temp++, FRSKY_RX_finetune);
|
|
if(FRSKY_RX_format != FRSKY_RX_D16v2FCC && FRSKY_RX_format != FRSKY_RX_D16v2LBT)
|
|
for (ch = 0; ch < 47; ch++)
|
|
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]);
|
|
FRSKY_RX_data();
|
|
debugln("FRSKY_RX_DATA");
|
|
}
|
|
}
|
|
FRSKY_RX_strobe_rx();
|
|
}
|
|
return 1000;
|
|
|
|
case FRSKY_RX_DATA:
|
|
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
|
|
{
|
|
CC2500_ReadData(packet, len);
|
|
if(frskyx_rx_check_crc_id(false,false))
|
|
{
|
|
RX_RSSI = packet[len-2];
|
|
if(RX_RSSI >= 128)
|
|
RX_RSSI -= 128;
|
|
else
|
|
RX_RSSI += 128;
|
|
bool chanskip_valid=true;
|
|
// hop to next channel
|
|
if (FRSKY_RX_format != FRSKY_RX_D8)
|
|
{//D16v1 & D16v2
|
|
if(rx_data_started)
|
|
{
|
|
if(FRSKY_RX_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2)))
|
|
{
|
|
chanskip_valid=false; // chanskip value has changed which surely indicates a bad frame
|
|
packet_count++;
|
|
if(packet_count>5) // the TX must have changed chanskip...
|
|
FRSKY_RX_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
|
}
|
|
else
|
|
packet_count=0;
|
|
}
|
|
else
|
|
FRSKY_RX_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
|
}
|
|
hopping_frequency_no = (hopping_frequency_no + FRSKY_RX_chanskip) % 47;
|
|
FRSKY_RX_set_channel(hopping_frequency_no);
|
|
if(chanskip_valid)
|
|
{
|
|
if (telemetry_link == 0)
|
|
{ // send channels to TX
|
|
FRSKY_RX_build_telemetry_packet();
|
|
telemetry_link = 1;
|
|
}
|
|
pps_counter++;
|
|
}
|
|
rx_data_started = true;
|
|
read_retry = 0;
|
|
}
|
|
}
|
|
|
|
// packets per second
|
|
if (millis() - pps_timer >= 1000) {
|
|
pps_timer = millis();
|
|
debugln("%d pps", pps_counter);
|
|
RX_LQI = pps_counter;
|
|
if(pps_counter==0) // no packets for 1 sec or more...
|
|
{// restart the search
|
|
rx_data_started=false;
|
|
packet_count=0;
|
|
}
|
|
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
|