Compare commits

..

17 Commits

Author SHA1 Message Date
pascallanger
7327265e55 Update Compiling.md 2025-02-22 11:23:15 +01:00
pascallanger
496c07943f KAMTOM new surface protocol
Missing low batt telem
2025-02-21 21:46:18 +01:00
pascallanger
af87b0f6d1 Update UDIRC_ccnrf.ino 2025-02-19 17:16:04 +01:00
pascallanger
2918e63fb4 XN297Emu add ReSendPayload 2025-02-19 11:54:29 +01:00
pascallanger
ed63ef7efe Update UDIRC_ccnrf.ino 2025-02-19 11:33:17 +01:00
pascallanger
36d25c7773 Update UDIRC_ccnrf.ino 2025-02-19 11:21:26 +01:00
pascallanger
a3ef2b94d4 Update MultiChan.txt 2025-02-18 19:32:19 +01:00
pascallanger
ad8b45773d UDIRC new protocol / WIP 2025-02-18 11:18:13 +01:00
pascallanger
b2dec9b331 Update Protocols_Details.md 2025-02-12 11:57:04 +01:00
pascallanger
565aaed0c7 New XK2/P10 sub protocol 2025-02-09 12:01:28 +01:00
pascallanger
2f520f2e91 Update Protocols_Details.md 2025-02-06 12:03:15 +01:00
pascallanger
f1470a80dd Update Protocols_Details.md 2025-02-06 12:00:07 +01:00
pascallanger
b6f78e93a0 Yuxiang multi IDs/Freqs 2025-02-06 11:57:40 +01:00
pascallanger
58bfd3b8b0 New JIABAILE/Gyro subprotocol 2025-02-06 11:56:24 +01:00
pascallanger
9e5e907f4a Hontai/XKK170 new subprotocol 2025-01-30 23:14:15 +01:00
pascallanger
4b68443c8f Update Multiprotocol.h 2025-01-30 10:37:53 +01:00
pascallanger
f092e137c7 Improve DSM telemetry stability? 2025-01-30 10:28:57 +01:00
19 changed files with 911 additions and 347 deletions

View File

@@ -110,6 +110,7 @@
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
26,4,Hontai,XKK170,1,Rate,Emerg,TakLan,Calib,TrimA,TrimE
57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
@@ -194,6 +195,7 @@
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video,Flip,Light
62,2,XK,Cars,0,FMode,TakeOf,Emerg,3D_6G,Pict,Video,Flip,Light
99,0,XK2,X4,0,Rate,Mode,Hover,Light
99,1,XK2,P10,0,Rate,Mode,Hover,Light
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
@@ -226,5 +228,7 @@
61,0,EazyRC
98,0,Kyosho3,ASF,0
100,0,YuXiang,Std,0,Lock,Rate,Land,Manual,Flip,Mode,Pitch
102,0,JIABAILE,Std,1,Speed,Light,Flash
102,0,JIABAILE,Std,0,Speed,Light,Flash
102,1,JIABAILE,Gyro,0,Speed,Light,Flash,ST_Tr
103,0,H36,Std,1,Flip,HLess,RTH
104,0,KAMTOM,Std,0,ST_Tr,TH_Tr,TH_DR

View File

@@ -292,10 +292,11 @@ uint16_t DSM_callback()
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#ifdef STM32_BOARD
#define DSM_WRITE_DELAY 1600 // Time after write to verify write complete
#define DSM_READ_DELAY 400 // Time before write to check read phase, and switch channels.
#else
#define DSM_WRITE_DELAY 1950 // Time after write to verify write complete
#define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels.
#endif
#define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels. Was 400 but 600 seems what the 328p needs to read a packet
#if defined DSM_TELEMETRY
uint8_t rx_phase;
uint8_t length;

View File

