Compare commits

...

19 Commits

Author SHA1 Message Date
pascallanger
6a9b6ed4be XN297EMU: option=0->nrf24L01, option!=0 -> CC2500
XN297L@250kbps is emulated by default with the NRF24L01. If option (freq tune) is diffrent from 0, the CC2500 module (if installed) will be used instead with option being the freq usual tuning.
2020-01-12 14:06:27 +01:00
pascallanger
953a97dae4 Flyzone: add channel 5 2020-01-12 13:17:17 +01:00
pascallanger
86778c5997 XN297Dump: new auto mode
Automatically:
 - find XN297L packet -> bitrate, scrambling, enhanced...
 - use address to filter incoming packets
 - find all frequencies
 - determine channel order (basic)
 - help to find out the changes by only displaying packets when there is a change in the packet
2020-01-12 13:16:30 +01:00
pascallanger
8c32cdf5fd Pelikan: fix TX and multi ID
Still 1 hopping freq table
2020-01-12 13:00:30 +01:00
pascallanger
d092593e5c Fix FrSky RX bind which could fail if another TX was around 2020-01-12 12:57:16 +01:00
pascallanger
edbf4b6908 Merge pull request #311 from benlye/multi-status-fix
Fix module status on erSkyTX
2020-01-11 10:20:03 +01:00
Ben Lye
43f688d011 Fix module status on erSkyTX 2020-01-10 18:25:56 +00:00
pascallanger
054c3088c3 Merge pull request #305 from Shkolik/Direct_inputs
Direct inputs
2020-01-02 17:29:45 +01:00
Andrew Shkolik
0cedd5bb66 disable myConfig 2019-12-30 16:53:12 -06:00
Andrew Shkolik
1961579fe4 code cleanup 2019-12-30 15:44:16 -06:00
Andrew Shkolik
6906f1652e Inputs logic added 2019-12-24 23:41:04 -06:00
Andrew Shkolik
e2bbe8a422 definitions for direct inputs 2019-12-24 15:03:35 -06:00
pascallanger
8ea4e00d31 Pelikan protocol fix ? 2019-12-20 15:43:44 +01:00
pascallanger
917e27280f Pelikan and Tiger protocol fixes 2019-12-20 09:29:37 +01:00
pascallanger
ec92edfc85 New protocol Tiger
Model: Tiger drone 1400782
Protocol number: 61
No sub_protocol
CH5: Flip
CH6: Light
2019-12-19 23:40:33 +01:00
pascallanger
afd2be6c59 New Pelikan protocol
Protocol number: 60
No sub proto
8 channels AETR...
Extended limit supported
!!Only 1 ID for now!!
2019-12-19 22:39:01 +01:00
pascallanger
a23d50bf0d FrSkyX add bind options CH1-8/CH9-16 & Telem ON/OFF 2019-12-19 17:26:47 +01:00
pascallanger
cace1144db Add TX_LQI (TLQY) comment 2019-12-09 10:47:17 +01:00
pascallanger
0d646ed1a6 Update Protocols_Details.md 2019-12-05 17:14:26 +01:00
20 changed files with 1450 additions and 533 deletions

View File

@@ -197,6 +197,11 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
offset=(int16_t)FORCE_FLYZONE_TUNING;
#endif
break;
case PROTO_PELIKAN:
#ifdef FORCE_PELIKAN_TUNING
offset=(int16_t)FORCE_PELIKAN_TUNING;
#endif
break;
case PROTO_AFHDS2A:
case PROTO_AFHDS2A_RX:
#ifdef FORCE_AFHDS2A_TUNING
@@ -293,6 +298,14 @@ const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
0xFF, 0xFF // 30 - 31
};
#endif
#ifdef PELIKAN_A7105_INO
const uint8_t PROGMEM PELIKAN_A7105_regs[] = {
0xff, 0x42, 0x00, 0x0F, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x01, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x07, // 10 - 1f
0x16, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x1f, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#define ID_NORMAL 0x55201041
#define ID_PLUS 0xAA201041
@@ -309,6 +322,14 @@ void A7105_Init(void)
}
else
#endif
#ifdef PELIKAN_A7105_INO
if(protocol==PROTO_PELIKAN)
{
A7105_Regs=(uint8_t*)PELIKAN_A7105_regs;
A7105_WriteID(0x06230623);
}
else
#endif
#ifdef BUGS_A7105_INO
if(protocol==PROTO_BUGS)
A7105_Regs=(uint8_t*)BUGS_A7105_regs;
@@ -391,17 +412,21 @@ void A7105_Init(void)
case PROTO_FLYZONE:
vco_calibration1=0x02;
break;
case PROTO_PELIKAN:
vco_calibration1=0x0C;
break;
default:
vco_calibration1=0x0A;
break;
}
A7105_WriteReg(A7105_25_VCO_SBCAL_I,vco_calibration1); //Reset VCO Band calibration
}
A7105_SetTxRxMode(TX_EN);
A7105_SetPower();
A7105_AdjustLOBaseFreq(0);
#ifdef USE_A7105_CH15_TUNING
A7105_AdjustLOBaseFreq(0);
#endif
A7105_Strobe(A7105_STANDBY);
}

View File

@@ -32,7 +32,7 @@ static void __attribute__((unused)) flyzone_build_packet()
packet[4] = convert_channel_8b(ELEVATOR); //00..80..FF
packet[5] = convert_channel_8b(THROTTLE); //00..FF
packet[6] = convert_channel_8b(RUDDER); //00..80..FF
packet[7] = 0xFF;
packet[7] = convert_channel_8b(CH5); //00..80..FF
}
uint16_t ReadFlyzone()

View File

@@ -85,6 +85,11 @@ static void __attribute__((unused)) FrSkyX_build_bind_packet()
//
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
memset(&packet[13], 0, limit - 13);
if(binding_idx&0x01)
memcpy(&packet[13],(void *)"\x55\xAA\x5A\xA5",4); // Telem off
if(binding_idx&0x02)
memcpy(&packet[17],(void *)"\x55\xAA\x5A\xA5",4); // CH9-16
//
uint16_t lcrc = FrSkyX_crc(&packet[3], limit-3);
//
packet[limit++] = lcrc >> 8;
@@ -431,6 +436,7 @@ uint16_t initFrSkyX()
SportHead=SportTail=0; // empty data buffer
#endif
FrSkyX_RX_Seq = 0 ; // Seq 0 to start with
binding_idx=0; // CH1-8 and Telem on
return 10000;
}
#endif

View File

