mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-02-04 16:38:12 +00:00
4a626eaf14
Loads of protocols have been touched by this change. Some testing has been done but please test on all your models. The XN297 emulation selects in this order: - the CC2500 if it is available and bitrate=250K. Configure the option field automatically for RF tune. - the NRF for all bitrates if it is available - if NRF is not available and bitrate=1M then an invalid protocol is sent automatically to the radio. CC2500 @250K can now receive normal and enhanced payloads. OMP protocol supports telemetry on CC2500 and is also for NRF only modules including telemetry. Separation of E016H (new protocol) from E01X due to different structure. MJXQ, MT99XX, Q303 and XK: some sub protocols available on CC2500 only.
741 lines
22 KiB
C++
741 lines
22 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/>.
|
|
*/
|
|
|
|
// sub_protocol: 0=250Kbps, 1=1Mbps, 2=2Mbps. Other values default to 1Mbps.
|
|
// RX_num = address length 3 or 4 or 5. Other values default to 5.
|
|
// option = RF channel number 0..84 and -1 = scan all channels. Other values default to RF channel 0.
|
|
|
|
#ifdef XN297DUMP_NRF24L01_INO
|
|
|
|
#include "iface_xn297.h"
|
|
|
|
// Parameters which can be modified
|
|
#define XN297DUMP_PERIOD_SCAN 50000 // 25000
|
|
#define XN297DUMP_MAX_RF_CHANNEL 127 // Default 84
|
|
|
|
// Do not touch from there
|
|
#define XN297DUMP_INITIAL_WAIT 500
|
|
#define XN297DUMP_MAX_PACKET_LEN 32
|
|
#define XN297DUMP_CRC_LENGTH 2
|
|
|
|
uint8_t address_length;
|
|
uint16_t timeH=0;
|
|
boolean scramble;
|
|
boolean enhanced;
|
|
boolean ack;
|
|
uint8_t pid;
|
|
uint8_t bitrate;
|
|
|
|
static void __attribute__((unused)) XN297Dump_RF_init()
|
|
{
|
|
NRF24L01_Initialize();
|
|
NRF24L01_SetTxRxMode(RX_EN);
|
|
|
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3 bytes RX/TX address
|
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x55\x0F\x71", 3); // set up RX address to xn297 preamble
|
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, XN297DUMP_MAX_PACKET_LEN); // Enable rx pipe 0
|
|
|
|
debug("XN297 dump, address length=%d, bitrate=",address_length);
|
|
switch(bitrate)
|
|
{
|
|
case XN297DUMP_250K:
|
|
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
|
debugln("250K");
|
|
break;
|
|
case XN297DUMP_2M:
|
|
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
|
debugln("2M");
|
|
break;
|
|
default:
|
|
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
|
debugln("1M");
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
extern const uint8_t xn297_scramble[];
|
|
extern const uint16_t PROGMEM xn297_crc_xorout_scrambled[];
|
|
extern const uint16_t PROGMEM xn297_crc_xorout[];
|
|
extern const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[];
|
|
extern const uint16_t xn297_crc_xorout_enhanced[];
|
|
|
|
static boolean __attribute__((unused)) XN297Dump_process_packet(void)
|
|
{
|
|
uint16_t crcxored;
|
|
uint8_t packet_sc[XN297DUMP_MAX_PACKET_LEN], packet_un[XN297DUMP_MAX_PACKET_LEN];
|
|
enhanced=false;
|
|
// init crc
|
|
crc = 0xb5d2;
|
|
|
|
/*debug("P: 71 0F 55 ");
|
|
for(uint8_t i=0; i<XN297DUMP_MAX_PACKET_LEN; i++)
|
|
debug("%02X ",packet[i]);
|
|
debugln("");*/
|
|
//Try normal payload
|
|
// address
|
|
for (uint8_t i = 0; i < address_length; i++)
|
|
{
|
|
crc16_update( packet[i], 8);
|
|
packet_un[address_length-1-i]=packet[i];
|
|
packet_sc[address_length-1-i]=packet[i] ^ xn297_scramble[i];
|
|
}
|
|
|
|
// payload
|
|
for (uint8_t i = address_length; i < XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH; i++)
|
|
{
|
|
crc16_update( packet[i], 8);
|
|
packet_sc[i] = bit_reverse(packet[i]^xn297_scramble[i]);
|
|
packet_un[i] = bit_reverse(packet[i]);
|
|
// check crc
|
|
crcxored = crc ^ pgm_read_word(&xn297_crc_xorout[i+1 - 3]);
|
|
if( (crcxored >> 8) == packet[i + 1] && (crcxored & 0xff) == packet[i + 2])
|
|
{
|
|
packet_length=i+1;
|
|
memcpy(packet,packet_un,packet_length);
|
|
scramble=false;
|
|
return true;
|
|
}
|
|
crcxored = crc ^ pgm_read_word(&xn297_crc_xorout_scrambled[i+1 - 3]);
|
|
if( (crcxored >> 8) == packet[i + 1] && (crcxored & 0xff) == packet[i + 2])
|
|
{
|
|
packet_length=i+1;
|
|
memcpy(packet,packet_sc,packet_length);
|
|
scramble=true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//Try enhanced payload
|
|
crc = 0xb5d2;
|
|
packet_length=0;
|
|
for (uint8_t i = 0; i < XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH; i++)
|
|
{
|
|
packet_sc[i]=packet[i]^xn297_scramble[i];
|
|
crc16_update( packet[i], 8);
|
|
crc16_update( packet[i+1] & 0xC0, 2);
|
|
crcxored=(packet[i+1]<<10)|(packet[i+2]<<2)|(packet[i+3]>>6) ;
|
|
if((crc ^ pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[i - 3])) == crcxored)
|
|
{ // Found a valid CRC for the enhanced payload mode
|
|
packet_length=i;
|
|
scramble=true;
|
|
i++;
|
|
packet_sc[i]=packet[i]^xn297_scramble[i];
|
|
memcpy(packet_un,packet_sc,packet_length+2); // unscramble packet
|
|
break;
|
|
}
|
|
if((crc ^ pgm_read_word(&xn297_crc_xorout_enhanced[i - 3])) == crcxored)
|
|
{ // Found a valid CRC for the enhanced payload mode
|
|
packet_length=i;
|
|
scramble=false;
|
|
memcpy(packet_un,packet,packet_length+2); // packet is unscrambled
|
|
break;
|
|
}
|
|
}
|
|
if(packet_length!=0)
|
|
{ // Found a valid CRC for the enhanced payload mode
|
|
enhanced=true;
|
|
//check selected address length
|
|
if((packet_un[address_length]>>1)!=packet_length-address_length)
|
|
{
|
|
for(uint8_t i=3;i<=5;i++)
|
|
if((packet_un[i]>>1)==packet_length-i)
|
|
address_length=i;
|
|
debugln("Detected wrong address length, using %d intead", address_length );
|
|
}
|
|
pid=((packet_un[address_length]&0x01)<<1)|(packet_un[address_length+1]>>7);
|
|
ack=(packet_un[address_length+1]>>6)&0x01;
|
|
// address
|
|
for (uint8_t i = 0; i < address_length; i++)
|
|
packet[address_length-1-i]=packet_un[i];
|
|
// payload
|
|
for (uint8_t i = address_length; i < packet_length; i++)
|
|
packet[i] = bit_reverse((packet_un[i+1]<<2)|(packet_un[i+2]>>6));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static void __attribute__((unused)) XN297Dump_overflow()
|
|
{
|
|
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
|
{ // timer overflow
|
|
timeH++;
|
|
TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_UIF; // Clear Timer2 overflow flag
|
|
}
|
|
}
|
|
static uint16_t XN297Dump_callback()
|
|
{
|
|
static uint32_t time=0,*time_rf;
|
|
|
|
//!!!Blocking mode protocol!!!
|
|
TX_MAIN_PAUSE_off;
|
|
tx_resume();
|
|
while(1)
|
|
{
|
|
if(sub_protocol<XN297DUMP_AUTO)
|
|
{
|
|
if(option==0xFF && bind_counter>XN297DUMP_PERIOD_SCAN)
|
|
{ // Scan frequencies
|
|
hopping_frequency_no++;
|
|
bind_counter=0;
|
|
}
|
|
if(hopping_frequency_no!=rf_ch_num)
|
|
{ // Channel has changed
|
|
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
|
hopping_frequency_no=0; // Invalid channel 0 by default
|
|
rf_ch_num=hopping_frequency_no;
|
|
debugln("Channel=%d,0x%02X",hopping_frequency_no,hopping_frequency_no);
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency_no);
|
|
// switch to RX mode
|
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
|
NRF24L01_SetTxRxMode(RX_EN);
|
|
NRF24L01_FlushRx();
|
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to RX mode and disable CRC
|
|
| (1 << NRF24L01_00_CRCO)
|
|
| (1 << NRF24L01_00_PWR_UP)
|
|
| (1 << NRF24L01_00_PRIM_RX));
|
|
phase=0; // init timer
|
|
}
|
|
XN297Dump_overflow();
|
|
|
|
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
|
{ // RX fifo data ready
|
|
if(NRF24L01_ReadReg(NRF24L01_09_CD) || option != 0xFF)
|
|
{
|
|
NRF24L01_ReadPayload(packet,XN297DUMP_MAX_PACKET_LEN);
|
|
XN297Dump_overflow();
|
|
uint16_t timeL=TCNT1;
|
|
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
|
{//timer just rolled over...
|
|
XN297Dump_overflow();
|
|
timeL=0;
|
|
}
|
|
if((phase&0x01)==0)
|
|
{
|
|
phase=1;
|
|
time=0;
|
|
}
|
|
else
|
|
time=(timeH<<16)+timeL-time;
|
|
if(XN297Dump_process_packet())
|
|
{ // valid crc found
|
|
debug("RX: %5luus C=%d ", time>>1 , hopping_frequency_no);
|
|
time=(timeH<<16)+timeL;
|
|
if(enhanced)
|
|
{
|
|
debug("Enhanced ");
|
|
debug("pid=%d ",pid);
|
|
if(ack) debug("ack ");
|
|
}
|
|
debug("S=%c A=",scramble?'Y':'N');
|
|
for(uint8_t i=0; i<address_length; i++)
|
|
{
|
|
debug(" %02X",packet[i]);
|
|
}
|
|
debug(" P(%d)=",packet_length-address_length);
|
|
for(uint8_t i=address_length; i<packet_length; i++)
|
|
{
|
|
debug(" %02X",packet[i]);
|
|
}
|
|
debugln("");
|
|
}
|
|
else
|
|
{
|
|
debugln("RX: %5luus C=%d Bad CRC", time>>1 , hopping_frequency_no);
|
|
}
|
|
}
|
|
|
|
XN297Dump_overflow();
|
|
// restart RX mode
|
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
|
NRF24L01_SetTxRxMode(RX_EN);
|
|
NRF24L01_FlushRx();
|
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to RX mode and disable CRC
|
|
| (1 << NRF24L01_00_CRCO)
|
|
| (1 << NRF24L01_00_PWR_UP)
|
|
| (1 << NRF24L01_00_PRIM_RX));
|
|
XN297Dump_overflow();
|
|
}
|
|
}
|
|
else if(sub_protocol==XN297DUMP_AUTO)
|
|
{
|
|
switch(phase)
|
|
{
|
|
case 0:
|
|
debugln("------------------------");
|
|
debugln("Detecting XN297 packets.");
|
|
XN297Dump_RF_init();
|
|
debug("Trying RF channel: 0");
|
|
hopping_frequency_no=0;
|
|
bitrate=0;
|
|
phase++;
|
|
break;
|
|
case 1:
|
|
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
|
{ // Scan frequencies
|
|
hopping_frequency_no++;
|
|
bind_counter=0;
|
|
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
|
{
|
|
hopping_frequency_no=0;
|
|
bitrate++;
|
|
bitrate%=3;
|
|
debugln("");
|
|
XN297Dump_RF_init();
|
|
debug("Trying RF channel: 0");
|
|
}
|
|
if(hopping_frequency_no)
|
|
debug(",%d",hopping_frequency_no);
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency_no);
|
|
// switch to RX mode
|
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
|
NRF24L01_SetTxRxMode(RX_EN);
|
|
NRF24L01_FlushRx();
|
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to RX mode and disable CRC
|
|
| (1 << NRF24L01_00_CRCO)
|
|
| (1 << NRF24L01_00_PWR_UP)
|
|
| (1 << NRF24L01_00_PRIM_RX));
|
|
}
|
|
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
|
{ // RX fifo data ready
|
|
if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
|
{
|
|
NRF24L01_ReadPayload(packet,XN297DUMP_MAX_PACKET_LEN);
|
|
if(XN297Dump_process_packet())
|
|
{ // valid crc found
|
|
debug("\r\n\r\nPacket detected: bitrate=");
|
|
switch(bitrate)
|
|
{
|
|
case XN297DUMP_250K:
|
|
XN297_Configure(XN297_CRCEN, scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED, XN297_250K);
|
|
debug("250K");
|
|
break;
|
|
case XN297DUMP_2M:
|
|
XN297_Configure(XN297_CRCEN, scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED, XN297_1M);
|
|
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
|
debug("2M");
|
|
break;
|
|
default:
|
|
XN297_Configure(XN297_CRCEN, scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED, XN297_1M);
|
|
debug("1M");
|
|
break;
|
|
|
|
}
|
|
debug(" C=%d ", hopping_frequency_no);
|
|
if(enhanced)
|
|
{
|
|
debug("Enhanced ");
|
|
debug("pid=%d ",pid);
|
|
if(ack) debug("ack ");
|
|
}
|
|
debug("S=%c A=",scramble?'Y':'N');
|
|
for(uint8_t i=0; i<address_length; i++)
|
|
{
|
|
debug(" %02X",packet[i]);
|
|
rx_tx_addr[i]=packet[i];
|
|
}
|
|
debug(" P(%d)=",packet_length-address_length);
|
|
for(uint8_t i=address_length; i<packet_length; i++)
|
|
{
|
|
debug(" %02X",packet[i]);
|
|
}
|
|
packet_length=packet_length-address_length;
|
|
debugln("\r\n--------------------------------");
|
|
phase=2;
|
|
debugln("Identifying all RF channels in use.");
|
|
bind_counter=0;
|
|
hopping_frequency_no=0;
|
|
rf_ch_num=0;
|
|
packet_count=0;
|
|
debug("Trying RF channel: 0");
|
|
|
|
XN297_SetTXAddr(rx_tx_addr,address_length);
|
|
XN297_SetRXAddr(rx_tx_addr,packet_length);
|
|
XN297_RFChannel(0);
|
|
XN297_SetTxRxMode(TXRX_OFF);
|
|
XN297_SetTxRxMode(RX_EN);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
|
{ // Scan frequencies
|
|
hopping_frequency_no++;
|
|
bind_counter=0;
|
|
if(packet_count && packet_count<=20)
|
|
debug("\r\nTrying RF channel: ");
|
|
packet_count=0;
|
|
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
|
{
|
|
debug("\r\n\r\n%d RF channels identified:",rf_ch_num);
|
|
for(uint8_t i=0;i<rf_ch_num;i++)
|
|
debug(" %d",hopping_frequency[i]);
|
|
time_rf=(uint32_t*)malloc(rf_ch_num*sizeof(time));
|
|
if(time_rf==NULL)
|
|
{
|
|
debugln("\r\nCan't allocate memory for next phase!!!");
|
|
phase=0;
|
|
break;
|
|
}
|
|
debugln("\r\n--------------------------------");
|
|
debugln("Identifying RF channels order.");
|
|
hopping_frequency_no=1;
|
|
phase=3;
|
|
packet_count=0;
|
|
bind_counter=0;
|
|
debugln("Time between CH:%d and CH:%d",hopping_frequency[0],hopping_frequency[hopping_frequency_no]);
|
|
time_rf[hopping_frequency_no]=0xFFFFFFFF;
|
|
XN297_RFChannel(hopping_frequency[0]);
|
|
uint16_t timeL=TCNT1;
|
|
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
|
{//timer just rolled over...
|
|
XN297Dump_overflow();
|
|
timeL=0;
|
|
}
|
|
time=(timeH<<16)+timeL;
|
|
XN297_SetTxRxMode(TXRX_OFF);
|
|
XN297_SetTxRxMode(RX_EN);
|
|
XN297Dump_overflow();
|
|
break;
|
|
}
|
|
debug(",%d",hopping_frequency_no);
|
|
XN297_RFChannel(hopping_frequency_no);
|
|
// switch to RX mode
|
|
XN297_SetTxRxMode(TXRX_OFF);
|
|
XN297_SetTxRxMode(RX_EN);
|
|
}
|
|
if( XN297_IsRX() )
|
|
{ // RX fifo data ready
|
|
// if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
|
{
|
|
boolean res;
|
|
if(enhanced)
|
|
res=XN297_ReadEnhancedPayload(packet, packet_length);
|
|
else
|
|
res=XN297_ReadPayload(packet, packet_length);
|
|
if(res)
|
|
{ // valid crc found
|
|
XN297Dump_overflow();
|
|
uint16_t timeL=TCNT1;
|
|
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
|
{//timer just rolled over...
|
|
XN297Dump_overflow();
|
|
timeL=0;
|
|
}
|
|
if(packet_count==0)
|
|
{//save channel
|
|
hopping_frequency[rf_ch_num]=hopping_frequency_no;
|
|
rf_ch_num++;
|
|
time=0;
|
|
}
|
|
else
|
|
time=(timeH<<16)+timeL-time;
|
|
debug("\r\nRX on channel: %d, Time: %5luus P:",hopping_frequency_no, time>>1);
|
|
time=(timeH<<16)+timeL;
|
|
for(uint8_t i=0;i<packet_length;i++)
|
|
debug(" %02X",packet[i]);
|
|
packet_count++;
|
|
if(packet_count>20)
|
|
{//change channel
|
|
bind_counter=XN297DUMP_PERIOD_SCAN+1;
|
|
debug("\r\nTrying RF channel: ");
|
|
}
|
|
}
|
|
}
|
|
// restart RX mode
|
|
XN297_SetTxRxMode(TXRX_OFF);
|
|
XN297_SetTxRxMode(RX_EN);
|
|
}
|
|
XN297Dump_overflow();
|
|
break;
|
|
case 3:
|
|
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
|
{ // Scan frequencies
|
|
hopping_frequency_no++;
|
|
bind_counter=0;
|
|
if(hopping_frequency_no>=rf_ch_num)
|
|
{
|
|
uint8_t next=0;
|
|
debugln("\r\n\r\nChannel order:");
|
|
debugln("%d: 0us",hopping_frequency[0]);
|
|
uint8_t i=1;
|
|
do
|
|
{
|
|
time=time_rf[i];
|
|
if(time!=0xFFFFFFFF)
|
|
{
|
|
next=i;
|
|
for(uint8_t j=2;j<rf_ch_num;j++)
|
|
if(time>time_rf[j])
|
|
{
|
|
next=j;
|
|
time=time_rf[j];
|
|
}
|
|
time_rf[next]=-1;
|
|
debugln("%d: %5luus",hopping_frequency[next],time);
|
|
i=0;
|
|
}
|
|
i++;
|
|
}
|
|
while(i<rf_ch_num);
|
|
free(time_rf);
|
|
debugln("\r\n--------------------------------");
|
|
debugln("Identifying Sticks and features.");
|
|
phase=4;
|
|
hopping_frequency_no=0;
|
|
break;
|
|
}
|
|
debugln("Time between CH:%d and CH:%d",hopping_frequency[0],hopping_frequency[hopping_frequency_no]);
|
|
time_rf[hopping_frequency_no]=-1;
|
|
XN297_RFChannel(hopping_frequency[0]);
|
|
uint16_t timeL=TCNT1;
|
|
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
|
{//timer just rolled over...
|
|
XN297Dump_overflow();
|
|
timeL=0;
|
|
}
|
|
time=(timeH<<16)+timeL;
|
|
// switch to RX mode
|
|
XN297_SetTxRxMode(TXRX_OFF);
|
|
XN297_SetTxRxMode(RX_EN);
|
|
}
|
|
if( XN297_IsRX() )
|
|
{ // RX fifo data ready
|
|
//if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
|
{
|
|
boolean res;
|
|
if(enhanced)
|
|
res=XN297_ReadEnhancedPayload(packet, packet_length);
|
|
else
|
|
res=XN297_ReadPayload(packet, packet_length);
|
|
if(res)
|
|
{ // valid crc found
|
|
XN297Dump_overflow();
|
|
uint16_t timeL=TCNT1;
|
|
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
|
{//timer just rolled over...
|
|
XN297Dump_overflow();
|
|
timeL=0;
|
|
}
|
|
if(packet_count&1)
|
|
{
|
|
time=(timeH<<16)+timeL-time;
|
|
if(time_rf[hopping_frequency_no] > (time>>1))
|
|
time_rf[hopping_frequency_no]=time>>1;
|
|
debugln("Time: %5luus", time>>1);
|
|
XN297_RFChannel(hopping_frequency[0]);
|
|
}
|
|
else
|
|
{
|
|
time=(timeH<<16)+timeL;
|
|
XN297_RFChannel(hopping_frequency[hopping_frequency_no]);
|
|
}
|
|
packet_count++;
|
|
if(packet_count>24)
|
|
{
|
|
bind_counter=XN297DUMP_PERIOD_SCAN+1;
|
|
packet_count=0;
|
|
}
|
|
}
|
|
}
|
|
// restart RX mode
|
|
XN297_SetTxRxMode(TXRX_OFF);
|
|
XN297_SetTxRxMode(RX_EN);
|
|
}
|
|
XN297Dump_overflow();
|
|
break;
|
|
case 4:
|
|
if( XN297_IsRX() )
|
|
{ // RX fifo data ready
|
|
//if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
|
{
|
|
boolean res;
|
|
if(enhanced)
|
|
res=XN297_ReadEnhancedPayload(packet, packet_length);
|
|
else
|
|
res=XN297_ReadPayload(packet, packet_length);
|
|
if(res)
|
|
{ // valid crc found
|
|
if(memcmp(packet_in,packet,packet_length))
|
|
{
|
|
debug("P:");
|
|
for(uint8_t i=0;i<packet_length;i++)
|
|
debug(" %02X",packet[i]);
|
|
debugln("");
|
|
memcpy(packet_in,packet,packet_length);
|
|
}
|
|
}
|
|
}
|
|
// restart RX mode
|
|
XN297_SetTxRxMode(TXRX_OFF);
|
|
XN297_SetTxRxMode(RX_EN);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(phase==0)
|
|
{
|
|
address_length=4;
|
|
memcpy(rx_tx_addr, (uint8_t *)"\x5A\xF6\xC1\x71", address_length); //"\xA3\x05\x22\xC1""\x5A\x20\x12\xAC"
|
|
bitrate=XN297DUMP_250K;
|
|
packet_length=32;
|
|
hopping_frequency_no=58; //bind ?, normal 60
|
|
|
|
NRF24L01_Initialize();
|
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
|
NRF24L01_SetTxRxMode(RX_EN);
|
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, address_length-2); // RX/TX address length
|
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, address_length); // set up RX address
|
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // Enable rx pipe 0
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
|
|
|
|
debug("NRF dump, len=%d, rf=%d, address length=%d, bitrate=",packet_length,hopping_frequency_no,address_length);
|
|
switch(bitrate)
|
|
{
|
|
case XN297DUMP_250K:
|
|
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
|
debugln("250K");
|
|
break;
|
|
case XN297DUMP_2M:
|
|
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
|
debugln("2M");
|
|
break;
|
|
default:
|
|
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
|
debugln("1M");
|
|
break;
|
|
|
|
}
|
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX)); //_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) |
|
|
phase++;
|
|
}
|
|
else
|
|
{
|
|
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
|
{ // RX fifo data ready
|
|
if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
|
{
|
|
NRF24L01_ReadPayload(packet, packet_length);
|
|
//bool ok=true;
|
|
uint8_t buffer[40];
|
|
memcpy(buffer,packet,packet_length);
|
|
if(memcmp(&packet_in[0],&packet[0],packet_length))
|
|
{
|
|
debug("P:");
|
|
for(uint8_t i=0;i<packet_length;i++)
|
|
debug(" %02X",packet[i]);
|
|
debugln("");
|
|
memcpy(packet_in,packet,packet_length);
|
|
}
|
|
/*//realign bits
|
|
for(uint8_t i=0; i<packet_length; i++)
|
|
buffer[i]=buffer[i+2];
|
|
//for(uint8_t i=0; i<packet_length; i++)
|
|
// buffer[i]=(buffer[i]<<4)+(buffer[i+1]>>4);
|
|
|
|
//check for validity and decode
|
|
memset(packet_in,0,packet_length);
|
|
for(uint8_t i=0; i<packet_length-2; i++)
|
|
{
|
|
for(uint8_t j=0;j<2;j++)
|
|
{
|
|
packet_in[i>>2] >>= 1;
|
|
if( (buffer[i]&0xC0) == 0xC0 && (buffer[i]&0x30) == 0x00 )
|
|
packet_in[i>>2] |= 0x80;
|
|
else if( (buffer[i]&0xC0) == 0x00 && (buffer[i]&0x30) == 0x30 )
|
|
packet_in[i>>2] |= 0x00;
|
|
else
|
|
ok=false; // error
|
|
buffer[i] <<= 4;
|
|
}
|
|
}
|
|
if(ok)
|
|
{
|
|
debug("P:(%02X,%02X):",packet[0],packet[1]);
|
|
for(uint8_t i=0;i<packet_length/4;i++)
|
|
debug(" %02X",packet_in[i]);
|
|
debugln("");
|
|
memcpy(packet_in,packet,packet_length);
|
|
}
|
|
}*/
|
|
/*crc=0;
|
|
for (uint8_t i = 1; i < 12; ++i)
|
|
crc16_update( packet[i], 8);
|
|
if(packet[12]==((crc>>8)&0xFF) && packet[13]==(crc&0xFF))
|
|
if(memcmp(&packet_in[1],&packet[1],packet_length-1))
|
|
{
|
|
debug("P:");
|
|
for(uint8_t i=0;i<packet_length;i++)
|
|
debug(" %02X",packet[i]);
|
|
debug(" CRC: %04X",crc);
|
|
debugln("");
|
|
debug("P(%02X):",packet[0]);
|
|
for(uint8_t i=1;i<packet_length-2;i++)
|
|
debug(" %02X",((bit_reverse(packet[i])<<1)|(bit_reverse(packet[i-1])>>7))&0xFF);
|
|
debugln("");
|
|
memcpy(packet_in,packet,packet_length);
|
|
}*/
|
|
}
|
|
// restart RX mode
|
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
|
NRF24L01_SetTxRxMode(RX_EN);
|
|
NRF24L01_FlushRx();
|
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX)); // _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) |
|
|
}
|
|
}
|
|
}
|
|
bind_counter++;
|
|
if(IS_RX_FLAG_on) // Let the radio update the protocol
|
|
{
|
|
if(Update_All()) return 10000; // New protocol selected
|
|
if(prev_option!=option && sub_protocol<XN297DUMP_AUTO)
|
|
{ // option has changed
|
|
hopping_frequency_no=option;
|
|
prev_option=option;
|
|
}
|
|
}
|
|
XN297Dump_overflow();
|
|
}
|
|
return 100;
|
|
}
|
|
|
|
void XN297Dump_init(void)
|
|
{
|
|
BIND_DONE;
|
|
if(sub_protocol<XN297DUMP_AUTO)
|
|
bitrate=sub_protocol;
|
|
else
|
|
bitrate=0;
|
|
address_length=RX_num;
|
|
if(address_length<3||address_length>5)
|
|
address_length=5; //default
|
|
XN297Dump_RF_init();
|
|
bind_counter=0;
|
|
rf_ch_num=0xFF;
|
|
prev_option=option^0x55;
|
|
phase=0; // init
|
|
}
|
|
|
|
#endif
|