@@ -17,21 +17,25 @@
#include "iface_xn297.h" // mix of nrf and xn297 at 1Mb...
#define HONTAI_BIND_COUNT 80
#define HONTAI_PACKET_PERIOD 13500
#define FQ777_951_PACKET_PERIOD 10000
#define HONTAI_INITIAL_WAIT 500
#define HONTAI_BIND_PACKET_SIZE 10
#define HONTAI_PACKET_SIZE 12
#define HONTAI_RF_BIND_CHANNEL 0
#define HONTAI_BIND_COUNT 80
#define HONTAI_PACKET_PERIOD 13500
#define FQ777_951_PACKET_PERIOD 10000
#define HONTAI_INITIAL_WAIT 500
#define HONTAI_BIND_PACKET_SIZE 10
#define HONTAI_PACKET_SIZE 12
#define HONTAI_RF_BIND_CHANNEL 0
#define HONTAI_XKK170_RF_BIND_CHANNEL 20
#define HONTAI_XKK170_PACKET_PERIOD 8085
//#define FORCE_HONTAI_XKK170_ORIGINAL_ID
enum{
HONTAI_FLAG_FLIP = 0x01,
HONTAI_FLAG_PICTURE = 0x02,
HONTAI_FLAG_VIDEO = 0x04,
HONTAI_FLAG_HEADLESS = 0x08,
HONTAI_FLAG_RTH = 0x10,
HONTAI_FLAG_CALIBRATE = 0x20,
HONTAI_FLAG_FLIP = 0x01,
HONTAI_FLAG_PICTURE = 0x02,
HONTAI_FLAG_VIDEO = 0x04,
HONTAI_FLAG_HEADLESS = 0x08,
HONTAI_FLAG_RTH = 0x10,
HONTAI_FLAG_CALIBRATE = 0x20,
};
static void __attribute__((unused)) HONTAI_send_packet()
@@ -40,6 +44,8 @@ static void __attribute__((unused)) HONTAI_send_packet()
{
memcpy(packet, rx_tx_addr, 5);
memset(&packet[5], 0, 3);
//if(sub_protocol == HONTAI_XKK170)
// packet[6] = 0xD2;
packet_length = HONTAI_BIND_PACKET_SIZE;
}
else
@@ -50,58 +56,87 @@ static void __attribute__((unused)) HONTAI_send_packet()
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no %= 3;
memset(packet,0,HONTAI_PACKET_SIZE);
packet[3] = convert_channel_16b_limit(THROTTLE, 0, 127) << 1; // Throttle
packet[4] = convert_channel_16b_limit(AILERON, 63, 0); // Aileron
packet[5] = convert_channel_16b_limit(ELEVATOR, 0, 63); // Elevator
packet[6] = convert_channel_16b_limit(RUDDER, 0, 63); // Rudder
if(sub_protocol == X5C1)
packet[7] = convert_channel_16b_limit(AILERON, 0, 63)-31; // Aileron trim
for(uint8_t i=0; i<4; i++)
packet[i+3] = convert_channel_8b(CH_TAER[i]);
if(sub_protocol != HONTAI_XKK170)
{
//Drive trims
packet[7] = (packet[4]>>3)-16;
packet[8] = (packet[6]>>3)-16;
packet[9] = (packet[5]>>3)-16;
//Reverse aileron
packet[4] ^= 0xFF;
//Limit range
for(uint8_t i=3; i<7; i++)
packet[i] >>= 2; //00..63
}
else
packet[7] = convert_channel_16b_limit(AILERON, 0, 32)-16; // Aileron trim
packet[8] = convert_channel_16b_limit(RUDDER, 0, 32)-16; // Rudder trim
if (sub_protocol == X5C1)
packet[9] = convert_channel_16b_limit(ELEVATOR, 0, 63)-31; // Elevator trim
else
packet[9] = convert_channel_16b_limit(ELEVATOR, 0, 32)-16; // Elevator trim
{//K170
//packet[2] = 0xAB; //This value keeps changing when touching any button... Left over from debug?
//Sticks
for(uint8_t i=1; i<4; i++)
packet[i+3] = convert_channel_16b_limit(CH_TAER[i],0x28,0xD8);
packet[6] ^= 0xFF; //Reverse rudder
//flags
packet[1] = GET_FLAG(CH8_SW, 0x04); //Gyro calibration (momentary)
// |GET_FLAG(CH_SW, 0x08) //Unk long press second top right button (momentary)
// |GET_FLAG(CH_SW, 0x10) //Unk short press second top right button (toggle)
// |GET_FLAG(CH_SW, 0x40) //Unk short press second top left button (momentary)
// |GET_FLAG(CH_SW, 0x80); //Unk long press second top left button (momentary)
uint8_t rate = 0x80; //Mid rate
if(CH5_SW)
rate = 0xC0; //High rate
else if(Channel_data[CH5] < CHANNEL_MIN_COMMAND)
rate = 0x40; //Low rate
packet[8] = rate
|GET_FLAG(CH7_SW, 0x04) //Take-off/Landing (momentary)
|GET_FLAG(CH6_SW, 0x10); //Emergency (momentary)
//Trims
packet[7] = ((convert_channel_8b(CH9)^0xFF)>>2)-31; // Trim Aileron
packet[9] = ( convert_channel_8b(CH10) >>2)-32; // Trim Elevator
}
switch(sub_protocol)
{
case HONTAI:
packet[0] = 0x0B;
packet[3] |= GET_FLAG(CH7_SW, 0x01); // Picture
packet[4] |= GET_FLAG(CH10_SW, 0x80) // RTH
packet[4] |= GET_FLAG(CH10_SW, 0x80) // RTH
| GET_FLAG(CH9_SW, 0x40); // Headless
packet[5] |= GET_FLAG(CH11_SW, 0x80) // Calibrate
packet[5] |= GET_FLAG(CH11_SW, 0x80) // Calibrate
| GET_FLAG(CH5_SW, 0x40); // Flip
packet[6] |= GET_FLAG(CH8_SW, 0x80); // Video
break;
case JJRCX1:
packet[0] = GET_FLAG(CH6_SW, 0x02); // Arm
packet[3] |= GET_FLAG(CH7_SW, 0x01); // Picture
packet[4] |= 0x80; // unknown
packet[5] |= GET_FLAG(CH11_SW, 0x80) // Calibrate
packet[4] |= 0x80; // unknown
packet[5] |= GET_FLAG(CH11_SW, 0x80) // Calibrate
| GET_FLAG(CH5_SW, 0x40); // Flip
packet[6] |= GET_FLAG(CH8_SW, 0x80); // Video
packet[8] = 0xC0 // high rate, no rudder trim
| GET_FLAG(CH10_SW, 0x02) // RTH
packet[8] = 0xC0 // high rate, no rudder trim
| GET_FLAG(CH10_SW, 0x02) // RTH
| GET_FLAG(CH9_SW, 0x01); // Headless
break;
case X5C1:
packet[0] = 0x0B;
packet[3] |= GET_FLAG(CH7_SW, 0x01); // Picture
packet[4] = 0x80 // unknown
packet[4] = 0x80 // unknown
| GET_FLAG(CH6_SW, 0x40); // Lights
packet[5] |= GET_FLAG(CH11_SW, 0x80) // Calibrate
packet[5] |= GET_FLAG(CH11_SW, 0x80) // Calibrate
| GET_FLAG(CH5_SW, 0x40); // Flip
packet[6] |= GET_FLAG(CH8_SW, 0x80); // Video
packet[8] = 0xC0 // high rate, no rudder trim
| GET_FLAG(CH10_SW, 0x02) // RTH
packet[7] <<= 1; // Aileron trim
packet[8] = 0xC0 // high rate, no rudder trim
| GET_FLAG(CH10_SW, 0x02) // RTH
| GET_FLAG(CH9_SW, 0x01); // Headless
packet[9] <<= 1; // Elevator trim
break;
case FQ777_951:
packet[0] = GET_FLAG(CH7_SW, 0x01) // Picture
| GET_FLAG(CH8_SW, 0x02); // Video
packet[3] |= GET_FLAG(CH5_SW, 0x01); // Flip
packet[4] |= 0xC0; // High rate (mid=0xa0, low=0x60)
packet[4] |= 0xC0; // High rate (mid=0xa0, low=0x60)
packet[5] |= GET_FLAG(CH11_SW, 0x80); // Calibrate
packet[6] |= GET_FLAG(CH9_SW, 0x40); // Headless
break;
@@ -109,13 +144,18 @@ static void __attribute__((unused)) HONTAI_send_packet()
packet_length = HONTAI_PACKET_SIZE;
}
// CRC 16 bits reflected in and out
crc=0xFFFF;
for(uint8_t i=0; i< packet_length-2; i++)
crc16_update(bit_reverse(packet[i]),8);
crc ^= 0xFFFF;
packet[packet_length-2]=bit_reverse(crc>>8);
packet[packet_length-1]=bit_reverse(crc);
if(sub_protocol != HONTAI_XKK170)
{
// CRC 16 bits reflected in and out
crc=0xFFFF;
for(uint8_t i=0; i< packet_length-2; i++)
crc16_update(bit_reverse(packet[i]),8);
crc ^= 0xFFFF;
packet[packet_length-2]=bit_reverse(crc>>8);
packet[packet_length-1]=bit_reverse(crc);
}
else
memset(&packet[packet_length-2], 0xAA, 2);
// Power on, TX mode, 2byte CRC
/*if(sub_protocol == JJRCX1)
@@ -135,6 +175,11 @@ static void __attribute__((unused)) HONTAI_send_packet()
NRF24L01_WritePayload(packet, packet_length);
else
XN297_WritePayload(packet, packet_length);
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < packet_length; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) HONTAI_RF_init()
@@ -152,15 +197,16 @@ static void __attribute__((unused)) HONTAI_RF_init()
}
else
{
XN297_SetTXAddr((const uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
memcpy(rx_id,(const uint8_t*)"\xD2\xB5\x99\xB3\x41",5);
if(sub_protocol == HONTAI_XKK170)
rx_id[4] = 0x4A;
XN297_SetTXAddr(rx_id, 5);
//XN297_HoppingCalib(3);
}
XN297_RFChannel(HONTAI_RF_BIND_CHANNEL);
XN297_RFChannel(sub_protocol==HONTAI_XKK170?HONTAI_XKK170_RF_BIND_CHANNEL:HONTAI_RF_BIND_CHANNEL);
}
const uint8_t PROGMEM HONTAI_hopping_frequency_nonels[][3] = {
{0x05, 0x19, 0x28}, // Hontai
{0x0a, 0x1e, 0x2d}}; // JJRC X1
const uint8_t PROGMEM HONTAI_hopping_frequency[3] = { 0x05, 0x19, 0x28 };
const uint8_t PROGMEM HONTAI_addr_vals[4][16] = {
{0x24, 0x26, 0x2a, 0x2c, 0x32, 0x34, 0x36, 0x4a, 0x4c, 0x4e, 0x54, 0x56, 0x5a, 0x64, 0x66, 0x6a},
@@ -178,32 +224,69 @@ static void __attribute__((unused)) HONTAI_init2()
data_tx_addr[2] = pgm_read_byte_near( &HONTAI_addr_vals[2][ rx_tx_addr[4] & 0x0f]);
data_tx_addr[3] = pgm_read_byte_near( &HONTAI_addr_vals[3][(rx_tx_addr[4] >> 4) & 0x0f]);
data_tx_addr[4] = 0x24;
#ifdef DEBUG_SERIAL
debug("A N");
for(uint8_t i=0; i < 5; i++)
debug(" %02X", data_tx_addr[i]);
debugln();
#endif
if(sub_protocol == JJRCX1)
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, data_tx_addr, 5);
else
XN297_SetTXAddr(data_tx_addr, 5);
//Hopping frequency table
uint8_t val;
for(uint8_t i=0;i<3;i++)
hopping_frequency[i]=pgm_read_byte_near( &HONTAI_hopping_frequency_nonels[sub_protocol == JJRCX1?1:0][i] );
{
if(sub_protocol==HONTAI_XKK170)
val = 60+10*i;
else
{
val = pgm_read_byte_near( &HONTAI_hopping_frequency[i] );
if(sub_protocol == JJRCX1)
val += 5;
}
hopping_frequency[i] = val;
}
hopping_frequency_no=0;
#ifdef DEBUG_SERIAL
debug("H");
for(uint8_t i=0; i < 3; i++)
debug(" %d(%02X)", hopping_frequency[i], hopping_frequency[i]);
debugln();
#endif
}
static void __attribute__((unused)) HONTAI_initialize_txid()
{
rx_tx_addr[4] = rx_tx_addr[2];
if(sub_protocol == HONTAI || sub_protocol == FQ777_951)
{
rx_tx_addr[0] = 0x4c; // first three bytes some kind of model id? - set same as stock tx
rx_tx_addr[1] = 0x4b;
rx_tx_addr[2] = 0x3a;
// First three bytes some kind of model id? - set same as stock tx
if(sub_protocol == JJRCX1 || sub_protocol == X5C1)
{//JJRCX1 & X5C1
rx_tx_addr[0] = 0x4B;
rx_tx_addr[1] = 0x59;
rx_tx_addr[2] = 0x3A;
}
else
{
rx_tx_addr[0] = 0x4b; // JJRC X1
rx_tx_addr[1] = 0x59;
rx_tx_addr[2] = 0x3a;
{//HONTAI, FQ777_951, HONTAI_XKK170
rx_tx_addr[0] = 0x4C;
rx_tx_addr[1] = 0x4B;
rx_tx_addr[2] = 0x3A;
#ifdef FORCE_HONTAI_XKK170_ORIGINAL_ID
if(sub_protocol == HONTAI_XKK170)
{
rx_tx_addr[3] = 0x5A;
rx_tx_addr[4] = 0x06;
}
#endif
}
#ifdef DEBUG_SERIAL
debug("A B");
for(uint8_t i=0; i < 5; i++)
debug(" %02X", rx_tx_addr[i]);
debugln();
#endif
}
uint16_t HONTAI_callback()
@@ -228,8 +311,14 @@ void HONTAI_init()
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = HONTAI_BIND_COUNT;
HONTAI_initialize_txid();
HONTAI_RF_init();
packet_period = sub_protocol == FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD;
HONTAI_initialize_txid();
if(sub_protocol == FQ777_951)
packet_period = FQ777_951_PACKET_PERIOD;
else if(sub_protocol == HONTAI_XKK170)
packet_period = HONTAI_XKK170_PACKET_PERIOD;
else
packet_period = HONTAI_PACKET_PERIOD;
}
#endif

View File

@@ -17,12 +17,14 @@ Multiprotocol is distributed in the hope that it will be useful,
#include "iface_xn297.h"
//#define FORCE_JIABAILE_ORIGINAL_ID
//#define FORCE_JIABAILE_GYRO_ORIGINAL_ID
#define JIABAILE_PAYLOAD_SIZE 8
#define JIABAILE_RX_PAYLOAD_SIZE 7
#define JIABAILE_RF_NUM_CHANNELS 3
#define JIABAILE_BIND_PACKET_PERIOD 12700
#define JIABAILE_PACKET_PERIOD 2408
#define JIABAILE_GYRO_PACKET_PERIOD 8205
#define JIABAILE_BIND_COUNT 160 //2 sec
#define JIABAILE_WRITE_TIME 1000
@@ -51,43 +53,98 @@ static uint8_t __attribute__((unused)) JIABAILE_channel(uint8_t num)
static void __attribute__((unused)) JIABAILE_send_packet()
{
hopping_frequency_no++;
if(hopping_frequency_no > 2)
hopping_frequency_no = 0;
XN297_Hopping(hopping_frequency_no);
if(!(sub_protocol == JIABAILE_GYRO && IS_BIND_IN_PROGRESS))
{
hopping_frequency_no++;
if(hopping_frequency_no > 2)
hopping_frequency_no = 0;
XN297_Hopping(hopping_frequency_no);
}
memcpy(packet,rx_tx_addr,3);
memset(&packet[3], 0x00, 4);
if(IS_BIND_DONE)
{//Normal
packet[4] = convert_channel_16b_limit(RUDDER,0,50)-25; //ST Trim
packet[6] = JIABAILE_channel(AILERON); //ST
packet[3] ^= 0x03; //Reverse ST channel
packet[3] <<= 2; //Move ST channel where it should be
packet[5] = JIABAILE_channel(ELEVATOR); //TH
packet[3] |= GET_FLAG(CH5_SW, 0x20) //Low speed
|GET_FLAG(CH7_SW, 0x40) //Flash light
|GET_FLAG(!CH6_SW, 0x80); //Light
if(!CH5_SW && Channel_data[CH5] > CHANNEL_MIN_COMMAND)
packet[3] |= 0x10; //Mid speed
if(sub_protocol == JIABAILE_STD)
{//Std
memcpy(packet,rx_tx_addr,3);
memset(&packet[3], 0x00, 4);
if(IS_BIND_DONE)
{//Normal
packet[4] = convert_channel_16b_limit(RUDDER,0,50)-25; //ST Trim
packet[6] = JIABAILE_channel(AILERON); //ST
packet[3] ^= 0x03; //Reverse ST channel
packet[3] <<= 2; //Move ST channel where it should be
packet[5] = JIABAILE_channel(ELEVATOR); //TH
packet[3] |= GET_FLAG(CH5_SW, 0x20) //Low speed
|GET_FLAG(CH7_SW, 0x40) //Flash light
|GET_FLAG(!CH6_SW, 0x80); //Light
if(!CH5_SW && Channel_data[CH5] > CHANNEL_MIN_COMMAND)
packet[3] |= 0x10; //Mid speed
}
else
{
bind_counter--;
if(!bind_counter)
{
BIND_DONE;
phase = JIABAILE_PREP_DATA;
}
}
packet[7] = 0x55 + hopping_frequency[hopping_frequency_no];
for(uint8_t i=0;i<JIABAILE_PAYLOAD_SIZE-1;i++)
packet[7] += packet[i];
}
else
{
bind_counter--;
if(!bind_counter)
{//Gyro
if(bind_counter)
{
BIND_DONE;
phase = JIABAILE_PREP_DATA;
bind_counter--;
if(!bind_counter)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 4);
}
}
uint8_t crc_pos;
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet,rx_tx_addr,4);
packet[4] = hopping_frequency[1];
packet[5] = hopping_frequency[2];
crc_pos = 6;
packet[7] = 0x55;
}
else
{
packet[0] = convert_channel_16b_limit(CH2,0x60,0xA0); //Throttle
packet[1] = convert_channel_16b_limit(CH1,0x40,0xC0); //Steering
if(Channel_data[CH5] < CHANNEL_MIN_COMMAND)
packet[2] = 0x02; //High speed
else if(CH5_SW)
packet[2] = 0x00; //Low speed
else
packet[2] = 0x01; //Mid speed
packet[3] = convert_channel_8b(CH3) ^0xFF; //Gyro
uint8_t val = GET_FLAG(CH6_SW, 0x04) //Light
|GET_FLAG(CH7_SW, 0x08); //Flash
if(Channel_data[CH4] > CHANNEL_MAX_COMMAND)
val |= 0x01; //Trim right
else if(Channel_data[CH4] < CHANNEL_MIN_COMMAND)
val |= 0x02; //Trim left
packet[4] = val;
packet[5] = packet[6] = 0x00; //?
crc_pos = 7;
}
uint8_t sum=0;
for(uint8_t i=0; i<crc_pos; i++)
sum += packet[i];
sum ^= 0xFF;
packet[crc_pos] = sum;
}
packet[7] = 0x55 + hopping_frequency[hopping_frequency_no];
for(uint8_t i=0;i<JIABAILE_PAYLOAD_SIZE-1;i++)
packet[7] += packet[i];
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, JIABAILE_PAYLOAD_SIZE);
#ifdef DEBUG_SERIAL
#if 0
debug("B%d ",bind_counter);
debug("H%d RF%d",hopping_frequency_no,hopping_frequency[hopping_frequency_no]);
for(uint8_t i=0; i < JIABAILE_PAYLOAD_SIZE; i++)
debug(" %02X", packet[i]);
@@ -97,25 +154,56 @@ static void __attribute__((unused)) JIABAILE_send_packet()
static void __attribute__((unused)) JIABAILE_initialize_txid()
{
rx_tx_addr[0] = rx_tx_addr[3];
#ifdef FORCE_JIABAILE_ORIGINAL_ID
memcpy(rx_tx_addr,(uint8_t *)"\xCB\x03\xA5",3);
//memcpy(rx_tx_addr,(uint8_t *)"\x3D\x08\xA2",3);
//Normal frequencies are calculated from the car ID...
//memcpy(&hopping_frequency[3],(uint8_t *)"\x23\x2D\x4B",3); //35,45,75
memcpy(&hopping_frequency[3],(uint8_t *)"\x24\x43\x4C",3); //36,67,76
#endif
//Bind frequencies
memcpy(hopping_frequency,(uint8_t *)"\x07\x27\x45",3); //7,39,69
if(sub_protocol == JIABAILE_STD)
{//Std
rx_tx_addr[0] = rx_tx_addr[3];
#ifdef FORCE_JIABAILE_ORIGINAL_ID
memcpy(rx_tx_addr,(uint8_t *)"\xCB\x03\xA5",3);
//memcpy(rx_tx_addr,(uint8_t *)"\x3D\x08\xA2",3);
//Normal frequencies are calculated from the car ID...
//memcpy(&hopping_frequency[3],(uint8_t *)"\x23\x2D\x4B",3); //35,45,75
memcpy(&hopping_frequency[3],(uint8_t *)"\x24\x43\x4C",3); //36,67,76
#endif
//Bind frequencies
memcpy(hopping_frequency,(uint8_t *)"\x07\x27\x45",3); //7,39,69
}
else
{//Gyro
rx_tx_addr[0] += RX_num;
uint8_t val = (rx_tx_addr[0] & 0x0F) + 5; //5..20
for(uint8_t i=0; i<3; i++)
hopping_frequency[i] = val+ 20*i; //hopping_frequency[1,2] could be whatever but...
#ifdef FORCE_JIABAILE_GYRO_ORIGINAL_ID
if(RX_num)
{
memcpy(rx_tx_addr,(uint8_t *)"\x7D\x82\x28\xC2",4);
memcpy(hopping_frequency,(uint8_t *)"\x12\x1B\x35",3); //18,27,53
}
else
{
memcpy(rx_tx_addr,(uint8_t *)"\x0C\xF3\x59\xB3",4);
memcpy(hopping_frequency,(uint8_t *)"\x11\x1C\x36",3); //17,28,54
}
#endif
debugln("ID: %02X %02X %02X %02X, HOP: %2d %2d %2d",rx_tx_addr[0],rx_tx_addr[1],rx_tx_addr[2],rx_tx_addr[3],hopping_frequency[0],hopping_frequency[1],hopping_frequency[2]);
}
}
static void __attribute__((unused)) JIABAILE_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
//Bind address
memcpy(rx_id,(uint8_t*)"\xA7\x07\x57\xA7\x26", 5);
XN297_SetTXAddr(rx_id, 5);
XN297_SetRXAddr(rx_id, JIABAILE_RX_PAYLOAD_SIZE);
if(sub_protocol == JIABAILE_STD)
{//Std
memcpy(rx_id,(uint8_t*)"\xA7\x07\x57\xA7\x26", 5);
XN297_SetTXAddr(rx_id, 5);
XN297_SetRXAddr(rx_id, JIABAILE_RX_PAYLOAD_SIZE);
}
else
{//Gyro
XN297_SetTXAddr((uint8_t*)"\x14\x41\x11\x13", 4);
XN297_RFChannel(0x29); //41
}
}
uint16_t JIABAILE_callback()
@@ -216,25 +304,35 @@ uint16_t JIABAILE_callback()
phase++;
default: //JIABAILE_DATA
#ifdef MULTI_SYNC
telemetry_set_input_sync(JIABAILE_PACKET_PERIOD);
telemetry_set_input_sync(packet_period);
#endif
JIABAILE_send_packet();
break;
}
return JIABAILE_PACKET_PERIOD;
return packet_period;
}
void JIABAILE_init()
{
JIABAILE_initialize_txid();
JIABAILE_RF_init();
if(IS_BIND_IN_PROGRESS)
{
phase = JIABAILE_BIND;
bind_counter = JIABAILE_BIND_COUNT;
if(sub_protocol == JIABAILE_STD)
{//Std
if(IS_BIND_IN_PROGRESS)
{
phase = JIABAILE_BIND;
bind_counter = JIABAILE_BIND_COUNT;
}
else
phase = JIABAILE_PREP_DATA;
packet_period = JIABAILE_PACKET_PERIOD;
}
else
phase = JIABAILE_PREP_DATA;
{//Gyro
phase = JIABAILE_DATA;
bind_counter = IS_BIND_IN_PROGRESS?JIABAILE_BIND_COUNT>>2:1;
packet_period = JIABAILE_GYRO_PACKET_PERIOD;
}
hopping_frequency_no = 0;
}

View File

@@ -0,0 +1,179 @@
/*
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/>.
*/
#if defined(KAMTOM_NRF24L01_INO)
#include "iface_xn297.h"
//#define FORCE_KAMTOM_ORIGINAL_ID
#define KAMTOM_PAYLOAD_SIZE 16
#define KAMTOM_RF_NUM_CHANNELS 4
#define KAMTOM_BIND_COUNT 2000
#define KAMTOM_WRITE_TIME 650
#define KAMTOM_BIND_CHANNEL 0x28 //40
#define KAMTOM_PACKET_PERIOD 3585
enum {
KAMTOM_DATA,
KAMTOM_RX,
};
static void __attribute__((unused)) KAMTOM_send_packet()
{
if(bind_counter)
{
bind_counter--;
if(!bind_counter)
BIND_DONE;
}
memset(packet, 0x00, 16);
if(IS_BIND_DONE)
{//Normal
XN297_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= 3;
//RXID
packet[0] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
//Next RF channel
packet[1] = hopping_frequency[hopping_frequency_no];
//Channels and trims
for(uint8_t i=0; i<6; i++)
{
packet[4+i] = convert_channel_s8b(CH_TAER[i]);
if(i>3) //ST_TR and TH_TR
packet[4+i] >>= 2;
}
//packet[11] = 0x00; //??
//TH_DR
packet[12] = convert_channel_16b_limit(CH7,0x25,0x64);
}
else
{
packet[1] = KAMTOM_BIND_CHANNEL;
memcpy(&packet[4],hopping_frequency,4);
packet[12] = 0xA5;
}
packet[10] = 0x40; //??
//Checksum
uint16_t sum = packet[1];
for(uint8_t i=4;i<13;i++)
sum += packet[i];
packet[13] = sum;
packet[3] = (sum>>6) & 0xFC;
//TXID
packet[14] = rx_tx_addr[2];
packet[15] = rx_tx_addr[3];
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, KAMTOM_PAYLOAD_SIZE,false);
#if 0
//def DEBUG_SERIAL
for(uint8_t i=0; i < KAMTOM_PAYLOAD_SIZE; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) KAMTOM_initialize_txid()
{
calc_fh_channels(4);
#ifdef FORCE_KAMTOM_ORIGINAL_ID
rx_tx_addr[0] = 0xC7;
rx_tx_addr[1] = 0x78;
rx_tx_addr[2] = 0x2C;
rx_tx_addr[3] = 0x25;
hopping_frequency[0] = 59;
hopping_frequency[1] = 59;
hopping_frequency[2] = 71;
hopping_frequency[3] = 65;
#endif
}
static void __attribute__((unused)) KAMTOM_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
//Address
XN297_SetTXAddr((uint8_t*)"\xCC\xDD\xEE\xDD", 4);
XN297_SetRXAddr((uint8_t*)"\xCC\xDD\xEE\xDD", KAMTOM_PAYLOAD_SIZE);
XN297_RFChannel(KAMTOM_BIND_CHANNEL);
}
uint16_t KAMTOM_callback()
{
static bool rx=false;
switch(phase)
{
case KAMTOM_DATA:
rx = XN297_IsRX();
XN297_SetTxRxMode(TXRX_OFF);
#ifdef MULTI_SYNC
telemetry_set_input_sync(KAMTOM_PACKET_PERIOD);
#endif
KAMTOM_send_packet();
if(rx)
{
uint8_t val=XN297_ReadEnhancedPayload(packet_in, KAMTOM_PAYLOAD_SIZE);
if(val==KAMTOM_PAYLOAD_SIZE)
{
BIND_DONE;
if(packet_in[0] == 0xA0 && packet_in[14] == rx_tx_addr[2] && packet_in[15] == rx_tx_addr[3])
{
rx_tx_addr[0] = packet_in[9];
rx_tx_addr[1] = packet_in[10];
//if(packet_in[1] == 0x03) // low voltage
}
#if 0
for(uint8_t i=0; i < KAMTOM_PAYLOAD_SIZE; i++)
debug(" %02X", packet_in[i]);
debugln();
#endif
}
}
phase++;
return KAMTOM_WRITE_TIME;
default: //KAMTOM_RX
//{ // Wait for packet to be sent before switching to receive mode
// uint16_t start=(uint16_t)micros();
// while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
// if(XN297_IsPacketSent())
// break;
//}
//Switch to RX
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase = KAMTOM_DATA;
return KAMTOM_PACKET_PERIOD - KAMTOM_WRITE_TIME;
}
return 0;
}
void KAMTOM_init()
{
KAMTOM_initialize_txid();
KAMTOM_RF_init();
bind_counter = KAMTOM_BIND_COUNT;
phase = KAMTOM_DATA;
hopping_frequency_no = 0;
}
#endif