@@ -310,14 +310,14 @@ uint16_t FrSky_Rx_callback()
case FRSKY_RX_TUNE_START:
if (len >= packet_length) {
CC2500_ReadData(packet, packet_length);
if(packet[1] == 0x03 && packet[2] == 0x01) {
if(frskyx_rx_check_crc()) {
frsky_rx_finetune = -127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
phase = FRSKY_RX_TUNE_LOW;
frsky_rx_strobe_rx();
return 1000;
}
if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc()) {
rx_tx_addr[0] = packet[3]; // TXID
rx_tx_addr[1] = packet[4]; // TXID
frsky_rx_finetune = -127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
phase = FRSKY_RX_TUNE_LOW;
frsky_rx_strobe_rx();
return 1000;
}
}
frsky_rx_format = (frsky_rx_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D16FCC, D16LBT, D8)
@@ -330,7 +330,7 @@ uint16_t FrSky_Rx_callback()
case FRSKY_RX_TUNE_LOW:
if (len >= packet_length) {
CC2500_ReadData(packet, packet_length);
if (frskyx_rx_check_crc()) {
if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1]) {
tune_low = frsky_rx_finetune;
frsky_rx_finetune = 127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
@@ -347,7 +347,7 @@ uint16_t FrSky_Rx_callback()
case FRSKY_RX_TUNE_HIGH:
if (len >= packet_length) {
CC2500_ReadData(packet, packet_length);
if (frskyx_rx_check_crc()) {
if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1]) {
tune_high = frsky_rx_finetune;
frsky_rx_finetune = (tune_low + tune_high) / 2;
CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frsky_rx_finetune);
@@ -367,35 +367,40 @@ uint16_t FrSky_Rx_callback()
case FRSKY_RX_BIND:
if(len >= packet_length) {
CC2500_ReadData(packet, packet_length);
if (frskyx_rx_check_crc()) {
if (packet[5] <= 0x2D) {
for (ch = 0; ch < 5; ch++)
hopping_frequency[packet[5]+ch] = packet[6+ch];
state |= 1 << (packet[5] / 5);
if(packet[1] == 0x03 && packet[2] == 0x01 && frskyx_rx_check_crc() && packet[3] == rx_tx_addr[0] && packet[4] == rx_tx_addr[1] && packet[5] <= 0x2D) {
for (ch = 0; ch < 5; ch++)
hopping_frequency[packet[5]+ch] = packet[6+ch];
state |= 1 << (packet[5] / 5);
if (state == 0x3ff) {
debug("Bind complete: ");
frsky_rx_calibrate();
rx_tx_addr[2] = packet[12]; // RX # (D16)
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[0]); // set address
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // check address
phase = FRSKY_RX_DATA;
frsky_rx_set_channel(hopping_frequency_no);
// store format, finetune setting, txid, channel list
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_format);
debug("format=%d, ", frsky_rx_format);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[0]);
debug("addr[0]=%02X, ", rx_tx_addr[0]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
debug("addr[1]=%02X, ", rx_tx_addr[1]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]);
debug("rx_num=%02X, ", rx_tx_addr[2]);
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune);
debugln("tune=%d", (int8_t)frsky_rx_finetune);
for (ch = 0; ch < 47; ch++)
{
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]);
debug("%02X ", hopping_frequency[ch]);
}
debugln("");
BIND_DONE;
}
}
if (state == 0x3ff) {
debugln("bind complete");
frsky_rx_calibrate();
rx_tx_addr[0] = packet[3]; // TXID
rx_tx_addr[1] = packet[4]; // TXID
rx_tx_addr[2] = packet[12]; // RX # (D16)
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[0]); // set address
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // check address
phase = FRSKY_RX_DATA;
frsky_rx_set_channel(hopping_frequency_no);
// store format, finetune setting, txid, channel list
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_format);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[0]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]);
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune);
for (ch = 0; ch < 47; ch++)
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]);
BIND_DONE;
}
frsky_rx_strobe_rx();
}
return 1000;

View File

@@ -56,4 +56,7 @@
56,AFHDS2A_RX
57,HoTT
58,FX816,P38
63,XN_DUMP,250K,1M,2M
59,Bayang_RX
60,Pelikan
61,Tiger
63,XN_DUMP,250K,1M,2M,AUTO

View File

@@ -73,6 +73,8 @@ const char STR_AFHDS2A_RX[] ="FS2A_RX";
const char STR_HOTT[] ="HoTT";
const char STR_FX816[] ="FX816";
const char STR_BAYANG_RX[] ="BayanRX";
const char STR_PELIKAN[] ="Pelikan";
const char STR_TIGER[] ="Tiger";
const char STR_XN297DUMP[] ="XN297DP";
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
@@ -110,8 +112,9 @@ const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
const char STR_SUBTYPE_FLYZONE[] = "\x05""FZ410";
const char STR_SUBTYPE_FX816[] = "\x03""P38";
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ";
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ";
const char STR_SUBTYPE_ESKY150[] = "\x03""4CH""7CH";
const char STR_SUBTYPE_V911S[] = "\x04""Std\0""E119";
enum
{
@@ -263,7 +266,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_E01X, STR_E01X, 3, STR_SUBTYPE_E01X, OPTION_OPTION },
#endif
#if defined(V911S_NRF24L01_INO)
{PROTO_V911S, STR_V911S, 0, NO_SUBTYPE, OPTION_NONE },
{PROTO_V911S, STR_V911S, 1, STR_SUBTYPE_V911S, OPTION_RFTUNE },
#endif
#if defined(GD00X_NRF24L01_INO)
{PROTO_GD00X, STR_GD00X, 2, STR_SUBTYPE_GD00X, OPTION_RFTUNE },
@@ -304,8 +307,14 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(BAYANG_RX_NRF24L01_INO)
{PROTO_BAYANG_RX, STR_BAYANG_RX, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(PELIKAN_A7105_INO)
{PROTO_PELIKAN, STR_PELIKAN , 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(TIGER_NRF24L01_INO)
{PROTO_TIGER, STR_TIGER , 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(XN297DUMP_NRF24L01_INO)
{PROTO_XN297DUMP, STR_XN297DUMP, 3, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN },
{PROTO_XN297DUMP, STR_XN297DUMP, 4, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN },
#endif
{0x00, nullptr, 0, nullptr, 0 }
};

View File

@@ -19,7 +19,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 0
#define VERSION_PATCH_LEVEL 47
#define VERSION_PATCH_LEVEL 53
//******************
// Protocols
@@ -86,6 +86,8 @@ enum PROTOCOLS
PROTO_HOTT = 57, // =>CC2500
PROTO_FX816 = 58, // =>NRF24L01
PROTO_BAYANG_RX = 59, // =>NRF24L01
PROTO_PELIKAN = 60, // =>A7105
PROTO_TIGER = 61, // =>NRF24L01
PROTO_XN297DUMP = 63, // =>NRF24L01
};
@@ -298,6 +300,18 @@ enum ESKY150
ESKY150_4CH = 0,
ESKY150_7CH = 1,
};
enum V911S
{
V911S_STD = 0,
V911S_E119 = 1,
};
enum XN297DUMP
{
XN297DUMP_250K = 0,
XN297DUMP_1M = 1,
XN297DUMP_2M = 2,
XN297DUMP_AUTO = 3,
};
#define NONE 0
#define P_HIGH 1
@@ -342,7 +356,7 @@ enum MultiPacketTypes
//*** Tests ***
//***************
#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX )
#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || protocol==PROTO_ESKY || protocol==PROTO_J6PRO )
#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN )
//***************
//*** Flags ***
@@ -687,6 +701,8 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
HOTT 57
FX816 58
BAYANG_RX 59
PELIKAN 60
TIGER 61
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
@@ -831,6 +847,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==ESKY150
ESKY150_4CH 0
ESKY150_7CH 1
sub_protocol==V911S
V911S_STD 0
V911S_E119 1
Power value => 0x80 0=High/1=Low
Stream[3] = option_protocol;

