From e8c6225ef0a712752472632e4adcdc95cfd3377c Mon Sep 17 00:00:00 2001 From: Pascal Langer Date: Wed, 5 Jun 2019 21:54:47 +0200 Subject: [PATCH] New XN297L 250Kbps emu layer based on CC2500 This layer can be enabled/disabled with the option XN297L_CC2500_EMU in _config.h Protocols which are using it so far: GD00X, KF606 and MJXQ/E010&PHOENIX --- Multiprotocol/GD00X_nrf24l01.ino | 39 +++--- Multiprotocol/KF606_nrf24l01.ino | 37 ++---- Multiprotocol/MJXQ_nrf24l01.ino | 169 ++---------------------- Multiprotocol/Multiprotocol.h | 2 +- Multiprotocol/Multiprotocol.ino | 2 +- Multiprotocol/Validate.h | 2 + Multiprotocol/XN297L_EMU.ino | 213 +++++++++++++++++++++++++++++++ Multiprotocol/_Config.h | 7 +- Multiprotocol/iface_xn297l.h | 20 +++ 9 files changed, 283 insertions(+), 208 deletions(-) create mode 100644 Multiprotocol/XN297L_EMU.ino create mode 100644 Multiprotocol/iface_xn297l.h diff --git a/Multiprotocol/GD00X_nrf24l01.ino b/Multiprotocol/GD00X_nrf24l01.ino index 917c950..307e089 100644 --- a/Multiprotocol/GD00X_nrf24l01.ino +++ b/Multiprotocol/GD00X_nrf24l01.ino @@ -16,18 +16,20 @@ Multiprotocol is distributed in the hope that it will be useful, #if defined(GD00X_NRF24L01_INO) -#include "iface_nrf24l01.h" +#include "iface_xn297l.h" //#define FORCE_GD00X_ORIGINAL_ID #define GD00X_INITIAL_WAIT 500 #define GD00X_PACKET_PERIOD 3500 #define GD00X_RF_BIND_CHANNEL 2 +#define GD00X_RF_NUM_CHANNELS 4 #define GD00X_PAYLOAD_SIZE 15 #define GD00X_BIND_COUNT 857 //3sec #define GD00X_V2_BIND_PACKET_PERIOD 5110 #define GD00X_V2_RF_BIND_CHANNEL 0x43 +#define GD00X_V2_RF_NUM_CHANNELS 2 #define GD00X_V2_PAYLOAD_SIZE 6 // flags going to packet[11] @@ -118,42 +120,31 @@ static void __attribute__((unused)) GD00X_send_packet() packet[5]='D'; } - // Power on, TX mode, CRC enabled - XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP)); if(IS_BIND_DONE) { - NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); + XN297L_Hopping(hopping_frequency_no); if(sub_protocol==GD_V1) { hopping_frequency_no++; - hopping_frequency_no &= 3; // 4 RF channels + hopping_frequency_no &= GD00X_RF_NUM_CHANNELS-1; // 4 RF channels } } - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); - NRF24L01_FlushTx(); - XN297_WritePayload(packet, packet_length); + XN297L_WritePayload(packet, packet_length); - NRF24L01_SetPower(); // Set tx_power + XN297L_SetPower(); // Set tx_power + XN297L_SetFreqOffset(); // Set frequency offset } static void __attribute__((unused)) GD00X_init() { - NRF24L01_Initialize(); - NRF24L01_SetTxRxMode(TX_EN); + XN297L_Init(); if(sub_protocol==GD_V1) - XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5); + XN297L_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5); else - XN297_SetTXAddr((uint8_t*)"GDKNx", 5); - - NRF24L01_WriteReg(NRF24L01_05_RF_CH, sub_protocol==GD_V1?GD00X_RF_BIND_CHANNEL:GD00X_V2_RF_BIND_CHANNEL); // Bind channel - NRF24L01_FlushTx(); - NRF24L01_FlushRx(); - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit - NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes - NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only - NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps - NRF24L01_SetPower(); + XN297L_SetTXAddr((uint8_t*)"GDKNx", 5); + XN297L_HoppingCalib(sub_protocol==GD_V1?GD00X_RF_NUM_CHANNELS:GD00X_V2_RF_NUM_CHANNELS); // Calibrate all channels + XN297L_RFChannel(sub_protocol==GD_V1?GD00X_RF_BIND_CHANNEL:GD00X_V2_RF_BIND_CHANNEL); // Set bind channel } static void __attribute__((unused)) GD00X_initialize_txid() @@ -161,14 +152,14 @@ static void __attribute__((unused)) GD00X_initialize_txid() if(sub_protocol==GD_V1) { uint8_t start=76+(rx_tx_addr[0]&0x03); - for(uint8_t i=0; i<4;i++) + for(uint8_t i=0; i 5) len = 5; - if (len < 3) len = 3; - xn297_addr_len = len; - memcpy(xn297_tx_addr, addr, len); -} - -static void __attribute__((unused)) XN297L_WritePayload(const uint8_t* msg, uint8_t len) -{ - uint8_t buf[32]; - uint8_t last = 0; - uint8_t i; - static const uint16_t initial = 0xb5d2; - - // address - for (i = 0; i < xn297_addr_len; ++i) { - buf[last++] = xn297_tx_addr[xn297_addr_len - i - 1] ^ xn297_scramble[i]; - } - - // payload - for (i = 0; i < len; ++i) { - // bit-reverse bytes in packet - uint8_t b_out = bit_reverse(msg[i]); - buf[last++] = b_out ^ xn297_scramble[xn297_addr_len + i]; - } - - uint8_t offset = xn297_addr_len < 4 ? 1 : 0; - - // crc - uint16_t crc = initial; - for (uint8_t i = offset; i < last; ++i) - crc = crc16_update(crc, buf[i], 8); - crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]); - buf[last++] = crc >> 8; - buf[last++] = crc & 0xff; - - // stop TX/RX - CC2500_Strobe(CC2500_SIDLE); - // flush tx FIFO - CC2500_Strobe(CC2500_SFTX); - // packet length - CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3); - // xn297L preamble - CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0f\x55", 3); - // xn297 packet - CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); - // transmit - CC2500_Strobe(CC2500_STX); -} - -static void __attribute__((unused)) calibrate_pll() -{ - //calibrate hop channels - for (uint8_t i = 0; i < MJXQ_RF_NUM_CHANNELS; i++) { - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3); - CC2500_Strobe(CC2500_SCAL); - delayMicroseconds(900); - fscal1[i] = CC2500_ReadReg(CC2500_25_FSCAL1); - } -} -#endif // CC2500_INSTALLED - static uint8_t __attribute__((unused)) MJXQ_pan_tilt_value() { // CH12_SW PAN // H26D @@ -318,26 +193,14 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind) for (uint8_t i=1; i < MJXQ_PACKET_SIZE-1; i++) sum += packet[i]; packet[15] = sum; hopping_frequency_no++; -#ifdef CC2500_INSTALLED - if (sub_protocol == E010 || sub_protocol == PHOENIX) { - // spacing is 333.25 kHz, must multiply xn297 channel by 3 - CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[hopping_frequency_no / 2] * 3); - // set PLL calibration - CC2500_WriteReg(CC2500_25_FSCAL1, fscal1[hopping_frequency_no / 2]); - // Make sure that the radio is in IDLE state before flushing the FIFO - CC2500_Strobe(CC2500_SIDLE); - // Flush TX FIFO - CC2500_Strobe(CC2500_SFTX); - // Frequency offset hack - if (prev_option != option) { - prev_option = option; - CC2500_WriteReg(CC2500_0C_FSCTRL0, option); - } + if (sub_protocol == E010 || sub_protocol == PHOENIX) + { + XN297L_Hopping(hopping_frequency_no / 2); + XN297L_SetFreqOffset(); + XN297L_SetPower(); XN297L_WritePayload(packet, MJXQ_PACKET_SIZE); - CC2500_SetPower(); } else -#endif { NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no / 2]); @@ -374,16 +237,13 @@ static void __attribute__((unused)) MJXQ_init() memcpy(hopping_frequency, "\x0a\x35\x42\x3d", MJXQ_RF_NUM_CHANNELS); memcpy(addr, "\x6d\x6a\x73\x73\x73", MJXQ_ADDRESS_LENGTH); } -#ifdef CC2500_INSTALLED - if (sub_protocol == E010 || sub_protocol == PHOENIX) { - XN297L_init(); // setup cc2500 for xn297L@250kbps emulation - CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack + if (sub_protocol == E010 || sub_protocol == PHOENIX) + { + XN297L_Init(); XN297L_SetTXAddr(addr, sizeof(addr)); - CC2500_SetPower(); - calibrate_pll(); + XN297L_HoppingCalib(MJXQ_RF_NUM_CHANNELS); } else -#endif { NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); @@ -403,10 +263,7 @@ static void __attribute__((unused)) MJXQ_init() NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE); - if (sub_protocol == E010 || sub_protocol == PHOENIX) - NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250K - else - NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps NRF24L01_SetPower(); } } @@ -428,9 +285,7 @@ static void __attribute__((unused)) MJXQ_init2() hopping_frequency[i]=pgm_read_byte_near( &E010_map_rfchan[rx_tx_addr[3]&0x0F][i] ); hopping_frequency[i+2]=hopping_frequency[i]+0x10; } -#ifdef CC2500_INSTALLED - calibrate_pll(); -#endif + XN297L_HoppingCalib(MJXQ_RF_NUM_CHANNELS); break; case WLH08: // do nothing diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index 073c218..9cb8318 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -19,7 +19,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_REVISION 1 -#define VERSION_PATCH_LEVEL 53 +#define VERSION_PATCH_LEVEL 54 //****************** // Protocols diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 252735a..7ceaf9c 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -112,7 +112,7 @@ uint16_t state; uint8_t len; uint8_t armed, arm_flags, arm_channel_previous; -#if defined(FRSKYX_CC2500_INO) || defined(SFHSS_CC2500_INO) || defined(HITEC_CC2500_INO) +#ifdef CC2500_INSTALLED uint8_t calData[48]; #endif diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index d52ab75..43d14ce 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -155,6 +155,7 @@ #undef SFHSS_CC2500_INO #undef CORONA_CC2500_INO #undef HITEC_CC2500_INO + #undef XN297L_CC2500_EMU #endif #ifndef NRF24L01_INSTALLED #undef BAYANG_NRF24L01_INO @@ -188,6 +189,7 @@ #undef E01X_NRF24L01_INO #undef V761_NRF24L01_INO #undef V911S_NRF24L01_INO + #undef XN297L_CC2500_EMU #endif //Make sure telemetry is selected correctly diff --git a/Multiprotocol/XN297L_EMU.ino b/Multiprotocol/XN297L_EMU.ino new file mode 100644 index 0000000..ef0bfd9 --- /dev/null +++ b/Multiprotocol/XN297L_EMU.ino @@ -0,0 +1,213 @@ +/* + 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 . + */ +#include "iface_xn297l.h" + +#if defined (XN297L_CC2500_EMU) +static void __attribute__((unused)) XN297L_Init() +{ + PE1_off; // antenna RF2 + PE2_on; + CC2500_Reset(); + CC2500_Strobe(CC2500_SIDLE); + + // Address Config = No address check + // Base Frequency = 2400 + // CRC Autoflush = false + // CRC Enable = false + // Channel Spacing = 333.251953 + // Data Format = Normal mode + // Data Rate = 249.939 + // Deviation = 126.953125 + // Device Address = 0 + // Manchester Enable = false + // Modulated = true + // Modulation Format = GFSK + // Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word + // RX Filter BW = 203.125000 + // Sync Word Qualifier Mode = No preamble/sync + // TX Power = 0 + // Whitening = false + // Fast Frequency Hopping - no PLL auto calibration + + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control + CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control + CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack + CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte + CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte + CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration + CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration + CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration + CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration + CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting + CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // Main Radio Control State Machine Configuration + CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration + CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration + CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control + CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control + CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control + CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration + CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration + + CC2500_SetTxRxMode(TX_EN); + CC2500_SetPower(); +} + +static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len) +{ + if (len > 5) len = 5; + if (len < 3) len = 3; + xn297_addr_len = len; + memcpy(xn297_tx_addr, addr, len); +} + +static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len) +{ + uint8_t buf[32]; + uint8_t last = 0; + uint8_t i; + static const uint16_t initial = 0xb5d2; + + // address + for (i = 0; i < xn297_addr_len; ++i) { + buf[last++] = xn297_tx_addr[xn297_addr_len - i - 1] ^ xn297_scramble[i]; + } + + // payload + for (i = 0; i < len; ++i) { + // bit-reverse bytes in packet + uint8_t b_out = bit_reverse(msg[i]); + buf[last++] = b_out ^ xn297_scramble[xn297_addr_len + i]; + } + + // crc + uint16_t crc = initial; + for (uint8_t i = 0; i < last; ++i) + crc = crc16_update(crc, buf[i], 8); + crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]); + buf[last++] = crc >> 8; + buf[last++] = crc & 0xff; + + // stop TX/RX + CC2500_Strobe(CC2500_SIDLE); + // flush tx FIFO + CC2500_Strobe(CC2500_SFTX); + // packet length + CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3); + // xn297L preamble + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0f\x55", 3); + // xn297 packet + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); + // transmit + CC2500_Strobe(CC2500_STX); +} + +static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq) +{ //calibrate hopping frequencies + for (uint8_t i = 0; i < num_freq; i++) + { + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3); + CC2500_Strobe(CC2500_SCAL); + delayMicroseconds(900); + calData[i]=CC2500_ReadReg(CC2500_25_FSCAL1); + } +} + +static void __attribute__((unused)) XN297L_Hopping(uint8_t index) +{ + // spacing is 333.25 kHz, must multiply xn297 channel by 3 + CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[index] * 3); + // set PLL calibration + CC2500_WriteReg(CC2500_25_FSCAL1, calData[index]); +} + +static void __attribute__((unused)) XN297L_RFChannel(uint8_t number) +{ //change channel + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, number*3); + CC2500_Strobe(CC2500_SCAL); + delayMicroseconds(900); +} + +static void __attribute__((unused)) XN297L_SetPower() +{ + CC2500_SetPower(); +} + +static void __attribute__((unused)) XN297L_SetFreqOffset() +{ // Frequency offset + if (prev_option != option) + { + prev_option = option; + CC2500_WriteReg(CC2500_0C_FSCTRL0, option); + } +} + +#elif defined (NRF24L01_INSTALLED) + +static void __attribute__((unused)) XN297L_Init() +{ + NRF24L01_Initialize(); + NRF24L01_SetTxRxMode(TX_EN); + NRF24L01_FlushTx(); + NRF24L01_FlushRx(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit + NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only + NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps + NRF24L01_SetPower(); +} + +static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len) +{ + XN297_SetTXAddr(addr,len); +} + +static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len) +{ + XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP)); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); + NRF24L01_FlushTx(); + XN297_WritePayload(msg, len); +} + +static void __attribute__((unused)) XN297L_HoppingCalib(__attribute__((unused)) uint8_t num_freq) +{ //calibrate hopping frequencies +} + +static void __attribute__((unused)) XN297L_Hopping(uint8_t index) +{ + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]); +} + +static void __attribute__((unused)) XN297L_RFChannel(uint8_t number) +{ //change channel + NRF24L01_WriteReg(NRF24L01_05_RF_CH, number); +} + +static void __attribute__((unused)) XN297L_SetPower() +{ + NRF24L01_SetPower(); +} + +static void __attribute__((unused)) XN297L_SetFreqOffset() +{ // Frequency offset +} + +#endif \ No newline at end of file diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index 0d1832d..20d6762 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -29,8 +29,8 @@ /*************************/ /*** BOOTLOADER USE ***/ /*************************/ -//Allow flashing multimodule directly with TX(erky9x or opentx modified firmwares) -//Instructions: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/tree/master/BootLoaders#compiling--uploading-firmware-with-the-flash-from-tx-bootloader +//Allow flashing multimodule directly with TX(erky9x or opentx maintenance mode) +//Instructions:https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Flash_from_Tx.md //To enable this feature remove the "//" on the next line. Requires a compatible bootloader or upload method to be selected when you use the Multi 4-in-1 Boards Manager definitions. //#define CHECK_FOR_BOOTLOADER @@ -78,6 +78,9 @@ #define CC2500_INSTALLED #define NRF24L01_INSTALLED +//If available use the CC2500 to emulate the XN297L @250Kbps instead of the NRF24L01. Comment to disable. +#define XN297L_CC2500_EMU + /** OrangeRX TX **/ //If you compile for the OrangeRX TX module you need to select the correct board type. //By default the compilation is done for the GREEN board, to switch to a BLUE board uncomment the line below by removing the "//" diff --git a/Multiprotocol/iface_xn297l.h b/Multiprotocol/iface_xn297l.h new file mode 100644 index 0000000..29bf09b --- /dev/null +++ b/Multiprotocol/iface_xn297l.h @@ -0,0 +1,20 @@ +#ifndef _IFACE_XN297L_H_ + +#define _IFACE_XN297L_H_ + +#if defined (XN297L_CC2500_EMU) + #include "iface_cc2500.h" +#elif defined (NRF24L01_INSTALLED) + #include "iface_nrf24l01.h" +#endif + +static void __attribute__((unused)) XN297L_Init(); +static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t*, uint8_t); +static void __attribute__((unused)) XN297L_WritePayload(uint8_t*, uint8_t); +static void __attribute__((unused)) XN297L_HoppingCalib(__attribute__((unused)) uint8_t); +static void __attribute__((unused)) XN297L_Hopping(uint8_t); +static void __attribute__((unused)) XN297L_RFChannel(uint8_t); +static void __attribute__((unused)) XN297L_SetPower(); +static void __attribute__((unused)) XN297L_SetFreqOffset(); + +#endif \ No newline at end of file