View File

@@ -23,7 +23,7 @@
23,FQ777
24,ASSAN
25,FrskyV
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951,XKK170
27,OpnLrs
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,PWM_IB16,PPM_IB16,PWM_SB16,PPM_SB16
29,Q2X2,Q222,Q242,Q282
@@ -95,7 +95,8 @@
96,BumbleB
97,SGF22,F22,F22S,J20
98,Kyosho3
99,XK2
99,XK2,X4,P10
100,YuXiang
102,JIABAILE
103,H36
102,JIABAILE,STD,GYRO
103,H36
104,KAMTOM

View File

@@ -113,8 +113,9 @@ const char STR_SGF22[] ="SGF22";
const char STR_EAZYRC[] ="EazyRC";
const char STR_KYOSHO3[] ="Kyosho3";
const char STR_YUXIANG[] ="YuXiang";
const char STR_PINECONE[] ="PineCone";
const char STR_JIABAILE[] ="JIABAILE";
const char STR_UDIRC[] ="UDIRC";
const char STR_JIABAILE[] ="JIABAILE";
const char STR_KAMTOM[] ="KAMTOM";
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
@@ -143,7 +144,7 @@ const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 "
const char STR_SUBTYPE_MT992[] = "\x04""PA18""SU35";
const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
const char STR_SUBTYPE_HONTAI[] = "\x06""Std\0 ""JJRCX1""X5C1\0 ""FQ_951""XKK170";
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""PWM,IB16""PPM,IB16""PWM,SB16""PPM,SB16";
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
@@ -165,6 +166,7 @@ const char STR_SUBTYPE_ESKY150[] = "\x03""4ch""7ch";
const char STR_SUBTYPE_ESKY150V2[] = "\x05""150V2";
const char STR_SUBTYPE_V911S[] = "\x05""V911S""E119\0";
const char STR_SUBTYPE_XK[] = "\x04""X450""X420""Cars";
const char STR_SUBTYPE_XK2[] = "\x03""X4\0""P10";
const char STR_SUBTYPE_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch""FCC\0 ""--\0 ""FCC 8ch""-- 8ch\0";
const char STR_SUBTYPE_ESKY[] = "\x03""Std""ET4";
const char STR_SUBTYPE_PROPEL[] = "\x04""74-Z";
@@ -185,6 +187,7 @@ const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0";
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
const char STR_SUBTYPE_FX[] = "\x04""816\0""620\0""9630""Q560";
const char STR_SUBTYPE_SGF22[] = "\x04""F22\0""F22S""J20\0";
const char STR_SUBTYPE_JIABAILE[] = "\x04""Std\0""Gyro";
#define NO_SUBTYPE nullptr
#ifdef SEND_CPPM
@@ -366,7 +369,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_HITEC, STR_HITEC, STR_SUBTYPE_HITEC, 3, OPTION_RFTUNE, 0, 0, SW_CC2500, HITEC_init, HITEC_callback },
#endif
#if defined(HONTAI_NRF24L01_INO)
{PROTO_HONTAI, STR_HONTAI, STR_SUBTYPE_HONTAI, 4, OPTION_NONE, 0, 0, SW_NRF, HONTAI_init, HONTAI_callback },
{PROTO_HONTAI, STR_HONTAI, STR_SUBTYPE_HONTAI, 5, OPTION_NONE, 0, 0, SW_NRF, HONTAI_init, HONTAI_callback },
#endif
#if defined(HOTT_CC2500_INO)
{PROTO_HOTT, STR_HOTT, STR_SUBTYPE_HOTT, 2, OPTION_RFTUNE, 1, 0, SW_CC2500, HOTT_init, HOTT_callback },
@@ -381,7 +384,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_J6PRO, STR_J6PRO, NO_SUBTYPE, 0, OPTION_NONE, 0, 1, SW_CYRF, J6PRO_init, J6PRO_callback },
#endif
#if defined(JIABAILE_NRF24L01_INO)
{PROTO_JIABAILE, STR_JIABAILE, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, JIABAILE_init, JIABAILE_callback },
{PROTO_JIABAILE, STR_JIABAILE, STR_SUBTYPE_JIABAILE, 2, OPTION_NONE, 0, 0, SW_NRF, JIABAILE_init, JIABAILE_callback },
#endif
#if defined(JJRC345_NRF24L01_INO)
{PROTO_JJRC345, STR_JJRC345, STR_SUBTYPE_JJRC345, 2, OPTION_NONE, 0, 0, SW_NRF, JJRC345_init, JJRC345_callback },
@@ -389,6 +392,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(JOYSWAY_A7105_INO)
{PROTO_JOYSWAY, STR_JOYSWAY, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, JOYSWAY_init, JOYSWAY_callback },
#endif
#if defined(KAMTOM_NRF24L01_INO)
{PROTO_KAMTOM, STR_KAMTOM, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, KAMTOM_init, KAMTOM_callback },
#endif
#if defined(KF606_CCNRF_INO)
{PROTO_KF606, STR_KF606, STR_SUBTYPE_KF606, 3, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
#endif
@@ -434,9 +440,6 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(PELIKAN_A7105_INO)
{PROTO_PELIKAN, STR_PELIKAN, STR_SUBTYPE_PELIKAN, 3, OPTION_NONE, 0, 1, SW_A7105, PELIKAN_init, PELIKAN_callback },
#endif
#if defined(PINECONE_CCNRF_INO)
{PROTO_PINECONE, STR_PINECONE, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, PINECONE_init, PINECONE_callback },
#endif
#if defined(POTENSIC_NRF24L01_INO)
{PROTO_POTENSIC, STR_POTENSIC, STR_SUBTYPE_POTENSIC, 1, OPTION_NONE, 0, 0, SW_NRF, POTENSIC_init, POTENSIC_callback },
#endif
@@ -485,6 +488,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(TRAXXAS_CYRF6936_INO)
{PROTO_TRAXXAS, STR_TRAXXAS, STR_SUBTYPE_TRAXXAS, 2, OPTION_NONE, 0, 0, SW_CYRF, TRAXXAS_init, TRAXXAS_callback },
#endif
#if defined(UDIRC_CCNRF_INO)
{PROTO_UDIRC, STR_UDIRC, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, UDIRC_init, UDIRC_callback },
#endif
#if defined(V2X2_NRF24L01_INO)
{PROTO_V2X2, STR_V2X2, STR_SUBTYPE_V2X2, 3, OPTION_NONE, 0, 0, SW_NRF, V2X2_init, V2X2_callback },
#endif
@@ -511,7 +517,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_XK, STR_XK, STR_SUBTYPE_XK, 3, OPTION_RFTUNE, 0, 0, SW_NRF, XK_init, XK_callback },
#endif
#if defined(XK2_CCNRF_INO)
{PROTO_XK2, STR_XK2, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, XK2_init, XK2_callback },
{PROTO_XK2, STR_XK2, STR_SUBTYPE_XK2, 2, OPTION_RFTUNE, 0, 0, SW_NRF, XK2_init, XK2_callback },
#endif
#if defined(XN297DUMP_NRF24L01_INO)
{PROTO_XN297DUMP, STR_XN297DUMP, STR_SUBTYPE_XN297DUMP, 7, OPTION_RFCHAN, 0, 0, SW_NRF, XN297Dump_init, XN297Dump_callback },