View File

@@ -179,7 +179,7 @@ volatile uint8_t rx_idx=0, rx_len=0;
// Telemetry
#define TELEMETRY_BUFFER_SIZE 30
#define TELEMETRY_BUFFER_SIZE 32
uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets
#if defined(TELEMETRY)
#ifdef MULTI_SYNC
@@ -331,6 +331,22 @@ void setup()
pinMode(S2_pin,INPUT_PULLUP);
pinMode(S3_pin,INPUT_PULLUP);
pinMode(S4_pin,INPUT_PULLUP);
#if defined ENABLE_DIRECT_INPUTS
#if defined (DI1_PIN)
pinMode(DI1_PIN,INPUT_PULLUP);
#endif
#if defined (DI2_PIN)
pinMode(DI2_PIN,INPUT_PULLUP);
#endif
#if defined (DI3_PIN)
pinMode(DI3_PIN,INPUT_PULLUP);
#endif
#if defined (DI4_PIN)
pinMode(DI4_PIN,INPUT_PULLUP);
#endif
#endif
//Random pins
pinMode(PB0, INPUT_ANALOG); // set up pin for analog input
@@ -666,8 +682,29 @@ bool Update_All()
if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received
{
uint32_t chan_or=chan_order;
uint8_t ch;
for(uint8_t i=0;i<PPM_chan_max;i++)
uint8_t ch;
uint8_t channelsCount = PPM_chan_max;
#ifdef ENABLE_DIRECT_INPUTS
#ifdef DI_CH1_read
PPM_data[channelsCount] = DI_CH1_read;
channelsCount++;
#endif
#ifdef DI_CH2_read
PPM_data[channelsCount] = DI_CH2_read;
channelsCount++;
#endif
#ifdef DI_CH3_read
PPM_data[channelsCount] = DI_CH3_read;
channelsCount++;
#endif
#ifdef DI_CH4_read
PPM_data[channelsCount] = DI_CH4_read;
channelsCount++;
#endif
#endif
for(uint8_t i=0;i<channelsCount;i++)
{ // update servo data without interrupts to prevent bad read
uint16_t val;
cli(); // disable global int
@@ -1058,6 +1095,13 @@ static void protocol_init()
remote_callback = AFHDS2A_Rx_callback;
break;
#endif
#if defined(PELIKAN_A7105_INO)
case PROTO_PELIKAN:
PE1_off; //antenna RF1
next_callback = initPelikan();
remote_callback = ReadPelikan;
break;
#endif
#endif
#ifdef CC2500_INSTALLED
#if defined(FRSKYD_CC2500_INO)
@@ -1428,6 +1472,12 @@ static void protocol_init()
remote_callback = Bayang_Rx_callback;
break;
#endif
#if defined(TIGER_NRF24L01_INO)
case PROTO_TIGER:
next_callback=initTIGER();
remote_callback = TIGER_callback;
break;
#endif
#if defined(XN297DUMP_NRF24L01_INO)
case PROTO_XN297DUMP:
next_callback=initXN297Dump();
@@ -1709,6 +1759,12 @@ void update_serial_data()
#endif
if(rx_len>27)
{ // Data available for the current protocol
#ifdef FRSKYX_CC2500_INO
if(protocol==PROTO_FRSKYX && rx_len==28)
{//Protocol waiting for 1 byte during bind
binding_idx=rx_ok_buff[27];
}
#endif
#ifdef SPORT_SEND
if(protocol==PROTO_FRSKYX && rx_len==35)
{//Protocol waiting for 8 bytes

View File

@@ -505,7 +505,7 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_tx_addr[xn297_addr_len-i-1];
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc = crc16_update(crc, b_in, 8);
@@ -525,10 +525,13 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{
{ //!!! Don't forget do a +2 and if using CRC add +2 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
NRF24L01_ReadPayload(buffer, len+2); // pcf + payload
if (xn297_crc)
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
else
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
pcf_size = buffer[0];
if(xn297_scramble_enabled)
pcf_size ^= xn297_scramble[xn297_addr_len];
@@ -540,7 +543,35 @@ uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
(xn297_scramble[xn297_addr_len+i+2] >> 6));
}
return pcf_size;
if (!xn297_crc)
return pcf_size; // No CRC so OK by default...
// Calculate CRC
uint16_t crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc = crc16_update(crc, b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len+1; ++i)
crc = crc16_update(crc, buffer[i], 8);
crc = crc16_update(crc, buffer[len+1] & 0xc0, 2);
//xorout
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
#ifdef XN297DUMP_NRF24L01_INO
else
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
#endif
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
if( crc == crcxored)
return pcf_size; // CRC OK
return 0; // CRC NOK
}
// End of XN297 emulation

View File

@@ -0,0 +1,157 @@
/*
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/>.
*/
// Compatible with CADET PRO V4 TX
#if defined(PELIKAN_A7105_INO)
#include "iface_a7105.h"
//#define PELIKAN_FORCE_ID
#define PELIKAN_BIND_COUNT 400
#define PELIKAN_BIND_RF 0x3C
#define PELIKAN_NUM_RF_CHAN 0x1D
#define PELIKAN_PAQUET_PERIOD 7980
static void __attribute__((unused)) pelikan_build_packet()
{
static boolean upper=false;
packet[0] = 0x15;
if(IS_BIND_IN_PROGRESS)
{
packet[1] = 0x04; //version??
packet[2] = rx_tx_addr[0];
packet[3] = rx_tx_addr[1];
packet[4] = rx_tx_addr[2];
packet[5] = rx_tx_addr[3];
packet[6] = 0x05; //??
packet[7] = 0x00; //??
packet[8] = 0x55; //??
packet_length = 10;
}
else
{
//ID
packet[1] = rx_tx_addr[0];
packet[7] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2];
packet[13] = rx_tx_addr[3];
//Channels
uint8_t offset=upper?4:0;
uint16_t channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
uint8_t top=(channel>>2) & 0xC0;
packet[2] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
top|=(channel>>4) & 0x30;
packet[3] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
top|=(channel>>6) & 0x0C;
packet[4] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871);
top|=(channel>>8) & 0x03;
packet[5] = channel;
packet[6] = top;
//Check
crc8=0x15;
for(uint8_t i=1;i<8;i++)
crc8+=packet[i];
packet[8]=crc8;
//Low/Up channel flag
packet[9]=upper?0xAA:0x00;
upper=!upper;
//Hopping counters
if(++packet_count>4)
{
packet_count=0;
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
hopping_frequency_no=0;
}
packet[10]=hopping_frequency_no;
packet[11]=packet_count;
packet_length = 15;
}
//Check
crc8=0x15;
for(uint8_t i=1; i<packet_length-1 ;i++)
crc8+=packet[i];
packet[packet_length-1]=crc8;
//Send
#ifdef DEBUG_SERIAL
if(packet[9]==0x00)
{
debug("C: %02X P(%d):",IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no],packet_length);
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
debugln("");
}
#endif
A7105_WriteData(packet_length, IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no]);
A7105_SetPower();
}
uint16_t ReadPelikan()
{
#ifndef FORCE_PELIKAN_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
{
bind_counter--;
if (bind_counter==0)
{
BIND_DONE;
A7105_Strobe(A7105_STANDBY);
A7105_WriteReg(A7105_03_FIFOI,0x28);
}
}
#ifdef MULTI_SYNC
telemetry_set_input_sync(PELIKAN_PAQUET_PERIOD);
#endif
pelikan_build_packet();
return PELIKAN_PAQUET_PERIOD;
}
const uint8_t PROGMEM pelikan_hopp[][PELIKAN_NUM_RF_CHAN] = {
{ 0x5A,0x46,0x32,0x6E,0x6C,0x58,0x44,0x42,0x40,0x6A,0x56,0x54,0x52,0x3E,0x68,0x66,0x64,0x50,0x3C,0x3A,0x38,0x62,0x4E,0x4C,0x5E,0x4A,0x36,0x5C,0x34 }
};
uint16_t initPelikan()
{
A7105_Init();
if(IS_BIND_IN_PROGRESS)
A7105_WriteReg(A7105_03_FIFOI,0x10);
//ID from dump
#ifdef PELIKAN_FORCE_ID
rx_tx_addr[0]=0x0D; // hopping freq
rx_tx_addr[1]=0xF4; // hopping freq
rx_tx_addr[2]=0x50; // ID
rx_tx_addr[3]=0x18; // ID
#endif
// Fill frequency table
rx_tx_addr[0]=0x0D; // hopping freq
rx_tx_addr[1]=0xF4; // hopping freq
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
hopping_frequency[i]=pgm_read_byte_near(&pelikan_hopp[0][i]);
hopping_frequency_no=PELIKAN_NUM_RF_CHAN;
packet_count=5;
return 2400;
}
#endif

