199 lines
6.1 KiB
Arduino
Raw Normal View History

/*
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/>.
*/
#ifdef XN297DUMP_NRF24L01_INO
#include "iface_nrf24l01.h"
// Parameters which can be modified
#define XN297DUMP_ADDRESS_LENGTH 5 // Default address length is 5, valid address length is between 3 and 5
#define XN297DUMP_PERIOD_DUMP 2000 // Multiplied by 50, default 2000=100ms
#define XN297DUMP_MAX_RF_CHANNEL 84 // Default 84
// Do not touch from there
#define XN297DUMP_INITIAL_WAIT 500
#define XN297DUMP_MAX_PACKET_LEN 32
#define XN297DUMP_CRC_LENGTH 2
static void __attribute__((unused)) XN297Dump_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(RX_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 Acknowledgment on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
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, scramble=%c, address length=%d, speed=",RX_num?'N':'Y', XN297DUMP_ADDRESS_LENGTH);
switch(sub_protocol)
{
case 0:
NRF24L01_SetBitrate(NRF24L01_BR_250K);
debugln("250K");
break;
case 2:
NRF24L01_SetBitrate(NRF24L01_BR_2M);
debugln("2M");
break;
default:
NRF24L01_SetBitrate(NRF24L01_BR_1M);
debugln("1M");
break;
}
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
NRF24L01_SetPower();
}
static boolean __attribute__((unused)) XN297Dump_process_packet(void)
{
uint8_t packet_ori[XN297DUMP_MAX_PACKET_LEN];
memcpy(packet_ori,packet,XN297DUMP_MAX_PACKET_LEN);
packet_length=XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH;
while(packet_length > XN297DUMP_ADDRESS_LENGTH)
{
// init crc
crc = 0xb5d2;
// unscramble address
for (uint8_t i = 0; i < XN297DUMP_ADDRESS_LENGTH; i++)
{
crc = crc16_update(crc, packet[i], 8);
rx_id[i]=packet[i];
if (!RX_num)
rx_id[i] ^= xn297_scramble[i];
}
// reverse address order
for (uint8_t i = 0; i < XN297DUMP_ADDRESS_LENGTH; i++)
packet[i]=rx_id[XN297DUMP_ADDRESS_LENGTH-1-i];
// unscramble payload
for (uint8_t i = XN297DUMP_ADDRESS_LENGTH; i < packet_length; i++)
{
crc = crc16_update(crc, packet[i], 8);
if (!RX_num)
packet[i] ^= xn297_scramble[i];
packet[i] = bit_reverse(packet[i]);
}
// check crc
if (RX_num)
crc ^= pgm_read_word(&xn297_crc_xorout[packet_length - 3]);
else
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[packet_length - 3]);
if( (crc >> 8) == packet[packet_length] && (crc & 0xff) == packet[packet_length + 1])
return true;
packet_length--;
memcpy(packet,packet_ori,XN297DUMP_MAX_PACKET_LEN);
}
return false;
}
static uint16_t XN297Dump_callback()
{
if(option==0xFF && bind_counter>XN297DUMP_PERIOD_DUMP)
{ // 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));
}
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);
debug_time("RX: ");
2019-05-09 18:23:19 +02:00
debug("us C=%d ", hopping_frequency_no);
if(XN297Dump_process_packet())
{ // valid crc found
debug("A=");
for(uint8_t i=0; i<XN297DUMP_ADDRESS_LENGTH; i++)
{
debug(" %02X",packet[i]);
}
debug(" P(%d)=",packet_length-XN297DUMP_ADDRESS_LENGTH);
for(uint8_t i=XN297DUMP_ADDRESS_LENGTH; i<packet_length; i++)
{
debug(" %02X",packet[i]);
}
debugln("");
}
else
{
debugln("Bad CRC");
}
}
// 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));
}
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)
{ // option has changed
hopping_frequency_no=option;
prev_option=option;
}
}
return 50;
}
uint16_t initXN297Dump(void)
{
BIND_DONE;
XN297Dump_init();
bind_counter=0;
rf_ch_num=0xFF;
prev_option=option^0x55;
return XN297DUMP_INITIAL_WAIT;
}
#endif