View File

@@ -19,7 +19,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 4
#define VERSION_PATCH_LEVEL 26
#define VERSION_PATCH_LEVEL 34
#define MODE_SERIAL 0
@@ -128,9 +128,10 @@ enum PROTOCOLS
PROTO_KYOSHO3 = 98, // =>CYRF6936
PROTO_XK2 = 99, // =>CC2500 & NRF24L01
PROTO_YUXIANG = 100, // =>NRF24L01
PROTO_PINECONE = 101, // =>CC2500 & NRF24L01
PROTO_UDIRC = 101, // =>CC2500 & NRF24L01
PROTO_JIABAILE = 102, // =>NRF24L01
PROTO_H36 = 103, // =>NRF24L01
PROTO_KAMTOM = 104, // =>NRF24L01
PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500
@@ -288,10 +289,11 @@ enum FRSKYX
};
enum HONTAI
{
HONTAI = 0,
JJRCX1 = 1,
X5C1 = 2,
FQ777_951 =3,
HONTAI = 0,
JJRCX1 = 1,
X5C1 = 2,
FQ777_951 = 3,
HONTAI_XKK170 = 4,
};
enum V2X2
{
@@ -494,6 +496,16 @@ enum SGF22
SGF22_F22S = 1,
SGF22_J20 = 2,
};
enum JIABAILE
{
JIABAILE_STD = 0,
JIABAILE_GYRO = 1,
};
enum XK2
{
XK2_X4 = 0,
XK2_P10 = 1,
};
#define NONE 0
#define P_HIGH 1