View File

@@ -125,7 +125,11 @@ static void multi_send_status()
multi_send_header(MULTI_TELEMETRY_STATUS, 24);
else
#endif
#ifdef MULTI_TELEMETRY
multi_send_header(MULTI_TELEMETRY_STATUS, 6);
#else
multi_send_header(MULTI_TELEMETRY_STATUS, 6);
#endif
// Build flags
uint8_t flags=0;
@@ -166,8 +170,10 @@ static void multi_send_status()
Serial_write(VERSION_REVISION);
Serial_write(VERSION_PATCH_LEVEL);
// Channel order
Serial_write(RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON);
#ifdef MULTI_TELEMETRY
// Channel order
Serial_write(RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON);
#endif
#ifdef MULTI_NAMES
if(multi_protocols_index != 0xFF)

View File

@@ -0,0 +1,182 @@
/*
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/>.
*/
// Compatible with Tiger Drone 1400782.
#if defined(TIGER_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define TIGER_FORCE_ID
#define TIGER_INITIAL_WAIT 500
#define TIGER_PACKET_PERIOD 3940
#define TIGER_RF_NUM_CHANNELS 4
#define TIGER_BIND_RF_NUM_CHANNELS 8
#define TIGER_PAYLOAD_SIZE 16
#define TIGER_BIND_COUNT 761 //3sec
static uint8_t __attribute__((unused)) TIGER_convert_channel(uint8_t num)
{
uint8_t val=convert_channel_8b(num);
// 7F..01=left, 00=center, 80..FF=right
if(val==0x80)
val=0; // 0
else
if(val>0x80)
val--; // 80..FE
else
{
val=0x80-val; // 80..01
if(val==0x80)
val--; // 7F..01
}
return val;
}
static void __attribute__((unused)) TIGER_send_packet()
{
if(IS_BIND_DONE)
{
//Channels
packet[0]=convert_channel_8b(THROTTLE); // 00..FF
packet[1]=TIGER_convert_channel(RUDDER); // 7F..01=left, 00=center, 80..FF=right
packet[2]=TIGER_convert_channel(ELEVATOR); // 7F..01=down, 00=center, 80..FF=up
packet[3]=TIGER_convert_channel(AILERON); // 7F..01=left, 00=center, 80..FF=right
//Flags
packet[14]= GET_FLAG(CH5_SW, 0x04) //FLIP
| GET_FLAG(CH6_SW, 0x10); //LIGHT
}
//Check
crc8=0;
for(uint8_t i=0;i<TIGER_PAYLOAD_SIZE-1;i++)
crc8+=packet[i];
packet[TIGER_PAYLOAD_SIZE-1]=crc8;
//Hopping frequency
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no>>1]);
hopping_frequency_no++;
if(IS_BIND_IN_PROGRESS)
{
if(hopping_frequency_no>=2*TIGER_BIND_RF_NUM_CHANNELS)
hopping_frequency_no=0;
}
else
{
if(hopping_frequency_no>=2*(TIGER_BIND_RF_NUM_CHANNELS+TIGER_RF_NUM_CHANNELS))
hopping_frequency_no=2*TIGER_BIND_RF_NUM_CHANNELS;
}
//Clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
//Send packet
XN297_WritePayload(packet, TIGER_PAYLOAD_SIZE);
//Set tx_power
NRF24L01_SetPower();
}
static void __attribute__((unused)) TIGER_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x68\x94\xA6\xD5\xC3", 5);
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_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
NRF24L01_SetPower();
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);
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
}
static void __attribute__((unused)) TIGER_initialize_txid()
{
#ifdef TIGER_FORCE_ID
rx_tx_addr[0]=0x64;
rx_tx_addr[1]=0x39;
rx_tx_addr[2]=0x12;
rx_tx_addr[3]=0x00;
rx_tx_addr[4]=0x00;
memcpy(hopping_frequency,"\x0E\x39\x1C\x07\x24\x3E\x2B\x47",TIGER_BIND_RF_NUM_CHANNELS);
memcpy(&hopping_frequency[TIGER_BIND_RF_NUM_CHANNELS],"\x36\x41\x37\x4E",TIGER_RF_NUM_CHANNELS);
#endif
//prepare bind packet
memset(&packet[0], 0x00, 4);
memset(&packet[4], 0x40, 10);
memcpy(&packet[7], rx_tx_addr, 5);
packet[14]=0xC0;
}
uint16_t TIGER_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(TIGER_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr((uint8_t *)"\x49\xA6\x83\xEB\x4B", 5);
}
TIGER_send_packet();
return TIGER_PACKET_PERIOD;
}
uint16_t initTIGER()
{
BIND_IN_PROGRESS; // autobind protocol
TIGER_initialize_txid();
TIGER_init();
hopping_frequency_no = 0;
bind_counter=TIGER_BIND_COUNT;
return TIGER_INITIAL_WAIT;
}
#endif
/*Bind
- RF setup: 1Mbps, scrambled, CRC
- TX addr: 0x68 0x94 0xA6 0xD5 0xC3
- 8 RF channels: 0x0E 0x39 0x1C 0x07 0x24 0x3E 0x2B 0x47
- 2 packets per RF channel, 3940µs between packets
- payload 16 bytes: 0x00 0x00 0x00 0x00 0x40 0x40 0x40 0x64 0x39 0x12 0x00 0x00 0x40 0x40 0xC0 0xAF
- payload[15]=sum of payload[0..14]
- the only difference with normal packets is the payload[14]=0xC0
- ??? payload[7..11] TX ID ???
Normal
- RF setup: 1Mbps
- TX addr: 0x49 0xA6 0x83 0xEB 0x4B
- 4 RF channels: 0x36 0x41 0x37 0x4E
- 2 packets per RF channel, 3940µs between packets
- payload 16 bytes: 0x00 0x00 0x00 0x00 0x40 0x40 0x40 0x64 0x39 0x12 0x00 0x00 0x40 0x40 0x00 0xEF
- payload[15]=sum of payload[0..14]
- throttle is on payload[0] 00..FF
- rudder is on payload[1] 00=center, 80..FF=right, 01..7F=left
- elevator is on payload[2] 00=center, 80..FF=up, 01..7F=down
- aileron is on payload[3] 00=center, 80..FF=right, 01..7F=left
- trims payload[4..6]
- ??? payload[7..11] TX ID ???
- ??? payload[12..13] ???
- flip is on payload[14] and flag 0x04
- light is on payload[14] and flag 0x10
*/

