mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-03 03:57:51 +00:00
Ajout de 5 protocoles
This commit is contained in:
parent
bdb8eec3ea
commit
f6b4db1618
@ -191,10 +191,16 @@ const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
|
|||||||
0xFF, 0xFF, 0xFF
|
0xFF, 0xFF, 0xFF
|
||||||
};
|
};
|
||||||
const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
|
const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
|
||||||
|
/*
|
||||||
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50,
|
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50,
|
||||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f,
|
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f,
|
||||||
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
|
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
|
||||||
0x01, 0x0f, 0xff
|
0x01, 0x0f, 0xff
|
||||||
|
*/
|
||||||
|
-1, 0x42, 0x00, 0x14, 0x00, -1 , -1 , 0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50,
|
||||||
|
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f,
|
||||||
|
0x13, 0xc3, 0x00, -1, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
|
||||||
|
0x01, 0x0f, -1
|
||||||
};
|
};
|
||||||
#define ID_NORMAL 0x55201041
|
#define ID_NORMAL 0x55201041
|
||||||
#define ID_PLUS 0xAA201041
|
#define ID_PLUS 0xAA201041
|
||||||
|
@ -114,14 +114,6 @@ uint8_t data_col;
|
|||||||
uint16_t cyrf_state;
|
uint16_t cyrf_state;
|
||||||
uint8_t crcidx;
|
uint8_t crcidx;
|
||||||
uint8_t binding;
|
uint8_t binding;
|
||||||
/*
|
|
||||||
#ifdef USE_FIXED_MFGID
|
|
||||||
const uint8_t cyrfmfg_id[6] = {0x5e, 0x28, 0xa3, 0x1b, 0x00, 0x00}; //dx8
|
|
||||||
const uint8_t cyrfmfg_id[6] = {0xd4, 0x62, 0xd6, 0xad, 0xd3, 0xff}; //dx6i
|
|
||||||
#else
|
|
||||||
//uint8_t cyrfmfg_id[6];
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void __attribute__((unused)) build_bind_packet()
|
static void __attribute__((unused)) build_bind_packet()
|
||||||
{
|
{
|
||||||
|
@ -117,7 +117,6 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
|
|||||||
// For arithmetic simplicity, channels are repeated in rf_channels array
|
// For arithmetic simplicity, channels are repeated in rf_channels array
|
||||||
if (hopping_frequency_no == 0)
|
if (hopping_frequency_no == 0)
|
||||||
{
|
{
|
||||||
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2};
|
|
||||||
for (uint8_t i = 0; i < 6; i++)
|
for (uint8_t i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
packet[i*2] = Servo_data[ch[i]]>>8; //high byte of servo timing(1000-2000us)
|
packet[i*2] = Servo_data[ch[i]]>>8; //high byte of servo timing(1000-2000us)
|
||||||
|
@ -22,51 +22,51 @@
|
|||||||
#define FLYSKY_BIND_COUNT 2500
|
#define FLYSKY_BIND_COUNT 2500
|
||||||
|
|
||||||
const uint8_t PROGMEM tx_channels[] = {
|
const uint8_t PROGMEM tx_channels[] = {
|
||||||
0x0a, 0x5a, 0x14, 0x64, 0x1e, 0x6e, 0x28, 0x78, 0x32, 0x82, 0x3c, 0x8c, 0x46, 0x96, 0x50, 0xa0,
|
0x0a, 0x5a, 0x14, 0x64, 0x1e, 0x6e, 0x28, 0x78, 0x32, 0x82, 0x3c, 0x8c, 0x46, 0x96, 0x50, 0xa0,
|
||||||
0xa0, 0x50, 0x96, 0x46, 0x8c, 0x3c, 0x82, 0x32, 0x78, 0x28, 0x6e, 0x1e, 0x64, 0x14, 0x5a, 0x0a,
|
0xa0, 0x50, 0x96, 0x46, 0x8c, 0x3c, 0x82, 0x32, 0x78, 0x28, 0x6e, 0x1e, 0x64, 0x14, 0x5a, 0x0a,
|
||||||
0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x46, 0x96, 0x1e, 0x6e, 0x3c, 0x8c, 0x28, 0x78, 0x32, 0x82,
|
0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x46, 0x96, 0x1e, 0x6e, 0x3c, 0x8c, 0x28, 0x78, 0x32, 0x82,
|
||||||
0x82, 0x32, 0x78, 0x28, 0x8c, 0x3c, 0x6e, 0x1e, 0x96, 0x46, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a,
|
0x82, 0x32, 0x78, 0x28, 0x8c, 0x3c, 0x6e, 0x1e, 0x96, 0x46, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a,
|
||||||
0x28, 0x78, 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96,
|
0x28, 0x78, 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96,
|
||||||
0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, 0x78, 0x28,
|
0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, 0x78, 0x28,
|
||||||
0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, 0x14, 0x64,
|
0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, 0x14, 0x64,
|
||||||
0x64, 0x14, 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50,
|
0x64, 0x14, 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50,
|
||||||
0x50, 0xa0, 0x46, 0x96, 0x3c, 0x8c, 0x28, 0x78, 0x0a, 0x5a, 0x32, 0x82, 0x1e, 0x6e, 0x14, 0x64,
|
0x50, 0xa0, 0x46, 0x96, 0x3c, 0x8c, 0x28, 0x78, 0x0a, 0x5a, 0x32, 0x82, 0x1e, 0x6e, 0x14, 0x64,
|
||||||
0x64, 0x14, 0x6e, 0x1e, 0x82, 0x32, 0x5a, 0x0a, 0x78, 0x28, 0x8c, 0x3c, 0x96, 0x46, 0xa0, 0x50,
|
0x64, 0x14, 0x6e, 0x1e, 0x82, 0x32, 0x5a, 0x0a, 0x78, 0x28, 0x8c, 0x3c, 0x96, 0x46, 0xa0, 0x50,
|
||||||
0x46, 0x96, 0x3c, 0x8c, 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64,
|
0x46, 0x96, 0x3c, 0x8c, 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64,
|
||||||
0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, 0x8c, 0x3c, 0x96, 0x46,
|
0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, 0x8c, 0x3c, 0x96, 0x46,
|
||||||
0x46, 0x96, 0x0a, 0x5a, 0x3c, 0x8c, 0x14, 0x64, 0x50, 0xa0, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82,
|
0x46, 0x96, 0x0a, 0x5a, 0x3c, 0x8c, 0x14, 0x64, 0x50, 0xa0, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82,
|
||||||
0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0xa0, 0x50, 0x64, 0x14, 0x8c, 0x3c, 0x5a, 0x0a, 0x96, 0x46,
|
0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0xa0, 0x50, 0x64, 0x14, 0x8c, 0x3c, 0x5a, 0x0a, 0x96, 0x46,
|
||||||
0x46, 0x96, 0x0a, 0x5a, 0x50, 0xa0, 0x3c, 0x8c, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64,
|
0x46, 0x96, 0x0a, 0x5a, 0x50, 0xa0, 0x3c, 0x8c, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64,
|
||||||
0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0x8c, 0x3c, 0xa0, 0x50, 0x5a, 0x0a, 0x96, 0x46
|
0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0x8c, 0x3c, 0xa0, 0x50, 0x5a, 0x0a, 0x96, 0x46
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// flags going to byte 10
|
// flags going to byte 10
|
||||||
FLAG_V9X9_VIDEO = 0x40,
|
FLAG_V9X9_VIDEO = 0x40,
|
||||||
FLAG_V9X9_CAMERA= 0x80,
|
FLAG_V9X9_CAMERA= 0x80,
|
||||||
// flags going to byte 12
|
// flags going to byte 12
|
||||||
FLAG_V9X9_UNK = 0x10, // undocumented ?
|
FLAG_V9X9_FLIP = 0x10,
|
||||||
FLAG_V9X9_LED = 0x20,
|
FLAG_V9X9_LED = 0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// flags going to byte 13
|
// flags going to byte 13
|
||||||
FLAG_V6X6_HLESS1= 0x80,
|
FLAG_V6X6_HLESS1= 0x80,
|
||||||
// flags going to byte 14
|
// flags going to byte 14
|
||||||
FLAG_V6X6_VIDEO = 0x01,
|
FLAG_V6X6_VIDEO = 0x01,
|
||||||
FLAG_V6X6_YCAL = 0x02,
|
FLAG_V6X6_YCAL = 0x02,
|
||||||
FLAG_V6X6_XCAL = 0x04,
|
FLAG_V6X6_XCAL = 0x04,
|
||||||
FLAG_V6X6_RTH = 0x08,
|
FLAG_V6X6_RTH = 0x08,
|
||||||
FLAG_V6X6_CAMERA= 0x10,
|
FLAG_V6X6_CAMERA= 0x10,
|
||||||
FLAG_V6X6_HLESS2= 0x20,
|
FLAG_V6X6_HLESS2= 0x20,
|
||||||
FLAG_V6X6_LED = 0x40,
|
FLAG_V6X6_LED = 0x40,
|
||||||
FLAG_V6X6_FLIP = 0x80,
|
FLAG_V6X6_FLIP = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// flags going to byte 14
|
// flags going to byte 14
|
||||||
FLAG_V912_TOPBTN= 0x40,
|
FLAG_V912_TOPBTN= 0x40,
|
||||||
FLAG_V912_BTMBTN= 0x80,
|
FLAG_V912_BTMBTN= 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t chanrow;
|
uint8_t chanrow;
|
||||||
@ -75,138 +75,139 @@ uint8_t chanoffset;
|
|||||||
|
|
||||||
static void __attribute__((unused)) flysky_apply_extension_flags()
|
static void __attribute__((unused)) flysky_apply_extension_flags()
|
||||||
{
|
{
|
||||||
const uint8_t V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ?
|
const uint8_t V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ?
|
||||||
0x49, 0x49, 0x49, 0x49, 0x49, };
|
0x49, 0x49, 0x49, 0x49, 0x49, };
|
||||||
static uint8_t seq_counter;
|
static uint8_t seq_counter;
|
||||||
switch(sub_protocol)
|
switch(sub_protocol)
|
||||||
{
|
{
|
||||||
case V9X9:
|
case V9X9:
|
||||||
if(Servo_AUX1)
|
if(Servo_AUX1)
|
||||||
packet[12] |= FLAG_V9X9_UNK;
|
packet[12] |= FLAG_V9X9_FLIP;
|
||||||
if(Servo_AUX2)
|
if(Servo_AUX2)
|
||||||
packet[12] |= FLAG_V9X9_LED;
|
packet[12] |= FLAG_V9X9_LED;
|
||||||
if(Servo_AUX3)
|
if(Servo_AUX3)
|
||||||
packet[10] |= FLAG_V9X9_CAMERA;
|
packet[10] |= FLAG_V9X9_CAMERA;
|
||||||
if(Servo_AUX4)
|
if(Servo_AUX4)
|
||||||
packet[10] |= FLAG_V9X9_VIDEO;
|
packet[10] |= FLAG_V9X9_VIDEO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V6X6:
|
case V6X6:
|
||||||
packet[13] = 0x03; // 3 = 100% rate (0=40%, 1=60%, 2=80%)
|
packet[13] = 0x03; // 3 = 100% rate (0=40%, 1=60%, 2=80%)
|
||||||
packet[14] = 0x00;
|
packet[14] = 0x00;
|
||||||
if(Servo_AUX1)
|
if(Servo_AUX1)
|
||||||
packet[14] |= FLAG_V6X6_FLIP;
|
packet[14] |= FLAG_V6X6_FLIP;
|
||||||
if(Servo_AUX2)
|
if(Servo_AUX2)
|
||||||
packet[14] |= FLAG_V6X6_LED;
|
packet[14] |= FLAG_V6X6_LED;
|
||||||
if(Servo_AUX3)
|
if(Servo_AUX3)
|
||||||
packet[14] |= FLAG_V6X6_CAMERA;
|
packet[14] |= FLAG_V6X6_CAMERA;
|
||||||
if(Servo_AUX4)
|
if(Servo_AUX4)
|
||||||
packet[14] |= FLAG_V6X6_VIDEO;
|
packet[14] |= FLAG_V6X6_VIDEO;
|
||||||
if(Servo_AUX5)
|
if(Servo_AUX5)
|
||||||
{
|
{
|
||||||
packet[13] |= FLAG_V6X6_HLESS1;
|
packet[13] |= FLAG_V6X6_HLESS1;
|
||||||
packet[14] |= FLAG_V6X6_HLESS2;
|
packet[14] |= FLAG_V6X6_HLESS2;
|
||||||
}
|
}
|
||||||
if(Servo_AUX6) //use option to manipulate these bytes
|
if(Servo_AUX6) //use option to manipulate these bytes
|
||||||
packet[14] |= FLAG_V6X6_RTH;
|
packet[14] |= FLAG_V6X6_RTH;
|
||||||
if(Servo_AUX7)
|
if(Servo_AUX7)
|
||||||
packet[14] |= FLAG_V6X6_XCAL;
|
packet[14] |= FLAG_V6X6_XCAL;
|
||||||
if(Servo_AUX8)
|
if(Servo_AUX8)
|
||||||
packet[14] |= FLAG_V6X6_YCAL;
|
packet[14] |= FLAG_V6X6_YCAL;
|
||||||
packet[15] = 0x10; // unknown
|
packet[15] = 0x10; // unknown
|
||||||
packet[16] = 0x10; // unknown
|
packet[16] = 0x10; // unknown
|
||||||
packet[17] = 0xAA; // unknown
|
packet[17] = 0xAA; // unknown
|
||||||
packet[18] = 0xAA; // unknown
|
packet[18] = 0xAA; // unknown
|
||||||
packet[19] = 0x60; // unknown, changes at irregular interval in stock TX
|
packet[19] = 0x60; // unknown, changes at irregular interval in stock TX
|
||||||
packet[20] = 0x02; // unknown
|
packet[20] = 0x02; // unknown
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V912:
|
case V912:
|
||||||
seq_counter++;
|
seq_counter++;
|
||||||
if( seq_counter > 9)
|
if( seq_counter > 9)
|
||||||
seq_counter = 0;
|
seq_counter = 0;
|
||||||
packet[12] |= 0x20; // bit 6 is always set ?
|
packet[12] |= 0x20; // bit 6 is always set ?
|
||||||
packet[13] = 0x00; // unknown
|
packet[13] = 0x00; // unknown
|
||||||
packet[14] = 0x00;
|
packet[14] = 0x00;
|
||||||
if(Servo_AUX1)
|
if(Servo_AUX1)
|
||||||
packet[14] = FLAG_V912_BTMBTN;
|
packet[14] = FLAG_V912_BTMBTN;
|
||||||
if(Servo_AUX2)
|
if(Servo_AUX2)
|
||||||
packet[14] |= FLAG_V912_TOPBTN;
|
packet[14] |= FLAG_V912_TOPBTN;
|
||||||
packet[15] = 0x27; // [15] and [16] apparently hold an analog channel with a value lower than 1000
|
packet[15] = 0x27; // [15] and [16] apparently hold an analog channel with a value lower than 1000
|
||||||
packet[16] = 0x03; // maybe it's there for a pitch channel for a CP copter ?
|
packet[16] = 0x03; // maybe it's there for a pitch channel for a CP copter ?
|
||||||
packet[17] = V912_X17_SEQ[seq_counter]; // not sure what [17] & [18] are for
|
packet[17] = V912_X17_SEQ[seq_counter]; // not sure what [17] & [18] are for
|
||||||
if(seq_counter == 0) // V912 Rx does not even read those bytes... [17-20]
|
if(seq_counter == 0) // V912 Rx does not even read those bytes... [17-20]
|
||||||
packet[18] = 0x02;
|
packet[18] = 0x02;
|
||||||
else
|
else
|
||||||
packet[18] = 0x00;
|
packet[18] = 0x00;
|
||||||
packet[19] = 0x00; // unknown
|
packet[19] = 0x00; // unknown
|
||||||
packet[20] = 0x00; // unknown
|
packet[20] = 0x00; // unknown
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused)) flysky_build_packet(uint8_t init)
|
static void __attribute__((unused)) flysky_build_packet(uint8_t init)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
//servodata timing range for flysky.
|
//servodata timing range for flysky.
|
||||||
////-100% =~ 0x03e8//=1000us(min)
|
////-100% =~ 0x03e8//=1000us(min)
|
||||||
//+100% =~ 0x07ca//=1994us(max)
|
//+100% =~ 0x07ca//=1994us(max)
|
||||||
//Center = 0x5d9//=1497us(center)
|
//Center = 0x5d9//=1497us(center)
|
||||||
//channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4
|
//channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4
|
||||||
packet[0] = init ? 0xaa : 0x55;
|
packet[0] = init ? 0xaa : 0x55;
|
||||||
packet[1] = rx_tx_addr[3];
|
packet[1] = rx_tx_addr[3];
|
||||||
packet[2] = rx_tx_addr[2];
|
packet[2] = rx_tx_addr[2];
|
||||||
packet[3] = rx_tx_addr[1];
|
packet[3] = rx_tx_addr[1];
|
||||||
packet[4] = rx_tx_addr[0];
|
packet[4] = rx_tx_addr[0];
|
||||||
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
|
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
|
||||||
for(i = 0; i < 8; i++)
|
for(i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
packet[5+2*i]=lowByte(Servo_data[ch[i]]); //low byte of servo timing(1000-2000us)
|
packet[5+2*i]=lowByte(Servo_data[ch[i]]); //low byte of servo timing(1000-2000us)
|
||||||
packet[6+2*i]=highByte(Servo_data[ch[i]]); //high byte of servo timing(1000-2000us)
|
packet[6+2*i]=highByte(Servo_data[ch[i]]); //high byte of servo timing(1000-2000us)
|
||||||
}
|
}
|
||||||
flysky_apply_extension_flags();
|
flysky_apply_extension_flags();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ReadFlySky()
|
uint16_t ReadFlySky()
|
||||||
{
|
{
|
||||||
if (bind_counter)
|
if (bind_counter)
|
||||||
{
|
{
|
||||||
flysky_build_packet(1);
|
flysky_build_packet(1);
|
||||||
A7105_WriteData(21, 1);
|
A7105_WriteData(21, 1);
|
||||||
bind_counter--;
|
bind_counter--;
|
||||||
if (! bind_counter)
|
if (! bind_counter)
|
||||||
BIND_DONE;
|
BIND_DONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
flysky_build_packet(0);
|
flysky_build_packet(0);
|
||||||
A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow*16+chancol])-chanoffset);
|
A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow*16+chancol])-chanoffset);
|
||||||
chancol = (chancol + 1) % 16;
|
chancol = (chancol + 1) % 16;
|
||||||
if (! chancol) //Keep transmit power updated
|
if (! chancol) //Keep transmit power updated
|
||||||
A7105_SetPower();
|
A7105_SetPower();
|
||||||
}
|
}
|
||||||
return 1460;
|
return 1460;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t initFlySky() {
|
uint16_t initFlySky() {
|
||||||
//A7105_Reset();
|
//A7105_Reset();
|
||||||
A7105_Init(INIT_FLYSKY); //flysky_init();
|
A7105_Init(INIT_FLYSKY); //flysky_init();
|
||||||
|
|
||||||
if (rx_tx_addr[3] > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912)
|
if (rx_tx_addr[3] > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912)
|
||||||
rx_tx_addr[3] = rx_tx_addr[3] - 0x70;
|
rx_tx_addr[3] = rx_tx_addr[3] - 0x70;
|
||||||
chanrow=rx_tx_addr[3] % 16;
|
chanrow=rx_tx_addr[3] % 16;
|
||||||
chancol=0;
|
chancol=0;
|
||||||
chanoffset=rx_tx_addr[3] / 16;
|
chanoffset=rx_tx_addr[3] / 16;
|
||||||
|
|
||||||
|
|
||||||
if(IS_AUTOBIND_FLAG_on)
|
if(IS_AUTOBIND_FLAG_on)
|
||||||
bind_counter = FLYSKY_BIND_COUNT;
|
bind_counter = FLYSKY_BIND_COUNT;
|
||||||
else
|
else
|
||||||
bind_counter = 0;
|
bind_counter = 0;
|
||||||
return 2400;
|
return 2400;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -43,101 +43,12 @@
|
|||||||
0x34, 0x1B, 0x00, 0x1D, 0x03
|
0x34, 0x1B, 0x00, 0x1D, 0x03
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t hop(uint8_t byte)
|
static uint8_t __attribute__((unused)) hop(uint8_t byte)
|
||||||
{
|
{
|
||||||
return pgm_read_byte_near(&hop_data[byte]);
|
return pgm_read_byte_near(&hop_data[byte]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t initFrSkyX()
|
static void __attribute__((unused)) set_start(uint8_t ch )
|
||||||
{
|
|
||||||
while(!chanskip)
|
|
||||||
{
|
|
||||||
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
|
|
||||||
chanskip=random(0xfefefefe)%47;
|
|
||||||
}
|
|
||||||
while((chanskip-ctr)%4)
|
|
||||||
ctr=(ctr+1)%4;
|
|
||||||
|
|
||||||
counter_rst=(chanskip-ctr)>>2;
|
|
||||||
//for test***************
|
|
||||||
//rx_tx_addr[3]=0xB3;
|
|
||||||
//rx_tx_addr[2]=0xFD;
|
|
||||||
//************************
|
|
||||||
frskyX_init();
|
|
||||||
//
|
|
||||||
if(IS_AUTOBIND_FLAG_on)
|
|
||||||
{
|
|
||||||
state = FRSKY_BIND;
|
|
||||||
initialize_data(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = FRSKY_DATA1;
|
|
||||||
initialize_data(0);
|
|
||||||
}
|
|
||||||
return 10000;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ReadFrSkyX()
|
|
||||||
{
|
|
||||||
switch(state)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
set_start(47);
|
|
||||||
CC2500_SetPower();
|
|
||||||
cc2500_strobe(CC2500_SFRX);
|
|
||||||
//
|
|
||||||
frskyX_build_bind_packet();
|
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
|
||||||
cc2500_writeFifo(packet, packet[0]+1);
|
|
||||||
state++;
|
|
||||||
return 9000;
|
|
||||||
case FRSKY_BIND_DONE:
|
|
||||||
initialize_data(0);
|
|
||||||
channr=0;
|
|
||||||
BIND_DONE;
|
|
||||||
state++;
|
|
||||||
break;
|
|
||||||
case FRSKY_DATA1:
|
|
||||||
LED_ON;
|
|
||||||
CC2500_SetTxRxMode(TX_EN);
|
|
||||||
set_start(channr);
|
|
||||||
CC2500_SetPower();
|
|
||||||
cc2500_strobe(CC2500_SFRX);
|
|
||||||
channr = (channr+chanskip)%47;
|
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
|
||||||
cc2500_writeFifo(packet, packet[0]+1);
|
|
||||||
//
|
|
||||||
frskyX_data_frame();
|
|
||||||
state++;
|
|
||||||
return 5500;
|
|
||||||
case FRSKY_DATA2:
|
|
||||||
CC2500_SetTxRxMode(RX_EN);
|
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
|
||||||
state++;
|
|
||||||
return 200;
|
|
||||||
case FRSKY_DATA3:
|
|
||||||
cc2500_strobe(CC2500_SRX);
|
|
||||||
state++;
|
|
||||||
return 3000;
|
|
||||||
case FRSKY_DATA4:
|
|
||||||
len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
|
||||||
if (len &&(len<MAX_PKT))
|
|
||||||
{
|
|
||||||
cc2500_readFifo(pkt, len);
|
|
||||||
#if defined TELEMETRY
|
|
||||||
frsky_check_telemetry(pkt,len); //check if valid telemetry packets
|
|
||||||
//parse telemetry packets here
|
|
||||||
//The same telemetry function used by FrSky(D8).
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
state = FRSKY_DATA1;
|
|
||||||
return 300;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_start(uint8_t ch )
|
|
||||||
{
|
{
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
cc2500_writeReg(CC2500_23_FSCAL3, calData[ch][0]);
|
cc2500_writeReg(CC2500_23_FSCAL3, calData[ch][0]);
|
||||||
@ -146,45 +57,39 @@
|
|||||||
cc2500_writeReg(CC2500_0A_CHANNR, ch==47?0:pgm_read_word(&hop_data[ch]));
|
cc2500_writeReg(CC2500_0A_CHANNR, ch==47?0:pgm_read_word(&hop_data[ch]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void frskyX_init()
|
static void __attribute__((unused)) frskyX_init()
|
||||||
{
|
{
|
||||||
CC2500_Reset();
|
CC2500_Reset();
|
||||||
cc2500_writeReg(CC2500_02_IOCFG0, 0x06);
|
|
||||||
cc2500_writeReg(CC2500_00_IOCFG2, 0x06);
|
for(uint8_t i=0;i<36;i++)
|
||||||
cc2500_writeReg(CC2500_17_MCSM1, 0x0C);
|
{
|
||||||
cc2500_writeReg(CC2500_18_MCSM0, 0x18);
|
uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]);
|
||||||
cc2500_writeReg(CC2500_06_PKTLEN, 0x1E);
|
uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]);
|
||||||
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04);
|
|
||||||
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x01);
|
if(reg==CC2500_06_PKTLEN)
|
||||||
cc2500_writeReg(CC2500_3E_PATABLE, 0xff);
|
val=0x1E;
|
||||||
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x0A);
|
else
|
||||||
cc2500_writeReg(CC2500_0C_FSCTRL0, 0x00);
|
if(reg==CC2500_08_PKTCTRL0)
|
||||||
cc2500_writeReg(CC2500_0D_FREQ2, 0x5c);
|
val=0x01;
|
||||||
cc2500_writeReg(CC2500_0E_FREQ1, 0x76);
|
else
|
||||||
cc2500_writeReg(CC2500_0F_FREQ0, 0x27);
|
if(reg==CC2500_0B_FSCTRL1)
|
||||||
cc2500_writeReg(CC2500_10_MDMCFG4, 0x7B);
|
val=0x0A;
|
||||||
cc2500_writeReg(CC2500_11_MDMCFG3, 0x61);
|
else
|
||||||
cc2500_writeReg(CC2500_12_MDMCFG2, 0x13);
|
if(reg==CC2500_10_MDMCFG4)
|
||||||
cc2500_writeReg(CC2500_13_MDMCFG1, 0x23);
|
val=0x7B;
|
||||||
cc2500_writeReg(CC2500_14_MDMCFG0, 0x7a);
|
else
|
||||||
cc2500_writeReg(CC2500_15_DEVIATN, 0x51);
|
if(reg==CC2500_11_MDMCFG3)
|
||||||
cc2500_writeReg(CC2500_19_FOCCFG, 0x16);
|
val=0x61;
|
||||||
cc2500_writeReg(CC2500_1A_BSCFG, 0x6c);
|
else
|
||||||
cc2500_writeReg(CC2500_1B_AGCCTRL2,0x43);
|
if(reg==CC2500_12_MDMCFG2)
|
||||||
cc2500_writeReg(CC2500_1C_AGCCTRL1,0x40);
|
val=0x13;
|
||||||
cc2500_writeReg(CC2500_1D_AGCCTRL0,0x91);
|
else
|
||||||
cc2500_writeReg(CC2500_21_FREND1, 0x56);
|
if(reg==CC2500_15_DEVIATN)
|
||||||
cc2500_writeReg(CC2500_22_FREND0, 0x10);
|
val=0x51;
|
||||||
cc2500_writeReg(CC2500_23_FSCAL3, 0xa9);
|
|
||||||
cc2500_writeReg(CC2500_24_FSCAL2, 0x0A);
|
cc2500_writeReg(reg,val);
|
||||||
cc2500_writeReg(CC2500_25_FSCAL1, 0x00);
|
}
|
||||||
cc2500_writeReg(CC2500_26_FSCAL0, 0x11);
|
|
||||||
cc2500_writeReg(CC2500_29_FSTEST, 0x59);
|
|
||||||
cc2500_writeReg(CC2500_2C_TEST2, 0x88);
|
|
||||||
cc2500_writeReg(CC2500_2D_TEST1, 0x31);
|
|
||||||
cc2500_writeReg(CC2500_2E_TEST0, 0x0B);
|
|
||||||
cc2500_writeReg(CC2500_03_FIFOTHR, 0x07);
|
|
||||||
cc2500_writeReg(CC2500_09_ADDR, 0x00);
|
|
||||||
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04);
|
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04);
|
||||||
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
|
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
@ -208,7 +113,7 @@
|
|||||||
//#######END INIT########
|
//#######END INIT########
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_data(uint8_t adr)
|
static void __attribute__((unused)) initialize_data(uint8_t adr)
|
||||||
{
|
{
|
||||||
cc2500_writeReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
|
cc2500_writeReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
|
||||||
cc2500_writeReg(CC2500_18_MCSM0, 0x8);
|
cc2500_writeReg(CC2500_18_MCSM0, 0x8);
|
||||||
@ -216,7 +121,18 @@
|
|||||||
cc2500_writeReg(CC2500_07_PKTCTRL1,0x05);
|
cc2500_writeReg(CC2500_07_PKTCTRL1,0x05);
|
||||||
}
|
}
|
||||||
|
|
||||||
void frskyX_build_bind_packet()
|
static uint8_t __attribute__((unused)) crc_Byte( uint8_t byte )
|
||||||
|
{
|
||||||
|
crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ byte) & 0xFF]);
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i )
|
||||||
|
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
|
||||||
|
return (uint16_t)(((Servo_data[i]-PPM_MIN)*3)>>1)+64;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((unused)) frskyX_build_bind_packet()
|
||||||
{
|
{
|
||||||
crc=0;
|
crc=0;
|
||||||
packet[0] = 0x1D;
|
packet[0] = 0x1D;
|
||||||
@ -243,7 +159,7 @@
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void frskyX_data_frame()
|
static void __attribute__((unused)) frskyX_data_frame()
|
||||||
{
|
{
|
||||||
//0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12
|
//0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12
|
||||||
//
|
//
|
||||||
@ -302,14 +218,92 @@
|
|||||||
packet[29]=lowByte(crc);
|
packet[29]=lowByte(crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t scaleForPXX( uint8_t i )
|
uint16_t ReadFrSkyX()
|
||||||
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
|
|
||||||
return (uint16_t)(((Servo_data[i]-PPM_MIN)*3)>>1)+64;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t crc_Byte( uint8_t byte )
|
|
||||||
{
|
{
|
||||||
crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ byte) & 0xFF]);
|
switch(state)
|
||||||
return byte;
|
{
|
||||||
|
default:
|
||||||
|
set_start(47);
|
||||||
|
CC2500_SetPower();
|
||||||
|
cc2500_strobe(CC2500_SFRX);
|
||||||
|
//
|
||||||
|
frskyX_build_bind_packet();
|
||||||
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
|
cc2500_writeFifo(packet, packet[0]+1);
|
||||||
|
state++;
|
||||||
|
return 9000;
|
||||||
|
case FRSKY_BIND_DONE:
|
||||||
|
initialize_data(0);
|
||||||
|
channr=0;
|
||||||
|
BIND_DONE;
|
||||||
|
state++;
|
||||||
|
break;
|
||||||
|
case FRSKY_DATA1:
|
||||||
|
LED_ON;
|
||||||
|
CC2500_SetTxRxMode(TX_EN);
|
||||||
|
set_start(channr);
|
||||||
|
CC2500_SetPower();
|
||||||
|
cc2500_strobe(CC2500_SFRX);
|
||||||
|
channr = (channr+chanskip)%47;
|
||||||
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
|
cc2500_writeFifo(packet, packet[0]+1);
|
||||||
|
//
|
||||||
|
frskyX_data_frame();
|
||||||
|
state++;
|
||||||
|
return 5500;
|
||||||
|
case FRSKY_DATA2:
|
||||||
|
CC2500_SetTxRxMode(RX_EN);
|
||||||
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
|
state++;
|
||||||
|
return 200;
|
||||||
|
case FRSKY_DATA3:
|
||||||
|
cc2500_strobe(CC2500_SRX);
|
||||||
|
state++;
|
||||||
|
return 3000;
|
||||||
|
case FRSKY_DATA4:
|
||||||
|
len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||||
|
if (len &&(len<MAX_PKT))
|
||||||
|
{
|
||||||
|
cc2500_readFifo(pkt, len);
|
||||||
|
#if defined TELEMETRY
|
||||||
|
frsky_check_telemetry(pkt,len); //check if valid telemetry packets
|
||||||
|
//parse telemetry packets here
|
||||||
|
//The same telemetry function used by FrSky(D8).
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
state = FRSKY_DATA1;
|
||||||
|
return 300;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t initFrSkyX()
|
||||||
|
{
|
||||||
|
while(!chanskip)
|
||||||
|
{
|
||||||
|
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
|
||||||
|
chanskip=random(0xfefefefe)%47;
|
||||||
|
}
|
||||||
|
while((chanskip-ctr)%4)
|
||||||
|
ctr=(ctr+1)%4;
|
||||||
|
|
||||||
|
counter_rst=(chanskip-ctr)>>2;
|
||||||
|
//for test***************
|
||||||
|
//rx_tx_addr[3]=0xB3;
|
||||||
|
//rx_tx_addr[2]=0xFD;
|
||||||
|
//************************
|
||||||
|
frskyX_init();
|
||||||
|
//
|
||||||
|
if(IS_AUTOBIND_FLAG_on)
|
||||||
|
{
|
||||||
|
state = FRSKY_BIND;
|
||||||
|
initialize_data(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = FRSKY_DATA1;
|
||||||
|
initialize_data(0);
|
||||||
|
}
|
||||||
|
return 10000;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
@ -38,45 +38,19 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
|
|||||||
// Configure cc2500 for tx mode
|
// Configure cc2500 for tx mode
|
||||||
CC2500_Reset();
|
CC2500_Reset();
|
||||||
//
|
//
|
||||||
cc2500_writeReg(CC2500_02_IOCFG0, 0x06);
|
for(uint8_t i=0;i<36;i++)
|
||||||
cc2500_writeReg(CC2500_00_IOCFG2, 0x06);
|
{
|
||||||
cc2500_writeReg(CC2500_17_MCSM1, 0x0c);
|
uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]);
|
||||||
cc2500_writeReg(CC2500_18_MCSM0, 0x18);
|
uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]);
|
||||||
cc2500_writeReg(CC2500_06_PKTLEN, 0x19);
|
|
||||||
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04);
|
if(reg==CC2500_0C_FSCTRL0)
|
||||||
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x05);
|
val=option;
|
||||||
cc2500_writeReg(CC2500_3E_PATABLE, 0xff);
|
else
|
||||||
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x08);
|
if(reg==CC2500_1B_AGCCTRL2)
|
||||||
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
|
val=bind ? 0x43 : 0x03;
|
||||||
//base freq FREQ = 0x5C7627 (F = 2404MHz)
|
cc2500_writeReg(reg,val);
|
||||||
cc2500_writeReg(CC2500_0D_FREQ2, 0x5c);
|
}
|
||||||
cc2500_writeReg(CC2500_0E_FREQ1, 0x76);
|
|
||||||
cc2500_writeReg(CC2500_0F_FREQ0, 0x27);
|
|
||||||
//
|
|
||||||
cc2500_writeReg(CC2500_10_MDMCFG4, 0xAA);
|
|
||||||
cc2500_writeReg(CC2500_11_MDMCFG3, 0x39);
|
|
||||||
cc2500_writeReg(CC2500_12_MDMCFG2, 0x11);
|
|
||||||
cc2500_writeReg(CC2500_13_MDMCFG1, 0x23);
|
|
||||||
cc2500_writeReg(CC2500_14_MDMCFG0, 0x7a);
|
|
||||||
cc2500_writeReg(CC2500_15_DEVIATN, 0x42);
|
|
||||||
cc2500_writeReg(CC2500_19_FOCCFG, 0x16);
|
|
||||||
cc2500_writeReg(CC2500_1A_BSCFG, 0x6c);
|
|
||||||
cc2500_writeReg(CC2500_1B_AGCCTRL2, bind ? 0x43 : 0x03);
|
|
||||||
cc2500_writeReg(CC2500_1C_AGCCTRL1,0x40);
|
|
||||||
cc2500_writeReg(CC2500_1D_AGCCTRL0,0x91);
|
|
||||||
cc2500_writeReg(CC2500_21_FREND1, 0x56);
|
|
||||||
cc2500_writeReg(CC2500_22_FREND0, 0x10);
|
|
||||||
cc2500_writeReg(CC2500_23_FSCAL3, 0xa9);
|
|
||||||
cc2500_writeReg(CC2500_24_FSCAL2, 0x0A);
|
|
||||||
cc2500_writeReg(CC2500_25_FSCAL1, 0x00);
|
|
||||||
cc2500_writeReg(CC2500_26_FSCAL0, 0x11);
|
|
||||||
cc2500_writeReg(CC2500_29_FSTEST, 0x59);
|
|
||||||
cc2500_writeReg(CC2500_2C_TEST2, 0x88);
|
|
||||||
cc2500_writeReg(CC2500_2D_TEST1, 0x31);
|
|
||||||
cc2500_writeReg(CC2500_2E_TEST0, 0x0B);
|
|
||||||
cc2500_writeReg(CC2500_03_FIFOTHR, 0x07);
|
|
||||||
cc2500_writeReg(CC2500_09_ADDR, 0x00);
|
|
||||||
//
|
|
||||||
CC2500_SetTxRxMode(TX_EN);
|
CC2500_SetTxRxMode(TX_EN);
|
||||||
CC2500_SetPower();
|
CC2500_SetPower();
|
||||||
|
|
||||||
|
@ -45,8 +45,7 @@ uint8_t packet[40];
|
|||||||
// Servo data
|
// Servo data
|
||||||
uint16_t Servo_data[NUM_CHN];
|
uint16_t Servo_data[NUM_CHN];
|
||||||
uint8_t Servo_AUX;
|
uint8_t Servo_AUX;
|
||||||
// PPM variable
|
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
|
||||||
volatile uint16_t PPM_data[NUM_CHN];
|
|
||||||
|
|
||||||
// Protocol variables
|
// Protocol variables
|
||||||
uint8_t rx_tx_addr[5];
|
uint8_t rx_tx_addr[5];
|
||||||
@ -73,9 +72,11 @@ uint8_t RX_num;
|
|||||||
|
|
||||||
// Mode_select variables
|
// Mode_select variables
|
||||||
uint8_t mode_select;
|
uint8_t mode_select;
|
||||||
uint8_t ppm_select=0, flag_decal=0;
|
|
||||||
uint8_t protocol_flags=0,protocol_flags2=0;
|
uint8_t protocol_flags=0,protocol_flags2=0;
|
||||||
|
|
||||||
|
// PPM variable
|
||||||
|
volatile uint16_t PPM_data[NUM_CHN];
|
||||||
|
|
||||||
// Serial variables
|
// Serial variables
|
||||||
#define RXBUFFER_SIZE 25
|
#define RXBUFFER_SIZE 25
|
||||||
#define TXBUFFER_SIZE 12
|
#define TXBUFFER_SIZE 12
|
||||||
@ -158,25 +159,24 @@ void setup()
|
|||||||
MProtocol_id_master=random_id(10,false);
|
MProtocol_id_master=random_id(10,false);
|
||||||
|
|
||||||
//Init RF modules
|
//Init RF modules
|
||||||
CC2500_Reset();
|
#ifdef CC2500_INSTALLED
|
||||||
|
CC2500_Reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
//Protocol and interrupts initialization
|
//Protocol and interrupts initialization
|
||||||
#if !defined(POTAR_SELECT)
|
if(mode_select != MODE_SERIAL)
|
||||||
if(mode_select == MODE_SERIAL)
|
|
||||||
{ // Serial
|
|
||||||
cur_protocol[0]=0;
|
|
||||||
cur_protocol[1]=0;
|
|
||||||
prev_protocol=0;
|
|
||||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#else
|
|
||||||
if(mode_select==MODE_SERIAL) { flag_decal=1; } else { flag_decal=0;}
|
|
||||||
#endif
|
|
||||||
{ // PPM
|
{ // PPM
|
||||||
prev_protocol=0;
|
mode_select--;
|
||||||
CHANGE_PROTOCOL_FLAG_on;
|
cur_protocol[0] = PPM_prot[mode_select].protocol;
|
||||||
update_ppm_data();
|
sub_protocol = PPM_prot[mode_select].sub_proto;
|
||||||
|
RX_num = PPM_prot[mode_select].rx_num;
|
||||||
|
MProtocol_id = RX_num + MProtocol_id_master;
|
||||||
|
option = PPM_prot[mode_select].option;
|
||||||
|
if(PPM_prot[mode_select].power) POWER_FLAG_on;
|
||||||
|
if(PPM_prot[mode_select].autobind) AUTOBIND_FLAG_on;
|
||||||
|
mode_select++;
|
||||||
|
|
||||||
|
protocol_init();
|
||||||
|
|
||||||
//Configure PPM interrupt
|
//Configure PPM interrupt
|
||||||
EICRA |=(1<<ISC11); // The rising edge of INT1 pin D3 generates an interrupt request
|
EICRA |=(1<<ISC11); // The rising edge of INT1 pin D3 generates an interrupt request
|
||||||
@ -185,32 +185,41 @@ void setup()
|
|||||||
PPM_Telemetry_serial_init(); // Configure serial for telemetry
|
PPM_Telemetry_serial_init(); // Configure serial for telemetry
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{ // Serial
|
||||||
|
cur_protocol[0]=0;
|
||||||
|
cur_protocol[1]=0;
|
||||||
|
prev_protocol=0;
|
||||||
|
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
#if !defined(POTAR_SELECT)
|
|
||||||
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
|
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
|
||||||
{
|
{
|
||||||
update_serial_data(); // Update protocol and data
|
update_serial_data(); // Update protocol and data
|
||||||
update_aux_flags();
|
update_aux_flags();
|
||||||
}
|
if(IS_CHANGE_PROTOCOL_FLAG_on)
|
||||||
if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
{ // Protocol needs to be changed
|
||||||
#else
|
|
||||||
if(IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
update_PPM_servo();
|
|
||||||
update_aux_flags();
|
|
||||||
update_ppm_data();
|
|
||||||
}
|
|
||||||
if(IS_CHANGE_PROTOCOL_FLAG_on) { // Protocol needs to be changed
|
|
||||||
LED_OFF; //led off during protocol init
|
LED_OFF; //led off during protocol init
|
||||||
module_reset(); //reset previous module
|
module_reset(); //reset previous module
|
||||||
protocol_init(); //init new protocol
|
protocol_init(); //init new protocol
|
||||||
CHANGE_PROTOCOL_FLAG_off; //done
|
CHANGE_PROTOCOL_FLAG_off; //done
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
||||||
|
{
|
||||||
|
for(uint8_t i=0;i<NUM_CHN;i++)
|
||||||
|
{ // update servo data without interrupts to prevent bad read in protocols
|
||||||
|
cli(); // disable global int
|
||||||
|
Servo_data[i]=PPM_data[i];
|
||||||
|
sei(); // enable global int
|
||||||
|
}
|
||||||
|
update_aux_flags();
|
||||||
|
PPM_FLAG_off; // wait for next frame before update
|
||||||
|
}
|
||||||
update_led_status();
|
update_led_status();
|
||||||
#if defined(TELEMETRY)
|
#if defined(TELEMETRY)
|
||||||
if( ((cur_protocol[0]&0x1F)==MODE_FRSKY) || ((cur_protocol[0]&0x1F)==MODE_HUBSAN) || ((cur_protocol[0]&0x1F)==MODE_FRSKYX) )
|
if( ((cur_protocol[0]&0x1F)==MODE_FRSKY) || ((cur_protocol[0]&0x1F)==MODE_HUBSAN) || ((cur_protocol[0]&0x1F)==MODE_FRSKYX) )
|
||||||
@ -220,20 +229,12 @@ void loop()
|
|||||||
CheckTimer(remote_callback);
|
CheckTimer(remote_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_PPM_servo(void) {
|
|
||||||
for(uint8_t i=0;i<NUM_CHN;i++) { // update servo data without interrupts to prevent bad read in protocols
|
|
||||||
cli(); // disable global int
|
|
||||||
Servo_data[i]=PPM_data[i];
|
|
||||||
sei(); // enable global int
|
|
||||||
}
|
|
||||||
PPM_FLAG_off; // wait for next frame before update
|
|
||||||
}
|
|
||||||
// Update Servo_AUX flags based on servo AUX positions
|
// Update Servo_AUX flags based on servo AUX positions
|
||||||
static void update_aux_flags(void)
|
static void update_aux_flags(void)
|
||||||
{
|
{
|
||||||
Servo_AUX=0;
|
Servo_AUX=0;
|
||||||
for(uint8_t i=0;i<8;i++)
|
for(uint8_t i=0;i<8;i++)
|
||||||
if(Servo_data[AUX1+i+flag_decal]>PPM_SWITCH)
|
if(Servo_data[AUX1+i]>PPM_SWITCH)
|
||||||
Servo_AUX|=1<<i;
|
Servo_AUX|=1<<i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +358,36 @@ static void protocol_init()
|
|||||||
remote_callback = fy326_callback;
|
remote_callback = fy326_callback;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(ESKY150_NRF24L01_INO)
|
||||||
|
case MODE_ESKY150:
|
||||||
|
next_callback=esky150_setup();
|
||||||
|
remote_callback = esky150_callback;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(BlueFly_NRF24L01_INO)
|
||||||
|
case MODE_BlueFly:
|
||||||
|
next_callback=BlueFly_setup();
|
||||||
|
remote_callback = bluefly_cb;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(HonTai_NRF24L01_INO)
|
||||||
|
case MODE_BlueFly:
|
||||||
|
next_callback=ht_setup();
|
||||||
|
remote_callback = ht_callback;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(UDI_NRF24L01_INO)
|
||||||
|
case MODE_UDI:
|
||||||
|
next_callback=UDI_setup();
|
||||||
|
remote_callback = UDI_callback;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(NE260_NRF24L01_INO)
|
||||||
|
case MODE_NE260:
|
||||||
|
next_callback=NE260_setup();
|
||||||
|
remote_callback = ne260_cb;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(FLYSKY_A7105_INO)
|
#if defined(FLYSKY_A7105_INO)
|
||||||
case MODE_FLYSKY:
|
case MODE_FLYSKY:
|
||||||
@ -475,6 +506,12 @@ static void protocol_init()
|
|||||||
next_callback=initMJXQ();
|
next_callback=initMJXQ();
|
||||||
remote_callback = MJXQ_callback;
|
remote_callback = MJXQ_callback;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(SHENQI_NRF24L01_INO)
|
||||||
|
case MODE_SHENQI:
|
||||||
|
next_callback=initSHENQI();
|
||||||
|
remote_callback = SHENQI_callback;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,59 +527,6 @@ static void protocol_init()
|
|||||||
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
|
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_ppm_data() {
|
|
||||||
#if defined(POTAR_SELECT)
|
|
||||||
if(Servo_data[AUX1]>PPM_SWITCH) {
|
|
||||||
CHANGE_PROTOCOL_FLAG_on;
|
|
||||||
tone(BUZZER, BUZZER_HTZ);
|
|
||||||
delay(BUZZER_TPS);
|
|
||||||
noTone(BUZZER);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(IS_CHANGE_PROTOCOL_FLAG_on) {
|
|
||||||
ppm_select = 10;
|
|
||||||
|
|
||||||
if(mode_select == 0) {
|
|
||||||
while(ppm_select) {
|
|
||||||
while(!IS_PPM_FLAG_on) {} // wait
|
|
||||||
update_PPM_servo();
|
|
||||||
if(Servo_data[AUX1] < PPM_MAX_100) { ppm_select--; }
|
|
||||||
} // attente de la d<>activation du rebind
|
|
||||||
}
|
|
||||||
prev_protocol = ppm_select;
|
|
||||||
|
|
||||||
// protocol selection
|
|
||||||
ppm_select = 0;
|
|
||||||
if(Servo_data[POTAR_SELECT_M] > PPM_MAX_COMMAND) { ppm_select += 18; } // THROTTLE up
|
|
||||||
else if(Servo_data[POTAR_SELECT_M] < PPM_MIN_COMMAND) { ppm_select += 9; } // THROTTLE down
|
|
||||||
else { ppm_select += 0; } // THROTTLE middle
|
|
||||||
|
|
||||||
|
|
||||||
if(Servo_data[POTAR_SELECT_V] > PPM_MAX_COMMAND) { ppm_select += 7; } // Elevator up
|
|
||||||
else if(Servo_data[POTAR_SELECT_V] < PPM_MIN_COMMAND) { ppm_select += 1; } // Elevator down
|
|
||||||
else { ppm_select += 4; } // Elevator middle
|
|
||||||
|
|
||||||
if(Servo_data[POTAR_SELECT_H] > PPM_MAX_COMMAND) { ppm_select += 2; } // Aileron right
|
|
||||||
else if(Servo_data[POTAR_SELECT_H] < PPM_MIN_COMMAND) { ppm_select += 0; } // Aileron left
|
|
||||||
else { ppm_select += 1; } // Aileron middle
|
|
||||||
|
|
||||||
// if(ppm_select == 5) { ppm_select = eeprom_read_byte(30); } else { eeprom_update_byte(30, ppm_select); }
|
|
||||||
|
|
||||||
if(ppm_select != 5) {
|
|
||||||
if(ppm_select > 5) { ppm_select--; }
|
|
||||||
ppm_select--;
|
|
||||||
cur_protocol[0] = PPM_prot[ppm_select].protocol;
|
|
||||||
sub_protocol = PPM_prot[ppm_select].sub_proto;
|
|
||||||
MProtocol_id = PPM_prot[ppm_select].rx_num + MProtocol_id_master;
|
|
||||||
option = PPM_prot[ppm_select].option;
|
|
||||||
if(PPM_prot[ppm_select].power) POWER_FLAG_on;
|
|
||||||
if(PPM_prot[ppm_select].autobind) AUTOBIND_FLAG_on;
|
|
||||||
ppm_select++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(Servo_data[THROTTLE] > PPM_MIN_100) { delay(100); update_PPM_servo(); } // attente de la remise des gaz <20> z<>ro (pouss<73> <20> fond avec le script lua)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void update_serial_data()
|
static void update_serial_data()
|
||||||
{
|
{
|
||||||
if(rx_ok_buff[0]&0x20) //check range
|
if(rx_ok_buff[0]&0x20) //check range
|
||||||
@ -610,7 +594,7 @@ static void module_reset()
|
|||||||
case MODE_DEVO:
|
case MODE_DEVO:
|
||||||
CYRF_Reset();
|
CYRF_Reset();
|
||||||
break;
|
break;
|
||||||
default: // MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY, MODE_MT99XX, MODE_MJXQ
|
default: // MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY, MODE_MT99XX, MODE_MJXQ, MODE_SHENQI
|
||||||
NRF24L01_Reset();
|
NRF24L01_Reset();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -682,7 +666,6 @@ void Serial_write(uint8_t data)
|
|||||||
|
|
||||||
static void Mprotocol_serial_init()
|
static void Mprotocol_serial_init()
|
||||||
{
|
{
|
||||||
#define BAUD 100000
|
|
||||||
#include <util/setbaud.h>
|
#include <util/setbaud.h>
|
||||||
UBRR0H = UBRRH_VALUE;
|
UBRR0H = UBRRH_VALUE;
|
||||||
UBRR0L = UBRRL_VALUE;
|
UBRR0L = UBRRL_VALUE;
|
||||||
@ -778,7 +761,6 @@ ISR(INT1_vect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Serial RX
|
//Serial RX
|
||||||
#if !defined(POTAR_SELECT)
|
|
||||||
ISR(USART_RX_vect)
|
ISR(USART_RX_vect)
|
||||||
{ // RX interrupt
|
{ // RX interrupt
|
||||||
if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error
|
if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error
|
||||||
@ -815,7 +797,6 @@ ISR(USART_RX_vect)
|
|||||||
idx=0; // Error encountered discard full frame...
|
idx=0; // Error encountered discard full frame...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
//Serial timer
|
//Serial timer
|
||||||
ISR(TIMER1_COMPB_vect)
|
ISR(TIMER1_COMPB_vect)
|
||||||
|
@ -154,7 +154,7 @@ void NRF24L01_SetBitrate(uint8_t bitrate)
|
|||||||
// Note that bitrate 250kbps (and bit RF_DR_LOW) is valid only
|
// Note that bitrate 250kbps (and bit RF_DR_LOW) is valid only
|
||||||
// for nRF24L01+. There is no way to programmatically tell it from
|
// for nRF24L01+. There is no way to programmatically tell it from
|
||||||
// older version, nRF24L01, but the older is practically phased out
|
// older version, nRF24L01, but the older is practically phased out
|
||||||
// by Nordic, so we assume that we deal with with modern version.
|
// by Nordic, so we assume that we deal with modern version.
|
||||||
|
|
||||||
// Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
|
// Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
|
||||||
rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
|
rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
|
||||||
@ -409,3 +409,196 @@ void XN297_ReadPayload(uint8_t* msg, uint8_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// End of XN297 emulation
|
// End of XN297 emulation
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// LT8910 emulation layer
|
||||||
|
uint8_t LT8910_buffer[64];
|
||||||
|
uint8_t LT8910_buffer_start;
|
||||||
|
uint16_t LT8910_buffer_overhead_bits;
|
||||||
|
uint8_t LT8910_addr[8];
|
||||||
|
uint8_t LT8910_addr_size;
|
||||||
|
uint8_t LT8910_Preamble_Len;
|
||||||
|
uint8_t LT8910_Tailer_Len;
|
||||||
|
uint8_t LT8910_CRC_Initial_Data;
|
||||||
|
uint8_t LT8910_Flags;
|
||||||
|
#define LT8910_CRC_ON 6
|
||||||
|
#define LT8910_SCRAMBLE_ON 5
|
||||||
|
#define LT8910_PACKET_LENGTH_EN 4
|
||||||
|
#define LT8910_DATA_PACKET_TYPE_1 3
|
||||||
|
#define LT8910_DATA_PACKET_TYPE_0 2
|
||||||
|
#define LT8910_FEC_TYPE_1 1
|
||||||
|
#define LT8910_FEC_TYPE_0 0
|
||||||
|
|
||||||
|
void LT8910_Config(uint8_t preamble_len, uint8_t trailer_len, uint8_t flags, uint8_t crc_init)
|
||||||
|
{
|
||||||
|
//Preamble 1 to 8 bytes
|
||||||
|
LT8910_Preamble_Len=preamble_len;
|
||||||
|
//Trailer 4 to 18 bits
|
||||||
|
LT8910_Tailer_Len=trailer_len;
|
||||||
|
//Flags
|
||||||
|
// CRC_ON: 1 on, 0 off
|
||||||
|
// SCRAMBLE_ON: 1 on, 0 off
|
||||||
|
// PACKET_LENGTH_EN: 1 1st byte of payload is payload size
|
||||||
|
// DATA_PACKET_TYPE: 00 NRZ, 01 Manchester, 10 8bit/10bit line code, 11 interleave data type
|
||||||
|
// FEC_TYPE: 00 No FEC, 01 FEC13, 10 FEC23, 11 reserved
|
||||||
|
LT8910_Flags=flags;
|
||||||
|
//CRC init constant
|
||||||
|
LT8910_CRC_Initial_Data=crc_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LT8910_SetChannel(uint8_t channel)
|
||||||
|
{
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, channel +2); //NRF24L01 is 2400+channel but LT8900 is 2402+channel
|
||||||
|
}
|
||||||
|
|
||||||
|
void LT8910_SetTxRxMode(enum TXRX_State mode)
|
||||||
|
{
|
||||||
|
if(mode == TX_EN)
|
||||||
|
{
|
||||||
|
//Switch to TX
|
||||||
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
//Disable CRC
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (mode == RX_EN)
|
||||||
|
{
|
||||||
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||||
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 32);
|
||||||
|
//Switch to RX
|
||||||
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
NRF24L01_SetTxRxMode(RX_EN);
|
||||||
|
// Disable CRC
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP) | (1 << NRF24L01_00_PRIM_RX) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LT8910_BuildOverhead()
|
||||||
|
{
|
||||||
|
uint8_t pos;
|
||||||
|
|
||||||
|
//Build overhead
|
||||||
|
//preamble
|
||||||
|
memset(LT8910_buffer,LT8910_addr[0]&0x01?0xAA:0x55,LT8910_Preamble_Len-1);
|
||||||
|
pos=LT8910_Preamble_Len-1;
|
||||||
|
//address
|
||||||
|
for(uint8_t i=0;i<LT8910_addr_size;i++)
|
||||||
|
{
|
||||||
|
LT8910_buffer[pos]=bit_reverse(LT8910_addr[i]);
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
//trailer
|
||||||
|
memset(LT8910_buffer+pos,(LT8910_buffer[pos-1]&0x01)==0?0xAA:0x55,3);
|
||||||
|
LT8910_buffer_overhead_bits=pos*8+LT8910_Tailer_Len;
|
||||||
|
//nrf address length max is 5
|
||||||
|
pos+=LT8910_Tailer_Len/8;
|
||||||
|
LT8910_buffer_start=pos>5?5:pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LT8910_SetAddress(uint8_t *address,uint8_t addr_size)
|
||||||
|
{
|
||||||
|
uint8_t addr[5];
|
||||||
|
|
||||||
|
//Address size (SyncWord) 2 to 8 bytes, 16/32/48/64 bits
|
||||||
|
LT8910_addr_size=addr_size;
|
||||||
|
memcpy(LT8910_addr,address,LT8910_addr_size);
|
||||||
|
|
||||||
|
//Build overhead
|
||||||
|
LT8910_BuildOverhead();
|
||||||
|
|
||||||
|
//Set NRF RX&TX address based on overhead content
|
||||||
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, LT8910_buffer_start-2);
|
||||||
|
for(uint8_t i=0;i<LT8910_buffer_start;i++) // reverse bytes order
|
||||||
|
addr[i]=LT8910_buffer[LT8910_buffer_start-i-1];
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, addr,LT8910_buffer_start);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr,LT8910_buffer_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t LT8910_ReadPayload(uint8_t* msg, uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t i,pos=0,shift,end,buffer[32];
|
||||||
|
unsigned int crc=LT8910_CRC_Initial_Data,a;
|
||||||
|
pos=LT8910_buffer_overhead_bits/8-LT8910_buffer_start;
|
||||||
|
end=pos+len+(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN)?1:0)+(LT8910_Flags&_BV(LT8910_CRC_ON)?2:0);
|
||||||
|
//Read payload
|
||||||
|
NRF24L01_ReadPayload(buffer,end+1);
|
||||||
|
//Check address + trail
|
||||||
|
for(i=0;i<pos;i++)
|
||||||
|
if(LT8910_buffer[LT8910_buffer_start+i]!=buffer[i])
|
||||||
|
return 0; // wrong address...
|
||||||
|
//Shift buffer to remove trail bits
|
||||||
|
shift=LT8910_buffer_overhead_bits&0x7;
|
||||||
|
for(i=pos;i<end;i++)
|
||||||
|
{
|
||||||
|
a=(buffer[i]<<8)+buffer[i+1];
|
||||||
|
a<<=shift;
|
||||||
|
buffer[i]=(a>>8)&0xFF;
|
||||||
|
}
|
||||||
|
//Check len
|
||||||
|
if(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN))
|
||||||
|
{
|
||||||
|
crc=crc16_update(crc,buffer[pos]);
|
||||||
|
if(bit_reverse(len)!=buffer[pos++])
|
||||||
|
return 0; // wrong len...
|
||||||
|
}
|
||||||
|
//Decode message
|
||||||
|
for(i=0;i<len;i++)
|
||||||
|
{
|
||||||
|
crc=crc16_update(crc,buffer[pos]);
|
||||||
|
msg[i]=bit_reverse(buffer[pos++]);
|
||||||
|
}
|
||||||
|
//Check CRC
|
||||||
|
if(LT8910_Flags&_BV(LT8910_CRC_ON))
|
||||||
|
{
|
||||||
|
if(buffer[pos++]!=((crc>>8)&0xFF)) return 0; // wrong CRC...
|
||||||
|
if(buffer[pos]!=(crc&0xFF)) return 0; // wrong CRC...
|
||||||
|
}
|
||||||
|
//Everything ok
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LT8910_WritePayload(uint8_t* msg, uint8_t len)
|
||||||
|
{
|
||||||
|
unsigned int crc=LT8910_CRC_Initial_Data,a,mask;
|
||||||
|
uint8_t i, pos=0,tmp, buffer[64], pos_final,shift;
|
||||||
|
//Add packet len
|
||||||
|
if(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN))
|
||||||
|
{
|
||||||
|
tmp=bit_reverse(len);
|
||||||
|
buffer[pos++]=tmp;
|
||||||
|
crc=crc16_update(crc,tmp);
|
||||||
|
}
|
||||||
|
//Add payload
|
||||||
|
for(i=0;i<len;i++)
|
||||||
|
{
|
||||||
|
tmp=bit_reverse(msg[i]);
|
||||||
|
buffer[pos++]=tmp;
|
||||||
|
crc=crc16_update(crc,tmp);
|
||||||
|
}
|
||||||
|
//Add CRC
|
||||||
|
if(LT8910_Flags&_BV(LT8910_CRC_ON))
|
||||||
|
{
|
||||||
|
buffer[pos++]=crc>>8;
|
||||||
|
buffer[pos++]=crc;
|
||||||
|
}
|
||||||
|
//Shift everything to fit behind the trailer (4 to 18 bits)
|
||||||
|
shift=LT8910_buffer_overhead_bits&0x7;
|
||||||
|
pos_final=LT8910_buffer_overhead_bits/8;
|
||||||
|
mask=~(0xFF<<(8-shift));
|
||||||
|
LT8910_buffer[pos_final+pos]=0xFF;
|
||||||
|
for(i=pos-1;i!=0xFF;i--)
|
||||||
|
{
|
||||||
|
a=buffer[i]<<(8-shift);
|
||||||
|
LT8910_buffer[pos_final+i]=(LT8910_buffer[pos_final+i]&mask>>8)|a>>8;
|
||||||
|
LT8910_buffer[pos_final+i+1]=(LT8910_buffer[pos_final+i+1]&mask)|a;
|
||||||
|
}
|
||||||
|
if(shift)
|
||||||
|
pos++;
|
||||||
|
//Send everything
|
||||||
|
NRF24L01_WritePayload(LT8910_buffer+LT8910_buffer_start,pos_final+pos-LT8910_buffer_start);
|
||||||
|
}
|
||||||
|
// End of LT8910 emulation
|
||||||
|
183
Multiprotocol/Nrf24l01_bluefly.ino
Normal file
183
Multiprotocol/Nrf24l01_bluefly.ino
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(BlueFly_NRF24L01_INO)
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
#define BIND_BlueFly_COUNT 800
|
||||||
|
|
||||||
|
#define TXID_BlueFly_SIZE 5
|
||||||
|
|
||||||
|
#define PAYLOAD_BlueFly_SIZE 12
|
||||||
|
// available frequency must be in between 2402 and 2477
|
||||||
|
static uint8_t hopping_frequency_start;
|
||||||
|
|
||||||
|
static uint8_t bluefly_binding_adr_rf[TXID_BlueFly_SIZE]={0x32,0xaa,0x45,0x45,0x78}; // fixed binding ids for all planes
|
||||||
|
// bluefly_rf_adr_buf can be used for fixed id
|
||||||
|
static uint8_t bluefly_rf_adr_buf[TXID_BlueFly_SIZE]; // ={0x13,0x88,0x46,0x57,0x76};
|
||||||
|
|
||||||
|
static uint8_t bind_payload[PAYLOAD_BlueFly_SIZE];
|
||||||
|
|
||||||
|
static unsigned int ch_data_bluefly[8];
|
||||||
|
|
||||||
|
|
||||||
|
static void bluefly_binding_packet(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < TXID_BlueFly_SIZE; ++i)
|
||||||
|
bind_payload[i] = bluefly_rf_adr_buf[i];
|
||||||
|
bind_payload[i++] = hopping_frequency_start;
|
||||||
|
for (; i < PAYLOAD_BlueFly_SIZE; ++i) bind_payload[i] = 0x55;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bluefly_init() {
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable p0 rx
|
||||||
|
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bluefly_rf_adr_buf, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bluefly_rf_adr_buf, 5);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, PAYLOAD_BlueFly_SIZE); // payload size = 12
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
|
||||||
|
|
||||||
|
// 2-bytes CRC, radio on
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
|
||||||
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
|
||||||
|
NRF24L01_SetBitrate(NRF24L01_BR_250K); // BlueFly - 250kbps
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||||
|
}
|
||||||
|
|
||||||
|
// HiSky channel sequence: AILE ELEV THRO RUDD GEAR PITCH, channel data value is from 0 to 1000
|
||||||
|
static void bluefly_ch_data() {
|
||||||
|
uint32_t temp;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i< 8; ++i) {
|
||||||
|
temp = (uint32_t)Servo_data[ch[i]] * 300/PPM_MAX + 500; // 200-800 range
|
||||||
|
if (temp < 0)
|
||||||
|
ch_data_bluefly[i] = 0;
|
||||||
|
else if (temp > 1000)
|
||||||
|
ch_data_bluefly[i] = 1000;
|
||||||
|
else
|
||||||
|
ch_data_bluefly[i] = (unsigned int)temp;
|
||||||
|
|
||||||
|
packet[i] = (uint8_t)ch_data_bluefly[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
packet[8] = (uint8_t)((ch_data_bluefly[0]>>8)&0x0003);
|
||||||
|
packet[8] |= (uint8_t)((ch_data_bluefly[1]>>6)&0x000c);
|
||||||
|
packet[8] |= (uint8_t)((ch_data_bluefly[2]>>4)&0x0030);
|
||||||
|
packet[8] |= (uint8_t)((ch_data_bluefly[3]>>2)&0x00c0);
|
||||||
|
|
||||||
|
packet[9] = (uint8_t)((ch_data_bluefly[4]>>8)&0x0003);
|
||||||
|
packet[9] |= (uint8_t)((ch_data_bluefly[5]>>6)&0x000c);
|
||||||
|
packet[9] |= (uint8_t)((ch_data_bluefly[6]>>4)&0x0030);
|
||||||
|
packet[9] |= (uint8_t)((ch_data_bluefly[7]>>2)&0x00c0);
|
||||||
|
|
||||||
|
unsigned char l, h, t;
|
||||||
|
l = h = 0xff;
|
||||||
|
for (int i=0; i<10; ++i) {
|
||||||
|
h ^= packet[i];
|
||||||
|
h ^= h >> 4;
|
||||||
|
t = h;
|
||||||
|
h = l;
|
||||||
|
l = t;
|
||||||
|
t = (l<<4) | (l>>4);
|
||||||
|
h ^= ((t<<2) | (t>>6)) & 0x1f;
|
||||||
|
h ^= t & 0xf0;
|
||||||
|
l ^= ((t<<1) | (t>>7)) & 0xe0;
|
||||||
|
}
|
||||||
|
// Checksum
|
||||||
|
packet[10] = h;
|
||||||
|
packet[11] = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t bluefly_cb() {
|
||||||
|
switch(phase++) {
|
||||||
|
case 0:
|
||||||
|
bluefly_ch_data();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bluefly_rf_adr_buf, 5);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_start + hopping_frequency_no*2);
|
||||||
|
hopping_frequency_no++;
|
||||||
|
hopping_frequency_no %= 15;
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_WritePayload(packet, PAYLOAD_BlueFly_SIZE);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (counter>0) {
|
||||||
|
counter--;
|
||||||
|
if (! counter) { BIND_DONE; }
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bluefly_binding_adr_rf, 5);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_WritePayload(bind_payload, PAYLOAD_BlueFly_SIZE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
default:
|
||||||
|
phase = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1000; // send 1 binding packet and 1 data packet per 9ms
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate internal id from TX id and manufacturer id (STM32 unique id)
|
||||||
|
static void initialize_tx_id() {
|
||||||
|
uint32_t lfsr = 0x7649eca9ul;
|
||||||
|
|
||||||
|
if (Model.fixed_id) {
|
||||||
|
for (uint8_t i = 0, j = 0; i < sizeof(Model.fixed_id); ++i, j += 8)
|
||||||
|
rand32_r(&lfsr, (Model.fixed_id >> j) & 0xff);
|
||||||
|
}
|
||||||
|
// Pump zero bytes for LFSR to diverge more
|
||||||
|
for (int i = 0; i < TXID_BlueFly_SIZE; ++i) rand32_r(&lfsr, 0);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < TXID_BlueFly_SIZE; ++i) {
|
||||||
|
bluefly_rf_adr_buf[i] = lfsr & 0xff;
|
||||||
|
rand32_r(&lfsr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Effective id: %02X%02X%02X%02X%02X\r\n", bluefly_rf_adr_buf[0], bluefly_rf_adr_buf[1], bluefly_rf_adr_buf[2], bluefly_rf_adr_buf[3], bluefly_rf_adr_buf[4]);
|
||||||
|
|
||||||
|
// Use LFSR to seed frequency hopping sequence after another
|
||||||
|
// divergence round
|
||||||
|
for (uint8_t i = 0; i < sizeof(lfsr); ++i) rand32_r(&lfsr, 0);
|
||||||
|
hopping_frequency_start = ((lfsr >> 8) % 47) + 2;
|
||||||
|
bluefly_binding_packet();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t BlueFly_setup() {
|
||||||
|
initialize_tx_id();
|
||||||
|
|
||||||
|
bluefly_init();
|
||||||
|
|
||||||
|
if(IS_AUTOBIND_FLAG_on) {
|
||||||
|
counter = BIND_BlueFly_COUNT;
|
||||||
|
// PROTOCOL_SetBindState(BIND_BlueFly_COUNT * 10); //8 seconds binding time
|
||||||
|
} else {
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
#endif
|
172
Multiprotocol/Nrf24l01_esky150.ino
Normal file
172
Multiprotocol/Nrf24l01_esky150.ino
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(ESKY150_NRF24L01_INO)
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Timeout for callback in uSec, 4.8ms=4800us for ESky150
|
||||||
|
#define ESKY150_PERIOD 4800
|
||||||
|
#define ESKY150_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short)
|
||||||
|
|
||||||
|
#define esky150_PAYLOADSIZE 15
|
||||||
|
#define ADDR_esky150_SIZE 4
|
||||||
|
|
||||||
|
static uint32_t total_packets;
|
||||||
|
enum {
|
||||||
|
ESKY150_INIT2 = 0,
|
||||||
|
ESKY150_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t esky150_packet_ack() {
|
||||||
|
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
|
||||||
|
case BV(NRF24L01_07_TX_DS): return PKT_ACKED;
|
||||||
|
case BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
|
||||||
|
}
|
||||||
|
return PKT_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2-bytes CRC
|
||||||
|
#define CRC_CONFIG (BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO))
|
||||||
|
static uint16_t esky150_init() {
|
||||||
|
uint8_t rx_addr[ADDR_esky150_SIZE] = { 0x73, 0x73, 0x74, 0x63 };
|
||||||
|
uint8_t tx_addr[ADDR_esky150_SIZE] = { 0x71, 0x0A, 0x31, 0xF4 };
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, CRC_CONFIG);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||||
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||||
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, ADDR_esky150_SIZE-2); // 4-byte RX/TX address
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_addr, ADDR_esky150_SIZE);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, tx_addr, ADDR_esky150_SIZE);
|
||||||
|
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||||
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, esky150_PAYLOADSIZE); // bytes of data payload for pipe 0
|
||||||
|
|
||||||
|
|
||||||
|
NRF24L01_Activate(0x73);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
|
||||||
|
// Enable: Dynamic Payload Length, Payload with ACK , W_TX_PAYLOAD_NOACK
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL) | BV(NRF2401_1D_EN_ACK_PAY) | BV(NRF2401_1D_EN_DYN_ACK));
|
||||||
|
|
||||||
|
// Delay 50 ms
|
||||||
|
return 50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t esky150_init2() {
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
packet_sent = 0;
|
||||||
|
packet_count = 0;
|
||||||
|
rf_ch_num = 0;
|
||||||
|
|
||||||
|
// Turn radio power on
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, CRC_CONFIG | BV(NRF24L01_00_PWR_UP));
|
||||||
|
// delayMicroseconds(150);
|
||||||
|
return 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void calc_fh_channels(uint32_t seed) {
|
||||||
|
// Use channels 2..79
|
||||||
|
uint8_t first = seed % 37 + 2;
|
||||||
|
uint8_t second = first + 40;
|
||||||
|
hopping_frequency[0] = first; // 0x22;
|
||||||
|
hopping_frequency[1] = second; // 0x4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t convert_channel(uint8_t num) {
|
||||||
|
uint32_t ch = Servo_data[num];
|
||||||
|
if (ch < PPM_MIN) { ch = PPM_MIN; }
|
||||||
|
else if (ch > PPM_MAX) { ch = PPM_MAX; }
|
||||||
|
return (uint8_t) ((ch * 500 / PPM_MAX) + 1500);
|
||||||
|
}
|
||||||
|
static void read_controls(uint8_t* throttle, uint8_t* aileron, uint8_t* elevator, uint8_t* rudder) {
|
||||||
|
*throttle = convert_channel(THROTTLE);
|
||||||
|
*aileron = convert_channel(AILERON);
|
||||||
|
*elevator = convert_channel(ELEVATOR);
|
||||||
|
*rudder = convert_channel(RUDDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void esky150_send_packet() {
|
||||||
|
uint8_t rf_ch = hopping_frequency[rf_ch_num];
|
||||||
|
rf_ch_num = 1 - rf_ch_num;
|
||||||
|
|
||||||
|
read_controls(&throttle, &aileron, &elevator, &rudder);
|
||||||
|
|
||||||
|
packet[0] = hopping_frequency[0];
|
||||||
|
packet[1] = hopping_frequency[1];
|
||||||
|
packet[2] = (throttle >> 8) & 0xFF;
|
||||||
|
packet[3] = throttle & 0xFF;
|
||||||
|
packet[4] = (aileron >> 8) & 0xFF;
|
||||||
|
packet[5] = aileron & 0xFF;
|
||||||
|
packet[6] = (elevator >> 8) & 0xFF;
|
||||||
|
packet[7] = elevator & 0xFF;
|
||||||
|
packet[8] = (rudder >> 8) & 0xFF;
|
||||||
|
packet[9] = rudder & 0xFF;
|
||||||
|
// Constant values 00 d8 18 f8
|
||||||
|
packet[10] = 0x00;
|
||||||
|
packet[11] = 0xd8;
|
||||||
|
packet[12] = 0x18;
|
||||||
|
packet[13] = 0xf8;
|
||||||
|
uint8_t sum = 0;
|
||||||
|
for (int i = 0; i < 14; ++i) sum += packet[i];
|
||||||
|
packet[14] = sum;
|
||||||
|
|
||||||
|
packet_sent = 0;
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_WritePayload(packet, sizeof(packet));
|
||||||
|
++total_packets;
|
||||||
|
packet_sent = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t esky150_callback() {
|
||||||
|
uint16_t timeout = ESKY150_PERIOD;
|
||||||
|
switch (phase) {
|
||||||
|
case ESKY150_INIT2:
|
||||||
|
timeout = esky150_init2();
|
||||||
|
phase = ESKY150_DATA;
|
||||||
|
break;
|
||||||
|
case ESKY150_DATA:
|
||||||
|
if (packet_count == 4)
|
||||||
|
packet_count = 0;
|
||||||
|
else {
|
||||||
|
if (packet_sent && esky150_packet_ack() != PKT_ACKED) {
|
||||||
|
return ESKY150_CHKTIME;
|
||||||
|
}
|
||||||
|
esky150_send_packet();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t esky150_setup() {
|
||||||
|
total_packets = 0;
|
||||||
|
uint16_t timeout = esky150_init();
|
||||||
|
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
#endif
|
@ -75,14 +75,14 @@ static void send_packet(uint8_t bind)
|
|||||||
| GET_FLAG(CHANNEL_CALIBRATE, 0x01)
|
| GET_FLAG(CHANNEL_CALIBRATE, 0x01)
|
||||||
| GET_FLAG(CHANNEL_EXPERT, 4);
|
| GET_FLAG(CHANNEL_EXPERT, 4);
|
||||||
}
|
}
|
||||||
packet[2] = 200 - scale_channel(AILERON, 0, 200); // aileron
|
packet[2] = 200 - scale_channel(AILERON, 0, 200); // aileron 1
|
||||||
packet[3] = scale_channel(ELEVATOR, 0, 200); // elevator
|
packet[3] = scale_channel(ELEVATOR, 0, 200); // elevator 2
|
||||||
packet[4] = 200 - scale_channel(RUDDER, 0, 200); // rudder
|
packet[4] = 200 - scale_channel(RUDDER, 0, 200); // rudder 4
|
||||||
packet[5] = scale_channel(THROTTLE, 0, 200); // throttle
|
packet[5] = scale_channel(THROTTLE, 0, 200); // throttle 3
|
||||||
if(sub_protocol == FY319) {
|
if(sub_protocol == FY319) {
|
||||||
packet[6] = 255 - scale_channel(CHANNEL1, 0, 255);
|
packet[6] = 255 - scale_channel(AILERON, 0, 255);
|
||||||
packet[7] = scale_channel(CHANNEL2, 0, 255);
|
packet[7] = scale_channel(ELEVATOR, 0, 255);
|
||||||
packet[8] = 255 - scale_channel(CHANNEL4, 0, 255);
|
packet[8] = 255 - scale_channel(RUDDER, 0, 255);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
packet[6] = txid[0];
|
packet[6] = txid[0];
|
||||||
@ -112,7 +112,7 @@ static void send_packet(uint8_t bind)
|
|||||||
|
|
||||||
static void fy326_init()
|
static void fy326_init()
|
||||||
{
|
{
|
||||||
uint8_t rx_tx_addr[] = {0x15, 0x59, 0x23, 0xc6, 0x29};
|
uint8_t rx_tx_addr[] = {0x15, 0x59, 0x23, 0xc6, 0x29};
|
||||||
|
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
@ -148,7 +148,7 @@ static uint16_t fy326_callback()
|
|||||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
|
||||||
phase = FY319_BIND1;
|
phase = FY319_BIND1;
|
||||||
BIND_IN_PROGRESS;
|
BIND_IN_PROGRESS;
|
||||||
return PACKET_CHKTIME;
|
return FY326_CHKTIME;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FY319_BIND1:
|
case FY319_BIND1:
|
||||||
@ -158,7 +158,7 @@ static uint16_t fy326_callback()
|
|||||||
packet[0] = txid[3];
|
packet[0] = txid[3];
|
||||||
packet[1] = 0x80;
|
packet[1] = 0x80;
|
||||||
packet[14]= txid[4];
|
packet[14]= txid[4];
|
||||||
bind_counter = BIND_COUNT;
|
bind_counter = FY326_BIND_COUNT;
|
||||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||||
@ -168,7 +168,7 @@ static uint16_t fy326_callback()
|
|||||||
packet[i] = rf_chans[0];
|
packet[i] = rf_chans[0];
|
||||||
phase = FY319_BIND2;
|
phase = FY319_BIND2;
|
||||||
}
|
}
|
||||||
return PACKET_CHKTIME;
|
return FY326_CHKTIME;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FY319_BIND2:
|
case FY319_BIND2:
|
||||||
@ -243,7 +243,7 @@ static void fy_txid()
|
|||||||
rf_chans[2] = 0x20 + (txid[1] & 0x0F);
|
rf_chans[2] = 0x20 + (txid[1] & 0x0F);
|
||||||
rf_chans[3] = 0x30 + (txid[1] >> 4);
|
rf_chans[3] = 0x30 + (txid[1] >> 4);
|
||||||
rf_chans[4] = 0x40 + (txid[2] >> 4);
|
rf_chans[4] = 0x40 + (txid[2] >> 4);
|
||||||
|
|
||||||
if(sub_protocol == FY319) {
|
if(sub_protocol == FY319) {
|
||||||
for(uint8_t i=0; i<5; i++)
|
for(uint8_t i=0; i<5; i++)
|
||||||
rf_chans[i] = txid[0] & ~0x80;
|
rf_chans[i] = txid[0] & ~0x80;
|
||||||
@ -264,3 +264,4 @@ static uint16_t FY326_setup()
|
|||||||
return INITIAL_WAIT;
|
return INITIAL_WAIT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
272
Multiprotocol/Nrf24l01_hontai.ino
Normal file
272
Multiprotocol/Nrf24l01_hontai.ino
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HonTai_NRF24L01_INO)
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
#define BIND_HT_COUNT 80
|
||||||
|
#define PACKET_HT_PERIOD 13500 // Timeout for callback in uSec
|
||||||
|
//printf inside an interrupt handler is really dangerous
|
||||||
|
//this shouldn't be enabled even in debug builds without explicitly
|
||||||
|
//turning it on
|
||||||
|
#define dbgprintf if(0) printf
|
||||||
|
|
||||||
|
#define INITIAL_HT_WAIT 500
|
||||||
|
#define BIND_HT_PACKET_SIZE 10
|
||||||
|
#define PACKET_HT_SIZE 12
|
||||||
|
#define RF_BIND_HT_CHANNEL 0
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FORMAT_HONTAI = 0,
|
||||||
|
FORMAT_JJRCX1,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define CHANNEL_LED AUX1
|
||||||
|
#define CHANNEL_ARM AUX1 // for JJRC X1
|
||||||
|
#define CHANNEL_FLIP AUX2
|
||||||
|
#define CHANNEL_PICTURE AUX3
|
||||||
|
#define CHANNEL_VIDEO AUX4
|
||||||
|
#define CHANNEL_HEADLESS AUX5
|
||||||
|
#define CHANNEL_RTH AUX6
|
||||||
|
#define CHANNEL_CALIBRATE AUX7
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HonTai_INIT1 = 0,
|
||||||
|
HonTai_BIND2,
|
||||||
|
HonTai_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t ht_txid[5];
|
||||||
|
|
||||||
|
static uint8_t rf_chan = 0;
|
||||||
|
static uint8_t rf_channels[][3] = {{0x05, 0x19, 0x28}, // Hontai
|
||||||
|
{0x0a, 0x1e, 0x2d}}; // JJRC X1
|
||||||
|
static uint8_t rx_tx_ht_addr[] = {0xd2, 0xb5, 0x99, 0xb3, 0x4a};
|
||||||
|
static uint8_t addr_vals[4][16] = {
|
||||||
|
{0x24, 0x26, 0x2a, 0x2c, 0x32, 0x34, 0x36, 0x4a, 0x4c, 0x4e, 0x54, 0x56, 0x5a, 0x64, 0x66, 0x6a},
|
||||||
|
{0x92, 0x94, 0x96, 0x9a, 0xa4, 0xa6, 0xac, 0xb2, 0xb4, 0xb6, 0xca, 0xcc, 0xd2, 0xd4, 0xd6, 0xda},
|
||||||
|
{0x93, 0x95, 0x99, 0x9b, 0xa5, 0xa9, 0xab, 0xad, 0xb3, 0xb5, 0xc9, 0xcb, 0xcd, 0xd3, 0xd5, 0xd9},
|
||||||
|
{0x25, 0x29, 0x2b, 0x2d, 0x33, 0x35, 0x49, 0x4b, 0x4d, 0x59, 0x5b, 0x65, 0x69, 0x6b, 0x6d, 0x6e}};
|
||||||
|
|
||||||
|
// proudly swiped from http://www.drdobbs.com/implementing-the-ccitt-cyclical-redundan/199904926
|
||||||
|
#define POLY 0x8408
|
||||||
|
static uint16_t crc16(uint8_t *data_p, uint32_t length)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
uint32_t data;
|
||||||
|
uint32_t crc;
|
||||||
|
|
||||||
|
crc = 0xffff;
|
||||||
|
|
||||||
|
if (length == 0) return (~crc);
|
||||||
|
|
||||||
|
length -= 2;
|
||||||
|
do {
|
||||||
|
for (i = 0, data = (uint8_t)0xff & *data_p++;
|
||||||
|
i < 8;
|
||||||
|
i++, data >>= 1) {
|
||||||
|
if ((crc & 0x0001) ^ (data & 0x0001))
|
||||||
|
crc = (crc >> 1) ^ POLY;
|
||||||
|
else
|
||||||
|
crc >>= 1;
|
||||||
|
}
|
||||||
|
} while (--length);
|
||||||
|
|
||||||
|
crc = ~crc;
|
||||||
|
data = crc;
|
||||||
|
crc = (crc << 8) | (data >> 8 & 0xFF);
|
||||||
|
*data_p++ = crc >> 8;
|
||||||
|
*data_p = crc & 0xff;
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHAN_RANGE (PPM_MAX - PPM_MIN)
|
||||||
|
static uint8_t scale_HT_channel(uint8_t ch, uint8_t start, uint8_t end)
|
||||||
|
{
|
||||||
|
uint32_t range = end - start;
|
||||||
|
uint32_t chanval = Servo_data[ch];
|
||||||
|
|
||||||
|
if (chanval < PPM_MIN) chanval = PPM_MIN;
|
||||||
|
else if (chanval > PPM_MAX) chanval = PPM_MAX;
|
||||||
|
|
||||||
|
uint32_t round = range < 0 ? 0 : CHAN_RANGE / range; // channels round up
|
||||||
|
if (start < 0) round = CHAN_RANGE / range / 2; // trims zero centered around zero
|
||||||
|
return (range * (chanval - PPM_MIN + round)) / CHAN_RANGE + start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_FLAG(ch, mask) (Servo_data[ch] > 0 ? mask : 0)
|
||||||
|
static void send_HT_packet(uint8_t bind)
|
||||||
|
{
|
||||||
|
if (bind) {
|
||||||
|
memcpy(packet, ht_txid, 5);
|
||||||
|
memset(&packet[5], 0, 3);
|
||||||
|
} else {
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
packet[0] = 0x0b;
|
||||||
|
} else {
|
||||||
|
packet[0] = GET_FLAG(CHANNEL_ARM, 0x02);
|
||||||
|
}
|
||||||
|
packet[1] = 0x00;
|
||||||
|
packet[2] = 0x00;
|
||||||
|
packet[3] = (scale_HT_channel(THROTTLE, 0, 127) << 1) // throttle
|
||||||
|
| GET_FLAG(CHANNEL_PICTURE, 0x01);
|
||||||
|
packet[4] = scale_HT_channel(AILERON, 63, 0); // aileron
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
packet[4] |= GET_FLAG(CHANNEL_RTH, 0x80)
|
||||||
|
| GET_FLAG(CHANNEL_HEADLESS, 0x40);
|
||||||
|
} else {
|
||||||
|
packet[4] |= 0x80; // not sure what this bit does
|
||||||
|
}
|
||||||
|
packet[5] = scale_channel(CHANNEL2, 0, 63) // elevator
|
||||||
|
| GET_FLAG(CHANNEL_CALIBRATE, 0x80)
|
||||||
|
| GET_FLAG(CHANNEL_FLIP, 0x40);
|
||||||
|
packet[6] = scale_HT_channel(RUDDER, 0, 63) // rudder
|
||||||
|
| GET_FLAG(CHANNEL_VIDEO, 0x80);
|
||||||
|
packet[7] = scale_HT_channel(AILERON, -16, 16); // aileron trim
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
packet[8] = scale_HT_channel(RUDDER, -16, 16); // rudder trim
|
||||||
|
} else {
|
||||||
|
packet[8] = 0xc0 // always in expert mode
|
||||||
|
| GET_FLAG(CHANNEL_RTH, 0x02)
|
||||||
|
| GET_FLAG(CHANNEL_HEADLESS, 0x01);
|
||||||
|
}
|
||||||
|
packet[9] = scale_HT_channel(ELEVATOR, -16, 16); // elevator trim
|
||||||
|
}
|
||||||
|
crc16(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
|
||||||
|
|
||||||
|
// Power on, TX mode, 2byte CRC
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
|
||||||
|
} else {
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? RF_BIND_HT_CHANNEL : rf_channels[sub_protocol][rf_chan++]);
|
||||||
|
rf_chan %= sizeof(rf_channels);
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
XN297_WritePayload(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
|
||||||
|
} else {
|
||||||
|
NRF24L01_WritePayload(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ht_init()
|
||||||
|
{
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
|
||||||
|
// SPI trace of stock TX has these writes to registers that don't appear in
|
||||||
|
// nRF24L01 or Beken 2421 datasheets. Uncomment if you have an XN297 chip?
|
||||||
|
// NRF24L01_WriteRegisterMulti(0x3f, "\x4c\x84\x67,\x9c,\x20", 5);
|
||||||
|
// NRF24L01_WriteRegisterMulti(0x3e, "\xc9\x9a\xb0,\x61,\xbb,\xab,\x9c", 7);
|
||||||
|
// NRF24L01_WriteRegisterMulti(0x39, "\x0b\xdf\xc4,\xa7,\x03,\xab,\x9c", 7);
|
||||||
|
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
XN297_SetTXAddr(rx_tx_ht_addr, sizeof(rx_tx_ht_addr));
|
||||||
|
} else {
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_ht_addr, sizeof(rx_tx_ht_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
NRF24L01_Activate(0x73); // Activate feature register
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00);
|
||||||
|
NRF24L01_Activate(0x73); // Deactivate feature register
|
||||||
|
} else {
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xff); // JJRC uses dynamic payload length
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // match other stock settings even though AA disabled...
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ht_init2()
|
||||||
|
{
|
||||||
|
uint8_t data_tx_addr[] = {0x2a, 0xda, 0xa5, 0x25, 0x24};
|
||||||
|
|
||||||
|
data_tx_addr[0] = addr_vals[0][ ht_txid[3] & 0x0f];
|
||||||
|
data_tx_addr[1] = addr_vals[1][(ht_txid[3] >> 4) & 0x0f];
|
||||||
|
data_tx_addr[2] = addr_vals[2][ ht_txid[4] & 0x0f];
|
||||||
|
data_tx_addr[3] = addr_vals[3][(ht_txid[4] >> 4) & 0x0f];
|
||||||
|
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
XN297_SetTXAddr(data_tx_addr, sizeof(data_tx_addr));
|
||||||
|
} else {
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, data_tx_addr, sizeof(data_tx_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t ht_callback()
|
||||||
|
{
|
||||||
|
switch (phase) {
|
||||||
|
case HonTai_INIT1:
|
||||||
|
phase = HonTai_BIND2;
|
||||||
|
break;
|
||||||
|
case HonTai_BIND2:
|
||||||
|
if (counter == 0) {
|
||||||
|
ht_init2();
|
||||||
|
phase = HonTai_DATA;
|
||||||
|
BIND_DONE;
|
||||||
|
} else {
|
||||||
|
send_HT_packet(1);
|
||||||
|
counter -= 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HonTai_DATA:
|
||||||
|
send_HT_packet(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return PACKET_HT_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t ht_setup()
|
||||||
|
{
|
||||||
|
counter = BIND_HT_COUNT;
|
||||||
|
|
||||||
|
if (sub_protocol == FORMAT_HONTAI) {
|
||||||
|
ht_txid[0] = 0x4c; // first three bytes some kind of model id? - set same as stock tx
|
||||||
|
ht_txid[1] = 0x4b;
|
||||||
|
ht_txid[2] = 0x3a;
|
||||||
|
} else {
|
||||||
|
ht_txid[0] = 0x4b; // JJRC X1
|
||||||
|
ht_txid[1] = 0x59;
|
||||||
|
ht_txid[2] = 0x3a;
|
||||||
|
}
|
||||||
|
ht_txid[3] = (MProtocol_id >> 8 ) & 0xff;
|
||||||
|
ht_txid[4] = MProtocol_id & 0xff;
|
||||||
|
|
||||||
|
ht_init();
|
||||||
|
phase = HonTai_INIT1;
|
||||||
|
|
||||||
|
return INITIAL_HT_WAIT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
274
Multiprotocol/Nrf24l01_ne260.ino
Normal file
274
Multiprotocol/Nrf24l01_ne260.ino
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/* This code is based upon code from:
|
||||||
|
http://www.rcgroups.com/forums/showthread.php?t=1564343
|
||||||
|
Author : Ferenc Szili (kile at the rcgroups.net forum)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(NE260_NRF24L01_INO)
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////
|
||||||
|
// register bits
|
||||||
|
///////////////////////
|
||||||
|
|
||||||
|
// CONFIG
|
||||||
|
#define MASK_RX_DR 6
|
||||||
|
#define MASK_TX_DS 5
|
||||||
|
#define MASK_MAX_RT 4
|
||||||
|
#define EN_CRC 3
|
||||||
|
#define CRCO 2
|
||||||
|
#define PWR_UP 1
|
||||||
|
#define PRIM_RX 0
|
||||||
|
|
||||||
|
// EN_AA
|
||||||
|
#define ENAA_P5 5
|
||||||
|
#define ENAA_P4 4
|
||||||
|
#define ENAA_P3 3
|
||||||
|
#define ENAA_P2 2
|
||||||
|
#define ENAA_P1 1
|
||||||
|
#define ENAA_P0 0
|
||||||
|
|
||||||
|
// EN_RXADDR
|
||||||
|
#define ERX_P5 5
|
||||||
|
#define ERX_P4 4
|
||||||
|
#define ERX_P3 3
|
||||||
|
#define ERX_P2 2
|
||||||
|
#define ERX_P1 1
|
||||||
|
#define ERX_P0 0
|
||||||
|
|
||||||
|
// RF_SETUP
|
||||||
|
#define CONT_WAVE 7
|
||||||
|
#define RF_DR_LOW 5
|
||||||
|
#define PLL_LOCK 4
|
||||||
|
#define RF_DR_HIGH 3
|
||||||
|
#define RF_PWR_HIGH 2
|
||||||
|
#define RF_PWR_LOW 1
|
||||||
|
#define LNA_HCURR 0 // obsolete in nRF24L01+
|
||||||
|
|
||||||
|
// STATUS
|
||||||
|
#define RX_DR 6
|
||||||
|
#define TX_DS 5
|
||||||
|
#define MAX_RT 4
|
||||||
|
#define TX_FULL 0
|
||||||
|
|
||||||
|
// FIFO_STATUS
|
||||||
|
#define TX_REUSE 6
|
||||||
|
#define FIFO_TX_FULL 5
|
||||||
|
#define TX_EMPTY 4
|
||||||
|
#define RX_FULL 1
|
||||||
|
#define RX_EMPTY 0
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// register bit values
|
||||||
|
///////////////////////
|
||||||
|
|
||||||
|
// CONFIG
|
||||||
|
#define vMASK_RX_DR (1<<(MASK_RX_DR))
|
||||||
|
#define vMASK_TX_DS (1<<(MASK_TX_DS))
|
||||||
|
#define vMASK_MAX_RT (1<<(MASK_MAX_RT))
|
||||||
|
#define vEN_CRC (1<<(EN_CRC))
|
||||||
|
#define vCRCO (1<<(CRCO))
|
||||||
|
#define vPWR_UP (1<<(PWR_UP))
|
||||||
|
#define vPRIM_RX (1<<(PRIM_RX))
|
||||||
|
|
||||||
|
// EN_AA
|
||||||
|
#define vENAA_P5 (1<<(ENAA_P5))
|
||||||
|
#define vENAA_P4 (1<<(ENAA_P4))
|
||||||
|
#define vENAA_P3 (1<<(ENAA_P3))
|
||||||
|
#define vENAA_P2 (1<<(ENAA_P2))
|
||||||
|
#define vENAA_P1 (1<<(ENAA_P1))
|
||||||
|
#define vENAA_P0 (1<<(ENAA_P0))
|
||||||
|
|
||||||
|
// EN_RXADDR
|
||||||
|
#define vERX_P5 (1<<(ERX_P5))
|
||||||
|
#define vERX_P4 (1<<(ERX_P4))
|
||||||
|
#define vERX_P3 (1<<(ERX_P3))
|
||||||
|
#define vERX_P2 (1<<(ERX_P2))
|
||||||
|
#define vERX_P1 (1<<(ERX_P1))
|
||||||
|
#define vERX_P0 (1<<(ERX_P0))
|
||||||
|
|
||||||
|
// SETUP_AW -- address widths in bytes
|
||||||
|
#define vAW_3 1
|
||||||
|
#define vAW_4 2
|
||||||
|
#define vAW_5 3
|
||||||
|
|
||||||
|
// RF_SETUP
|
||||||
|
#define vCONT_WAVE (1<<(CONT_WAVE))
|
||||||
|
#define vRF_DR_LOW (1<<(RF_DR_LOW))
|
||||||
|
#define vPLL_LOCK (1<<(PLL_LOCK))
|
||||||
|
#define vRF_DR_HIGH (1<<(RF_DR_HIGH))
|
||||||
|
#define vRF_PWR_HIGH (1<<(RF_PWR_HIGH))
|
||||||
|
#define vRF_PWR_LOW (1<<(RF_PWR_LOW))
|
||||||
|
#define vLNA_HCURR (1<<(LNA_HCURR)) // obsolete in nRF24L01+
|
||||||
|
|
||||||
|
#define vRF_DR_1MBPS 0
|
||||||
|
#define vRF_DR_2MBPS (1<<(RF_DR_HIGH))
|
||||||
|
#define vRF_DR_250KBPS (1<<(RF_DR_LOW))
|
||||||
|
|
||||||
|
#define vRF_PWR_M18DBM 0x00
|
||||||
|
#define vRF_PWR_M12DBM 0x02
|
||||||
|
#define vRF_PWR_M6DBM 0x04
|
||||||
|
#define vRF_PWR_0DBM 0x06
|
||||||
|
|
||||||
|
#define vARD_250us 0x00
|
||||||
|
#define vARD_500us 0x10
|
||||||
|
#define vARD_750us 0x20
|
||||||
|
#define vARD_1000us 0x30
|
||||||
|
#define vARD_1250us 0x40
|
||||||
|
#define vARD_1500us 0x50
|
||||||
|
#define vARD_1750us 0x60
|
||||||
|
#define vARD_2000us 0x70
|
||||||
|
#define vARD_2250us 0x80
|
||||||
|
#define vARD_2500us 0x90
|
||||||
|
#define vARD_2750us 0xA0
|
||||||
|
#define vARD_3000us 0xB0
|
||||||
|
#define vARD_3250us 0xC0
|
||||||
|
#define vARD_3500us 0xD0
|
||||||
|
#define vARD_3750us 0xE0
|
||||||
|
#define vARD_4000us 0xF0
|
||||||
|
|
||||||
|
// STATUS
|
||||||
|
#define vRX_DR (1<<(RX_DR))
|
||||||
|
#define vTX_DS (1<<(TX_DS))
|
||||||
|
#define vMAX_RT (1<<(MAX_RT))
|
||||||
|
#define vTX_FULL (1<<(TX_FULL))
|
||||||
|
|
||||||
|
#define RX_P_NO(stat) ((stat >> 1) & 7)
|
||||||
|
#define HAS_RX_PAYLOAD(stat) ((stat & 0b1110) < 0b1100)
|
||||||
|
|
||||||
|
// FIFO_STATUS
|
||||||
|
#define vTX_REUSE (1<<(TX_REUSE))
|
||||||
|
#define vTX_FULL (1<<(TX_FULL))
|
||||||
|
#define vTX_EMPTY (1<<(TX_EMPTY))
|
||||||
|
#define vRX_FULL (1<<(RX_FULL))
|
||||||
|
#define vRX_EMPTY (1<<(RX_EMPTY))
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
uint8_t neChannel = 10;
|
||||||
|
uint8_t neChannelOffset = 0;
|
||||||
|
#define PACKET_NE_LENGTH 7
|
||||||
|
|
||||||
|
static u32 bind_count;
|
||||||
|
static uint16_t model_id = 0xA04A;
|
||||||
|
|
||||||
|
uint8_t NE_ch[]={THROTTLE, RUDDER, ELEVATOR, AILERON, AUX1};
|
||||||
|
uint8_t NEAddr[] = {0x34, 0x43, 0x10, 0x10, 0x01};
|
||||||
|
enum {
|
||||||
|
NE260_BINDTX,
|
||||||
|
NE260_BINDRX,
|
||||||
|
NE260_DATA1,
|
||||||
|
NE260_DATA2,
|
||||||
|
NE260_DATA3,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void ne260_init() {
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, NEAddr, 5); // write the address
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, NEAddr, 5);
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_01_EN_AA, vENAA_P0); // enable auto acknoledge
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, vARD_500us); // ARD=500us, ARC=disabled
|
||||||
|
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, vRF_DR_250KBPS | vLNA_HCURR | vRF_PWR_0DBM); // data rate, output power and noise cancel
|
||||||
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, PACKET_NE_LENGTH); // RX payload length
|
||||||
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, vERX_P0); // enable RX address
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, vRX_DR | vTX_DS | vMAX_RT); // reset the IRQ flags
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_data_packet() {
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
uint32_t value = (uint32_t)Servo_data[NE_ch[i]] * 0x40 / PPM_MAX + 0x40;
|
||||||
|
if (value > 0x7f)
|
||||||
|
value = 0x7f;
|
||||||
|
else if(value < 0)
|
||||||
|
value = 0;
|
||||||
|
packet[i] = value;
|
||||||
|
}
|
||||||
|
packet[4] = 0x55;
|
||||||
|
packet[5] = model_id & 0xff;
|
||||||
|
packet[6] = (model_id >> 8) & 0xff;
|
||||||
|
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, vMAX_RT);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, neChannel + neChannelOffset);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, vEN_CRC | vCRCO | vPWR_UP);
|
||||||
|
// send a fresh packet to the nRF
|
||||||
|
NRF24L01_WritePayload((uint8_t*) packet, PACKET_NE_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_bind_packet() {
|
||||||
|
packet[0] = 0xAA; //throttle
|
||||||
|
packet[1] = 0xAA; //rudder
|
||||||
|
packet[2] = 0xAA; //elevator
|
||||||
|
packet[3] = 0xAA; //aileron
|
||||||
|
packet[4] = 0xAA; //command
|
||||||
|
packet[5] = model_id & 0xff;
|
||||||
|
packet[6] = (model_id >> 8) & 0xff;
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, vRX_DR | vTX_DS | vMAX_RT); // reset the status flags
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, neChannel + neChannelOffset);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_WritePayload((uint8_t*) &packet, PACKET_NE_LENGTH); // send the bind packet
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t ne260_cb() {
|
||||||
|
if (state == NE260_BINDTX) {
|
||||||
|
// do we have a packet?
|
||||||
|
if ((NRF24L01_ReadReg(NRF24L01_07_STATUS) & vRX_DR) != 0) {
|
||||||
|
// read the packet contents
|
||||||
|
NRF24L01_ReadPayload(packet, PACKET_NE_LENGTH);
|
||||||
|
|
||||||
|
// is this the bind response packet?
|
||||||
|
if (strncmp("\x55\x55\x55\x55\x55", (char*) (packet + 1), 5) == 0 && *((uint16_t*)(packet + 6)) == model_id) {
|
||||||
|
// exit the bind loop
|
||||||
|
state = NE260_DATA1;
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
return 2000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
send_bind_packet();
|
||||||
|
state = NE260_BINDRX;
|
||||||
|
return 500;
|
||||||
|
} else if (state == NE260_BINDRX) {
|
||||||
|
// switch to RX mode
|
||||||
|
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & (vMAX_RT | vTX_DS))) ;
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, vTX_DS);
|
||||||
|
|
||||||
|
NRF24L01_SetTxRxMode(RX_EN);
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
state = NE260_BINDTX;
|
||||||
|
return 2000;
|
||||||
|
}
|
||||||
|
else if (state == NE260_DATA1) { neChannel = 10; state = NE260_DATA2; }
|
||||||
|
else if (state == NE260_DATA2) { neChannel = 30; state = NE260_DATA3; }
|
||||||
|
else if (state == NE260_DATA3) { neChannel = 50; state = NE260_DATA1; }
|
||||||
|
send_data_packet();
|
||||||
|
return 2500;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t NE260_setup() {
|
||||||
|
ne260_init();
|
||||||
|
bind_count = 10000;
|
||||||
|
state = NE260_BINDTX;
|
||||||
|
|
||||||
|
return 10000;
|
||||||
|
}
|
||||||
|
#endif
|
583
Multiprotocol/Nrf24l01_udi.ino
Normal file
583
Multiprotocol/Nrf24l01_udi.ino
Normal file
@ -0,0 +1,583 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Known UDI 2.4GHz protocol variants, all using BK2421
|
||||||
|
// * UDI U819 coaxial 3ch helicoper
|
||||||
|
// * UDI U816/817/818 quadcopters
|
||||||
|
// - "V1" with orange LED on TX, U816 RX labeled '' , U817/U818 RX labeled 'UD-U817B'
|
||||||
|
// - "V2" with red LEDs on TX, U816 RX labeled '', U817/U818 RX labeled 'UD-U817OG'
|
||||||
|
// - "V3" with green LEDs on TX. Did not get my hands on yet.
|
||||||
|
// * U830 mini quadcopter with tilt steering ("Protocol 2014")
|
||||||
|
// * U839 nano quadcopter ("Protocol 2014")
|
||||||
|
|
||||||
|
#if defined(UDI_NRF24L01_INO)
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
#define BIND_UDI_COUNT 1000
|
||||||
|
|
||||||
|
// Timeout for callback in uSec, 4ms=4000us for UDI
|
||||||
|
// ???
|
||||||
|
//#define PACKET_UDI_PERIOD 4000
|
||||||
|
|
||||||
|
#define BIND_PACKET_UDI_PERIOD 5000
|
||||||
|
#define PACKET_UDI_PERIOD 15000
|
||||||
|
|
||||||
|
#define BIND_PACKETS_UDI_PER_CHANNEL 11
|
||||||
|
#define PACKETS_UDI_PER_CHANNEL 11
|
||||||
|
|
||||||
|
#define NUM_UDI_RF_CHANNELS 16
|
||||||
|
|
||||||
|
|
||||||
|
#define INITIAL_UDI_WAIT 50000
|
||||||
|
|
||||||
|
#define PACKET_UDI_CHKTIME 100
|
||||||
|
|
||||||
|
// For readability
|
||||||
|
enum {
|
||||||
|
UDI_CAMERA = 1,
|
||||||
|
UDI_VIDEO = 2,
|
||||||
|
UDI_MODE2 = 4,
|
||||||
|
UDI_FLIP360 = 8,
|
||||||
|
UDI_FLIP =16,
|
||||||
|
UDI_LIGHTS =32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is maximum payload size used in UDI protocols
|
||||||
|
#define UDI_PAYLOADSIZE 16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t payload_size; // Bytes in payload for selected variant
|
||||||
|
static uint8_t bind_channel;
|
||||||
|
static uint8_t packets_to_hop;
|
||||||
|
static uint8_t packets_to_check; // BIND_RX phase needs to receive/auto-ack more than one packet for RX to switch to next phase, it seems
|
||||||
|
static uint8_t packets_to_send; // Number of packets to send / check for in current bind phase
|
||||||
|
static uint8_t bind_step_success; // Indicates successfull transmission / receive of bind reply during current bind phase
|
||||||
|
static uint8_t tx_id[3];
|
||||||
|
static uint8_t rx_id[3];
|
||||||
|
static uint8_t randoms[3]; // 3 random bytes choosen by TX, sent in BIND packets. Lower nibble of first byte sets index in RF CH table to use for BIND2
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
enum {
|
||||||
|
UDI_INIT2 = 0,
|
||||||
|
UDI_INIT2_NO_BIND,
|
||||||
|
UDI_BIND1_TX,
|
||||||
|
UDI_BIND1_RX,
|
||||||
|
UDI_BIND2_TX,
|
||||||
|
UDI_BIND2_RX,
|
||||||
|
UDI_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROTOOPTS_FORMAT = 0,
|
||||||
|
PROTOOPTS_STARTBIND,
|
||||||
|
};
|
||||||
|
enum {
|
||||||
|
STARTBIND_NO = 0,
|
||||||
|
STARTBIND_YES = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This are frequency hopping tables for UDI protocols
|
||||||
|
|
||||||
|
// uint8_t16 V1 (Orange LED) Bind CH 0x07
|
||||||
|
// TX ID 0x57, 0x5A, 0x2D
|
||||||
|
static const uint8_t freq_hopping_uint8_t16_v1[NUM_UDI_RF_CHANNELS] = {
|
||||||
|
0x07, 0x21, 0x49, 0x0B, 0x39, 0x10, 0x25, 0x42,
|
||||||
|
0x1D, 0x31, 0x35, 0x14, 0x28, 0x3D, 0x18, 0x2D
|
||||||
|
};
|
||||||
|
|
||||||
|
// Protocol 2014 (uint8_t30,uint8_t39,...) BIND CH 0x23 (second entry)
|
||||||
|
// DATA: hops ~ every 0.361s (0.350 ... 0.372)
|
||||||
|
static const uint8_t freq_hopping_uint8_t39[NUM_UDI_RF_CHANNELS] = {
|
||||||
|
0x08, 0x23, 0x48, 0x0D, 0x3B, 0x12, 0x27, 0x44,
|
||||||
|
0x1F, 0x33, 0x37, 0x16, 0x2A, 0x3F, 0x1A, 0x2F
|
||||||
|
};
|
||||||
|
|
||||||
|
// Points to proper table
|
||||||
|
static const uint8_t * rf_udi_channels = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t packet_udi_ack()
|
||||||
|
{
|
||||||
|
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
|
||||||
|
case BV(NRF24L01_07_TX_DS): return PKT_ACKED;
|
||||||
|
case BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
|
||||||
|
}
|
||||||
|
return PKT_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UDI_init()
|
||||||
|
{
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
//NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
|
||||||
|
switch (sub_protocol) {
|
||||||
|
case U816_V1:
|
||||||
|
rf_udi_channels = freq_hopping_uint8_t16_v1;
|
||||||
|
payload_size = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case U816_V2:
|
||||||
|
rf_udi_channels = NULL; // NO HOPPING !
|
||||||
|
payload_size = 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case U839_2014:
|
||||||
|
// UDI 2014 Protocol (uint8_t30, uint8_t39, all other new products ?)
|
||||||
|
rf_udi_channels = freq_hopping_uint8_t39;
|
||||||
|
payload_size = 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, payload_size);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // Clear status bits
|
||||||
|
|
||||||
|
if ((sub_protocol == U816_V1) || (sub_protocol == U816_V2)) {
|
||||||
|
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x27); //
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x3A); //
|
||||||
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3 byte address
|
||||||
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||||
|
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3F); // Auto-acknowledge on all data pipers, same as YD
|
||||||
|
if (sub_protocol == U816_V1) {
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7F); //
|
||||||
|
} else {
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7A); //
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (sub_protocol == U839_2014) {
|
||||||
|
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x0F); // 2Mbps air rate, 5dBm RF output power, high LNA gain
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x1A); // 500uS retransmit t/o, 10 tries (same as YD)
|
||||||
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3 byte address
|
||||||
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||||
|
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3F); // Auto-acknowledge on all data pipers, same as YD
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // Enable CRC, 2 byte CRC, PWR UP, PRIMARY RX
|
||||||
|
}
|
||||||
|
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, status);
|
||||||
|
|
||||||
|
status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, status);
|
||||||
|
|
||||||
|
// Implicit delay in callback
|
||||||
|
// delayMicroseconds(120)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UDI_init2()
|
||||||
|
{
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
bind_step_success = 0;
|
||||||
|
packet_sent = 0;
|
||||||
|
|
||||||
|
switch (sub_protocol) {
|
||||||
|
case U816_V1:
|
||||||
|
rf_ch_num = 0;
|
||||||
|
bind_channel = rf_udi_channels[rf_ch_num++];
|
||||||
|
break;
|
||||||
|
case U816_V2:
|
||||||
|
rf_ch_num = 0x07; // This is actual channel. No hopping here
|
||||||
|
bind_channel = 0;
|
||||||
|
break;
|
||||||
|
case U839_2014:
|
||||||
|
rf_ch_num = 1;
|
||||||
|
bind_channel = rf_udi_channels[rf_ch_num++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind_channel);
|
||||||
|
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *) "\xe7\x7e\xe7", 3);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *) "\xe7\x7e\xe7", 3);
|
||||||
|
|
||||||
|
// Turn radio power on
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
uint8_t config = BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, config);
|
||||||
|
// Implicit delay in callback
|
||||||
|
// delayMicroseconds(150);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_tx_id(uint32_t id)
|
||||||
|
{
|
||||||
|
tx_id[0] = (id >> 16) & 0xFF;
|
||||||
|
tx_id[1] = (id >> 8) & 0xFF;
|
||||||
|
tx_id[2] = (id >> 0) & 0xFF;
|
||||||
|
|
||||||
|
/*
|
||||||
|
uint32_t val = rand32(); randoms[0] = val & 0xff; randoms[1] = (val >> 8 ) & 0xff; randoms[2] = (val >> 16 ) & 0xff;
|
||||||
|
*/
|
||||||
|
// FIXME
|
||||||
|
// This one has been observed, leads to RF CH 0x1F (#08) used for BIND2
|
||||||
|
randoms[0] = 0x98; randoms[1] = 0x80; randoms[2] = 0x5B;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_pkt_checksum()
|
||||||
|
{
|
||||||
|
// CHECKSUM was introduced with 2014 protocol
|
||||||
|
if (sub_protocol < U839_2014) return;
|
||||||
|
uint8_t sum = 0;
|
||||||
|
for (uint8_t i = 0; i < payload_size-1; ++i) sum += packet[i];
|
||||||
|
packet[payload_size-1] = sum & 0x3f; // *sick*
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t convert_channel(uint8_t num, uint8_t chn_max, uint8_t sign_ofs)
|
||||||
|
{
|
||||||
|
uint32_t ch = Servo_data[num];
|
||||||
|
if (ch < PPM_MIN) {
|
||||||
|
ch = PPM_MIN;
|
||||||
|
} else if (ch > PPM_MAX) {
|
||||||
|
ch = PPM_MAX;
|
||||||
|
}
|
||||||
|
uint32_t chn_val;
|
||||||
|
if (sign_ofs) chn_val = (((ch * chn_max / PPM_MAX) + sign_ofs) >> 1);
|
||||||
|
else chn_val = (ch * chn_max / PPM_MAX);
|
||||||
|
if (chn_val < 0) chn_val = 0;
|
||||||
|
else if (chn_val > chn_max) chn_val = chn_max;
|
||||||
|
return (uint8_t) chn_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void read_controls(uint8_t* throttle, uint8_t* rudder, uint8_t* elevator, uint8_t* aileron,
|
||||||
|
uint8_t* flags)
|
||||||
|
{
|
||||||
|
// Protocol is registered AETRG, that is
|
||||||
|
// Aileron is channel 0, Elevator - 1, Throttle - 2, Rudder - 3
|
||||||
|
// Sometimes due to imperfect calibration or mixer settings
|
||||||
|
// throttle can be less than PPM_MIN or larger than
|
||||||
|
// PPM_MAX. As we have no space here, we hard-limit
|
||||||
|
// channels values by min..max range
|
||||||
|
|
||||||
|
// Channel 3: throttle is 0-100
|
||||||
|
*throttle = convert_channel(THROTTLE, 0x64, 0);
|
||||||
|
|
||||||
|
// Channel 4
|
||||||
|
*rudder = convert_channel(RUDDER, 0x3f, 0x20);
|
||||||
|
|
||||||
|
// Channel 2
|
||||||
|
*elevator = convert_channel(ELEVATOR, 0x3f, 0x20);
|
||||||
|
|
||||||
|
// Channel 1
|
||||||
|
*aileron = convert_channel(AILERON, 0x3f, 0x20);
|
||||||
|
|
||||||
|
// Channel 5
|
||||||
|
if (Servo_data[AUX1] <= 0) *flags &= ~UDI_FLIP360;
|
||||||
|
else *flags |= UDI_FLIP360;
|
||||||
|
|
||||||
|
// Channel 6
|
||||||
|
if (Servo_data[AUX2] <= 0) *flags &= ~UDI_FLIP;
|
||||||
|
else *flags |= UDI_FLIP;
|
||||||
|
|
||||||
|
// Channel 7
|
||||||
|
if (Servo_data[AUX3] <= 0) *flags &= ~UDI_CAMERA;
|
||||||
|
else *flags |= UDI_CAMERA;
|
||||||
|
|
||||||
|
// Channel 8
|
||||||
|
if (Servo_data[AUX4] <= 0) *flags &= ~UDI_VIDEO;
|
||||||
|
else *flags |= UDI_VIDEO;
|
||||||
|
|
||||||
|
// Channel 9
|
||||||
|
if (Servo_data[AUX5] <= 0) *flags &= ~UDI_LIGHTS;
|
||||||
|
else *flags |= UDI_LIGHTS;
|
||||||
|
|
||||||
|
// Channel 10
|
||||||
|
if (Servo_data[AUX6] <= 0) *flags &= ~UDI_MODE2;
|
||||||
|
else *flags |= UDI_MODE2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_udi_packet(uint8_t bind)
|
||||||
|
{
|
||||||
|
packet[7] = 0x4A;
|
||||||
|
if (bind == 1) {
|
||||||
|
// Bind phase 1
|
||||||
|
// MAGIC
|
||||||
|
packet[0] = 0x5A; // NOTE: Also 0xF3, when RX does not ACK packets (uint8_t39, only TX on) ...
|
||||||
|
// Current Address / TX ID
|
||||||
|
if (sub_protocol == U839_2014) {
|
||||||
|
// uint8_t39: Current RX/TX Addr
|
||||||
|
packet[1] = 0xE7;
|
||||||
|
packet[2] = 0x7E;
|
||||||
|
packet[3] = 0xE7;
|
||||||
|
} else {
|
||||||
|
// uint8_t16: ID Fixed per TX
|
||||||
|
packet[1] = tx_id[0];
|
||||||
|
packet[2] = tx_id[1];
|
||||||
|
packet[3] = tx_id[2];
|
||||||
|
}
|
||||||
|
// Pseudo random values (lower nibble of packet[4] determines index of RF CH used in BIND2)
|
||||||
|
packet[4] = randoms[0];
|
||||||
|
packet[5] = randoms[1];
|
||||||
|
packet[6] = randoms[2];
|
||||||
|
if (sub_protocol == U839_2014) {
|
||||||
|
packet[7] = (packet_counter < 4) ? 0x3f : 0x04; // first four packets use 0x3f here, then 0x04
|
||||||
|
}
|
||||||
|
} else if (bind == 2) {
|
||||||
|
// Bind phase 2
|
||||||
|
// MAGIC
|
||||||
|
packet[0] = 0xAA;
|
||||||
|
// Current Address (RX "ID", pseudorandom again)
|
||||||
|
packet[1] = rx_id[0];
|
||||||
|
packet[2] = rx_id[1];
|
||||||
|
packet[3] = rx_id[2];
|
||||||
|
// Pseudo random values
|
||||||
|
packet[4] = randoms[0];
|
||||||
|
packet[5] = randoms[1];
|
||||||
|
packet[6] = randoms[2];
|
||||||
|
if (sub_protocol == U839_2014) {
|
||||||
|
packet[7] = 0x04;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// regular packet
|
||||||
|
// Read channels (converts to required ranges)
|
||||||
|
read_controls(&throttle, &rudder, &elevator, &aileron, &flags);
|
||||||
|
// MAGIC
|
||||||
|
packet[0] = 0x55;
|
||||||
|
packet[1] = throttle; // throttle is 0-0x64
|
||||||
|
// 3 Channels packed into 2 bytes (5bit per channel)
|
||||||
|
uint16_t encoded = (rudder << 11) | (elevator << 6) | (aileron << 1);
|
||||||
|
packet[2] = (encoded >> 8) & 0xff;
|
||||||
|
packet[3] = encoded & 0xff;
|
||||||
|
// Trims and flags (0x20 = center)
|
||||||
|
packet[4] = 0x20; // rudder trim 6bit
|
||||||
|
packet[5] = 0x20; // elev trim 6bit
|
||||||
|
packet[6] = 0x20; // ail trim 6bit
|
||||||
|
|
||||||
|
if (flags & UDI_FLIP) packet[4] |= 0x80; // "Directional" flip
|
||||||
|
if (flags & UDI_LIGHTS) packet[4] |= 0x40; // Light on/off
|
||||||
|
|
||||||
|
if (flags & UDI_MODE2) packet[5] |= 0x80; // High rate ("Mode2")
|
||||||
|
if (flags & UDI_FLIP360) packet[5] |= 0x40; // 360 degree flip
|
||||||
|
|
||||||
|
if (flags & UDI_VIDEO) packet[6] |= 0x80; // Video recording on/off
|
||||||
|
if (flags & UDI_CAMERA) packet[6] |= 0x40; // Take picture
|
||||||
|
|
||||||
|
// NOTE: Only newer protocols have this (handled by routine)
|
||||||
|
add_pkt_checksum();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS,status);
|
||||||
|
|
||||||
|
if (packet_sent && bind && (status & BV(NRF24L01_07_TX_DS))) {
|
||||||
|
bind_step_success = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_sent = 0;
|
||||||
|
|
||||||
|
// Check if its time to change channel
|
||||||
|
// This seems to be done by measuring time,
|
||||||
|
// not by counting packets, on UDI transmitters
|
||||||
|
// NOTE: Seems even in bind phase channels are changed
|
||||||
|
|
||||||
|
// NOTE: Only hop in TX mode ???
|
||||||
|
if (rf_udi_channels && (bind == 0) && (packets_to_hop-- == 0)) {
|
||||||
|
uint8_t rf_ch = rf_udi_channels[rf_ch_num];
|
||||||
|
rf_ch_num++;
|
||||||
|
rf_ch_num %= NUM_UDI_RF_CHANNELS;
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||||
|
|
||||||
|
packets_to_hop = bind ? BIND_PACKETS_UDI_PER_CHANNEL : PACKETS_UDI_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_WritePayload(packet, payload_size);
|
||||||
|
++packet_counter;
|
||||||
|
packet_sent = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t UDI_callback() {
|
||||||
|
switch (phase) {
|
||||||
|
case UDI_INIT2:
|
||||||
|
UDI_init2();
|
||||||
|
phase = UDI_BIND1_TX;
|
||||||
|
return 120;
|
||||||
|
break;
|
||||||
|
case UDI_INIT2_NO_BIND:
|
||||||
|
// Do nothing (stay forever)
|
||||||
|
// Cannot re-bind on UDI protocol since IDs are random
|
||||||
|
return 10000; // 10ms
|
||||||
|
break;
|
||||||
|
case UDI_BIND1_TX:
|
||||||
|
if (packet_sent && packet_udi_ack() == PKT_ACKED) { bind_step_success = 1; }
|
||||||
|
if (bind_step_success) {
|
||||||
|
// All fine, wait for reply of receiver
|
||||||
|
phase = UDI_BIND1_RX;
|
||||||
|
|
||||||
|
NRF24L01_SetTxRxMode(RX_EN);
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||||
|
bind_step_success = 0;
|
||||||
|
//packets_to_check = 12; // according to SPI traces on uint8_t17B RX it receives 12 packets (and answers with 5)
|
||||||
|
packets_to_check = 3;
|
||||||
|
} else {
|
||||||
|
send_udi_packet(1);
|
||||||
|
}
|
||||||
|
return BIND_PACKET_UDI_PERIOD;
|
||||||
|
break;
|
||||||
|
case UDI_BIND1_RX:
|
||||||
|
// Check if data has been received
|
||||||
|
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR) ) {
|
||||||
|
uint8_t data[UDI_PAYLOADSIZE];
|
||||||
|
NRF24L01_ReadPayload(data, payload_size);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x4E); // On original TX this is done on LAST packet check only !
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
|
||||||
|
// Verify MAGIC and Random ID
|
||||||
|
// (may be reply to bind packet from other TX)
|
||||||
|
if ((data[0] == 0xA5) &&
|
||||||
|
(data[4] == randoms[0]) &&
|
||||||
|
(data[5] == randoms[1]) &&
|
||||||
|
(data[6] == randoms[2]) &&
|
||||||
|
(data[7] == randoms[2])) {
|
||||||
|
rx_id[0] = data[1];
|
||||||
|
rx_id[1] = data[2];
|
||||||
|
rx_id[2] = data[3];
|
||||||
|
if (sub_protocol != U816_V2) {
|
||||||
|
rf_ch_num = randoms[0] & 0x0f;
|
||||||
|
}
|
||||||
|
bind_step_success = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// RX seems to need more than one ACK
|
||||||
|
if (packets_to_check) packets_to_check--;
|
||||||
|
//NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||||
|
if (bind_step_success && !packets_to_check) {
|
||||||
|
// All fine, switch address and RF channel,
|
||||||
|
// send bind packets with channel hopping now
|
||||||
|
phase = UDI_BIND2_TX;
|
||||||
|
|
||||||
|
packet_sent = 0;
|
||||||
|
packets_to_send = 4;
|
||||||
|
bind_step_success = 0;
|
||||||
|
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_id, 3);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_id, 3);
|
||||||
|
|
||||||
|
if (sub_protocol != U816_V2) {
|
||||||
|
// Switch RF channel
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_udi_channels[rf_ch_num++]);
|
||||||
|
rf_ch_num %= NUM_UDI_RF_CHANNELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x7E);
|
||||||
|
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
//NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0E)
|
||||||
|
|
||||||
|
return 10; // 10 µs (start sending immediately)
|
||||||
|
}
|
||||||
|
return BIND_PACKET_UDI_PERIOD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UDI_BIND2_TX:
|
||||||
|
if (packet_sent && packet_udi_ack() == PKT_ACKED) {
|
||||||
|
bind_step_success = 1;
|
||||||
|
}
|
||||||
|
send_udi_packet(2);
|
||||||
|
if (packets_to_send) --packets_to_send;
|
||||||
|
if (bind_step_success || !packets_to_send) {
|
||||||
|
// Seems the original TX ignores AACK, too !
|
||||||
|
// U816 V1: 3 packets send, U839: 4 packets send
|
||||||
|
// All fine, wait for reply of receiver
|
||||||
|
phase = UDI_BIND2_RX;
|
||||||
|
|
||||||
|
NRF24L01_SetTxRxMode(RX_EN);
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||||
|
bind_step_success = 0;
|
||||||
|
packets_to_check = 14; // ???
|
||||||
|
}
|
||||||
|
return bind_step_success ? 4000 : 12000; // 4ms if no packed acked yet, 12ms afterwards
|
||||||
|
// return 120; // FIXME: Varies for first three packets !!!
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UDI_BIND2_RX:
|
||||||
|
// Check if data has been received
|
||||||
|
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR) ) {
|
||||||
|
uint8_t data[UDI_PAYLOADSIZE];
|
||||||
|
NRF24L01_ReadPayload(data, payload_size);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x4E);
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
|
||||||
|
// Verify MAGIC, RX Addr, Random ID
|
||||||
|
// (may be reply to bind packet from other TX)
|
||||||
|
if ((data[0] == 0xDD) &&
|
||||||
|
(data[1] == rx_id[0]) &&
|
||||||
|
(data[2] == rx_id[1]) &&
|
||||||
|
(data[3] == rx_id[2]) &&
|
||||||
|
(data[4] == randoms[0]) &&
|
||||||
|
(data[5] == randoms[1]) &&
|
||||||
|
(data[6] == randoms[2]) &&
|
||||||
|
(data[7] == randoms[2])) {
|
||||||
|
bind_step_success = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// RX seems to need more than one ACK
|
||||||
|
if (packets_to_check) packets_to_check--;
|
||||||
|
//NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||||
|
if (bind_step_success && !packets_to_check) {
|
||||||
|
phase = UDI_DATA;
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x7E);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0E);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
|
||||||
|
// Switch RF channel
|
||||||
|
if (sub_protocol == U816_V2) {
|
||||||
|
// FIXED RF Channel
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
|
||||||
|
} else {
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_udi_channels[rf_ch_num++]);
|
||||||
|
rf_ch_num %= NUM_UDI_RF_CHANNELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
BIND_DONE;
|
||||||
|
}
|
||||||
|
return BIND_PACKET_UDI_PERIOD;
|
||||||
|
break;
|
||||||
|
case UDI_DATA:
|
||||||
|
if (packet_sent && packet_udi_ack() != PKT_ACKED) {
|
||||||
|
return PACKET_UDI_CHKTIME;
|
||||||
|
}
|
||||||
|
send_udi_packet(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Packet every 15ms
|
||||||
|
return PACKET_UDI_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t UDI_setup()
|
||||||
|
{
|
||||||
|
packet_counter = 0;
|
||||||
|
UDI_init();
|
||||||
|
phase = UDI_INIT2;
|
||||||
|
counter = BIND_UDI_COUNT;
|
||||||
|
|
||||||
|
// observed on U839 TX
|
||||||
|
set_tx_id(0x457C27);
|
||||||
|
|
||||||
|
return INITIAL_UDI_WAIT;
|
||||||
|
}
|
||||||
|
#endif
|
108
Multiprotocol/SHENQI_nrf24l01.ino
Normal file
108
Multiprotocol/SHENQI_nrf24l01.ino
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#if defined(SHENQI_NRF24L01_INO)
|
||||||
|
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
const uint8_t PROGMEM SHENQI_Freq[] = {
|
||||||
|
50,50,20,60,30,40,
|
||||||
|
10,30,40,20,60,10,
|
||||||
|
50,20,50,40,10,60,
|
||||||
|
30,30,60,10,40,50,
|
||||||
|
20,10,60,20,50,30,
|
||||||
|
40,40,30,50,20,60,
|
||||||
|
10,10,20,30,40,50,
|
||||||
|
60,60,50,40,30,20,
|
||||||
|
10,60,10,50,30,40,
|
||||||
|
20,10,40,30,60,20 };
|
||||||
|
|
||||||
|
void SHENQI_init()
|
||||||
|
{
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes rx/tx address
|
||||||
|
|
||||||
|
LT8910_Config(4, 8, _BV(LT8910_CRC_ON)|_BV(LT8910_PACKET_LENGTH_EN), 0xAA);
|
||||||
|
LT8910_SetChannel(2);
|
||||||
|
LT8910_SetAddress((uint8_t *)"\x9A\x9A\x9A\x9A",4);
|
||||||
|
LT8910_SetTxRxMode(RX_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHENQI_send_packet()
|
||||||
|
{
|
||||||
|
packet[0]=0x00;
|
||||||
|
if(packet_count==0)
|
||||||
|
{
|
||||||
|
uint8_t bind_addr[4];
|
||||||
|
bind_addr[0]=0x9A;
|
||||||
|
bind_addr[1]=0x9A;
|
||||||
|
bind_addr[2]=rx_tx_addr[2];
|
||||||
|
bind_addr[3]=rx_tx_addr[3];
|
||||||
|
LT8910_SetAddress(bind_addr,4);
|
||||||
|
LT8910_SetChannel(2);
|
||||||
|
packet[1]=rx_tx_addr[1];
|
||||||
|
packet[2]=rx_tx_addr[0];
|
||||||
|
packet_period=2508;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LT8910_SetAddress(rx_tx_addr,4);
|
||||||
|
packet[1]=255-convert_channel_8b(RUDDER);
|
||||||
|
packet[2]=255-convert_channel_8b_scale(THROTTLE,0x60,0xA0);
|
||||||
|
uint8_t freq=pgm_read_byte_near(&SHENQI_Freq[hopping_frequency_no])+(rx_tx_addr[1]&0x0F);
|
||||||
|
LT8910_SetChannel(freq);
|
||||||
|
hopping_frequency_no++;
|
||||||
|
if(hopping_frequency_no==60)
|
||||||
|
hopping_frequency_no=0;
|
||||||
|
packet_period=1750;
|
||||||
|
}
|
||||||
|
// Send packet + 1 retransmit - not sure why but needed (not present on original TX...)
|
||||||
|
LT8910_WritePayload(packet,3);
|
||||||
|
while(NRF24L01_packet_ack()!=PKT_ACKED);
|
||||||
|
LT8910_WritePayload(packet,3);
|
||||||
|
|
||||||
|
packet_count++;
|
||||||
|
if(packet_count==7)
|
||||||
|
{
|
||||||
|
packet_count=0;
|
||||||
|
packet_period=3000;
|
||||||
|
}
|
||||||
|
// Set power
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t SHENQI_callback()
|
||||||
|
{
|
||||||
|
if(IS_BIND_DONE_on)
|
||||||
|
SHENQI_send_packet();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR))
|
||||||
|
{
|
||||||
|
if(LT8910_ReadPayload(packet, 3))
|
||||||
|
{
|
||||||
|
BIND_DONE;
|
||||||
|
rx_tx_addr[3]=packet[1];
|
||||||
|
rx_tx_addr[2]=packet[2];
|
||||||
|
LT8910_SetTxRxMode(TX_EN);
|
||||||
|
packet_period=14000;
|
||||||
|
}
|
||||||
|
NRF24L01_FlushRx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packet_period;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t initSHENQI()
|
||||||
|
{
|
||||||
|
BIND_IN_PROGRESS; // autobind protocol
|
||||||
|
SHENQI_init();
|
||||||
|
hopping_frequency_no = 0;
|
||||||
|
packet_count=0;
|
||||||
|
packet_period=100;
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -25,14 +25,6 @@
|
|||||||
//Uncomment to enable telemetry
|
//Uncomment to enable telemetry
|
||||||
#define TELEMETRY
|
#define TELEMETRY
|
||||||
|
|
||||||
|
|
||||||
//Uncomment to enable potar select
|
|
||||||
#define POTAR_SELECT
|
|
||||||
#define POTAR_SELECT_V ELEVATOR
|
|
||||||
#define POTAR_SELECT_H RUDDER
|
|
||||||
#define POTAR_SELECT_M AILERON
|
|
||||||
|
|
||||||
|
|
||||||
//Comment if a module is not installed
|
//Comment if a module is not installed
|
||||||
#define A7105_INSTALLED
|
#define A7105_INSTALLED
|
||||||
#define CYRF6936_INSTALLED
|
#define CYRF6936_INSTALLED
|
||||||
@ -62,6 +54,11 @@
|
|||||||
#define CFlie_NRF24L01_INO
|
#define CFlie_NRF24L01_INO
|
||||||
#define H377_NRF24L01_INO
|
#define H377_NRF24L01_INO
|
||||||
#define FY326_NRF24L01_INO
|
#define FY326_NRF24L01_INO
|
||||||
|
#define ESKY150_NRF24L01_INO
|
||||||
|
// #define BlueFly_NRF24L01_INO //probleme gene id
|
||||||
|
#define HonTai_NRF24L01_INO
|
||||||
|
#define UDI_NRF24L01_INO
|
||||||
|
#define NE260_NRF24L01_INO
|
||||||
|
|
||||||
#define BAYANG_NRF24L01_INO
|
#define BAYANG_NRF24L01_INO
|
||||||
#define CG023_NRF24L01_INO
|
#define CG023_NRF24L01_INO
|
||||||
@ -75,27 +72,27 @@
|
|||||||
#define YD717_NRF24L01_INO
|
#define YD717_NRF24L01_INO
|
||||||
#define MT99XX_NRF24L01_INO
|
#define MT99XX_NRF24L01_INO
|
||||||
#define MJXQ_NRF24L01_INO
|
#define MJXQ_NRF24L01_INO
|
||||||
|
// #define SHENQI_NRF24L01_INO
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Update this table to set which protocol and all associated settings are called for the corresponding dial number
|
//Update this table to set which protocol and all associated settings are called for the corresponding dial number
|
||||||
static const PPM_Parameters PPM_prot[15]=
|
const PPM_Parameters PPM_prot[15]= {
|
||||||
{
|
// Dial Protocol Sub protocol RX_Num Power Auto Bind Option
|
||||||
// Protocol Sub protocol RX_Num Power Auto Bind Option
|
/* 1 */ {MODE_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 },
|
||||||
{MODE_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 }, //Dial=1
|
/* 2 */ {MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=2
|
/* 3 */ {MODE_FRSKY , 0 , 0 , P_HIGH , NO_AUTOBIND , 0xD7 },
|
||||||
{MODE_FRSKY , 0 , 0 , P_HIGH , NO_AUTOBIND , 0xD7 }, //Dial=3
|
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=4
|
/* 5 */ {MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=5
|
/* 6 */ {MODE_DSM2 , DSM2 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_DSM2 , DSM2 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=6
|
/* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=7
|
/* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=8
|
/* 9 */ {MODE_KN , FEILUN , 0 , P_HIGH , AUTOBIND , 0 },
|
||||||
{MODE_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=9
|
/* 10 */ {MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=10
|
/* 11 */ {MODE_SLT , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_SLT , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=11
|
/* 12 */ {MODE_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=12
|
/* 13 */ {MODE_CG023 , CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_CG023 , CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=13
|
/* 14 */ {MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||||
{MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=14
|
/* 15 */ {MODE_SYMAX , SYMAX5C , 0 , P_HIGH , NO_AUTOBIND , 0 }
|
||||||
{MODE_SYMAX , SYMAX5C , 0 , P_HIGH , NO_AUTOBIND , 0 } //Dial=15
|
|
||||||
};
|
};
|
||||||
/* Available protocols and associated sub protocols:
|
/* Available protocols and associated sub protocols:
|
||||||
MODE_FLYSKY
|
MODE_FLYSKY
|
||||||
@ -159,6 +156,8 @@ static const PPM_Parameters PPM_prot[15]=
|
|||||||
X600
|
X600
|
||||||
X800
|
X800
|
||||||
H26D
|
H26D
|
||||||
|
MODE_SHENQI
|
||||||
|
NONE
|
||||||
|
|
||||||
RX_Num value between 0 and 15
|
RX_Num value between 0 and 15
|
||||||
|
|
||||||
@ -191,7 +190,7 @@ Option value between 0 and 255. 0xD7 or 0x00 for Frsky fine tuning.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// SPEKTRUM PPM and channels
|
// SPEKTRUM PPM and channels
|
||||||
#if defined(TX_SPEKTRUM) | defined(TARANIS)
|
#if defined(TX_SPEKTRUM)
|
||||||
#define PPM_MAX 2000
|
#define PPM_MAX 2000
|
||||||
#define PPM_MIN 1000
|
#define PPM_MIN 1000
|
||||||
#define PPM_MAX_100 1900
|
#define PPM_MAX_100 1900
|
||||||
@ -199,6 +198,15 @@ Option value between 0 and 255. 0xD7 or 0x00 for Frsky fine tuning.
|
|||||||
#define TAER
|
#define TAER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TARANIS PPM and channels
|
||||||
|
#if defined(TARANIS)
|
||||||
|
#define PPM_MAX 2000
|
||||||
|
#define PPM_MIN 1000
|
||||||
|
#define PPM_MAX_100 1900
|
||||||
|
#define PPM_MIN_100 1100
|
||||||
|
#define EATR
|
||||||
|
#endif
|
||||||
|
|
||||||
// HISKY
|
// HISKY
|
||||||
#if defined(TX_HISKY)
|
#if defined(TX_HISKY)
|
||||||
#define PPM_MAX 2000
|
#define PPM_MAX 2000
|
||||||
@ -249,3 +257,7 @@ enum chan_orders{
|
|||||||
#define PPM_MIN_COMMAND 1250
|
#define PPM_MIN_COMMAND 1250
|
||||||
#define PPM_SWITCH 1550
|
#define PPM_SWITCH 1550
|
||||||
#define PPM_MAX_COMMAND 1750
|
#define PPM_MAX_COMMAND 1750
|
||||||
|
|
||||||
|
//Uncoment the desired serial speed
|
||||||
|
#define BAUD 100000
|
||||||
|
//#define BAUD 125000
|
||||||
|
@ -156,4 +156,43 @@ enum {
|
|||||||
//void CC2500_WriteData(u8 *packet, u8 length);
|
//void CC2500_WriteData(u8 *packet, u8 length);
|
||||||
//void CC2500_ReadData(u8 *dpbuffer, int len);
|
//void CC2500_ReadData(u8 *dpbuffer, int len);
|
||||||
//void CC2500_SetTxRxMode(enum TXRX_State);
|
//void CC2500_SetTxRxMode(enum TXRX_State);
|
||||||
|
|
||||||
|
const PROGMEM uint8_t cc2500_conf[][2]={
|
||||||
|
{ CC2500_02_IOCFG0, 0x06 },
|
||||||
|
{ CC2500_00_IOCFG2, 0x06 },
|
||||||
|
{ CC2500_17_MCSM1, 0x0c },
|
||||||
|
{ CC2500_18_MCSM0, 0x18 },
|
||||||
|
{ CC2500_06_PKTLEN, 0x19 },
|
||||||
|
{ CC2500_07_PKTCTRL1, 0x04 },
|
||||||
|
{ CC2500_08_PKTCTRL0, 0x05 },
|
||||||
|
{ CC2500_3E_PATABLE, 0xff },
|
||||||
|
{ CC2500_0B_FSCTRL1, 0x08 },
|
||||||
|
{ CC2500_0C_FSCTRL0, 0x00 }, // option
|
||||||
|
{ CC2500_0D_FREQ2, 0x5c },
|
||||||
|
{ CC2500_0E_FREQ1, 0x76 },
|
||||||
|
{ CC2500_0F_FREQ0, 0x27 },
|
||||||
|
{ CC2500_10_MDMCFG4, 0xAA },
|
||||||
|
{ CC2500_11_MDMCFG3, 0x39 },
|
||||||
|
{ CC2500_12_MDMCFG2, 0x11 },
|
||||||
|
{ CC2500_13_MDMCFG1, 0x23 },
|
||||||
|
{ CC2500_14_MDMCFG0, 0x7a },
|
||||||
|
{ CC2500_15_DEVIATN, 0x42 },
|
||||||
|
{ CC2500_19_FOCCFG, 0x16 },
|
||||||
|
{ CC2500_1A_BSCFG, 0x6c },
|
||||||
|
{ CC2500_1B_AGCCTRL2, 0x43 }, // bind ? 0x43 : 0x03
|
||||||
|
{ CC2500_1C_AGCCTRL1,0x40 },
|
||||||
|
{ CC2500_1D_AGCCTRL0,0x91 },
|
||||||
|
{ CC2500_21_FREND1, 0x56 },
|
||||||
|
{ CC2500_22_FREND0, 0x10 },
|
||||||
|
{ CC2500_23_FSCAL3, 0xa9 },
|
||||||
|
{ CC2500_24_FSCAL2, 0x0A },
|
||||||
|
{ CC2500_25_FSCAL1, 0x00 },
|
||||||
|
{ CC2500_26_FSCAL0, 0x11 },
|
||||||
|
{ CC2500_29_FSTEST, 0x59 },
|
||||||
|
{ CC2500_2C_TEST2, 0x88 },
|
||||||
|
{ CC2500_2D_TEST1, 0x31 },
|
||||||
|
{ CC2500_2E_TEST0, 0x0B },
|
||||||
|
{ CC2500_03_FIFOTHR, 0x07 },
|
||||||
|
{ CC2500_09_ADDR, 0x00 }
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,11 @@ enum PROTOCOLS
|
|||||||
MODE_H377=44, // =>NRF24L01
|
MODE_H377=44, // =>NRF24L01
|
||||||
MODE_WK2x01 = 45, // =>CYRF6936
|
MODE_WK2x01 = 45, // =>CYRF6936
|
||||||
MODE_FY326=46, // =>NRF24L01
|
MODE_FY326=46, // =>NRF24L01
|
||||||
|
MODE_ESKY150=47, // =>NRF24L01
|
||||||
|
MODE_BlueFly=48, // =>NRF24L01
|
||||||
|
MODE_HonTai=49, // =>NRF24L01
|
||||||
|
MODE_UDI=50, // =>NRF24L01
|
||||||
|
MODE_NE260=51, // =>NRF24L01
|
||||||
|
|
||||||
MODE_SERIAL = 0, // Serial commands
|
MODE_SERIAL = 0, // Serial commands
|
||||||
MODE_FLYSKY = 1, // =>A7105
|
MODE_FLYSKY = 1, // =>A7105
|
||||||
@ -49,7 +54,8 @@ enum PROTOCOLS
|
|||||||
MODE_FRSKYX = 15, // =>CC2500
|
MODE_FRSKYX = 15, // =>CC2500
|
||||||
MODE_ESKY = 16, // =>NRF24L01
|
MODE_ESKY = 16, // =>NRF24L01
|
||||||
MODE_MT99XX=17, // =>NRF24L01
|
MODE_MT99XX=17, // =>NRF24L01
|
||||||
MODE_MJXQ=18 // =>NRF24L01
|
MODE_MJXQ=18, // =>NRF24L01
|
||||||
|
MODE_SHENQI=19 // =>NRF24L01
|
||||||
};
|
};
|
||||||
enum Flysky
|
enum Flysky
|
||||||
{
|
{
|
||||||
@ -127,6 +133,12 @@ enum FY326
|
|||||||
FY326 = 0,
|
FY326 = 0,
|
||||||
FY319 = 1
|
FY319 = 1
|
||||||
};
|
};
|
||||||
|
enum UDI
|
||||||
|
{
|
||||||
|
U816_V1 = 0,
|
||||||
|
U816_V2,
|
||||||
|
U839_2014
|
||||||
|
};
|
||||||
|
|
||||||
#define NONE 0
|
#define NONE 0
|
||||||
#define P_HIGH 1
|
#define P_HIGH 1
|
||||||
@ -147,10 +159,6 @@ struct PPM_Parameters
|
|||||||
//*******************
|
//*******************
|
||||||
//*** Pinouts ***
|
//*** Pinouts ***
|
||||||
//*******************
|
//*******************
|
||||||
#define BUZZER 19 //A5
|
|
||||||
#define BUZZER_HTZ 440 // La clé de sol
|
|
||||||
#define BUZZER_TPS 300
|
|
||||||
|
|
||||||
//#define BIND_pin 13
|
//#define BIND_pin 13
|
||||||
#define LED_pin 13 //Promini original led on B5
|
#define LED_pin 13 //Promini original led on B5
|
||||||
//
|
//
|
||||||
@ -440,6 +448,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
|||||||
ESky 16
|
ESky 16
|
||||||
MT99XX 17
|
MT99XX 17
|
||||||
MJXQ 18
|
MJXQ 18
|
||||||
|
SHENQI 19
|
||||||
BindBit=> 0x80 1=Bind/0=No
|
BindBit=> 0x80 1=Bind/0=No
|
||||||
AutoBindBit=> 0x40 1=Yes /0=No
|
AutoBindBit=> 0x40 1=Yes /0=No
|
||||||
RangeCheck=> 0x20 1=Yes /0=No
|
RangeCheck=> 0x20 1=Yes /0=No
|
||||||
|
63
README.md
63
README.md
@ -60,6 +60,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
|||||||
CH1|CH2|CH3|CH4|???|CONF|Gyro & Rudder mix
|
CH1|CH2|CH3|CH4|???|CONF|Gyro & Rudder mix
|
||||||
|
|
||||||
CONF: Option 1 = Rate Throtle
|
CONF: Option 1 = Rate Throtle
|
||||||
|
|
||||||
Option 2 = Pitch
|
Option 2 = Pitch
|
||||||
|
|
||||||
|
|
||||||
@ -76,6 +77,13 @@ CH1|CH2|CH3|CH4
|
|||||||
A|E|T|R
|
A|E|T|R
|
||||||
|
|
||||||
##NRF24L01 RF Module
|
##NRF24L01 RF Module
|
||||||
|
###BLUEFLY
|
||||||
|
Autobind
|
||||||
|
|
||||||
|
CH1|CH2|CH3|CH4|CH5|CH6
|
||||||
|
---|---|---|---|---|---
|
||||||
|
A|E|T|R|GEAR|PITCH
|
||||||
|
|
||||||
###CFLIE
|
###CFLIE
|
||||||
Modele: CrazyFlie Nano quad
|
Modele: CrazyFlie Nano quad
|
||||||
|
|
||||||
@ -85,6 +93,14 @@ CH1|CH2|CH3|CH4
|
|||||||
---|---|---|---
|
---|---|---|---
|
||||||
A|E|T|R
|
A|E|T|R
|
||||||
|
|
||||||
|
###ESKY150
|
||||||
|
|
||||||
|
Autobind
|
||||||
|
|
||||||
|
CH1|CH2|CH3|CH4
|
||||||
|
---|---|---|---
|
||||||
|
A|E|T|R
|
||||||
|
|
||||||
###Fy326
|
###Fy326
|
||||||
Autobind
|
Autobind
|
||||||
|
|
||||||
@ -107,6 +123,51 @@ Autobind
|
|||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5
|
CH1|CH2|CH3|CH4|CH5
|
||||||
---|---|---|---
|
---|---|---|---
|
||||||
A|Turbo|T|Trim|Bouton ???
|
A|Turbo|T|Trim|Bouton
|
||||||
|
|
||||||
|
###HONTAI
|
||||||
|
Autobind
|
||||||
|
|
||||||
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
||||||
|
---|---|---|---|---|---|---|---|---|---|---
|
||||||
|
A|E|T|R|LED|FLIP|PICTURE|VIDEO|HEADLESS|RTH|Calibrate
|
||||||
|
|
||||||
|
####Sub_protocol JJRCX1
|
||||||
|
Modele: JJRC X1
|
||||||
|
|
||||||
|
CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
||||||
|
---|---|---|---|---|---|---|---|---|---|---
|
||||||
|
ARM|FLIP|PICTURE|VIDEO|HEADLESS|RTH|Calibrate
|
||||||
|
|
||||||
|
###NE260
|
||||||
|
Modele: Nine Eagles SoloPro
|
||||||
|
|
||||||
|
Autobind
|
||||||
|
|
||||||
|
CH1|CH2|CH3|CH4
|
||||||
|
---|---|---|---
|
||||||
|
A|E|T|R
|
||||||
|
|
||||||
|
###UDI
|
||||||
|
Modele: Known UDI 2.4GHz protocol variants, all using BK2421
|
||||||
|
* UDI U819 coaxial 3ch helicoper
|
||||||
|
* UDI U816/817/818 quadcopters
|
||||||
|
- "V1" with orange LED on TX, U816 RX labeled '' , U817/U818 RX labeled 'UD-U817B'
|
||||||
|
- "V2" with red LEDs on TX, U816 RX labeled '', U817/U818 RX labeled 'UD-U817OG'
|
||||||
|
- "V3" with green LEDs on TX. Did not get my hands on yet.
|
||||||
|
* U830 mini quadcopter with tilt steering ("Protocol 2014")
|
||||||
|
* U839 nano quadcopter ("Protocol 2014")
|
||||||
|
|
||||||
|
Autobind
|
||||||
|
|
||||||
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
|
||||||
|
---|---|---|---|---|---|---|---|---|---
|
||||||
|
A|E|T|R|FLIP 360|FLIP|VIDEO|LED|MODE 2
|
||||||
|
|
||||||
|
####Sub_protocol U816 V1 (orange)
|
||||||
|
####Sub_protocol U816 V2 (red)
|
||||||
|
####Sub_protocol U816 (2014)
|
||||||
|
Same channels assignement as above.
|
||||||
|
|
||||||
|
|
||||||
###D'autres à venir
|
###D'autres à venir
|
Loading…
x
Reference in New Issue
Block a user