View File

@@ -1,167 +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/>.
*/
#if defined(PINECONE_CCNRF_INO)
#include "iface_xn297.h"
#define FORCE_PINECONE_ORIGINAL_ID
#define PINECONE_PAYLOAD_SIZE 15
#define PINECONE_RF_NUM_CHANNELS 4
#define PINECONE_PACKET_PERIOD 9000
#define PINECONE_BIND_COUNT 2000
#define PINECONE_WRITE_TIME 1500
enum {
PINECONE_DATA=0,
PINECONE_RX,
};
static void __attribute__((unused)) PINECONE_send_packet()
{
if(rf_ch_num==0)
{
XN297_Hopping(hopping_frequency_no);
debug("H %d ",hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= 3;
}
if(bind_counter==0) bind_counter=2;
memset(&packet[3], 0x00, 12);
if(bind_counter)
{//Bind in progress
bind_counter--;
if(bind_counter)
{//Bind
packet[0] = 0x01;
memcpy(&packet[1],rx_tx_addr,5);
}
else
{//Switch to normal
XN297_SetTXAddr(rx_tx_addr, 5);
XN297_SetRXAddr(rx_tx_addr, PINECONE_PAYLOAD_SIZE);
}
}
if(!bind_counter)
{//Normal
packet[0] = 0x08;
packet[1] = convert_channel_16b_limit(AILERON,0,200); //ST
packet[2] = convert_channel_16b_limit(THROTTLE,0,200); //TH
packet[3] = convert_channel_16b_limit(ELEVATOR,0,200); //CH4
packet[4] = convert_channel_16b_limit(RUDDER,0,200); //CH3
}
//packet[5/6..8] = 00 unknown
packet[9] = convert_channel_16b_limit(CH5,0,200); //ESP
packet[10] = convert_channel_16b_limit(CH6,0,200); //ST_TRIM
packet[11] = convert_channel_16b_limit(CH7,0,200); //ST_DR
packet[12] = GET_FLAG(CH8_SW, 0x40) //TH.REV
|GET_FLAG(CH9_SW, 0x80); //ST.REV
//packet[13] = 00 unknown
for(uint8_t i=0;i<PINECONE_PAYLOAD_SIZE-1;i++)
packet[14] += packet[i];
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, PINECONE_PAYLOAD_SIZE,false);
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < PINECONE_PAYLOAD_SIZE; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) PINECONE_initialize_txid()
{
#ifdef FORCE_PINECONE_ORIGINAL_ID
rx_tx_addr[0] = 0xD0;
rx_tx_addr[1] = 0x06;
rx_tx_addr[2] = 0x00;
rx_tx_addr[3] = 0x00;
rx_tx_addr[4] = 0x81;
hopping_frequency[0] = 45;
hopping_frequency[1] = 59;
hopping_frequency[2] = 52;
hopping_frequency[3] = 67;
#endif
}
static void __attribute__((unused)) PINECONE_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
//Bind address
XN297_SetTXAddr((uint8_t*)"\x01\x03\x05\x07\x09", 5);
XN297_SetRXAddr((uint8_t*)"\x01\x03\x05\x07\x09", PINECONE_PAYLOAD_SIZE);
XN297_HoppingCalib(PINECONE_RF_NUM_CHANNELS);
}
uint16_t PINECONE_callback()
{
bool rx;
switch(phase)
{
case PINECONE_DATA:
rx = XN297_IsRX();
XN297_SetTxRxMode(TXRX_OFF);
#ifdef MULTI_SYNC
telemetry_set_input_sync(PINECONE_PACKET_PERIOD);
#endif
PINECONE_send_packet();
if(rx)
{
uint8_t val=XN297_ReadEnhancedPayload(packet_in, PINECONE_PAYLOAD_SIZE);
debug("RX %d ",val);
if(val==0)
rf_ch_num = 1;
else
{
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < PINECONE_PAYLOAD_SIZE; i++)
debug("%02X ", packet_in[i]);
debugln();
#endif
//could check the validity of the packet by looking at the sum...
}
//else
// debug("NOK");
debugln("");
}
phase++;
return PINECONE_WRITE_TIME;
default: //PINECONE_RX
//Wait for the packet transmission to finish
while(XN297_IsPacketSent()==false);
//Switch to RX
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase = PINECONE_DATA;
return PINECONE_PACKET_PERIOD - PINECONE_WRITE_TIME;
}
return 0;
}
void PINECONE_init()
{
PINECONE_initialize_txid();
PINECONE_RF_init();
bind_counter = IS_BIND_IN_PROGRESS ? PINECONE_BIND_COUNT : 1;
phase = PINECONE_DATA;
hopping_frequency_no = 0;
rf_ch_num=0;
bind_counter = 2000;
}
#endif