View File

@@ -1,180 +0,0 @@
/*
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/>.
*/
// compatible with V911S
#if defined(V911S_NRF24L01_INO)
#include "iface_nrf24l01.h"
//#define V911S_ORIGINAL_ID
#define V911S_PACKET_PERIOD 5000
#define V911S_BIND_PACKET_PERIOD 3300
#define V911S_INITIAL_WAIT 500
#define V911S_PACKET_SIZE 16
#define V911S_RF_BIND_CHANNEL 35
#define V911S_NUM_RF_CHANNELS 8
#define V911S_BIND_COUNT 200
// flags going to packet[1]
#define V911S_FLAG_EXPERT 0x04
// flags going to packet[2]
#define V911S_FLAG_CALIB 0x01
static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
{
if(bind)
{
packet[0] = 0x42;
packet[1] = 0x4E;
packet[2] = 0x44;
for(uint8_t i=0;i<5;i++)
packet[i+3] = rx_tx_addr[i];
for(uint8_t i=0;i<8;i++)
packet[i+8] = hopping_frequency[i];
}
else
{
uint8_t channel=hopping_frequency_no;
if(rf_ch_num&1)
{
if((hopping_frequency_no&1)==0)
channel+=8;
channel>>=1;
}
if(rf_ch_num&2)
channel=7-channel;
packet[ 0]=(rf_ch_num<<3)|channel;
packet[ 1]=V911S_FLAG_EXPERT; // short press on left button
packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button
memset(packet+3, 0x00, V911S_PACKET_SIZE - 3);
//packet[3..6]=trims TAER signed
uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF);
packet[ 7] = ch;
packet[ 8] = ch>>8;
ch=convert_channel_16b_limit(AILERON ,0x7FF,0);
packet[ 8]|= ch<<3;
packet[ 9] = ch>>5;
ch=convert_channel_16b_limit(ELEVATOR,0,0x7FF);
packet[10] = ch;
packet[11] = ch>>8;
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
packet[11]|= ch<<3;
packet[12] = ch>>5;
}
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (!bind)
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[channel]);
hopping_frequency_no++;
hopping_frequency_no&=7; // 8 RF channels
}
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, V911S_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) V911S_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x4B\x4E\x42\x4E\x44", 5); // Bind address
NRF24L01_WriteReg(NRF24L01_05_RF_CH, V911S_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();
}
static void __attribute__((unused)) V911S_initialize_txid()
{
//channels
uint8_t offset=rx_tx_addr[3]%5; // 0-4
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x10+i*5+offset;
if(!offset) hopping_frequency[0]++;
// channels order
rf_ch_num=random(0xfefefefe)&0x03; // 0-3
}
uint16_t V911S_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(V911S_PACKET_PERIOD);
#endif
V911S_send_packet(0);
}
else
{
if (bind_counter == 0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 5);
packet_period=V911S_PACKET_PERIOD;
}
else
{
V911S_send_packet(1);
bind_counter--;
if(bind_counter==100) // same as original TX...
packet_period=V911S_BIND_PACKET_PERIOD*3;
}
}
return packet_period;
}
uint16_t initV911S(void)
{
V911S_initialize_txid();
#ifdef V911S_ORIGINAL_ID
rx_tx_addr[0]=0xA5;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0x70;
rx_tx_addr[3]=0x8D;
rx_tx_addr[4]=0x76;
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x10+i*5;
hopping_frequency[0]++;
rf_ch_num=0;
#endif
V911S_init();
if(IS_BIND_IN_PROGRESS)
{
bind_counter = V911S_BIND_COUNT;
packet_period= V911S_BIND_PACKET_PERIOD;
}
else
{
XN297_SetTXAddr(rx_tx_addr, 5);
packet_period= V911S_PACKET_PERIOD;
}
hopping_frequency_no=0;
return V911S_INITIAL_WAIT;
}
#endif

View File

