2019-06-05 21:54:47 +02:00
|
|
|
/*
|
|
|
|
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/>.
|
|
|
|
*/
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef NRF24L01_INSTALLED
|
2019-06-05 21:54:47 +02:00
|
|
|
#include "iface_xn297l.h"
|
|
|
|
|
|
|
|
static void __attribute__((unused)) XN297L_Init()
|
|
|
|
{
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
{//NRF
|
|
|
|
debugln("Using NRF");
|
|
|
|
PE1_on; //NRF24L01 antenna RF3 by default
|
|
|
|
PE2_off; //NRF24L01 antenna RF3 by default
|
|
|
|
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();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//CC2500
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
debugln("Using CC2500");
|
|
|
|
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();
|
|
|
|
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
|
|
|
|
{
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
{//NRF
|
|
|
|
XN297_SetTXAddr(addr,len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//CC2500
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if (len > 5) len = 5;
|
|
|
|
if (len < 3) len = 3;
|
|
|
|
xn297_addr_len = len;
|
|
|
|
memcpy(xn297_tx_addr, addr, len);
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
|
|
|
|
{
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
{//NRF
|
|
|
|
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);
|
|
|
|
return;
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
2020-01-12 14:06:27 +01:00
|
|
|
//CC2500
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
uint8_t buf[32];
|
|
|
|
uint8_t last = 0;
|
|
|
|
uint8_t i;
|
|
|
|
static const uint16_t initial = 0xb5d2;
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
// address
|
|
|
|
for (i = 0; i < xn297_addr_len; ++i)
|
|
|
|
{
|
|
|
|
buf[last] = xn297_tx_addr[xn297_addr_len - i - 1];
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
buf[last] ^= xn297_scramble[i];
|
|
|
|
last++;
|
|
|
|
}
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
// payload
|
|
|
|
for (i = 0; i < len; ++i) {
|
|
|
|
// bit-reverse bytes in packet
|
|
|
|
buf[last] = bit_reverse(msg[i]);
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
buf[last] ^= xn297_scramble[xn297_addr_len+i];
|
|
|
|
last++;
|
|
|
|
}
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
// crc
|
|
|
|
uint16_t crc = initial;
|
|
|
|
for (uint8_t i = 0; i < last; ++i)
|
|
|
|
crc = crc16_update(crc, buf[i], 8);
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
|
|
|
|
else
|
|
|
|
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
|
|
|
|
buf[last++] = crc >> 8;
|
|
|
|
buf[last++] = crc & 0xff;
|
|
|
|
|
|
|
|
// stop TX/RX
|
2019-06-05 21:54:47 +02:00
|
|
|
CC2500_Strobe(CC2500_SIDLE);
|
2020-01-12 14:06:27 +01:00
|
|
|
// 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);
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
|
2019-06-05 21:54:47 +02:00
|
|
|
{
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
{//NRF
|
|
|
|
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_WriteEnhancedPayload(msg, len, noack);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//CC2500
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
uint8_t buf[32];
|
|
|
|
uint8_t scramble_index=0;
|
|
|
|
uint8_t last = 0;
|
|
|
|
static uint8_t pid=0;
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
// address
|
|
|
|
if (xn297_addr_len < 4)
|
|
|
|
{
|
|
|
|
// If address length (which is defined by receive address length)
|
|
|
|
// is less than 4 the TX address can't fit the preamble, so the last
|
|
|
|
// byte goes here
|
|
|
|
buf[last++] = 0x55;
|
|
|
|
}
|
|
|
|
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
|
|
|
{
|
|
|
|
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
buf[last] ^= xn297_scramble[scramble_index++];
|
|
|
|
last++;
|
|
|
|
}
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
// pcf
|
|
|
|
buf[last] = (len << 1) | (pid>>1);
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
buf[last] ^= xn297_scramble[scramble_index++];
|
|
|
|
last++;
|
|
|
|
buf[last] = (pid << 7) | (noack << 6);
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
// payload
|
|
|
|
buf[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
buf[last] ^= xn297_scramble[scramble_index++];
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
for (uint8_t i = 0; i < len-1; ++i)
|
|
|
|
{
|
|
|
|
last++;
|
|
|
|
buf[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
buf[last] ^= xn297_scramble[scramble_index++];
|
|
|
|
}
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
last++;
|
|
|
|
buf[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
|
|
|
|
if(xn297_scramble_enabled)
|
|
|
|
buf[last] ^= xn297_scramble[scramble_index++] & 0xc0;
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
// crc
|
|
|
|
if (xn297_crc)
|
|
|
|
{
|
|
|
|
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
|
|
|
|
uint16_t crc = 0xb5d2;
|
|
|
|
for (uint8_t i = offset; i < last; ++i)
|
|
|
|
crc = crc16_update(crc, buf[i], 8);
|
|
|
|
crc = crc16_update(crc, buf[last] & 0xc0, 2);
|
|
|
|
if (xn297_scramble_enabled)
|
|
|
|
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
|
|
|
|
//else
|
|
|
|
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
|
2019-06-05 21:54:47 +02:00
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
buf[last++] |= (crc >> 8) >> 2;
|
|
|
|
buf[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
|
|
|
|
buf[last++] = (crc & 0xff) << 6;
|
|
|
|
}
|
|
|
|
NRF24L01_WritePayload(packet, last);
|
|
|
|
|
|
|
|
pid++;
|
|
|
|
if(pid>3)
|
|
|
|
pid=0;
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
2020-01-12 14:06:27 +01:00
|
|
|
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
|
2019-06-05 21:54:47 +02:00
|
|
|
{ //calibrate hopping frequencies
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
return; //NRF
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
|
|
|
|
{
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
{//NRF
|
|
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
// 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]);
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
|
|
|
|
{ //change channel
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
{//NRF
|
|
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
CC2500_Strobe(CC2500_SIDLE);
|
|
|
|
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
|
|
|
|
CC2500_Strobe(CC2500_SCAL);
|
|
|
|
delayMicroseconds(900);
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((unused)) XN297L_SetPower()
|
|
|
|
{
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0)
|
|
|
|
#endif
|
|
|
|
{//NRF
|
|
|
|
NRF24L01_SetPower();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
CC2500_SetPower();
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((unused)) XN297L_SetFreqOffset()
|
|
|
|
{ // Frequency offset
|
2020-01-12 14:06:27 +01:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if(option==0 && prev_option==0)
|
|
|
|
#endif
|
|
|
|
return; //NRF
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
if (prev_option != option)
|
|
|
|
{
|
|
|
|
if(prev_option==0 || option==0)
|
|
|
|
CHANGE_PROTOCOL_FLAG_on;
|
|
|
|
prev_option = option;
|
|
|
|
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
|
|
|
}
|
|
|
|
#endif
|
2019-06-05 21:54:47 +02:00
|
|
|
}
|
|
|
|
#endif
|