View File

@@ -169,7 +169,7 @@ uint16_t SGF22_callback()
}
else
{//send 3 times in total the same packet
NRF24L01_Strobe(REUSE_TX_PL);
XN297_ReSendPayload();
phase++;
if(phase > 2)
{

View File

@@ -0,0 +1,184 @@
/*
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/>.
*/
//Models: UDIRC UD160x(PRO), Pinecone Models SG-160x, Eachine EAT15
#if defined(UDIRC_CCNRF_INO)
#include "iface_xn297.h"
#define FORCE_UDIRC_ORIGINAL_ID
#define UDIRC_PAYLOAD_SIZE 15
#define UDIRC_RF_NUM_CHANNELS 4
#define UDIRC_PACKET_PERIOD 21000
#define UDIRC_BIND_COUNT 2000
#define UDIRC_P1_P2_TIME 5000
#define UDIRC_WRITE_TIME 1500
enum {
UDIRC_DATA1=0,
UDIRC_DATA2,
UDIRC_DATA3,
UDIRC_RX,
};
static void __attribute__((unused)) UDIRC_send_packet()
{
if(rf_ch_num==0)
{
XN297_Hopping(hopping_frequency_no);
debug("H %d ",hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= 3;
}
memset(&packet[3], 0x00, 12);
if(bind_counter)
{//Bind in progress
bind_counter--;
if(bind_counter)
{//Bind
packet[0] = 0x01;
memcpy(&packet[1],rx_tx_addr,5);
}
else
{//Switch to normal
rf_ch_num = 1;
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 5);
XN297_SetRXAddr(rx_tx_addr, UDIRC_PAYLOAD_SIZE);
}
}
if(!bind_counter)
{//Normal
packet[0] = 0x08;
//Channels SG-16xx: ST/TH/CH4 /CH3 /UNK/UNK/UNK/UNK/GYRO/ST_TRIM/ST_DR
//Channels EAT15 : ST/TH/RATE/LIGHT/UNK/UNK/UNK/UNK/GYRO/ST_TRIM/ST_DR
for(uint8_t i=0; i<12; i++)
packet[i+1] = convert_channel_16b_limit(i,0,200);
//Just for now let's set the additional channels to 0
packet[5] = packet[6] = packet[7] = packet[8] = 0;
}
packet[12] = GET_FLAG(CH12_SW, 0x40) //TH.REV
|GET_FLAG(CH13_SW, 0x80); //ST.REV
//packet[13] = 00; //Unknown, future flags?
for(uint8_t i=0;i<UDIRC_PAYLOAD_SIZE-1;i++)
packet[14] += packet[i];
// Send
XN297_SetFreqOffset();
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, UDIRC_PAYLOAD_SIZE,false);
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < UDIRC_PAYLOAD_SIZE; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) UDIRC_initialize_txid()
{
#ifdef FORCE_UDIRC_ORIGINAL_ID
if(RX_num)
{
rx_tx_addr[0] = 0xD0;
rx_tx_addr[1] = 0x06;
rx_tx_addr[2] = 0x00;
rx_tx_addr[3] = 0x00;
rx_tx_addr[4] = 0x81;
}
else
{
rx_tx_addr[0] = 0xF6;
rx_tx_addr[1] = 0x96;
rx_tx_addr[2] = 0x01;
rx_tx_addr[3] = 0x00;
rx_tx_addr[4] = 0x81;
}
hopping_frequency[0] = 45;
hopping_frequency[1] = 59;
hopping_frequency[2] = 52;
hopping_frequency[3] = 67;
#endif
}
static void __attribute__((unused)) UDIRC_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
//Bind address
XN297_SetTXAddr((uint8_t*)"\x01\x03\x05\x07\x09", 5);
XN297_SetRXAddr((uint8_t*)"\x01\x03\x05\x07\x09", UDIRC_PAYLOAD_SIZE);
XN297_HoppingCalib(UDIRC_RF_NUM_CHANNELS);
}
uint16_t UDIRC_callback()
{
bool rx;
switch(phase)
{
case UDIRC_DATA1:
rx = XN297_IsRX();
XN297_SetTxRxMode(TXRX_OFF);
#ifdef MULTI_SYNC
telemetry_set_input_sync(UDIRC_PACKET_PERIOD);
#endif
UDIRC_send_packet();
if(rx)
{
uint8_t val=XN297_ReadEnhancedPayload(packet_in, UDIRC_PAYLOAD_SIZE);
debug("RX(%d):",val);
if(val != 255)
{
rf_ch_num = 1;
if(bind_counter)
bind_counter=1;
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < UDIRC_PAYLOAD_SIZE; i++)
debug(" %02X", packet_in[i]);
#endif
}
debugln("");
}
phase++;
return UDIRC_P1_P2_TIME;
case UDIRC_DATA2:
//Resend packet
XN297_ReSendPayload();
phase++;
return UDIRC_WRITE_TIME;
default: //UDIRC_RX
//Wait for the packet transmission to finish
while(XN297_IsPacketSent()==false);
//Switch to RX
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase = UDIRC_DATA1;
return UDIRC_PACKET_PERIOD - UDIRC_P1_P2_TIME - UDIRC_WRITE_TIME;
}
return 0;
}
void UDIRC_init()
{
UDIRC_initialize_txid();
UDIRC_RF_init();
bind_counter = IS_BIND_IN_PROGRESS ? UDIRC_BIND_COUNT : 1;
phase = UDIRC_DATA1;
hopping_frequency_no = 0;
rf_ch_num = 0;
}
#endif

View File

@@ -326,6 +326,7 @@
#undef HONTAI_NRF24L01_INO
#undef JIABAILE_NRF24L01_INO
#undef JJRC345_NRF24L01_INO
#undef KAMTOM_NRF24L01_INO
#undef KN_NRF24L01_INO
#undef KYOSHO2_NRF24L01_INO
#undef LOLI_NRF24L01_INO
@@ -355,6 +356,7 @@
#undef Q303_CCNRF_INO
#undef Q90C_CCNRF_INO
#undef SLT_CCNRF_INO
#undef UDIRC_CCNRF_INO
#undef V911S_CCNRF_INO
#undef XK_CCNRF_INO
#undef XK2_CCNRF_INO
@@ -391,6 +393,8 @@
#undef MOULDKG_NRF24L01_INO
#undef SHENQI_NRF24L01_INO
#undef JIABAILE_NRF24L01_INO
#undef UDIRC_CCNRF_INO
#undef KAMTOM_NRF24L01_INO
#endif
#ifdef MULTI_SURFACE

View File