@@ -14,11 +14,11 @@
*/
// compatible with V911S
#if defined(V911S_XN297L_INO)
#if defined(V911S_NRF24L01_INO)
#include "iface_xn297l.h"
//#define V911S_ORIGINAL_ID
#define V911S_ORIGINAL_ID
#define V911S_PACKET_PERIOD 5000
#define V911S_BIND_PACKET_PERIOD 3300
@@ -82,7 +82,10 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
hopping_frequency_no&=7; // 8 RF channels
}
XN297L_WritePayload(packet, V911S_PACKET_SIZE);
if(sub_protocol==V911S_STD)
XN297L_WritePayload(packet, V911S_PACKET_SIZE);
else
XN297L_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, bind);
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
@@ -91,7 +94,10 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
static void __attribute__((unused)) V911S_init()
{
XN297L_Init();
XN297L_SetTXAddr((uint8_t *)"KNBND",5); // Bind address
if(sub_protocol==V911S_STD)
XN297L_SetTXAddr((uint8_t *)"KNBND",5); // V911S Bind address
else
XN297L_SetTXAddr((uint8_t *)"XPBND",5); // E119 Bind address
XN297L_HoppingCalib(V911S_NUM_RF_CHANNELS); // Calibrate all channels
XN297L_RFChannel(V911S_RF_BIND_CHANNEL); // Set bind channel
}
@@ -140,15 +146,30 @@ uint16_t initV911S(void)
{
V911S_initialize_txid();
#ifdef V911S_ORIGINAL_ID
rx_tx_addr[0]=0xA5;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0x70;
rx_tx_addr[3]=0x8D;
rx_tx_addr[4]=0x76;
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x10+i*5;
hopping_frequency[0]++;
rf_ch_num=0;
if(sub_protocol==V911S_STD)
{//V911S
rx_tx_addr[0]=0xA5;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0x70;
rx_tx_addr[3]=0x8D;
rx_tx_addr[4]=0x76;
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x10+i*5;
hopping_frequency[0]++;
rf_ch_num=0;
}
else
{
//E119
rx_tx_addr[0]=0x30;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0xD1;
rx_tx_addr[3]=0x2C;
rx_tx_addr[4]=0x2A;
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x0E + i*5;
rf_ch_num=0;
}
#endif
V911S_init();

View File

@@ -130,6 +130,11 @@
#error "The Flyzone forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_PELIKAN_TUNING
#if ( FORCE_PELIKAN_TUNING < -300 ) || ( FORCE_PELIKAN_TUNING > 300 )
#error "The Pelikan forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_HUBSAN_TUNING
#if ( FORCE_HUBSAN_TUNING < -300 ) || ( FORCE_HUBSAN_TUNING > 300 )
#error "The Hubsan forced frequency tuning value is outside of the range -300..300."
@@ -146,6 +151,9 @@
#ifndef FORCE_FLYZONE_TUNING
#define FORCE_FLYZONE_TUNING 0
#endif
#ifndef FORCE_PELIKAN_TUNING
#define FORCE_PELIKAN_TUNING 0
#endif
#ifndef FORCE_HUBSAN_TUNING
#define FORCE_HUBSAN_TUNING 0
#endif
@@ -180,6 +188,7 @@
#undef BUGS_A7105_INO
#undef FLYZONE_A7105_INO
#undef AFHDS2A_RX_A7105_INO
#undef PELIKAN_A7105_INO
#endif
#ifndef CYRF6936_INSTALLED
#undef DEVO_CYRF6936_INO
@@ -198,7 +207,6 @@
#undef CORONA_CC2500_INO
#undef REDPINE_CC2500_INO
#undef HITEC_CC2500_INO
#undef XN297L_CC2500_EMU
#undef SCANNER_CC2500_INO
#undef FRSKY_RX_CC2500_INO
#undef HOTT_CC2500_INO
@@ -236,10 +244,10 @@
#undef E01X_NRF24L01_INO
#undef V761_NRF24L01_INO
#undef V911S_NRF24L01_INO
#undef XN297L_CC2500_EMU
#undef POTENSIC_NRF24L01_INO
#undef ZSX_NRF24L01_INO
#undef BAYANG_RX_NRF24L01_INO
#undef TIGER_NRF24L01_INO
#endif
//Make sure telemetry is selected correctly
@@ -347,9 +355,7 @@
#if not defined(MULTI_TELEMETRY)
#undef MULTI_SYNC
#undef MULTI_NAMES
#endif
#if defined(MULTI_TELEMETRY)
#else
#define MULTI_NAMES
#endif
@@ -404,3 +410,18 @@
#if defined (STM32_BOARD) && defined (DEBUG_SERIAL) && defined (NRF24L01_INSTALLED)
#define XN297DUMP_NRF24L01_INO
#endif
//Check if Direct inputs defined correctly
#if defined (ENABLE_DIRECT_INPUTS)
#if not defined (STM32_BOARD) || not defined (ENABLE_PPM) || defined (ENABLE_SERIAL)
#error You can enable dirct inputs only in PPM mode and only for STM32 board.
#endif
#if not defined (DI1_PIN) && not defined (DI2_PIN) && not defined (DI3_PIN) && not defined (DI4_PIN)
#error You must define at least 1 direct input pin or undefine ENABLE_DIRECT_INPUTS in config.
#endif
#if not defined (DI_CH1_read) && not defined (DI_CH2_read) && not defined (DI_CH3_read) && not defined (DI_CH4_read)
#error You must define at least 1 direct input chanell read macros or undefine ENABLE_DIRECT_INPUTS in config.
#endif
#endif

View File

@@ -33,6 +33,10 @@
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_init()
{
@@ -48,14 +52,14 @@ static void __attribute__((unused)) XN297Dump_init()
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, speed=",address_length);
switch(sub_protocol)
debug("XN297 dump, address length=%d, bitrate=",address_length);
switch(bitrate)
{
case 0:
case XN297DUMP_250K:
NRF24L01_SetBitrate(NRF24L01_BR_250K);
debugln("250K");
break;
case 2:
case XN297DUMP_2M:
NRF24L01_SetBitrate(NRF24L01_BR_2M);
debugln("2M");
break;
@@ -76,6 +80,7 @@ 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;
@@ -142,17 +147,17 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
}
if(packet_length!=0)
{ // Found a valid CRC for the enhanced payload mode
debug("Enhanced ");
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;
debug("Wrong address length selected using %d ", address_length )
debugln("Detected wrong address length, using %d intead", address_length );
}
debug("pid=%d ",((packet_un[address_length]&0x01)<<1)|(packet_un[address_length+1]>>7));
debug("ack=%d ",(packet_un[address_length+1]>>6)&0x01);
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];
@@ -175,96 +180,449 @@ static void __attribute__((unused)) XN297Dump_overflow()
}
static uint16_t XN297Dump_callback()
{
static uint32_t time=0;
static uint32_t time=0,*time_rf;
//!!!Blocking mode protocol!!!
TX_MAIN_PAUSE_off;
tx_resume();
while(1)
{
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==0)
{
phase=1;
time=0;
}
else
time=(timeH<<16)+timeL-time;
debug("RX: %5luus C=%d ", time>>1 , hopping_frequency_no);
time=(timeH<<16)+timeL;
if(XN297Dump_process_packet())
{ // valid crc found
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("Bad CRC");
}
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();
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();
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
{
switch(phase)
{
case 0:
debugln("------------------------");
debugln("Detecting XN297 packets.");
XN297Dump_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_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:
NRF24L01_SetBitrate(NRF24L01_BR_250K);
debug("250K");
break;
case XN297DUMP_2M:
NRF24L01_SetBitrate(NRF24L01_BR_2M);
debug("2M");
break;
default:
NRF24L01_SetBitrate(NRF24L01_BR_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");
NRF24L01_Initialize();
XN297_SetScrambledMode(scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED);
XN297_SetTXAddr(rx_tx_addr,address_length);
XN297_SetRXAddr(rx_tx_addr,address_length);
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_WriteReg(NRF24L01_11_RX_PW_P0, packet_length + 2 + (enhanced?2:0) ); // 2 extra bytes for xn297 crc
NRF24L01_WriteReg(NRF24L01_05_RF_CH,0);
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
}
}
}
break;
case 2:
if(bind_counter>XN297DUMP_PERIOD_SCAN)
{ // Scan frequencies
hopping_frequency_no++;
bind_counter=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]=-1;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,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;
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();
break;
}
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();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(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))
{
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>5)
{
bind_counter=XN297DUMP_PERIOD_SCAN+1;
debug("\r\nTrying RF channel: ");
packet_count=0;
}
}
}
// 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();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
}
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!=-1)
{
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;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,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
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(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))
{
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);
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
}
else
{
time=(timeH<<16)+timeL;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[hopping_frequency_no]);
}
packet_count++;
if(packet_count>6)
{
bind_counter=XN297DUMP_PERIOD_SCAN+1;
packet_count=0;
}
}
}
// 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();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
}
XN297Dump_overflow();
break;
case 4:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // 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
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
}
break;
}
}
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)
if(prev_option!=option && sub_protocol<XN297DUMP_AUTO)
{ // option has changed
hopping_frequency_no=option;
prev_option=option;
@@ -278,6 +636,10 @@ static uint16_t XN297Dump_callback()
uint16_t initXN297Dump(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
@@ -285,7 +647,7 @@ uint16_t initXN297Dump(void)
bind_counter=0;
rf_ch_num=0xFF;
prev_option=option^0x55;
phase=0; // init timer
phase=0; // init
return XN297DUMP_INITIAL_WAIT;
}

View File

@@ -12,212 +12,344 @@
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef NRF24L01_INSTALLED
#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);
#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
// 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_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
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
#endif
}
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);
#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
}
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];
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[i];
last++;
#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;
}
//CC2500
#ifdef CC2500_INSTALLED
uint8_t buf[32];
uint8_t last = 0;
uint8_t i;
static const uint16_t initial = 0xb5d2;
// payload
for (i = 0; i < len; ++i) {
// bit-reverse bytes in packet
buf[last] = bit_reverse(msg[i]);
// 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++;
}
// 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++;
}
// crc
uint16_t crc = initial;
for (uint8_t i = 0; i < last; ++i)
crc = crc16_update(crc, buf[i], 8);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
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
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
}
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
#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;
// 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;
// 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++;
}
// 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);
// pcf
buf[last] = (len << 1) | (pid>>1);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++];
last++;
buf[last] = (pid << 7) | (noack << 6);
// payload
buf[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++];
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++];
}
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;
// 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]);
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
}
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
{ //calibrate hopping frequencies
for (uint8_t i = 0; i < num_freq; i++)
{
#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
}
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
{
#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
}
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
{ //change channel
#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, hopping_frequency[i]*3);
CC2500_WriteReg(CC2500_0A_CHANNR, number*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);
#endif
}
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);
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
NRF24L01_SetPower();
return;
}
}
#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();
#ifdef CC2500_INSTALLED
CC2500_SetPower();
#endif
}
static void __attribute__((unused)) XN297L_SetFreqOffset()
{ // Frequency offset
#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
}
#endif

View File

@@ -78,9 +78,6 @@
#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 "//"
@@ -113,6 +110,7 @@
//#define FORCE_BUGS_TUNING 0
//#define FORCE_FLYSKY_TUNING 0
//#define FORCE_FLYZONE_TUNING 0
//#define FORCE_PELIKAN_TUNING 0
//#define FORCE_HUBSAN_TUNING 0
/** CYRF6936 Fine Frequency Tuning **/
@@ -163,6 +161,7 @@
#define FLYSKY_A7105_INO
#define FLYZONE_A7105_INO
#define HUBSAN_A7105_INO
#define PELIKAN_A7105_INO
//The protocols below need a CYRF6936 to be installed
#define DEVO_CYRF6936_INO
@@ -215,6 +214,7 @@
#define SHENQI_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO
#define TIGER_NRF24L01_INO
#define V2X2_NRF24L01_INO
#define V761_NRF24L01_INO
#define V911S_NRF24L01_INO
@@ -624,6 +624,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
FY805
PROTO_NCC1701
NONE
PROTO_PELIKAN
NONE
PROTO_POTENSIC
NONE
PROTO_Q2X2
@@ -653,6 +655,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_SYMAX
SYMAX
SYMAX5C
PROTO_TIGER
NONE
PROTO_TRAXXAS
RX6519
PROTO_V2X2
@@ -661,7 +665,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_V761
NONE
PROTO_V911S
NONE
V911S_STD
V911S_E119
PROTO_WFLY
NONE
PROTO_WK2x01
@@ -680,3 +685,29 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_ZSX
NONE
*/
/**********************************/
/*** DIRECT INPUTS SETTINGS ***/
/**********************************/
//In this section you can configure the direct inputs.
//It enables switches wired directly to the board
//Direct inputs works only in ppm mode and only for stm_32 boards
//Uncomment following lines to enable derect inputs or define your own configuration in _MyConfig.h
/*
#define ENABLE_DIRECT_INPUTS
#define DI1_PIN PC13
#define IS_DI1_on (digitalRead(DI1_PIN)==LOW)
#define DI2_PIN PC14
#define IS_DI2_on (digitalRead(DI2_PIN)==LOW)
#define DI3_PIN PC15
#define IS_DI3_on (digitalRead(DI3_PIN)==LOW)
//Define up to 4 direct input channels
//CHANNEL1 - 2pos switch
#define DI_CH1_read IS_DI1_on ? PPM_MAX_100*2 : PPM_MIN_100*2
//CHANNEL2 - 3pos switch
#define DI_CH2_read IS_DI2_on ? PPM_MAX_100*2 : (IS_DI2_on ? PPM_MAX_100 + PPM_MIN_100 : PPM_MIN_100*2)
*/

View File

@@ -2,15 +2,17 @@
#define _IFACE_XN297L_H_
#if defined (XN297L_CC2500_EMU)
#if defined (CC2500_INSTALLED)
#include "iface_cc2500.h"
#elif defined (NRF24L01_INSTALLED)
#endif
#if 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_WriteEnhancedPayload(uint8_t*, 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);

View File