@@ -19,8 +19,10 @@ Multiprotocol is distributed in the hope that it will be useful,
#include "iface_xn297.h"
//#define FORCE_XK2_ID
//#define FORCE_XK2_P10_ID
#define XK2_RF_BIND_CHANNEL 71
#define XK2_P10_RF_BIND_CHANNEL 69
#define XK2_PAYLOAD_SIZE 9
#define XK2_PACKET_PERIOD 4911
#define XK2_RF_NUM_CHANNELS 4
@@ -46,7 +48,7 @@ static void __attribute__((unused)) XK2_send_packet()
//Unknown
packet[7] = 0x00;
//Checksum seed
packet[8] = 0xC0; //Constant?
packet[8] = 0xC0;
}
else
{
@@ -74,7 +76,7 @@ static void __attribute__((unused)) XK2_send_packet()
| GET_FLAG(CH8_SW, 0x40); //Light
//Telemetry not received=00, Telemetry received=01 but sometimes switch to 1 even if telemetry is not there...
packet[6] = 0x00;
//Unknown
//RXID checksum
packet[7] = crc8; //Sum RX_ID[0..2]
//Checksum seed
packet[8] = num_ch; //Based on TX ID
@@ -82,6 +84,8 @@ static void __attribute__((unused)) XK2_send_packet()
//Checksum
for(uint8_t i=0; i<XK2_PAYLOAD_SIZE-1; i++)
packet[8] += packet[i];
if(sub_protocol == XK2_P10)
packet[8] += 0x10;
// Send
XN297_SetFreqOffset();
@@ -104,11 +108,22 @@ static void __attribute__((unused)) XK2_RF_init()
XN297_SetRXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", XK2_PAYLOAD_SIZE);
XN297_HoppingCalib(XK2_RF_NUM_CHANNELS);
XN297_RFChannel(XK2_RF_BIND_CHANNEL);
XN297_RFChannel(sub_protocol==XK2_X4?XK2_RF_BIND_CHANNEL:XK2_P10_RF_BIND_CHANNEL);
}
static void __attribute__((unused)) XK2_initialize_txid()
{
rx_tx_addr[0] = rx_tx_addr[3]; // Use RX_num
num_ch = 0x21 + rx_tx_addr[0] - rx_tx_addr[1] + rx_tx_addr[2];
//RF frequencies for X4: 65=0x41, 69=0x45, 73=0x49, 77=0x4D
//RF frequencies for P10: 67, unknown
uint8_t start = 65;
if(sub_protocol == XK2_P10) start += 2;
for(uint8_t i=0;i<XK2_RF_NUM_CHANNELS;i++)
hopping_frequency[i] = start + i*4;
#ifdef FORCE_XK2_ID
if(rx_tx_addr[3]&1)
{//Pascal
@@ -127,13 +142,15 @@ static void __attribute__((unused)) XK2_initialize_txid()
//hopping frequencies 65=0x41, 69=0x45, 73=0x49, 77=0x4D
}
#endif
rx_tx_addr[0] = rx_tx_addr[3]; // Use RX_num
#ifdef FORCE_XK2_P10_ID
rx_tx_addr[0] = 0xE8;
rx_tx_addr[1] = 0x25;
rx_tx_addr[2] = 0x3B;
num_ch = 0x1F;
//hopping frequencies 67=0x43, =0x, =0x, =0x
#endif
rx_tx_addr[3] = rx_tx_addr[4] = 0xCC;
num_ch = 0x21 + rx_tx_addr[0] - rx_tx_addr[1] + rx_tx_addr[2];
for(uint8_t i=0;i<XK2_RF_NUM_CHANNELS;i++) // Are these RF frequencies always the same? It looks like yes...
hopping_frequency[i] = 65 + i*4; //65=0x41, 69=0x45, 73=0x49, 77=0x4D
debugln("ID: %02X %02X %02X %02X %02X, OFFSET: %02X, HOP: %02X %02X %02X %02X",rx_tx_addr[0],rx_tx_addr[1],rx_tx_addr[2],rx_tx_addr[3],rx_tx_addr[4],num_ch,hopping_frequency[0],hopping_frequency[1],hopping_frequency[2],hopping_frequency[3]);
}
@@ -160,6 +177,8 @@ uint16_t XK2_callback()
crc8 = 0xBF;
for(uint8_t i=0; i<XK2_PAYLOAD_SIZE-1; i++)
crc8 += packet[i];
if(sub_protocol == XK2_P10)
crc8 += 0x10;
if(crc8 != packet[8])
{
phase = XK2_BIND1;
@@ -292,8 +311,8 @@ P[5] = flags
08=6g/3d=short_press_right sequece also switches for a few packets to C1 if 8 C0 if 0
P[6] = 00 telemetry nok
01 telemetry ok but sometimes switch to 1 also when telemetry is nok...
P[7] = 5A -> ?? RX_ID checksum ?? => sum RX_ID[0..2]
P[8] = sum P[0..7] + 7F
P[7] = 5A -> sum RX_ID[0..2]
P[8] = sum P[0..7] + TX_ID[0] - TX_ID[1] + TX_ID[2] + 21
Telemetry
RX on channel: 69, Time: 3408us P: 66 4F 47 00 00 00 00 00 C8
@@ -313,4 +332,49 @@ RF
2477 151753 5769
2465 155330 3577
*/
/* P10 Piper CUB
Bind
----
Phase 1
Plane sends these packets:
250K C=69 S=Y A= CC CC CC CC CC P(9)= 9C BB CC DD 84 24 20 00 97
P[0] = 9C bind phase 1
P[1] = Dummy TX_ID
P[2] = Dummy TX_ID
P[3] = Dummy TX_ID
P[4] = RX_ID[0]
P[5] = RX_ID[1]
P[6] = RX_ID[2]
P[7] = 00
P[8] = sum P[0..7] + BF + 10
Normal
------
TX sends
C=67 -> only one channel when telemetry is working
A= E8 25 3B CC CC P(9)= 32 32 00 32 A0 40 01 C8 6E
P[0] = A 00..32..64
P[1] = E 00..32..64
P[2] = T 00..64
P[3] = R 00..32..64
P[4] = alternates 20,60,A0,E0
trims
A 01..20..3F
E 41..60..7F
R 81..A0..BF
telemetry
E0 present when the telemetry works
6g/3d
C1 few times if P[6] flag 00->08
C0 few times if P[6] = flag 08->00
P[5] = flags
01=high rate
20=hover=long_press_left
40=light -> temporary
08=6g/3d=short_press_right sequece also switches for a few packets to C1 if 8 C0 if 0
P[6] = 00 telemetry nok
01 telemetry ok but sometimes switch to 1 also when telemetry is nok...
P[7] = C8 -> sum RX_ID[0..2]
P[8] = sum P[0..7] + TX_ID[0] - TX_ID[1] + TX_ID[2] + 21 +10
*/

View File

@@ -207,6 +207,27 @@ static void __attribute__((unused)) XN297_SetTxRxMode(enum TXRX_State mode)
#endif
}
#ifdef CC2500_INSTALLED
uint8_t XN297_Buffer[32];
uint8_t XN297_Buffer_Len = 0;
static void __attribute__((unused)) XN297_SendCC2500Payload()
{
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_06_PKTLEN, XN297_Buffer_Len + 4); // Packet len, fix packet len
// xn297L preamble
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x0C\x71\x0F\x55", 4);
// xn297 packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, XN297_Buffer, XN297_Buffer_Len);
// transmit
CC2500_Strobe(CC2500_STX);
}
#endif
static void __attribute__((unused)) XN297_SendPayload(uint8_t* msg, uint8_t len)
{
#ifdef NRF24L01_INSTALLED
@@ -220,22 +241,25 @@ static void __attribute__((unused)) XN297_SendPayload(uint8_t* msg, uint8_t len)
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
{
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_06_PKTLEN, len + 4); // Packet len, fix packet len
// xn297L preamble
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x0C\x71\x0F\x55", 4);
// xn297 packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, msg, len);
// transmit
CC2500_Strobe(CC2500_STX);
memcpy(XN297_Buffer, msg, len);
XN297_Buffer_Len = len;
XN297_SendCC2500Payload();
}
#endif
}
static void __attribute__((unused)) XN297_ReSendPayload()
{
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
NRF24L01_Strobe(NRF24L01_E3_REUSE_TX_PL);
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
XN297_SendCC2500Payload();
#endif
}
static void __attribute__((unused)) XN297_WritePayload(uint8_t* msg, uint8_t len)
{
uint8_t buf[32];
@@ -329,9 +353,9 @@ static void __attribute__((unused)) XN297_WriteEnhancedPayload(uint8_t* msg, uin
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;
}
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++] & 0xc0;
// crc
if (xn297_crc)
@@ -351,8 +375,7 @@ static void __attribute__((unused)) XN297_WriteEnhancedPayload(uint8_t* msg, uin
buf[last++] = (crc & 0xff) << 6;
}
pid++;
if(pid>3)
pid=0;
pid &= 0x03;
// send packet
XN297_SendPayload(buf, last);

View File