@@ -108,6 +108,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805||||NRF24L01|XN297
[NCC1701](Protocols_Details.md#NCC1701---44)|44|NCC1701||||||||NRF24L01|
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|||||||||A7105|
[Potensic](Protocols_Details.md#Potensic---51)|51|A20||||||||NRF24L01|XN297
[Q2X2](Protocols_Details.md#Q2X2---29)|29|Q222|Q242|Q282||||||NRF24L01|
[Q303](Protocols_Details.md#Q303---31)|31|Q303|CX35|CX10D|CX10WD|||||NRF24L01|XN297
@@ -117,6 +118,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01|LT8900
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100||||NRF24L01|
[SymaX](Protocols_Details.md#Symax---10)|10|SYMAX|SYMAX5C|||||||NRF24L01|
[Tiger](Protocols_Details.md#Tiger---61)|61|Tiger||||||||NRF24L01|XN297
[Traxxas](Protocols_Details.md#Traxxas---43)|43|RX6519||||||||CYRF6936|
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|||||||NRF24L01|
[V761](Protocols_Details.md#V761---48)|48|V761||||||||NRF24L01|XN297
@@ -125,7 +127,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936|
[YD717](Protocols_Details.md#YD717---8)|8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01|
[ZSX](Protocols_Details.md#ZSX---52)|52|280||||||||NRF24L01|XN297
* "*" Sub Protocols designated by * suffix will use the NRF24L01 module by default to emulate the XN297L RF chip. If a CC2500 module is installed it will be used instead as it is proving to be a better option for the XN297L@250kbps. Each specific sub protocol has a more detailed explanation.
* "*" Sub Protocols designated by * suffix are using a XN297L@250kbps which will be emulated by default with the NRF24L01. If option (freq tune) is diffrent from 0, the CC2500 module (if installed) will be used instead. Each specific sub protocol has a more detailed explanation.
# A7105 RF Module
@@ -255,6 +257,19 @@ A|E|T|R|ARM|ANGLE|FLIP|PICTURE|VIDEO|LED
ANGLE: angle is +100%, acro is -100%
## Pelikan - *60*
Models: TX: CADET PRO V4, RX: RX-602 V4
Extended limits supported
**Only 1 set of frequencies for now**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
Note that the RX ouput will be AETR.
***
# CC2500 RF Module
@@ -307,7 +322,7 @@ Models: FrSky receivers D4R and D8R. DIY RX-F801 and RX-F802 receivers. Also kno
Extended limits supported
Telemetry enabled for A0, A1, RSSI, TSSI and Hub
Telemetry enabled for A0, A1, RSSI, TX_RSSI, TX_LQI and Hub. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
@@ -321,7 +336,7 @@ Models: FrSky receivers X4R, X6R and X8R. Also known as D16.
Extended limits and failsafe supported
Telemetry enabled for A1 (RxBatt), A2, RSSI, TSSI and Hub
Telemetry enabled for A1 (RxBatt), A2, RSSI, TX_RSSI, TX_LQI and Hub. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
@@ -397,14 +412,14 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
### Sub_protocol OPT_FW - *0*
OPTIMA RXs
Full telemetry available on OpenTX 2.3.3+, still in progress for erskyTx.
Full telemetry available on OpenTX 2.3.3+, still in progress for erskyTx. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
**The TX must be close to the RX for the bind negotiation to complete successfully**
### Sub_protocol OPT_HUB - *1*
OPTIMA RXs
Basic telemetry using FrSky Hub on er9x, erskyTX, OpenTX and any radio with FrSky telemetry support with RX voltage, VOLT2 voltage, TX RSSI and TX LQI.
Basic telemetry using FrSky Hub on er9x, erskyTX, OpenTX and any radio with FrSky telemetry support with RX voltage, VOLT2 voltage, TX_RSSI and TX_LQI. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
**The TX must be close to the RX for the bind negotiation to complete successfully**
@@ -429,7 +444,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
Basic telemetry is available on OpenTX 2.3.3+ with RX voltage, Rx temperature, RX RSSI, RX LQI, TX RSSI and TX LQI.
Basic telemetry is available on OpenTX 2.3.3+ with RX voltage, Rx temperature, RX RSSI, RX LQI, TX RSSI and TX LQI. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
## SFHSS - *21*
Models: Futaba RXs and XK models.
@@ -568,9 +583,9 @@ A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|TH_KILL
Notes:
- model/type/number of channels indicated on the RX can be different from what the RX is in fact wanting to see. So don't hesitate to test different combinations until you have something working. Using Auto is the best way to find these settings.
- RX output will match the Spektrum standard TAER independently of the input configuration AETR, RETA...
- RX output will match the Spektrum standard TAER independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- RX output will match the Spektrum standard throw (1500µs +/- 400µs -> 1100..1900µs) for a 100% input. This is true for both Serial and PPM input. For PPM, make sure the end points PPM_MIN_100 and PPM_MAX_100 in _config.h are matching your TX ouput. The maximum ouput is 1000..2000µs based on an input of 125%.
- If you want to override the above and get maximum throw (old way) uncomment in _config.h the line #define DSM_MAX_THROW . In this mode to achieve standard throw use a channel weight of 84%.
- If you want to override the above and get maximum throw either uncomment in _config.h the line #define DSM_MAX_THROW or on OpenTX 2.3.3+ use the "Enable max throw" feature on the GUI (0=No,1=Yes). In this mode to achieve standard throw use a channel weight of 84%.
- TH_KILL is a feature which is enabled on channel 14 by default (can be disabled/changed) in the _config.h file. Some models (X-Vert, Blade 230S...) require a special position to instant stop the motor(s). If the channel 14 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%. For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
### Sub_protocol DSM2_22 - *0*
@@ -883,9 +898,9 @@ A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
## GD00X - *47*
Model: GD005 C-17 Transport, GD006 DA62 and ZC-Z50
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If a CC2500 rf component is available it will be used in place of the NRF24L01 which might fix the issue mentioned above. Option is used for fine frequency tuning like any CC2500 protocols. Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it if necessary.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
@@ -986,9 +1001,9 @@ ARM|
## KF606 - *49*
Model: KF606
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If a CC2500 rf component is available it will be used in place of the NRF24L01 which might fix the issue mentioned above. Option is used for fine frequency tuning like any CC2500 protocols. Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it if necessary.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
@@ -1013,9 +1028,9 @@ Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol E010 - *4*
15 TX IDs available, change RX_Num value 0..14 to cycle through them
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If a CC2500 rf component is available it will be used in place of the NRF24L01 which might fix the issue mentioned above. Option is used for fine frequency tuning like any CC2500 protocols. Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it if necessary.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
### Sub_protocol H26WH - *5*
CH6|
@@ -1045,7 +1060,9 @@ Model: Yi Zhan i6S
Only one model can be flown at the same time since the ID is hardcoded.
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
### Sub_protocol LS - *3*
Models: LS114, 124, 215
@@ -1115,7 +1132,10 @@ CH1|CH2|CH3|CH4
A|E|T|R
### Sub_protocol Q303 - *0*
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
@@ -1264,6 +1284,15 @@ CH10|CH11|CH12
---|---|---
Start/Stop|EMERGENCY|CAMERA_UP/DN
## Tiger - *61*
Autobind protocol
**Only 1 ID**
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT
## V761 - *48*
Model: Volantex V761 and may be other
@@ -1278,9 +1307,9 @@ Gyro: -100%=Beginer mode (Gyro on, yaw and pitch rate limited), 0%=Mid Mode ( Gy
## V911S - *46*
Models: WLtoys V911S, XK A110
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If a CC2500 rf component is available it will be used in place of the NRF24L01 which might fix the issue mentioned above. Option is used for fine frequency tuning like any CC2500 protocols. Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it if necessary.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---