@@ -17,12 +17,12 @@ Multiprotocol is distributed in the hope that it will be useful,
#include "iface_xn297.h"
#define YUXIANG_FORCE_ID
//#define YUXIANG_FORCE_ID
#define YUXIANG_PACKET_PERIOD 12422
#define YUXIANG_PACKET_SIZE 9
#define YUXIANG_BIND_COUNT 150
#define YUXIANG_BIND_FREQ 0x30
#define YUXIANG_BIND_FREQ 0x30 //48
#define YUXIANG_RF_NUM_CHANNELS 4
#define YUXIANG_WRITE_TIME 1000
@@ -118,23 +118,43 @@ static void __attribute__((unused)) YUXIANG_RF_init()
static void __attribute__((unused)) YUXIANG_initialize_txid()
{
//Modify address to influence hop
rx_tx_addr[0] += RX_num;
//Calc hop
uint8_t val;
for(uint8_t i=0; i<4; i++)
{
val = i*0x06;
if(i) val |= 0x01;
val += rx_tx_addr[0];
val &= 0x1F;
val += 47;
if(val < 50)
val = 50;
if(val > 62 && val < 66)
val = 62;
hopping_frequency[i] = val;
}
#ifdef YUXIANG_FORCE_ID
if(rx_tx_addr[3] & 0x01)
{//TX1
memcpy(rx_tx_addr,(uint8_t *)"\xB3\x13\x36\xDD",4); //rx_tx_addr[4]=0xD9
memcpy(hopping_frequency,(uint8_t *)"\x49\x32\x35\x42",4);
}
else
{//TX2
memcpy(rx_tx_addr,(uint8_t *)"\xEB\x13\x36\xAC",4); //rx_tx_addr[4]=0xE0
memcpy(hopping_frequency,(uint8_t *)"\x4D\x3A\x3E\x47",4);
switch(RX_num)
{
case 0://TX1
memcpy(rx_tx_addr,(uint8_t *)"\xB3\x13\x36\xDD",4); //rx_tx_addr[4]=0xD9
memcpy(hopping_frequency,(uint8_t *)"\x42\x49\x32\x35",4); //66,73,50,53
break;
case 1://TX2
memcpy(rx_tx_addr,(uint8_t *)"\xEB\x13\x36\xAC",4); //rx_tx_addr[4]=0xE0
memcpy(hopping_frequency,(uint8_t *)"\x47\x4D\x3A\x3E",4); //58,62,71,77
break;
}
#endif
uint8_t sum=0;
for(uint8_t i=0; i<4; i++)
sum += rx_tx_addr[i];
rx_tx_addr[4] = sum;
debugln("ID: %02X %02X %02X %02X %02X , HOP: %02X %02X %02X %02X",rx_tx_addr[0],rx_tx_addr[1],rx_tx_addr[2],rx_tx_addr[3],rx_tx_addr[4],hopping_frequency[0],hopping_frequency[1],hopping_frequency[2],hopping_frequency[3]);
debugln("ID: %02X %02X %02X %02X %02X , HOP: %2d %2d %2d %2d",rx_tx_addr[0],rx_tx_addr[1],rx_tx_addr[2],rx_tx_addr[3],rx_tx_addr[4],hopping_frequency[0],hopping_frequency[1],hopping_frequency[2],hopping_frequency[3]);
}
uint16_t YUXIANG_callback()

View File

@@ -246,6 +246,7 @@
#define HONTAI_NRF24L01_INO
#define JIABAILE_NRF24L01_INO
#define JJRC345_NRF24L01_INO
#define KAMTOM_NRF24L01_INO
#define KN_NRF24L01_INO
#define KYOSHO2_NRF24L01_INO
#define LOLI_NRF24L01_INO
@@ -273,6 +274,7 @@
#define Q303_CCNRF_INO
#define Q90C_CCNRF_INO
#define SLT_CCNRF_INO
#define UDIRC_CCNRF_INO
#define V911S_CCNRF_INO
#define XK_CCNRF_INO
#define XK2_CCNRF_INO
@@ -724,6 +726,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
JJRCX1
X5C1
FQ777_951
HONTAI_XKK170
PROTO_HOTT
HOTT_SYNC
HOTT_NO_SYNC
@@ -736,12 +739,15 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_J6PRO
NONE
PROTO_JIABAILE
NONE
JIABAILE_STD
JIABAILE_GYRO
PROTO_JJRC345
JJRC345
SKYTMBLR
PROTO_JOYSWAY
NONE
PROTO_KAMTOM
NONE
PROTO_KF606
KF606_KF606
KF606_MIG320
@@ -843,6 +849,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
SYMAX5C
PROTO_TRAXXAS
NONE
PROTO_UDIRC
NONE
PROTO_V2X2
V2X2
JXD506
@@ -871,7 +879,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
X420
XK_CARS
PROTO_XK2
NONE
XK2_X4
XK2_P10
PROTO_YD717
YD717
SKYWLKR

View File

@@ -28,6 +28,7 @@ static void __attribute__((unused)) XN297_SetTXAddr(const uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_SetRXAddr(const uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_SetTxRxMode(enum TXRX_State);
static void __attribute__((unused)) XN297_SendPayload(uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_ReSendPayload();
static void __attribute__((unused)) XN297_WritePayload(uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_WriteEnhancedPayload(uint8_t*, uint8_t, uint8_t);
static bool __attribute__((unused)) XN297_IsRX();

View File

@@ -108,11 +108,11 @@ CFlie|38|CFlie||||||||NRF24L01|
[Height](Protocols_Details.md#HEIGHT---53)|53|5ch|8ch|||||||A7105|
[Hisky](Protocols_Details.md#HISKY---4)|4|Hisky|HK310|||||||NRF24L01|
[Hitec](Protocols_Details.md#HITEC---39)|39|OPT_FW|OPT_HUB|MINIMA||||||CC2500|
[Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|||||NRF24L01|XN297
[Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|XKK170||||NRF24L01|XN297
[HoTT](Protocols_Details.md#HoTT---57)|57|Sync|No_Sync|||||||CC2500|
[Hubsan](Protocols_Details.md#HUBSAN---2)|2|H107|H301|H501||||||A7105|
[J6Pro](Protocols_Details.md#J6Pro---22)|22|||||||||CYRF6936|
[JIABAILE](Protocols_Details.md#JIABAILE---102)|102|||||||||NRF24L01|XN297
[JIABAILE](Protocols_Details.md#JIABAILE---102)|102|Std|Gyro|||||||NRF24L01|XN297
[JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
[JOYSWAY](Protocols_Details.md#JOYSWAY---84)|84|||||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|ZCZ50||||||NRF24L01|XN297
@@ -155,7 +155,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|
[XERALL](Protocols_Details.md#XERALL---91)|91|Tank||||||||NRF24L01|XN297
[XK](Protocols_Details.md#XK---62)|62|X450|X420|Cars||||||NRF24L011&CC2500|XN297
[XK2](Protocols_Details.md#XK2---99)|99|X4||||||||NRF24L01&CC2500|XN297
[XK2](Protocols_Details.md#XK2---99)|99|X4|P10|||||||NRF24L01&CC2500|XN297
[YD717](Protocols_Details.md#YD717---8)|8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01|
[YuXiang](Protocols_Details.md#YuXiang---100)|100|||||||||NRF24L01|XN297
[ZSX](Protocols_Details.md#ZSX---52)|52|280||||||||NRF24L01|XN297
@@ -1520,9 +1520,6 @@ Models: WLtoys cars 284131/284161/284010/124016/124017/144010 and Eachine EAT14
You must assign a different RX number for each receiver/plane. Otherwise the new receiver/plane ID will overwrite the previous one.
### Sub_protocol X4 - *0*
Transmitter: XK X4-A160, X5S, model: XK A160S, XK A280, XK A300
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
@@ -1535,6 +1532,12 @@ The plane does not need to be bound each time if it is powered on **after** the
The rudder trim is driven from the rudder channel to increase the range (Original TX rudder has no range once the motor has been turned on...).
### Sub_protocol X4 - *0*
Transmitter: XK X4-A160, X5S, model: XK A160S, XK A280, XK A300
### Sub_protocol P10 - *1*
Model: Park10 J3-CUB
***
# NRF24L01 RF Module
@@ -1927,8 +1930,19 @@ ARM|
### Sub_protocol FQ777_951 - *3*
### Sub_protocol XKK170 - *3*
Model: XK K170 UH-60L Black hawk
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|RATE|EMERGENCY|TAKE_OFF/LANDING|CALIB|TrimA|TrimE
RATE: -100% Low, 0% Mid, +100% High
## JIABAILE - *102*
### Sub_protocol Std - *0*
Models: JBL-430x 1:43 car without gyro
You must assign a different RX number for each car. Otherwise the new car ID will overwrite the previous one.
@@ -1937,7 +1951,21 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
ST|TH|-|ST_TRIM|SPEED|LIGHT|FLASH
SPEED: -100% High, 0% Mid, +100% Low
- Extended Steering comparing to original
- SPEED: -100% High, 0% Mid, +100% Low
- ST_TRIM: value between -100% and +100% but using the radio steering trim looks better
### Sub_protocol Gyro - *1*
Models: JBL-430x 1:43 car with gyro
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
ST|TH|GYRO|ST_TRIM|SPEED|LIGHT|FLASH
- Extended Steering comparing to original
- SPEED: -100% High, 0% Mid, +100% Low
- GYRO: -100% Off..+100% Max
- ST_TRIM: momentary switch, -100% Trim left, 0% Idle, +100% Trim right. Configure the radio steering trim has buttons (ST- and ST+) and assign them to that channel. Don't forget to disable the steering trim in the driving modes.
## JJRC345 - *71*
@@ -1953,6 +1981,15 @@ Model: DF-Models SkyTumbler
RTH not supported
## KAMTOM - *104*
Models: KAMTOM KM24xx (KM32xx?), Pinecone SG-24xx
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
ST|TH|UNK1|UNK2|ST_TR|TH_TR|TH_DR
Low batt telemetry is not yet added.
## KYOSHO2 - *93*
Model: TX KT-17, Minium Edge 540, Minium Citabria
@@ -2246,9 +2283,8 @@ Same channels assignement as above.
## YuXiang - *100*
Models: E190, F07 UH-1D
Models: E190 F07 UH-1D, E186 F08 Bell-206
**Only 2 TX ID, use the RX number to switch**.
Telemetry A1=Batt voltage with a Ratio 3.5 and Offset 7, A2=Low batt with 0=OK, everything else=BAD
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11

View File

@@ -108,7 +108,7 @@ The images below indicate the pin layout and the location of the ground pin on t
|:---:|:---:|:---:|
<img src="images/V2b_ISP.jpeg" width="189" height="200" /> | <img src="images/MPTM_PCB_2.3d_ISP.png" width="486" height="201" /> | <img src="images/ProMini_ISP.png" width="195" height="200" /> |
You are now ready to plug in the USB programmer to the computer. If you are looking for a good working USBasp Windows driver, [use this one](http://www.protostack.com/download/USBasp-win-driver-x86-x64-v3.0.7.zip).
You are now ready to plug in the USB programmer to the computer. If you are looking for a good working USBasp Windows driver, [use this one](https://protostack.com.au/download/USBasp-win-driver-x86-x64-v3.0.7.zip).
### Burn bootloader and set fuses
The bootloader only needs to be burned once, unless you decide to switch from one option to the other (or it is accidentally erased). If you have already burned the bootloader / set the fuses you can skip this step.