mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-03 12:07:52 +00:00
Suit du projet, ajout de la sélection PPM, ajout protocole H7
This commit is contained in:
parent
3fcaf93788
commit
ab5f4e9194
@ -196,8 +196,19 @@ const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
|
|||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ID_NORMAL 0x55201041
|
#define ID_NORMAL 0x55201041
|
||||||
#define ID_PLUS 0xAA201041
|
#define ID_PLUS 0xAA201041
|
||||||
|
|
||||||
|
/*
|
||||||
|
static const uint8_t a7105Regs[] = {
|
||||||
|
-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,
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
void A7105_Init(uint8_t protocol)
|
void A7105_Init(uint8_t protocol)
|
||||||
{
|
{
|
||||||
void *A7105_Regs;
|
void *A7105_Regs;
|
||||||
|
@ -38,7 +38,7 @@ enum BAYANG_FLAGS {
|
|||||||
BAYANG_FLAG_INVERTED = 0x80 // inverted flight on Floureon H101
|
BAYANG_FLAG_INVERTED = 0x80 // inverted flight on Floureon H101
|
||||||
};
|
};
|
||||||
|
|
||||||
static void BAYANG_send_packet(uint8_t bind)
|
static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
if (bind)
|
if (bind)
|
||||||
@ -112,7 +112,7 @@ static void BAYANG_send_packet(uint8_t bind)
|
|||||||
NRF24L01_SetPower(); // Set tx_power
|
NRF24L01_SetPower(); // Set tx_power
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BAYANG_init()
|
static void __attribute__((unused)) BAYANG_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
@ -148,7 +148,7 @@ uint16_t BAYANG_callback()
|
|||||||
return BAYANG_PACKET_PERIOD;
|
return BAYANG_PACKET_PERIOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BAYANG_initialize_txid()
|
static void __attribute__((unused)) BAYANG_initialize_txid()
|
||||||
{
|
{
|
||||||
//Could be using txid[0..2] but using rx_tx_addr everywhere instead...
|
//Could be using txid[0..2] but using rx_tx_addr everywhere instead...
|
||||||
hopping_frequency[0]=0;
|
hopping_frequency[0]=0;
|
||||||
|
@ -70,7 +70,7 @@ enum H8_3D_FLAGS_2 {
|
|||||||
H8_3D_FLAG_CALIBRATE = 0x20, // accelerometer calibration
|
H8_3D_FLAG_CALIBRATE = 0x20, // accelerometer calibration
|
||||||
};
|
};
|
||||||
|
|
||||||
static void CG023_send_packet(uint8_t bind)
|
static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
// throttle : 0x00 - 0xFF
|
// throttle : 0x00 - 0xFF
|
||||||
throttle=convert_channel_8b(THROTTLE);
|
throttle=convert_channel_8b(THROTTLE);
|
||||||
@ -205,7 +205,7 @@ static void CG023_send_packet(uint8_t bind)
|
|||||||
NRF24L01_SetPower(); // Set tx_power
|
NRF24L01_SetPower(); // Set tx_power
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CG023_init()
|
static void __attribute__((unused)) CG023_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
@ -246,7 +246,7 @@ uint16_t CG023_callback()
|
|||||||
return H8_3D_PACKET_PERIOD;
|
return H8_3D_PACKET_PERIOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CG023_initialize_txid()
|
static void __attribute__((unused)) CG023_initialize_txid()
|
||||||
{
|
{
|
||||||
if(sub_protocol==H8_3D)
|
if(sub_protocol==H8_3D)
|
||||||
{
|
{
|
||||||
@ -255,10 +255,10 @@ static void CG023_initialize_txid()
|
|||||||
rx_tx_addr[2] = rx_tx_addr[2] % 0x20;
|
rx_tx_addr[2] = rx_tx_addr[2] % 0x20;
|
||||||
rx_tx_addr[3] = rx_tx_addr[3] % 0x11;
|
rx_tx_addr[3] = rx_tx_addr[3] % 0x11;
|
||||||
|
|
||||||
hopping_frequency[0] = 0x06 + (rx_tx_addr[0]&0x0f);
|
hopping_frequency[0] = 0x06 + ((rx_tx_addr[0]&0x0f) % 0x0f);
|
||||||
hopping_frequency[1] = 0x15 + (rx_tx_addr[1]&0x0f);
|
hopping_frequency[1] = 0x15 + ((rx_tx_addr[1]&0x0f) % 0x0f);
|
||||||
hopping_frequency[2] = 0x24 + (rx_tx_addr[2]&0x0f);
|
hopping_frequency[2] = 0x24 + ((rx_tx_addr[2]&0x0f) % 0x0f);
|
||||||
hopping_frequency[3] = 0x33 + (rx_tx_addr[3]&0x0f);
|
hopping_frequency[3] = 0x33 + ((rx_tx_addr[3]&0x0f) % 0x0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // CG023 and YD829
|
{ // CG023 and YD829
|
||||||
|
@ -46,7 +46,7 @@ enum {
|
|||||||
CX10_DATA
|
CX10_DATA
|
||||||
};
|
};
|
||||||
|
|
||||||
static void CX10_Write_Packet(uint8_t bind)
|
static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
uint8_t offset = 0;
|
uint8_t offset = 0;
|
||||||
if(sub_protocol == CX10_BLUE)
|
if(sub_protocol == CX10_BLUE)
|
||||||
@ -90,9 +90,15 @@ static void CX10_Write_Packet(uint8_t bind)
|
|||||||
if(Servo_AUX4) flags |= 0x08; // Channel 8 - video
|
if(Servo_AUX4) flags |= 0x08; // Channel 8 - video
|
||||||
break;
|
break;
|
||||||
case Q282:
|
case Q282:
|
||||||
|
case Q242:
|
||||||
|
memcpy(&packet[15], "\x10\x10\xaa\xaa\x00\x00", 6);
|
||||||
//FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
|
//FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
|
||||||
if(Servo_AUX1) flags2 =0x80; // Channel 5 - FLIP
|
if(Servo_AUX1) flags2 =0x80; // Channel 5 - FLIP
|
||||||
if(Servo_AUX2) flags2|=0x40; // Channel 6 - LED
|
if(Servo_AUX2) flags2|=0x40; // Channel 6 - LED
|
||||||
|
|
||||||
|
if(Servo_AUX5) flags2|=0x08; // Channel 9 - HEADLESS
|
||||||
|
if(sub_protocol==Q282)
|
||||||
|
{
|
||||||
if(Servo_AUX3) flags2|=0x10; // Channel 7 - picture
|
if(Servo_AUX3) flags2|=0x10; // Channel 7 - picture
|
||||||
if(Servo_AUX4) // Channel 8 - video
|
if(Servo_AUX4) // Channel 8 - video
|
||||||
{
|
{
|
||||||
@ -101,13 +107,19 @@ static void CX10_Write_Packet(uint8_t bind)
|
|||||||
else
|
else
|
||||||
if (video_state & 0x20) video_state &= 0x01;
|
if (video_state & 0x20) video_state &= 0x01;
|
||||||
flags2 |= video_state;
|
flags2 |= video_state;
|
||||||
|
|
||||||
if(Servo_AUX5) flags2|=0x08; // Channel 9 - HEADLESS
|
|
||||||
flags=3;
|
flags=3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Servo_AUX3) flags2|=0x01; // Channel 7 - picture
|
||||||
|
if(Servo_AUX4) flags2|=0x10; // Channel 8 - video
|
||||||
|
flags=2;
|
||||||
|
packet[17]=0x00;
|
||||||
|
packet[18]=0x00;
|
||||||
|
}
|
||||||
if(Servo_AUX6) flags |=0x80; // Channel 10 - RTH
|
if(Servo_AUX6) flags |=0x80; // Channel 10 - RTH
|
||||||
if(Servo_AUX7) flags2|=0x04; // Channel 11 - XCAL
|
if(Servo_AUX7) flags2|=0x04; // Channel 11 - XCAL
|
||||||
if(Servo_AUX8) flags2|=0x02; // Channel 12 - YCAL
|
if(Servo_AUX8) flags2|=0x02; // Channel 12 - YCAL
|
||||||
memcpy(&packet[15], "\x10\x10\xaa\xaa\x00\x00", 6);
|
|
||||||
break;
|
break;
|
||||||
case DM007:
|
case DM007:
|
||||||
//FLIP|MODE|PICTURE|VIDEO|HEADLESS
|
//FLIP|MODE|PICTURE|VIDEO|HEADLESS
|
||||||
@ -154,7 +166,7 @@ static void CX10_Write_Packet(uint8_t bind)
|
|||||||
NRF24L01_SetPower();
|
NRF24L01_SetPower();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CX10_init()
|
static void __attribute__((unused)) CX10_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
@ -199,7 +211,7 @@ uint16_t CX10_callback() {
|
|||||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
CX10_Write_Packet(1);
|
CX10_Write_Packet(1);
|
||||||
delay(1); // used to be 300µs in deviation but not working so 1ms now
|
delayMicroseconds(400); // 300µs in deviation but not working so using 400µs instead
|
||||||
// switch to RX mode
|
// switch to RX mode
|
||||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||||
NRF24L01_FlushRx();
|
NRF24L01_FlushRx();
|
||||||
@ -214,7 +226,7 @@ uint16_t CX10_callback() {
|
|||||||
return packet_period;
|
return packet_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initialize_txid()
|
static void __attribute__((unused)) initialize_txid()
|
||||||
{
|
{
|
||||||
rx_tx_addr[1]%= 0x30;
|
rx_tx_addr[1]%= 0x30;
|
||||||
if(sub_protocol==Q282)
|
if(sub_protocol==Q282)
|
||||||
@ -224,6 +236,14 @@ static void initialize_txid()
|
|||||||
hopping_frequency[2] = 0x4a;
|
hopping_frequency[2] = 0x4a;
|
||||||
hopping_frequency[3] = 0x4c;
|
hopping_frequency[3] = 0x4c;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
if(sub_protocol==Q242)
|
||||||
|
{
|
||||||
|
hopping_frequency[0] = 0x48;
|
||||||
|
hopping_frequency[1] = 0x4a;
|
||||||
|
hopping_frequency[2] = 0x4c;
|
||||||
|
hopping_frequency[3] = 0x4e;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hopping_frequency[0] = 0x03 + (rx_tx_addr[0] & 0x0F);
|
hopping_frequency[0] = 0x03 + (rx_tx_addr[0] & 0x0F);
|
||||||
@ -247,7 +267,7 @@ uint16_t initCX10(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(sub_protocol==Q282)
|
if(sub_protocol==Q282||sub_protocol==Q242)
|
||||||
packet_length = Q282_PACKET_SIZE;
|
packet_length = Q282_PACKET_SIZE;
|
||||||
else
|
else
|
||||||
packet_length = CX10_PACKET_SIZE;
|
packet_length = CX10_PACKET_SIZE;
|
||||||
|
@ -110,7 +110,6 @@ uint16_t cyrf_state;
|
|||||||
uint8_t crcidx;
|
uint8_t crcidx;
|
||||||
uint8_t binding;
|
uint8_t binding;
|
||||||
uint16_t crc;
|
uint16_t crc;
|
||||||
uint8_t model;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifdef USE_FIXED_MFGID
|
#ifdef USE_FIXED_MFGID
|
||||||
@ -121,14 +120,14 @@ const uint8_t cyrfmfg_id[6] = {0xd4, 0x62, 0xd6, 0xad, 0xd3, 0xff}; //dx6i
|
|||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void build_bind_packet()
|
static void __attribute__((unused)) build_bind_packet()
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint16_t sum = 384 - 0x10;//
|
uint16_t sum = 384 - 0x10;//
|
||||||
packet[0] = crc >> 8;
|
packet[0] = crc >> 8;
|
||||||
packet[1] = crc & 0xff;
|
packet[1] = crc & 0xff;
|
||||||
packet[2] = 0xff ^ cyrfmfg_id[2];
|
packet[2] = 0xff ^ cyrfmfg_id[2];
|
||||||
packet[3] = (0xff ^ cyrfmfg_id[3]) + model;
|
packet[3] = (0xff ^ cyrfmfg_id[3]) + RX_num;
|
||||||
packet[4] = packet[0];
|
packet[4] = packet[0];
|
||||||
packet[5] = packet[1];
|
packet[5] = packet[1];
|
||||||
packet[6] = packet[2];
|
packet[6] = packet[2];
|
||||||
@ -154,7 +153,23 @@ static void build_bind_packet()
|
|||||||
packet[15] = sum & 0xff;
|
packet[15] = sum & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_data_packet(uint8_t upper)//
|
static uint8_t __attribute__((unused)) PROTOCOL_SticksMoved(uint8_t init)
|
||||||
|
{
|
||||||
|
#define STICK_MOVEMENT 15*(PPM_MAX-PPM_MIN)/100 // defines when the bind dialog should be interrupted (stick movement STICK_MOVEMENT %)
|
||||||
|
static uint16_t ele_start, ail_start;
|
||||||
|
uint16_t ele = Servo_data[ELEVATOR];//CHAN_ReadInput(MIXER_MapChannel(INP_ELEVATOR));
|
||||||
|
uint16_t ail = Servo_data[AILERON];//CHAN_ReadInput(MIXER_MapChannel(INP_AILERON));
|
||||||
|
if(init) {
|
||||||
|
ele_start = ele;
|
||||||
|
ail_start = ail;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t ele_diff = ele_start - ele;//abs(ele_start - ele);
|
||||||
|
uint16_t ail_diff = ail_start - ail;//abs(ail_start - ail);
|
||||||
|
return ((ele_diff + ail_diff) > STICK_MOVEMENT);//
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((unused)) build_data_packet(uint8_t upper)//
|
||||||
{
|
{
|
||||||
#if DSM2_NUM_CHANNELS==4
|
#if DSM2_NUM_CHANNELS==4
|
||||||
const uint8_t ch_map[] = {0, 1, 2, 3, 0xff, 0xff, 0xff}; //Guess
|
const uint8_t ch_map[] = {0, 1, 2, 3, 0xff, 0xff, 0xff}; //Guess
|
||||||
@ -187,13 +202,13 @@ static void build_data_packet(uint8_t upper)//
|
|||||||
if (sub_protocol==DSMX)
|
if (sub_protocol==DSMX)
|
||||||
{
|
{
|
||||||
packet[0] = cyrfmfg_id[2];
|
packet[0] = cyrfmfg_id[2];
|
||||||
packet[1] = cyrfmfg_id[3] + model;
|
packet[1] = cyrfmfg_id[3] + RX_num;
|
||||||
bits=11;
|
bits=11;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
packet[0] = (0xff ^ cyrfmfg_id[2]);
|
packet[0] = (0xff ^ cyrfmfg_id[2]);
|
||||||
packet[1] = (0xff ^ cyrfmfg_id[3]) + model;
|
packet[1] = (0xff ^ cyrfmfg_id[3]) + RX_num;
|
||||||
bits=10;
|
bits=10;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -252,23 +267,7 @@ static void build_data_packet(uint8_t upper)//
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t PROTOCOL_SticksMoved(uint8_t init)
|
static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel)
|
||||||
{
|
|
||||||
#define STICK_MOVEMENT 15*(PPM_MAX-PPM_MIN)/100 // defines when the bind dialog should be interrupted (stick movement STICK_MOVEMENT %)
|
|
||||||
static uint16_t ele_start, ail_start;
|
|
||||||
uint16_t ele = Servo_data[ELEVATOR];//CHAN_ReadInput(MIXER_MapChannel(INP_ELEVATOR));
|
|
||||||
uint16_t ail = Servo_data[AILERON];//CHAN_ReadInput(MIXER_MapChannel(INP_AILERON));
|
|
||||||
if(init) {
|
|
||||||
ele_start = ele;
|
|
||||||
ail_start = ail;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint16_t ele_diff = ele_start - ele;//abs(ele_start - ele);
|
|
||||||
uint16_t ail_diff = ail_start - ail;//abs(ail_start - ail);
|
|
||||||
return ((ele_diff + ail_diff) > STICK_MOVEMENT);//
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t get_pn_row(uint8_t channel)
|
|
||||||
{
|
{
|
||||||
return (sub_protocol == DSMX ? (channel - 2) % 5 : channel % 5);
|
return (sub_protocol == DSMX ? (channel - 2) % 5 : channel % 5);
|
||||||
}
|
}
|
||||||
@ -300,7 +299,7 @@ const uint8_t init_vals[][2] = {
|
|||||||
{CYRF_01_TX_LENGTH, 0x10}, //16byte packet
|
{CYRF_01_TX_LENGTH, 0x10}, //16byte packet
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cyrf_config()
|
static void __attribute__((unused)) cyrf_config()
|
||||||
{
|
{
|
||||||
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
|
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
|
||||||
CYRF_WriteRegister(init_vals[i][0], init_vals[i][1]);
|
CYRF_WriteRegister(init_vals[i][0], init_vals[i][1]);
|
||||||
@ -308,7 +307,7 @@ static void cyrf_config()
|
|||||||
CYRF_ConfigRFChannel(0x61);
|
CYRF_ConfigRFChannel(0x61);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initialize_bind_state()
|
static void __attribute__((unused)) initialize_bind_state()
|
||||||
{
|
{
|
||||||
const uint8_t pn_bind[] = { 0xc6,0x94,0x22,0xfe,0x48,0xe6,0x57,0x4e };
|
const uint8_t pn_bind[] = { 0xc6,0x94,0x22,0xfe,0x48,0xe6,0x57,0x4e };
|
||||||
uint8_t data_code[32];
|
uint8_t data_code[32];
|
||||||
@ -342,13 +341,13 @@ const uint8_t data_vals[][2] = {
|
|||||||
{CYRF_10_FRAMING_CFG, 0xea},
|
{CYRF_10_FRAMING_CFG, 0xea},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cyrf_configdata()
|
static void __attribute__((unused)) cyrf_configdata()
|
||||||
{
|
{
|
||||||
for(uint8_t i = 0; i < sizeof(data_vals) / 2; i++)
|
for(uint8_t i = 0; i < sizeof(data_vals) / 2; i++)
|
||||||
CYRF_WriteRegister(data_vals[i][0], data_vals[i][1]);
|
CYRF_WriteRegister(data_vals[i][0], data_vals[i][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_sop_data_crc()
|
static void __attribute__((unused)) set_sop_data_crc()
|
||||||
{
|
{
|
||||||
uint8_t pn_row = get_pn_row(hopping_frequency[chidx]);
|
uint8_t pn_row = get_pn_row(hopping_frequency[chidx]);
|
||||||
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[chidx], pn_row, sop_col, data_col);
|
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[chidx], pn_row, sop_col, data_col);
|
||||||
@ -363,7 +362,7 @@ static void set_sop_data_crc()
|
|||||||
crcidx = !crcidx;
|
crcidx = !crcidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calc_dsmx_channel()
|
static void __attribute__((unused)) calc_dsmx_channel()
|
||||||
{
|
{
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
|
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
|
||||||
@ -513,8 +512,6 @@ uint16_t initDsm2()
|
|||||||
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;//Ok
|
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;//Ok
|
||||||
data_col = 7 - sop_col;//ok
|
data_col = 7 - sop_col;//ok
|
||||||
|
|
||||||
model=MProtocol_id-MProtocol_id_master; // RxNum for serial or 0 for ppm
|
|
||||||
|
|
||||||
CYRF_SetTxRxMode(TX_EN);
|
CYRF_SetTxRxMode(TX_EN);
|
||||||
//
|
//
|
||||||
if(IS_AUTOBIND_FLAG_on)
|
if(IS_AUTOBIND_FLAG_on)
|
||||||
|
@ -66,7 +66,7 @@ uint8_t ch_idx;
|
|||||||
uint8_t use_fixed_id;
|
uint8_t use_fixed_id;
|
||||||
uint8_t failsafe_pkt;
|
uint8_t failsafe_pkt;
|
||||||
|
|
||||||
static void scramble_pkt()
|
static void __attribute__((unused)) scramble_pkt()
|
||||||
{
|
{
|
||||||
#ifdef NO_SCRAMBLE
|
#ifdef NO_SCRAMBLE
|
||||||
return;
|
return;
|
||||||
@ -77,7 +77,7 @@ static void scramble_pkt()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_pkt_suffix()
|
static void __attribute__((unused)) add_pkt_suffix()
|
||||||
{
|
{
|
||||||
uint8_t bind_state;
|
uint8_t bind_state;
|
||||||
if (use_fixed_id)
|
if (use_fixed_id)
|
||||||
@ -97,7 +97,7 @@ static void add_pkt_suffix()
|
|||||||
packet[15] = (fixed_id >> 16) & 0xff;
|
packet[15] = (fixed_id >> 16) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_beacon_pkt(uint8_t upper)
|
static void __attribute__((unused)) build_beacon_pkt(uint8_t upper)
|
||||||
{
|
{
|
||||||
packet[0] = ((DEVO_NUM_CHANNELS << 4) | 0x07);
|
packet[0] = ((DEVO_NUM_CHANNELS << 4) | 0x07);
|
||||||
// uint8_t enable = 0;
|
// uint8_t enable = 0;
|
||||||
@ -116,7 +116,7 @@ static void build_beacon_pkt(uint8_t upper)
|
|||||||
add_pkt_suffix();
|
add_pkt_suffix();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_bind_pkt()
|
static void __attribute__((unused)) build_bind_pkt()
|
||||||
{
|
{
|
||||||
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a;
|
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a;
|
||||||
packet[1] = bind_counter & 0xff;
|
packet[1] = bind_counter & 0xff;
|
||||||
@ -136,7 +136,7 @@ static void build_bind_pkt()
|
|||||||
packet[15] ^= cyrfmfg_id[2];
|
packet[15] ^= cyrfmfg_id[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_data_pkt()
|
static void __attribute__((unused)) build_data_pkt()
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
packet[0] = (DEVO_NUM_CHANNELS << 4) | (0x0b + ch_idx);
|
packet[0] = (DEVO_NUM_CHANNELS << 4) | (0x0b + ch_idx);
|
||||||
@ -161,7 +161,7 @@ static void build_data_pkt()
|
|||||||
add_pkt_suffix();
|
add_pkt_suffix();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cyrf_set_bound_sop_code()
|
static void __attribute__((unused)) cyrf_set_bound_sop_code()
|
||||||
{
|
{
|
||||||
/* crc == 0 isn't allowed, so use 1 if the math results in 0 */
|
/* crc == 0 isn't allowed, so use 1 if the math results in 0 */
|
||||||
uint8_t crc = (cyrfmfg_id[0] + (cyrfmfg_id[1] >> 6) + cyrfmfg_id[2]);
|
uint8_t crc = (cyrfmfg_id[0] + (cyrfmfg_id[1] >> 6) + cyrfmfg_id[2]);
|
||||||
@ -174,7 +174,7 @@ static void cyrf_set_bound_sop_code()
|
|||||||
CYRF_SetPower(0x08);
|
CYRF_SetPower(0x08);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cyrf_init()
|
static void __attribute__((unused)) cyrf_init()
|
||||||
{
|
{
|
||||||
/* Initialise CYRF chip */
|
/* Initialise CYRF chip */
|
||||||
CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x39);
|
CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x39);
|
||||||
@ -201,7 +201,7 @@ static void cyrf_init()
|
|||||||
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
|
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_radio_channels()
|
static void __attribute__((unused)) set_radio_channels()
|
||||||
{
|
{
|
||||||
//int i;
|
//int i;
|
||||||
CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80);
|
CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80);
|
||||||
@ -217,7 +217,7 @@ static void set_radio_channels()
|
|||||||
hopping_frequency[4] = hopping_frequency[1];
|
hopping_frequency[4] = hopping_frequency[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DEVO_BuildPacket()
|
static void __attribute__((unused)) DEVO_BuildPacket()
|
||||||
{
|
{
|
||||||
switch(phase)
|
switch(phase)
|
||||||
{
|
{
|
||||||
@ -302,7 +302,7 @@ uint16_t devo_callback()
|
|||||||
return 1200;
|
return 1200;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static void devo_bind()
|
/*static void __attribute__((unused)) devo_bind()
|
||||||
{
|
{
|
||||||
fixed_id = Model_fixed_id;
|
fixed_id = Model_fixed_id;
|
||||||
bind_counter = DEVO_BIND_COUNT;
|
bind_counter = DEVO_BIND_COUNT;
|
||||||
@ -311,7 +311,7 @@ uint16_t devo_callback()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void generate_fixed_id_bind(){
|
static void __attribute__((unused)) generate_fixed_id_bind(){
|
||||||
if(BIND_0){
|
if(BIND_0){
|
||||||
//randomSeed((uint32_t)analogRead(A6)<<10|analogRead(A7));//seed
|
//randomSeed((uint32_t)analogRead(A6)<<10|analogRead(A7));//seed
|
||||||
uint8_t txid[4];
|
uint8_t txid[4];
|
||||||
|
@ -23,14 +23,14 @@
|
|||||||
#define ESKY_PAYLOAD_SIZE 13
|
#define ESKY_PAYLOAD_SIZE 13
|
||||||
#define ESKY_PACKET_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short)
|
#define ESKY_PACKET_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short)
|
||||||
|
|
||||||
static void ESKY_set_data_address()
|
static void __attribute__((unused)) ESKY_set_data_address()
|
||||||
{
|
{
|
||||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address for regular packets
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address for regular packets
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 4);
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 4);
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ESKY_init(uint8_t bind)
|
static void __attribute__((unused)) ESKY_init(uint8_t bind)
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
@ -41,8 +41,8 @@ static void ESKY_init(uint8_t bind)
|
|||||||
if (bind)
|
if (bind)
|
||||||
{
|
{
|
||||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3-byte RX/TX address for bind packets
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3-byte RX/TX address for bind packets
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"x00x00x00", 3);
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x00\x00\x00", 3);
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"x00x00x00", 3);
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\x00\x00\x00", 3);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ESKY_set_data_address();
|
ESKY_set_data_address();
|
||||||
@ -60,7 +60,7 @@ static void ESKY_init(uint8_t bind)
|
|||||||
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ESKY_init2()
|
static void __attribute__((unused)) ESKY_init2()
|
||||||
{
|
{
|
||||||
NRF24L01_FlushTx();
|
NRF24L01_FlushTx();
|
||||||
packet_sent = 0;
|
packet_sent = 0;
|
||||||
@ -90,7 +90,7 @@ static void ESKY_init2()
|
|||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ESKY_send_packet(uint8_t bind)
|
static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
uint8_t rf_ch = 50; // bind channel
|
uint8_t rf_ch = 50; // bind channel
|
||||||
if (bind)
|
if (bind)
|
||||||
|
@ -73,7 +73,7 @@ uint8_t chanrow;
|
|||||||
uint8_t chancol;
|
uint8_t chancol;
|
||||||
uint8_t chanoffset;
|
uint8_t chanoffset;
|
||||||
|
|
||||||
static void 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, };
|
||||||
@ -148,7 +148,7 @@ static void flysky_apply_extension_flags()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void 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.
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
#include "iface_cc2500.h"
|
#include "iface_cc2500.h"
|
||||||
|
|
||||||
//##########Variables########
|
//##########Variables########
|
||||||
uint32_t state;
|
//uint32_t state;
|
||||||
uint8_t len;
|
//uint8_t len;
|
||||||
|
uint8_t telemetry_counter=0;
|
||||||
|
|
||||||
|
/*
|
||||||
enum {
|
enum {
|
||||||
FRSKY_BIND = 0,
|
FRSKY_BIND = 0,
|
||||||
FRSKY_BIND_DONE = 1000,
|
FRSKY_BIND_DONE = 1000,
|
||||||
@ -30,114 +32,9 @@ enum {
|
|||||||
FRSKY_DATA4,
|
FRSKY_DATA4,
|
||||||
FRSKY_DATA5
|
FRSKY_DATA5
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
uint16_t initFrSky_2way()
|
static void __attribute__((unused)) frsky2way_init(uint8_t bind)
|
||||||
{
|
|
||||||
if(IS_AUTOBIND_FLAG_on)
|
|
||||||
{
|
|
||||||
frsky2way_init(1);
|
|
||||||
state = FRSKY_BIND;//
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
frsky2way_init(0);
|
|
||||||
state = FRSKY_DATA2;
|
|
||||||
}
|
|
||||||
return 10000;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ReadFrSky_2way()
|
|
||||||
{
|
|
||||||
if (state < FRSKY_BIND_DONE)
|
|
||||||
{
|
|
||||||
frsky2way_build_bind_packet();
|
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
|
||||||
cc2500_writeReg(CC2500_0A_CHANNR, 0x00);
|
|
||||||
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
|
|
||||||
cc2500_strobe(CC2500_SFRX);//0x3A
|
|
||||||
cc2500_writeFifo(packet, packet[0]+1);
|
|
||||||
state++;
|
|
||||||
return 9000;
|
|
||||||
}
|
|
||||||
if (state == FRSKY_BIND_DONE)
|
|
||||||
{
|
|
||||||
state = FRSKY_DATA2;
|
|
||||||
frsky2way_init(0);
|
|
||||||
counter = 0;
|
|
||||||
BIND_DONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (state == FRSKY_DATA5)
|
|
||||||
{
|
|
||||||
cc2500_strobe(CC2500_SRX);//0x34 RX enable
|
|
||||||
state = FRSKY_DATA1;
|
|
||||||
return 9200;
|
|
||||||
}
|
|
||||||
counter = (counter + 1) % 188;
|
|
||||||
if (state == FRSKY_DATA4)
|
|
||||||
{ //telemetry receive
|
|
||||||
CC2500_SetTxRxMode(RX_EN);
|
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
|
||||||
cc2500_writeReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
|
|
||||||
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
|
|
||||||
state++;
|
|
||||||
return 1300;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (state == FRSKY_DATA1)
|
|
||||||
{
|
|
||||||
len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
|
||||||
if (len)//20 bytes
|
|
||||||
{
|
|
||||||
cc2500_readFifo(pkt, len); //received telemetry packets
|
|
||||||
#if defined(TELEMETRY)
|
|
||||||
//parse telemetry packet here
|
|
||||||
check_telemetry(pkt,len); //check if valid telemetry packets and buffer them.
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
CC2500_SetTxRxMode(TX_EN);
|
|
||||||
CC2500_SetPower(); // Set tx_power
|
|
||||||
}
|
|
||||||
cc2500_strobe(CC2500_SIDLE);
|
|
||||||
cc2500_writeReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
|
|
||||||
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
|
|
||||||
cc2500_strobe(CC2500_SFRX);
|
|
||||||
frsky2way_data_frame();
|
|
||||||
cc2500_writeFifo(packet, packet[0]+1);
|
|
||||||
state++;
|
|
||||||
}
|
|
||||||
return state == FRSKY_DATA4 ? 7500 : 9000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(TELEMETRY)
|
|
||||||
static void check_telemetry(uint8_t *pkt,uint8_t len)
|
|
||||||
{
|
|
||||||
if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3)
|
|
||||||
{//only packets with the required id and packet length
|
|
||||||
for(uint8_t i=3;i<6;i++)
|
|
||||||
pktt[i]=0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (uint8_t i=3;i<len;i++)
|
|
||||||
pktt[i]=pkt[i];
|
|
||||||
telemetry_link=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void compute_RSSIdbm(){
|
|
||||||
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5);
|
|
||||||
if(pktt[len-2] >=128)
|
|
||||||
RSSI_dBm -= 82;
|
|
||||||
else
|
|
||||||
RSSI_dBm += 65;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void frsky2way_init(uint8_t bind)
|
|
||||||
{
|
{
|
||||||
// Configure cc2500 for tx mode
|
// Configure cc2500 for tx mode
|
||||||
CC2500_Reset();
|
CC2500_Reset();
|
||||||
@ -151,7 +48,7 @@ static void frsky2way_init(uint8_t bind)
|
|||||||
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x05);
|
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x05);
|
||||||
cc2500_writeReg(CC2500_3E_PATABLE, 0xff);
|
cc2500_writeReg(CC2500_3E_PATABLE, 0xff);
|
||||||
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x08);
|
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x08);
|
||||||
cc2500_writeReg(CC2500_0C_FSCTRL0, fine);
|
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
|
||||||
//base freq FREQ = 0x5C7627 (F = 2404MHz)
|
//base freq FREQ = 0x5C7627 (F = 2404MHz)
|
||||||
cc2500_writeReg(CC2500_0D_FREQ2, 0x5c);
|
cc2500_writeReg(CC2500_0D_FREQ2, 0x5c);
|
||||||
cc2500_writeReg(CC2500_0E_FREQ1, 0x76);
|
cc2500_writeReg(CC2500_0E_FREQ1, 0x76);
|
||||||
@ -196,7 +93,7 @@ static void frsky2way_init(uint8_t bind)
|
|||||||
//#######END INIT########
|
//#######END INIT########
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t get_chan_num(uint16_t idx)
|
static uint8_t __attribute__((unused)) get_chan_num(uint16_t idx)
|
||||||
{
|
{
|
||||||
uint8_t ret = (idx * 0x1e) % 0xeb;
|
uint8_t ret = (idx * 0x1e) % 0xeb;
|
||||||
if(idx == 3 || idx == 23 || idx == 47)
|
if(idx == 3 || idx == 23 || idx == 47)
|
||||||
@ -206,7 +103,7 @@ static uint8_t get_chan_num(uint16_t idx)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frsky2way_build_bind_packet()
|
static void __attribute__((unused)) frsky2way_build_bind_packet()
|
||||||
{
|
{
|
||||||
//11 03 01 d7 2d 00 00 1e 3c 5b 78 00 00 00 00 00 00 01
|
//11 03 01 d7 2d 00 00 1e 3c 5b 78 00 00 00 00 00 00 01
|
||||||
//11 03 01 19 3e 00 02 8e 2f bb 5c 00 00 00 00 00 00 01
|
//11 03 01 19 3e 00 02 8e 2f bb 5c 00 00 00 00 00 00 01
|
||||||
@ -231,9 +128,9 @@ static void frsky2way_build_bind_packet()
|
|||||||
packet[17] = 0x01;
|
packet[17] = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t telemetry_counter=0;
|
|
||||||
|
|
||||||
static void frsky2way_data_frame()
|
|
||||||
|
static void __attribute__((unused)) frsky2way_data_frame()
|
||||||
{//pachet[4] is telemetry user frame counter(hub)
|
{//pachet[4] is telemetry user frame counter(hub)
|
||||||
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
|
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
|
||||||
//11 57 12 00 00 01 f2 f2 f2 f2 06 06 ca ca ca ca 18 18
|
//11 57 12 00 00 01 f2 f2 f2 f2 06 06 ca ca ca ca 18 18
|
||||||
@ -241,7 +138,8 @@ static void frsky2way_data_frame()
|
|||||||
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] = counter;//
|
packet[3] = counter;//
|
||||||
packet[4] = pkt[6]?(telemetry_counter++)%32:0;
|
packet[4]=telemetry_counter;
|
||||||
|
|
||||||
packet[5] = 0x01;
|
packet[5] = 0x01;
|
||||||
//
|
//
|
||||||
packet[10] = 0;
|
packet[10] = 0;
|
||||||
@ -265,4 +163,102 @@ static void frsky2way_data_frame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t initFrSky_2way()
|
||||||
|
{
|
||||||
|
if(IS_AUTOBIND_FLAG_on)
|
||||||
|
{
|
||||||
|
frsky2way_init(1);
|
||||||
|
state = FRSKY_BIND;//
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frsky2way_init(0);
|
||||||
|
state = FRSKY_DATA2;
|
||||||
|
}
|
||||||
|
return 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(TELEMETRY)
|
||||||
|
static void __attribute__((unused)) check_telemetry(uint8_t *pkt,uint8_t len)
|
||||||
|
{
|
||||||
|
if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3)
|
||||||
|
{//only packets with the required id and packet length
|
||||||
|
for(uint8_t i=3;i<6;i++)
|
||||||
|
pktt[i]=0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (uint8_t i=3;i<len;i++)
|
||||||
|
pktt[i]=pkt[i];
|
||||||
|
telemetry_link=1;
|
||||||
|
if(pktt[6]>0)
|
||||||
|
telemetry_counter=(telemetry_counter+1)%32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t ReadFrSky_2way()
|
||||||
|
{
|
||||||
|
if (state < FRSKY_BIND_DONE)
|
||||||
|
{
|
||||||
|
frsky2way_build_bind_packet();
|
||||||
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
|
cc2500_writeReg(CC2500_0A_CHANNR, 0x00);
|
||||||
|
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
|
||||||
|
cc2500_strobe(CC2500_SFRX);//0x3A
|
||||||
|
cc2500_writeFifo(packet, packet[0]+1);
|
||||||
|
state++;
|
||||||
|
return 9000;
|
||||||
|
}
|
||||||
|
if (state == FRSKY_BIND_DONE)
|
||||||
|
{
|
||||||
|
state = FRSKY_DATA2;
|
||||||
|
frsky2way_init(0);
|
||||||
|
counter = 0;
|
||||||
|
BIND_DONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (state == FRSKY_DATA5)
|
||||||
|
{
|
||||||
|
cc2500_strobe(CC2500_SRX);//0x34 RX enable
|
||||||
|
state = FRSKY_DATA1;
|
||||||
|
return 9200;
|
||||||
|
}
|
||||||
|
counter = (counter + 1) % 188;
|
||||||
|
if (state == FRSKY_DATA4)
|
||||||
|
{ //telemetry receive
|
||||||
|
CC2500_SetTxRxMode(RX_EN);
|
||||||
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
|
cc2500_writeReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
|
||||||
|
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
|
||||||
|
state++;
|
||||||
|
return 1300;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (state == FRSKY_DATA1)
|
||||||
|
{
|
||||||
|
len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||||
|
if (len<=MAX_PKT)//27 bytes
|
||||||
|
{
|
||||||
|
cc2500_readFifo(pkt, len); //received telemetry packets
|
||||||
|
#if defined(TELEMETRY)
|
||||||
|
//parse telemetry packet here
|
||||||
|
check_telemetry(pkt,len); //check if valid telemetry packets and buffer them.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
CC2500_SetTxRxMode(TX_EN);
|
||||||
|
CC2500_SetPower(); // Set tx_power
|
||||||
|
}
|
||||||
|
cc2500_strobe(CC2500_SIDLE);
|
||||||
|
cc2500_writeReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
|
||||||
|
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
|
||||||
|
cc2500_strobe(CC2500_SFRX);
|
||||||
|
frsky2way_data_frame();
|
||||||
|
cc2500_writeFifo(packet, packet[0]+1);
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
return state == FRSKY_DATA4 ? 7500 : 9000;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,21 +18,21 @@
|
|||||||
|
|
||||||
#include "iface_nrf24l01.h"
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
#define BIND_COUNT 1000
|
#define HISKY_BIND_COUNT 1000
|
||||||
#define TXID_SIZE 5
|
#define HISKY_TXID_SIZE 5
|
||||||
#define FREQUENCE_NUM 20
|
#define HISKY_FREQUENCE_NUM 20
|
||||||
//
|
//
|
||||||
uint8_t bind_buf_arry[4][10];
|
uint8_t bind_buf_arry[4][10];
|
||||||
|
|
||||||
// HiSky protocol uses TX id as an address for nRF24L01, and uses frequency hopping sequence
|
// HiSky protocol uses TX id as an address for nRF24L01, and uses frequency hopping sequence
|
||||||
// which does not depend on this id and is passed explicitly in binding sequence. So we are free
|
// which does not depend on this id and is passed explicitly in binding sequence. So we are free
|
||||||
// to generate this sequence as we wish. It should be in the range [02..77]
|
// to generate this sequence as we wish. It should be in the range [02..77]
|
||||||
static void calc_fh_channels(uint32_t seed)
|
static void __attribute__((unused)) calc_fh_channels()
|
||||||
{
|
{
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
uint32_t rnd = seed;
|
uint32_t rnd = MProtocol_id;
|
||||||
|
|
||||||
while (idx < FREQUENCE_NUM)
|
while (idx < HISKY_FREQUENCE_NUM)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t count_2_26 = 0, count_27_50 = 0, count_51_74 = 0;
|
uint8_t count_2_26 = 0, count_27_50 = 0, count_51_74 = 0;
|
||||||
@ -41,7 +41,7 @@ static void calc_fh_channels(uint32_t seed)
|
|||||||
// Use least-significant byte. 73 is prime, so channels 76..77 are unused
|
// Use least-significant byte. 73 is prime, so channels 76..77 are unused
|
||||||
uint8_t next_ch = ((rnd >> 8) % 73) + 2;
|
uint8_t next_ch = ((rnd >> 8) % 73) + 2;
|
||||||
// Keep the distance 2 between the channels - either odd or even
|
// Keep the distance 2 between the channels - either odd or even
|
||||||
if (((next_ch ^ (uint8_t)seed) & 0x01 )== 0)
|
if (((next_ch ^ (uint8_t)rx_tx_addr[3]) & 0x01 )== 0)
|
||||||
continue;
|
continue;
|
||||||
// Check that it's not duplicated and spread uniformly
|
// Check that it's not duplicated and spread uniformly
|
||||||
for (i = 0; i < idx; i++) {
|
for (i = 0; i < idx; i++) {
|
||||||
@ -61,7 +61,7 @@ static void calc_fh_channels(uint32_t seed)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_binding_packet(void)
|
static void __attribute__((unused)) build_binding_packet(void)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint16_t sum=0;
|
uint16_t sum=0;
|
||||||
@ -95,7 +95,7 @@ static void build_binding_packet(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hisky_init()
|
static void __attribute__((unused)) hisky_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ static void hisky_init()
|
|||||||
|
|
||||||
// HiSky channel sequence: AILE ELEV THRO RUDD GEAR PITCH, channel data value is from 0 to 1000
|
// HiSky channel sequence: AILE ELEV THRO RUDD GEAR PITCH, channel data value is from 0 to 1000
|
||||||
// Channel 7 - Gyro mode, 0 - 6 axis, 3 - 3 axis
|
// Channel 7 - Gyro mode, 0 - 6 axis, 3 - 3 axis
|
||||||
static void build_ch_data()
|
static void __attribute__((unused)) build_ch_data()
|
||||||
{
|
{
|
||||||
uint16_t temp;
|
uint16_t temp;
|
||||||
uint8_t i,j;
|
uint8_t i,j;
|
||||||
@ -144,10 +144,14 @@ uint16_t hisky_cb()
|
|||||||
NRF24L01_SetPower();
|
NRF24L01_SetPower();
|
||||||
phase=2;
|
phase=2;
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
if (! bind_counter)
|
||||||
|
NRF24L01_WritePayload(packet,10); // 2 packets per 5ms
|
||||||
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
phase=6;
|
phase=6;
|
||||||
break;
|
break;
|
||||||
case 7: // build packet and send failsafe every 100ms
|
case 7: // build packet with failsafe every 100ms
|
||||||
convert_channel_HK310(hopping_frequency_no!=0?RUDDER:AUX2,&packet[0],&packet[1]);
|
convert_channel_HK310(hopping_frequency_no!=0?RUDDER:AUX2,&packet[0],&packet[1]);
|
||||||
convert_channel_HK310(hopping_frequency_no!=0?THROTTLE:AUX3,&packet[2],&packet[3]);
|
convert_channel_HK310(hopping_frequency_no!=0?THROTTLE:AUX3,&packet[2],&packet[3]);
|
||||||
convert_channel_HK310(hopping_frequency_no!=0?AUX1:AUX4,&packet[4],&packet[5]);
|
convert_channel_HK310(hopping_frequency_no!=0?AUX1:AUX4,&packet[4],&packet[5]);
|
||||||
@ -195,7 +199,7 @@ uint16_t hisky_cb()
|
|||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
||||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||||
hopping_frequency_no++;
|
hopping_frequency_no++;
|
||||||
if (hopping_frequency_no >= FREQUENCE_NUM)
|
if (hopping_frequency_no >= HISKY_FREQUENCE_NUM)
|
||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
@ -213,15 +217,19 @@ uint16_t hisky_cb()
|
|||||||
return 1000; // send 1 binding packet and 1 data packet per 9ms
|
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 __attribute__((unused)) initialize_tx_id()
|
||||||
static void initialize_tx_id()
|
|
||||||
{
|
{
|
||||||
//Generate frequency hopping table
|
//Generate frequency hopping table
|
||||||
if(sub_protocol==HK310)
|
if(sub_protocol==HK310)
|
||||||
for(uint8_t i=0;i<FREQUENCE_NUM;i++)
|
{
|
||||||
hopping_frequency[i]=i; // Sequential order hop channels...
|
// for HiSky surface protocol, the transmitter always generates hop channels in sequential order.
|
||||||
|
// The transmitter only generates the first hop channel between 0 and 49. So the channel range is from 0 to 69.
|
||||||
|
hopping_frequency_no=rx_tx_addr[0]%50;
|
||||||
|
for(uint8_t i=0;i<HISKY_FREQUENCE_NUM;i++)
|
||||||
|
hopping_frequency[i]=hopping_frequency_no++; // Sequential order hop channels...
|
||||||
|
}
|
||||||
else
|
else
|
||||||
calc_fh_channels(MProtocol_id);
|
calc_fh_channels();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t initHiSky()
|
uint16_t initHiSky()
|
||||||
@ -234,7 +242,7 @@ uint16_t initHiSky()
|
|||||||
binding_idx = 0;
|
binding_idx = 0;
|
||||||
|
|
||||||
if(IS_AUTOBIND_FLAG_on)
|
if(IS_AUTOBIND_FLAG_on)
|
||||||
bind_counter = BIND_COUNT;
|
bind_counter = HISKY_BIND_COUNT;
|
||||||
else
|
else
|
||||||
bind_counter = 0;
|
bind_counter = 0;
|
||||||
return 1000;
|
return 1000;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
// compatible with Hubsan H102D, H107/L/C/D and H107P/C+/D+
|
||||||
// Last sync with hexfet new_protocols/hubsan_a7105.c dated 2015-12-11
|
// Last sync with hexfet new_protocols/hubsan_a7105.c dated 2015-12-11
|
||||||
|
|
||||||
#if defined(HUBSAN_A7105_INO)
|
#if defined(HUBSAN_A7105_INO)
|
||||||
@ -55,7 +56,7 @@ enum {
|
|||||||
};
|
};
|
||||||
#define WAIT_WRITE 0x80
|
#define WAIT_WRITE 0x80
|
||||||
|
|
||||||
static void update_crc()
|
static void __attribute__((unused)) hubsan_update_crc()
|
||||||
{
|
{
|
||||||
uint8_t sum = 0;
|
uint8_t sum = 0;
|
||||||
for(uint8_t i = 0; i < 15; i++)
|
for(uint8_t i = 0; i < 15; i++)
|
||||||
@ -63,7 +64,7 @@ static void update_crc()
|
|||||||
packet[15] = (256 - (sum % 256)) & 0xFF;
|
packet[15] = (256 - (sum % 256)) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hubsan_build_bind_packet(uint8_t bind_state)
|
static void __attribute__((unused)) hubsan_build_bind_packet(uint8_t bind_state)
|
||||||
{
|
{
|
||||||
static uint8_t handshake_counter;
|
static uint8_t handshake_counter;
|
||||||
if(phase < BIND_7)
|
if(phase < BIND_7)
|
||||||
@ -98,14 +99,14 @@ static void hubsan_build_bind_packet(uint8_t bind_state)
|
|||||||
if(phase == BIND_7)
|
if(phase == BIND_7)
|
||||||
packet[2] = handshake_counter++;
|
packet[2] = handshake_counter++;
|
||||||
}
|
}
|
||||||
update_crc();
|
hubsan_update_crc();
|
||||||
}
|
}
|
||||||
|
|
||||||
//cc : throttle observed range: 0x00 - 0xFF (smaller is down)
|
//cc : throttle observed range: 0x00 - 0xFF (smaller is down)
|
||||||
//ee : rudder observed range: 0x34 - 0xcc (smaller is right)52-204-60%
|
//ee : rudder observed range: 0x34 - 0xcc (smaller is right)52-204-60%
|
||||||
//gg : elevator observed range: 0x3e - 0xbc (smaller is up)62-188 -50%
|
//gg : elevator observed range: 0x3e - 0xbc (smaller is up)62-188 -50%
|
||||||
//ii : aileron observed range: 0x45 - 0xc3 (smaller is right)69-195-50%
|
//ii : aileron observed range: 0x45 - 0xc3 (smaller is right)69-195-50%
|
||||||
static void hubsan_build_packet()
|
static void __attribute__((unused)) hubsan_build_packet()
|
||||||
{
|
{
|
||||||
static uint8_t vtx_freq = 0;
|
static uint8_t vtx_freq = 0;
|
||||||
memset(packet, 0, 16);
|
memset(packet, 0, 16);
|
||||||
@ -176,7 +177,7 @@ static void hubsan_build_packet()
|
|||||||
packet_count++;
|
packet_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_crc();
|
hubsan_update_crc();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(TELEMETRY)
|
#if defined(TELEMETRY)
|
||||||
@ -192,8 +193,10 @@ static void hubsan_build_packet()
|
|||||||
|
|
||||||
uint16_t ReadHubsan()
|
uint16_t ReadHubsan()
|
||||||
{
|
{
|
||||||
static uint8_t txState=0;
|
#if defined(TELEMETRY)
|
||||||
static uint8_t rfMode=0;
|
static uint8_t rfMode=0;
|
||||||
|
#endif
|
||||||
|
static uint8_t txState=0;
|
||||||
static uint8_t bind_count=0;
|
static uint8_t bind_count=0;
|
||||||
uint16_t delay;
|
uint16_t delay;
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
@ -276,7 +279,9 @@ uint16_t ReadHubsan()
|
|||||||
case DATA_4:
|
case DATA_4:
|
||||||
case DATA_5:
|
case DATA_5:
|
||||||
if( txState == 0) { // send packet
|
if( txState == 0) { // send packet
|
||||||
|
#if defined(TELEMETRY)
|
||||||
rfMode = A7105_TX;
|
rfMode = A7105_TX;
|
||||||
|
#endif
|
||||||
if( phase == DATA_1)
|
if( phase == DATA_1)
|
||||||
A7105_SetPower(); //Keep transmit power in sync
|
A7105_SetPower(); //Keep transmit power in sync
|
||||||
hubsan_build_packet();
|
hubsan_build_packet();
|
||||||
|
@ -70,6 +70,205 @@ enum {
|
|||||||
KN_FLAG_GYROR = 0x80 // Always 0 so far
|
KN_FLAG_GYROR = 0x80 // Always 0 so far
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// This function init 24L01 regs and packet data for binding
|
||||||
|
// Send tx address, hopping table (for Wl Toys), and data rate to the KN receiver during binding.
|
||||||
|
// It seems that KN can remember these parameters, no binding needed after power up.
|
||||||
|
// Bind uses fixed TX address "KNDZK", 1 Mbps data rate and channel 83
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
static void __attribute__((unused)) kn_bind_init()
|
||||||
|
{
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"KNDZK", 5);
|
||||||
|
packet[0] = 'K';
|
||||||
|
packet[1] = 'N';
|
||||||
|
packet[2] = 'D';
|
||||||
|
packet[3] = 'Z';
|
||||||
|
//Use first four bytes of tx_addr
|
||||||
|
packet[4] = rx_tx_addr[0];
|
||||||
|
packet[5] = rx_tx_addr[1];
|
||||||
|
packet[6] = rx_tx_addr[2];
|
||||||
|
packet[7] = rx_tx_addr[3];
|
||||||
|
|
||||||
|
if(sub_protocol==WLTOYS)
|
||||||
|
{
|
||||||
|
packet[8] = hopping_frequency[0];
|
||||||
|
packet[9] = hopping_frequency[1];
|
||||||
|
packet[10] = hopping_frequency[2];
|
||||||
|
packet[11] = hopping_frequency[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
packet[8] = 0x00;
|
||||||
|
packet[9] = 0x00;
|
||||||
|
packet[10] = 0x00;
|
||||||
|
packet[11] = 0x00;
|
||||||
|
}
|
||||||
|
packet[12] = 0x00;
|
||||||
|
packet[13] = 0x00;
|
||||||
|
packet[14] = 0x00;
|
||||||
|
packet[15] = 0x01; //(USE1MBPS_YES) ? 0x01 : 0x00;
|
||||||
|
|
||||||
|
//Set RF channel
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 83);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Update control data to be sent
|
||||||
|
// Do it once per frequency, so the same values will be sent 4 times
|
||||||
|
// KN uses 4 10-bit data channels plus a 8-bit switch channel
|
||||||
|
//
|
||||||
|
// The packet[0] is used for pitch/throttle, the relation is hard coded, not changeable.
|
||||||
|
// We can change the throttle/pitch range though.
|
||||||
|
//
|
||||||
|
// How to use trim? V977 stock controller can trim 6-axis mode to eliminate the drift.
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
static void __attribute__((unused)) kn_update_packet_control_data()
|
||||||
|
{
|
||||||
|
uint16_t value;
|
||||||
|
value = convert_channel_10b(THROTTLE);
|
||||||
|
packet[0] = (value >> 8) & 0xFF;
|
||||||
|
packet[1] = value & 0xFF;
|
||||||
|
value = convert_channel_10b(AILERON);
|
||||||
|
packet[2] = (value >> 8) & 0xFF;
|
||||||
|
packet[3] = value & 0xFF;
|
||||||
|
value = convert_channel_10b(ELEVATOR);
|
||||||
|
packet[4] = (value >> 8) & 0xFF;
|
||||||
|
packet[5] = value & 0xFF;
|
||||||
|
value = convert_channel_10b(RUDDER);
|
||||||
|
packet[6] = (value >> 8) & 0xFF;
|
||||||
|
packet[7] = value & 0xFF;
|
||||||
|
// Trims, middle is 0x64 (100) range 0-200
|
||||||
|
packet[8] = convert_channel_8b_scale(AUX5,0,200); // 0x64; // T
|
||||||
|
packet[9] = convert_channel_8b_scale(AUX6,0,200); // 0x64; // A
|
||||||
|
packet[10] = convert_channel_8b_scale(AUX7,0,200); // 0x64; // E
|
||||||
|
packet[11] = 0x64; // R
|
||||||
|
|
||||||
|
flags=0;
|
||||||
|
if (Servo_data[AUX1] > PPM_SWITCH)
|
||||||
|
flags = KN_FLAG_DR;
|
||||||
|
if (Servo_data[AUX2] > PPM_SWITCH)
|
||||||
|
flags |= KN_FLAG_TH;
|
||||||
|
if (Servo_data[AUX3] > PPM_SWITCH)
|
||||||
|
flags |= KN_FLAG_IDLEUP;
|
||||||
|
if (Servo_data[AUX4] > PPM_SWITCH)
|
||||||
|
flags |= KN_FLAG_GYRO3;
|
||||||
|
|
||||||
|
packet[12] = flags;
|
||||||
|
|
||||||
|
packet[13] = 0x00;
|
||||||
|
if(sub_protocol==WLTOYS)
|
||||||
|
packet[13] = (packet_sent << 5) | (hopping_frequency_no << 2);
|
||||||
|
|
||||||
|
packet[14] = 0x00;
|
||||||
|
packet[15] = 0x00;
|
||||||
|
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// This function generate RF TX packet address
|
||||||
|
// V977 can remember the binding parameters; we do not need rebind when power up.
|
||||||
|
// This requires the address must be repeatable for a specific RF ID at power up.
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
static void __attribute__((unused)) kn_calculate_tx_addr()
|
||||||
|
{
|
||||||
|
if(sub_protocol==FEILUN)
|
||||||
|
{
|
||||||
|
uint8_t addr2;
|
||||||
|
// Generate TXID with sum of minimum 256 and maximum 256+MAX_RF_CHANNEL-32
|
||||||
|
rx_tx_addr[1] = 1 + rx_tx_addr[0] % (KN_MAX_RF_CHANNEL-33);
|
||||||
|
addr2 = 1 + rx_tx_addr[2] % (KN_MAX_RF_CHANNEL-33);
|
||||||
|
if ((uint16_t)(rx_tx_addr[0] + rx_tx_addr[1]) < 256)
|
||||||
|
rx_tx_addr[2] = addr2;
|
||||||
|
else
|
||||||
|
rx_tx_addr[2] = 0x00;
|
||||||
|
rx_tx_addr[3] = 0x00;
|
||||||
|
while((uint16_t)(rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2] + rx_tx_addr[3]) < 257)
|
||||||
|
rx_tx_addr[3] += addr2;
|
||||||
|
}
|
||||||
|
//The 5th byte is a constant, must be 'K'
|
||||||
|
rx_tx_addr[4] = 'K';
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// This function generates "random" RF hopping frequency channel numbers.
|
||||||
|
// These numbers must be repeatable for a specific seed
|
||||||
|
// The generated number range is from 0 to MAX_RF_CHANNEL. No repeat or adjacent numbers
|
||||||
|
//
|
||||||
|
// For Feilun variant, the channels are calculated from TXID, and since only 2 channels are used
|
||||||
|
// we copy them to fill up to MAX_RF_CHANNEL
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
static void __attribute__((unused)) kn_calculate_freqency_hopping_channels()
|
||||||
|
{
|
||||||
|
if(sub_protocol==WLTOYS)
|
||||||
|
{
|
||||||
|
uint8_t idx = 0;
|
||||||
|
uint32_t rnd = MProtocol_id;
|
||||||
|
while (idx < KN_RF_CH_COUNT)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
|
||||||
|
|
||||||
|
// Use least-significant byte. 73 is prime, so channels 76..77 are unused
|
||||||
|
uint8_t next_ch = ((rnd >> 8) % KN_MAX_RF_CHANNEL) + 2;
|
||||||
|
// Keep the distance 2 between the channels - either odd or even
|
||||||
|
if (((next_ch ^ MProtocol_id) & 0x01 )== 0)
|
||||||
|
continue;
|
||||||
|
// Check that it's not duplicate and spread uniformly
|
||||||
|
for (i = 0; i < idx; i++)
|
||||||
|
if(hopping_frequency[i] == next_ch)
|
||||||
|
break;
|
||||||
|
if (i != idx)
|
||||||
|
continue;
|
||||||
|
hopping_frequency[idx++] = next_ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{//FEILUN
|
||||||
|
hopping_frequency[0] = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2] + rx_tx_addr[3]; // - 256; ???
|
||||||
|
hopping_frequency[1] = hopping_frequency[0] + 32;
|
||||||
|
hopping_frequency[2] = hopping_frequency[0];
|
||||||
|
hopping_frequency[3] = hopping_frequency[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// This function setup 24L01
|
||||||
|
// V977 uses one way communication, receiving only. 24L01 RX is never enabled.
|
||||||
|
// V977 needs payload length in the packet. We should configure 24L01 to enable Packet Control Field(PCF)
|
||||||
|
// Some RX reg settings are actually for enable PCF
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
static void __attribute__((unused)) kn_init()
|
||||||
|
{
|
||||||
|
kn_calculate_tx_addr();
|
||||||
|
kn_calculate_freqency_hopping_channels();
|
||||||
|
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
|
||||||
|
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, 0x03); // 5-byte RX/TX address
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||||
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // 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 to enable PCF
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL));
|
||||||
|
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
// Turn radio power on
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
NRF24L01_SetBitrate(NRF24L01_BR_1M); //USE1MBPS_YES ? NRF24L01_BR_1M : NRF24L01_BR_250K;
|
||||||
|
}
|
||||||
|
|
||||||
//================================================================================================
|
//================================================================================================
|
||||||
// Private Functions
|
// Private Functions
|
||||||
//================================================================================================
|
//================================================================================================
|
||||||
@ -145,202 +344,4 @@ uint16_t kn_callback()
|
|||||||
return packet_period;
|
return packet_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
// This function init 24L01 regs and packet data for binding
|
|
||||||
// Send tx address, hopping table (for Wl Toys), and data rate to the KN receiver during binding.
|
|
||||||
// It seems that KN can remember these parameters, no binding needed after power up.
|
|
||||||
// Bind uses fixed TX address "KNDZK", 1 Mbps data rate and channel 83
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
static void kn_bind_init()
|
|
||||||
{
|
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"KNDZK", 5);
|
|
||||||
packet[0] = 'K';
|
|
||||||
packet[1] = 'N';
|
|
||||||
packet[2] = 'D';
|
|
||||||
packet[3] = 'Z';
|
|
||||||
//Use first four bytes of tx_addr
|
|
||||||
packet[4] = rx_tx_addr[0];
|
|
||||||
packet[5] = rx_tx_addr[1];
|
|
||||||
packet[6] = rx_tx_addr[2];
|
|
||||||
packet[7] = rx_tx_addr[3];
|
|
||||||
|
|
||||||
if(sub_protocol==WLTOYS)
|
|
||||||
{
|
|
||||||
packet[8] = hopping_frequency[0];
|
|
||||||
packet[9] = hopping_frequency[1];
|
|
||||||
packet[10] = hopping_frequency[2];
|
|
||||||
packet[11] = hopping_frequency[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
packet[8] = 0x00;
|
|
||||||
packet[9] = 0x00;
|
|
||||||
packet[10] = 0x00;
|
|
||||||
packet[11] = 0x00;
|
|
||||||
}
|
|
||||||
packet[12] = 0x00;
|
|
||||||
packet[13] = 0x00;
|
|
||||||
packet[14] = 0x00;
|
|
||||||
packet[15] = 0x01; //(USE1MBPS_YES) ? 0x01 : 0x00;
|
|
||||||
|
|
||||||
//Set RF channel
|
|
||||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 83);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
// Update control data to be sent
|
|
||||||
// Do it once per frequency, so the same values will be sent 4 times
|
|
||||||
// KN uses 4 10-bit data channels plus a 8-bit switch channel
|
|
||||||
//
|
|
||||||
// The packet[0] is used for pitch/throttle, the relation is hard coded, not changeable.
|
|
||||||
// We can change the throttle/pitch range though.
|
|
||||||
//
|
|
||||||
// How to use trim? V977 stock controller can trim 6-axis mode to eliminate the drift.
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
static void kn_update_packet_control_data()
|
|
||||||
{
|
|
||||||
uint16_t value;
|
|
||||||
value = convert_channel_10b(THROTTLE);
|
|
||||||
packet[0] = (value >> 8) & 0xFF;
|
|
||||||
packet[1] = value & 0xFF;
|
|
||||||
value = convert_channel_10b(AILERON);
|
|
||||||
packet[2] = (value >> 8) & 0xFF;
|
|
||||||
packet[3] = value & 0xFF;
|
|
||||||
value = convert_channel_10b(ELEVATOR);
|
|
||||||
packet[4] = (value >> 8) & 0xFF;
|
|
||||||
packet[5] = value & 0xFF;
|
|
||||||
value = convert_channel_10b(RUDDER);
|
|
||||||
packet[6] = (value >> 8) & 0xFF;
|
|
||||||
packet[7] = value & 0xFF;
|
|
||||||
// Trims, middle is 0x64 (100) range 0-200
|
|
||||||
packet[8] = convert_channel_8b_scale(AUX5,0,200); // 0x64; // T
|
|
||||||
packet[9] = convert_channel_8b_scale(AUX6,0,200); // 0x64; // A
|
|
||||||
packet[10] = convert_channel_8b_scale(AUX7,0,200); // 0x64; // E
|
|
||||||
packet[11] = 0x64; // R
|
|
||||||
|
|
||||||
flags=0;
|
|
||||||
if (Servo_data[AUX1] > PPM_SWITCH)
|
|
||||||
flags = KN_FLAG_DR;
|
|
||||||
if (Servo_data[AUX2] > PPM_SWITCH)
|
|
||||||
flags |= KN_FLAG_TH;
|
|
||||||
if (Servo_data[AUX3] > PPM_SWITCH)
|
|
||||||
flags |= KN_FLAG_IDLEUP;
|
|
||||||
if (Servo_data[AUX4] > PPM_SWITCH)
|
|
||||||
flags |= KN_FLAG_GYRO3;
|
|
||||||
|
|
||||||
packet[12] = flags;
|
|
||||||
|
|
||||||
packet[13] = 0x00;
|
|
||||||
if(sub_protocol==WLTOYS)
|
|
||||||
packet[13] = (packet_sent << 5) | (hopping_frequency_no << 2);
|
|
||||||
|
|
||||||
packet[14] = 0x00;
|
|
||||||
packet[15] = 0x00;
|
|
||||||
|
|
||||||
NRF24L01_SetPower();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
// This function setup 24L01
|
|
||||||
// V977 uses one way communication, receiving only. 24L01 RX is never enabled.
|
|
||||||
// V977 needs payload length in the packet. We should configure 24L01 to enable Packet Control Field(PCF)
|
|
||||||
// Some RX reg settings are actually for enable PCF
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
static void kn_init()
|
|
||||||
{
|
|
||||||
kn_calculate_tx_addr();
|
|
||||||
kn_calculate_freqency_hopping_channels();
|
|
||||||
|
|
||||||
NRF24L01_Initialize();
|
|
||||||
|
|
||||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
|
|
||||||
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, 0x03); // 5-byte RX/TX address
|
|
||||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
|
|
||||||
NRF24L01_SetPower();
|
|
||||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
|
||||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // 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 to enable PCF
|
|
||||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL));
|
|
||||||
|
|
||||||
NRF24L01_SetPower();
|
|
||||||
|
|
||||||
NRF24L01_FlushTx();
|
|
||||||
// Turn radio power on
|
|
||||||
NRF24L01_SetTxRxMode(TX_EN);
|
|
||||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); //USE1MBPS_YES ? NRF24L01_BR_1M : NRF24L01_BR_250K;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
// This function generate RF TX packet address
|
|
||||||
// V977 can remember the binding parameters; we do not need rebind when power up.
|
|
||||||
// This requires the address must be repeatable for a specific RF ID at power up.
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
static void kn_calculate_tx_addr()
|
|
||||||
{
|
|
||||||
if(sub_protocol==FEILUN)
|
|
||||||
{
|
|
||||||
uint8_t addr2;
|
|
||||||
// Generate TXID with sum of minimum 256 and maximum 256+MAX_RF_CHANNEL-32
|
|
||||||
rx_tx_addr[1] = 1 + rx_tx_addr[0] % (KN_MAX_RF_CHANNEL-33);
|
|
||||||
addr2 = 1 + rx_tx_addr[2] % (KN_MAX_RF_CHANNEL-33);
|
|
||||||
if ((uint16_t)(rx_tx_addr[0] + rx_tx_addr[1]) < 256)
|
|
||||||
rx_tx_addr[2] = addr2;
|
|
||||||
else
|
|
||||||
rx_tx_addr[2] = 0x00;
|
|
||||||
rx_tx_addr[3] = 0x00;
|
|
||||||
while((uint16_t)(rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2] + rx_tx_addr[3]) < 257)
|
|
||||||
rx_tx_addr[3] += addr2;
|
|
||||||
}
|
|
||||||
//The 5th byte is a constant, must be 'K'
|
|
||||||
rx_tx_addr[4] = 'K';
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
// This function generates "random" RF hopping frequency channel numbers.
|
|
||||||
// These numbers must be repeatable for a specific seed
|
|
||||||
// The generated number range is from 0 to MAX_RF_CHANNEL. No repeat or adjacent numbers
|
|
||||||
//
|
|
||||||
// For Feilun variant, the channels are calculated from TXID, and since only 2 channels are used
|
|
||||||
// we copy them to fill up to MAX_RF_CHANNEL
|
|
||||||
//-------------------------------------------------------------------------------------------------
|
|
||||||
static void kn_calculate_freqency_hopping_channels()
|
|
||||||
{
|
|
||||||
if(sub_protocol==WLTOYS)
|
|
||||||
{
|
|
||||||
uint8_t idx = 0;
|
|
||||||
uint32_t rnd = MProtocol_id;
|
|
||||||
while (idx < KN_RF_CH_COUNT)
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
|
|
||||||
|
|
||||||
// Use least-significant byte. 73 is prime, so channels 76..77 are unused
|
|
||||||
uint8_t next_ch = ((rnd >> 8) % KN_MAX_RF_CHANNEL) + 2;
|
|
||||||
// Keep the distance 2 between the channels - either odd or even
|
|
||||||
if (((next_ch ^ MProtocol_id) & 0x01 )== 0)
|
|
||||||
continue;
|
|
||||||
// Check that it's not duplicate and spread uniformly
|
|
||||||
for (i = 0; i < idx; i++)
|
|
||||||
if(hopping_frequency[i] == next_ch)
|
|
||||||
break;
|
|
||||||
if (i != idx)
|
|
||||||
continue;
|
|
||||||
hopping_frequency[idx++] = next_ch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{//FEILUN
|
|
||||||
hopping_frequency[0] = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2] + rx_tx_addr[3]; // - 256; ???
|
|
||||||
hopping_frequency[1] = hopping_frequency[0] + 32;
|
|
||||||
hopping_frequency[2] = hopping_frequency[0];
|
|
||||||
hopping_frequency[3] = hopping_frequency[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
http://www.rcgroups.com/forums/showthread.php?t=2165676
|
http://www.rcgroups.com/forums/showthread.php?t=2165676
|
||||||
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/edit/master/README.md
|
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/edit/master/README.md
|
||||||
|
|
||||||
Thanks to PhracturedBlue
|
Thanks to PhracturedBlue, Hexfet, Goebish and all protocol developers
|
||||||
Ported from deviation firmware
|
Ported from deviation firmware
|
||||||
|
|
||||||
This project is free software: you can redistribute it and/or modify
|
This project is free software: you can redistribute it and/or modify
|
||||||
@ -23,71 +23,10 @@
|
|||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
//******************************************************
|
|
||||||
//******************************************************
|
|
||||||
// Multiprotocol module configuration starts here
|
|
||||||
|
|
||||||
//Uncomment the type of TX
|
|
||||||
#define TX_ER9X //ER9X AETR (988<->2012µs)
|
|
||||||
//#define TX_DEVO7 //DEVO7 EATR (1120<->1920µs)
|
|
||||||
//#define TX_SPEKTRUM //Spektrum TAER (1100<->1900µs)
|
|
||||||
//#define TX_HISKY //HISKY AETR (1100<->1900µs)
|
|
||||||
|
|
||||||
#include "multiprotocol.h"
|
#include "multiprotocol.h"
|
||||||
|
|
||||||
//Uncomment to enable 8 channels serial protocol, 16 otherwise
|
//Multiprotocol module configuration file
|
||||||
//#define NUM_SERIAL_CH_8
|
#include "_Config.h"
|
||||||
|
|
||||||
//Uncomment to enable telemetry
|
|
||||||
#define TELEMETRY
|
|
||||||
|
|
||||||
//Comment protocols to exclude from compilation
|
|
||||||
#define BAYANG_NRF24L01_INO
|
|
||||||
#define CG023_NRF24L01_INO
|
|
||||||
#define CX10_NRF24L01_INO
|
|
||||||
#define DEVO_CYRF6936_INO
|
|
||||||
#define DSM2_CYRF6936_INO
|
|
||||||
#define ESKY_NRF24L01_INO
|
|
||||||
#define FLYSKY_A7105_INO
|
|
||||||
#define FRSKY_CC2500_INO
|
|
||||||
#define HISKY_NRF24L01_INO
|
|
||||||
#define HUBSAN_A7105_INO
|
|
||||||
#define KN_NRF24L01_INO
|
|
||||||
#define SLT_NRF24L01_INO
|
|
||||||
#define SYMAX_NRF24L01_INO
|
|
||||||
#define V2X2_NRF24L01_INO
|
|
||||||
#define YD717_NRF24L01_INO
|
|
||||||
//#define FRSKYX_CC2500_INO
|
|
||||||
|
|
||||||
//Update this table to set which protocol/sub_protocol is called for the corresponding dial number
|
|
||||||
static const uint8_t PPM_prot[15][2]= { {MODE_FLYSKY , Flysky }, //Dial=1
|
|
||||||
{MODE_HUBSAN , 0 }, //Dial=2
|
|
||||||
{MODE_FRSKY , 0 }, //Dial=3
|
|
||||||
{MODE_HISKY , Hisky }, //Dial=4
|
|
||||||
{MODE_V2X2 , 0 }, //Dial=5
|
|
||||||
{MODE_DSM2 , DSM2 }, //Dial=6
|
|
||||||
{MODE_DEVO , 0 }, //Dial=7
|
|
||||||
{MODE_YD717 , YD717 }, //Dial=8
|
|
||||||
{MODE_KN , WLTOYS }, //Dial=9
|
|
||||||
{MODE_SYMAX , SYMAX }, //Dial=10
|
|
||||||
{MODE_SLT , 0 }, //Dial=11
|
|
||||||
{MODE_CX10 , CX10_BLUE }, //Dial=12
|
|
||||||
{MODE_CG023 , CG023 }, //Dial=13
|
|
||||||
{MODE_BAYANG , 0 }, //Dial=14
|
|
||||||
{MODE_SYMAX , SYMAX5C } //Dial=15
|
|
||||||
};
|
|
||||||
|
|
||||||
//CC2500 RF module frequency adjustment, use in case you cannot bind with Frsky RX
|
|
||||||
//Note: this is set via Option when serial protocol is used
|
|
||||||
//values from 0-127 offset increase frequency, values from 255 to 127 decrease base frequency
|
|
||||||
//uint8_t fine = 0x00;
|
|
||||||
uint8_t fine = 0xd7; //* 215=-41 *
|
|
||||||
|
|
||||||
// Multiprotocol module configuration ends here
|
|
||||||
//******************************************************
|
|
||||||
//******************************************************
|
|
||||||
|
|
||||||
|
|
||||||
//Global constants/variables
|
//Global constants/variables
|
||||||
|
|
||||||
@ -126,17 +65,18 @@ uint8_t hopping_frequency_no=0;
|
|||||||
uint8_t rf_ch_num;
|
uint8_t rf_ch_num;
|
||||||
uint8_t throttle, rudder, elevator, aileron;
|
uint8_t throttle, rudder, elevator, aileron;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
//
|
||||||
|
uint32_t state;
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t RX_num;
|
||||||
|
|
||||||
// Mode_select variables
|
// Mode_select variables
|
||||||
uint8_t mode_select;
|
uint8_t mode_select;
|
||||||
|
uint8_t ppm_select;
|
||||||
uint8_t protocol_flags=0,protocol_flags2=0;
|
uint8_t protocol_flags=0,protocol_flags2=0;
|
||||||
|
|
||||||
// Serial variables
|
// Serial variables
|
||||||
#if defined(NUM_SERIAL_CH_8) //8 channels serial protocol
|
|
||||||
#define RXBUFFER_SIZE 14
|
|
||||||
#else //16 channels serial protocol
|
|
||||||
#define RXBUFFER_SIZE 25
|
#define RXBUFFER_SIZE 25
|
||||||
#endif
|
|
||||||
#define TXBUFFER_SIZE 12
|
#define TXBUFFER_SIZE 12
|
||||||
volatile uint8_t rx_buff[RXBUFFER_SIZE];
|
volatile uint8_t rx_buff[RXBUFFER_SIZE];
|
||||||
volatile uint8_t rx_ok_buff[RXBUFFER_SIZE];
|
volatile uint8_t rx_ok_buff[RXBUFFER_SIZE];
|
||||||
@ -150,16 +90,17 @@ uint8_t cur_protocol[2];
|
|||||||
uint8_t prev_protocol=0;
|
uint8_t prev_protocol=0;
|
||||||
|
|
||||||
// Telemetry
|
// Telemetry
|
||||||
|
#define MAX_PKT 27
|
||||||
|
uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||||
#if defined(TELEMETRY)
|
#if defined(TELEMETRY)
|
||||||
uint8_t pkt[27];//telemetry receiving packets
|
uint8_t pktt[MAX_PKT];//telemetry receiving packets
|
||||||
uint8_t pktt[27];//telemetry receiving packets
|
volatile uint8_t tx_head;
|
||||||
volatile uint8_t tx_head;
|
volatile uint8_t tx_tail;
|
||||||
volatile uint8_t tx_tail;
|
uint8_t v_lipo;
|
||||||
uint8_t v_lipo;
|
int16_t RSSI_dBm;
|
||||||
int16_t RSSI_dBm;
|
//const uint8_t RSSI_offset=72;//69 71.72 values db
|
||||||
//const uint8_t RSSI_offset=72;//69 71.72 values db
|
uint8_t telemetry_link=0;
|
||||||
uint8_t telemetry_link=0;
|
#include "telemetry.h"
|
||||||
#include "telemetry.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Callback
|
// Callback
|
||||||
@ -204,56 +145,55 @@ void setup()
|
|||||||
// Read status of mode select binary switch
|
// Read status of mode select binary switch
|
||||||
// after this mode_select will be one of {0000, 0001, ..., 1111}
|
// after this mode_select will be one of {0000, 0001, ..., 1111}
|
||||||
mode_select=0x0F - ( ( (PINB>>2)&0x07 ) | ( (PINC<<3)&0x08) );//encoder dip switches 1,2,4,8=>B2,B3,B4,C0
|
mode_select=0x0F - ( ( (PINB>>2)&0x07 ) | ( (PINC<<3)&0x08) );//encoder dip switches 1,2,4,8=>B2,B3,B4,C0
|
||||||
//**********************************
|
//**********************************
|
||||||
//mode_select=14; // here to test PPM
|
//mode_select=14; // here to test PPM
|
||||||
//**********************************
|
//**********************************
|
||||||
|
|
||||||
// Update LED
|
// Update LED
|
||||||
LED_OFF;
|
LED_OFF;
|
||||||
LED_SET_OUTPUT;
|
LED_SET_OUTPUT;
|
||||||
|
|
||||||
// Read or create protocol id
|
// Read or create protocol id
|
||||||
MProtocol_id=random_id(10,false);
|
MProtocol_id_master=random_id(10,false);
|
||||||
MProtocol_id_master=MProtocol_id;
|
|
||||||
|
|
||||||
//Set power transmission flags
|
//Init RF modules
|
||||||
POWER_FLAG_on; //By default high power for everything
|
CC2500_Reset();
|
||||||
|
|
||||||
//Protocol and interrupts initialization
|
//Protocol and interrupts initialization
|
||||||
if(mode_select != MODE_SERIAL)
|
#if !defined(POTAR_SELECT)
|
||||||
{ // PPM
|
if(mode_select == MODE_SERIAL)
|
||||||
cur_protocol[0]= PPM_prot[mode_select-1][0];
|
|
||||||
sub_protocol = PPM_prot[mode_select-1][1];
|
|
||||||
protocol_init(cur_protocol[0]);
|
|
||||||
|
|
||||||
//Configure PPM interrupt
|
|
||||||
EICRA |=(1<<ISC11); // The rising edge of INT1 pin D3 generates an interrupt request
|
|
||||||
EIMSK |= (1<<INT1); // INT1 interrupt enable
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Serial
|
{ // Serial
|
||||||
cur_protocol[0]=0;
|
cur_protocol[0]=0;
|
||||||
cur_protocol[1]=0;
|
cur_protocol[1]=0;
|
||||||
prev_protocol=0;
|
prev_protocol=0;
|
||||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{ // PPM
|
||||||
|
prev_protocol=0;
|
||||||
|
CHANGE_PROTOCOL_FLAG_on;
|
||||||
|
update_ppm_data();
|
||||||
|
|
||||||
|
//Configure PPM interrupt
|
||||||
|
EICRA |=(1<<ISC11); // The rising edge of INT1 pin D3 generates an interrupt request
|
||||||
|
EIMSK |= (1<<INT1); // INT1 interrupt enable
|
||||||
|
#if defined(TELEMETRY)
|
||||||
|
PPM_Telemetry_serial_init(); // Configure serial for telemetry
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
|
||||||
{ // Protocol needs to be changed
|
|
||||||
LED_OFF; //led off during protocol init
|
|
||||||
module_reset(); //reset previous module
|
|
||||||
protocol_init(cur_protocol[0]&0x1F); //init new protocol
|
|
||||||
CHANGE_PROTOCOL_FLAG_off; //done
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
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++)
|
for(uint8_t i=0;i<NUM_CHN;i++)
|
||||||
@ -261,13 +201,19 @@ void loop()
|
|||||||
cli(); // disable global int
|
cli(); // disable global int
|
||||||
Servo_data[i]=PPM_data[i];
|
Servo_data[i]=PPM_data[i];
|
||||||
sei(); // enable global int
|
sei(); // enable global int
|
||||||
update_aux_flags();
|
|
||||||
}
|
}
|
||||||
|
update_aux_flags();
|
||||||
PPM_FLAG_off; // wait for next frame before update
|
PPM_FLAG_off; // wait for next frame before update
|
||||||
}
|
}
|
||||||
|
if(IS_CHANGE_PROTOCOL_FLAG_on) { // Protocol needs to be changed
|
||||||
|
LED_OFF; //led off during protocol init
|
||||||
|
module_reset(); //reset previous module
|
||||||
|
protocol_init(); //init new protocol
|
||||||
|
CHANGE_PROTOCOL_FLAG_off; //done
|
||||||
|
}
|
||||||
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))
|
if( ((cur_protocol[0]&0x1F)==MODE_FRSKY) || ((cur_protocol[0]&0x1F)==MODE_HUBSAN) || ((cur_protocol[0]&0x1F)==MODE_FRSKYX) )
|
||||||
frskyUpdate();
|
frskyUpdate();
|
||||||
#endif
|
#endif
|
||||||
if (remote_callback != 0)
|
if (remote_callback != 0)
|
||||||
@ -279,7 +225,11 @@ 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 defined(POTAR_SELECT)
|
||||||
|
if(Servo_data[AUX2+i]>PPM_SWITCH)
|
||||||
|
#else
|
||||||
if(Servo_data[AUX1+i]>PPM_SWITCH)
|
if(Servo_data[AUX1+i]>PPM_SWITCH)
|
||||||
|
#endif
|
||||||
Servo_AUX|=1<<i;
|
Servo_AUX|=1<<i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +291,8 @@ static void CheckTimer(uint16_t (*cb)(void))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void protocol_init(uint8_t protocol)
|
// Protocol start
|
||||||
|
static void protocol_init()
|
||||||
{
|
{
|
||||||
uint16_t next_callback=0; // Default is immediate call back
|
uint16_t next_callback=0; // Default is immediate call back
|
||||||
remote_callback = 0;
|
remote_callback = 0;
|
||||||
@ -358,7 +309,7 @@ static void protocol_init(uint8_t protocol)
|
|||||||
CTRL1_on; //NRF24L01 antenna RF3 by default
|
CTRL1_on; //NRF24L01 antenna RF3 by default
|
||||||
CTRL2_off; //NRF24L01 antenna RF3 by default
|
CTRL2_off; //NRF24L01 antenna RF3 by default
|
||||||
|
|
||||||
switch(protocol) // Init the requested protocol
|
switch(cur_protocol[0]&0x1F) // Init the requested protocol
|
||||||
{
|
{
|
||||||
#if defined(FLYSKY_A7105_INO)
|
#if defined(FLYSKY_A7105_INO)
|
||||||
case MODE_FLYSKY:
|
case MODE_FLYSKY:
|
||||||
@ -465,6 +416,19 @@ static void protocol_init(uint8_t protocol)
|
|||||||
next_callback=initESKY();
|
next_callback=initESKY();
|
||||||
remote_callback = ESKY_callback;
|
remote_callback = ESKY_callback;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
// Ajout protocol
|
||||||
|
#if defined(H7_NRF24L01_INO)
|
||||||
|
case MODE_H7:
|
||||||
|
next_callback=H7_init();
|
||||||
|
remote_callback = process_H7;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(HM830_NRF24L01_INO)
|
||||||
|
case MODE_HM830:
|
||||||
|
next_callback=HM830_setup();
|
||||||
|
remote_callback = HM830_callback;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,6 +444,52 @@ static void protocol_init(uint8_t protocol)
|
|||||||
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+i]>PPM_SWITCH) { CHANGE_PROTOCOL_FLAG_on; }
|
||||||
|
#endif
|
||||||
|
if(IS_CHANGE_PROTOCOL_FLAG_on) {
|
||||||
|
prev_protocol = ppm_select;
|
||||||
|
|
||||||
|
ppm_select = 0;
|
||||||
|
// protocol selection
|
||||||
|
// THROTTLE up
|
||||||
|
if(Servo_data[POTAR_SELECT_M] > PPM_MAX_COMMAND) { ppm_select += 18; }
|
||||||
|
// THROTTLE down
|
||||||
|
else if(Servo_data[POTAR_SELECT_M] < PPM_MIN_COMMAND) { ppm_select += 9; }
|
||||||
|
// THROTTLE middle
|
||||||
|
else { ppm_select += 0; }
|
||||||
|
|
||||||
|
|
||||||
|
// Elevator up
|
||||||
|
if(Servo_data[POTAR_SELECT_V] > PPM_MAX_COMMAND) { ppm_select += 7; }
|
||||||
|
// Elevator down
|
||||||
|
else if(Servo_data[POTAR_SELECT_V] < PPM_MIN_COMMAND) { ppm_select += 1; }
|
||||||
|
// Elevator middle
|
||||||
|
else { ppm_select += 4; }
|
||||||
|
|
||||||
|
// Aileron right
|
||||||
|
if(Servo_data[POTAR_SELECT_H] > PPM_MAX_COMMAND) { ppm_select += 2; }
|
||||||
|
// Aileron left
|
||||||
|
else if(Servo_data[POTAR_SELECT_H] < PPM_MIN_COMMAND) { ppm_select += 0; }
|
||||||
|
// Aileron middle
|
||||||
|
else { ppm_select += 1; }
|
||||||
|
|
||||||
|
// if(ppm_select == 5) { ppm_select = eeprom_read_byte(30); } else { eeprom_update_byte(30, ppm_select); }
|
||||||
|
if(ppm_select > 5) { ppm_select--; }
|
||||||
|
|
||||||
|
if(mode_select > MODE_SERIAL) {
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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
|
||||||
@ -496,7 +506,6 @@ static void update_serial_data()
|
|||||||
POWER_FLAG_on; //power high
|
POWER_FLAG_on; //power high
|
||||||
|
|
||||||
option=rx_ok_buff[2];
|
option=rx_ok_buff[2];
|
||||||
fine=option; // Update FrSky fine tuning
|
|
||||||
|
|
||||||
if( ((rx_ok_buff[0]&0x5F) != (cur_protocol[0]&0x5F)) || ( (rx_ok_buff[1]&0x7F) != cur_protocol[1] ) )
|
if( ((rx_ok_buff[0]&0x5F) != (cur_protocol[0]&0x5F)) || ( (rx_ok_buff[1]&0x7F) != cur_protocol[1] ) )
|
||||||
{ // New model has been selected
|
{ // New model has been selected
|
||||||
@ -504,7 +513,8 @@ static void update_serial_data()
|
|||||||
cur_protocol[1] = rx_ok_buff[1]&0x7F; //store current protocol
|
cur_protocol[1] = rx_ok_buff[1]&0x7F; //store current protocol
|
||||||
CHANGE_PROTOCOL_FLAG_on; //change protocol
|
CHANGE_PROTOCOL_FLAG_on; //change protocol
|
||||||
sub_protocol=(rx_ok_buff[1]>>4)& 0x07; //subprotocol no (0-7) bits 4-6
|
sub_protocol=(rx_ok_buff[1]>>4)& 0x07; //subprotocol no (0-7) bits 4-6
|
||||||
MProtocol_id=MProtocol_id_master+(rx_ok_buff[1]& 0x0F); //personalized RX bind + rx num // rx_num bits 0---3
|
RX_num=rx_ok_buff[1]& 0x0F;
|
||||||
|
MProtocol_id=MProtocol_id_master+RX_num; //personalized RX bind + rx num // rx_num bits 0---3
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( ((rx_ok_buff[0]&0x80)!=0) && ((cur_protocol[0]&0x80)==0) ) // Bind flag has been set
|
if( ((rx_ok_buff[0]&0x80)!=0) && ((cur_protocol[0]&0x80)==0) ) // Bind flag has been set
|
||||||
@ -512,18 +522,6 @@ static void update_serial_data()
|
|||||||
cur_protocol[0] = rx_ok_buff[0]; //store current protocol
|
cur_protocol[0] = rx_ok_buff[0]; //store current protocol
|
||||||
|
|
||||||
// decode channel values
|
// decode channel values
|
||||||
#if defined(NUM_SERIAL_CH_8) //8 channels serial protocol
|
|
||||||
Servo_data[0]=rx_ok_buff[3]+((rx_ok_buff[11]&0xC0)<<2);
|
|
||||||
Servo_data[1]=rx_ok_buff[4]+((rx_ok_buff[11]&0x30)<<4);
|
|
||||||
Servo_data[2]=rx_ok_buff[5]+((rx_ok_buff[11]&0x0C)<<6);
|
|
||||||
Servo_data[3]=rx_ok_buff[6]+((rx_ok_buff[11]&0x03)<<8);
|
|
||||||
Servo_data[4]=rx_ok_buff[7]+((rx_ok_buff[12]&0xC0)<<2);
|
|
||||||
Servo_data[5]=rx_ok_buff[8]+((rx_ok_buff[12]&0x30)<<4);
|
|
||||||
Servo_data[6]=rx_ok_buff[9]+((rx_ok_buff[12]&0x0C)<<6);
|
|
||||||
Servo_data[7]=rx_ok_buff[10]+((rx_ok_buff[12]&0x03)<<8);
|
|
||||||
for(uint8_t i=0;i<8;i++)
|
|
||||||
Servo_data[i]=((Servo_data[i]*5)>>2)+860; //range 860-2140;
|
|
||||||
#else //16 channels serial protocol
|
|
||||||
volatile uint8_t *p=rx_ok_buff+2;
|
volatile uint8_t *p=rx_ok_buff+2;
|
||||||
uint8_t dec=-3;
|
uint8_t dec=-3;
|
||||||
for(uint8_t i=0;i<NUM_CHN;i++)
|
for(uint8_t i=0;i<NUM_CHN;i++)
|
||||||
@ -537,12 +535,13 @@ static void update_serial_data()
|
|||||||
p++;
|
p++;
|
||||||
Servo_data[i]=((((*((uint32_t *)p))>>dec)&0x7FF)*5)/8+860; //value range 860<->2140 -125%<->+125%
|
Servo_data[i]=((((*((uint32_t *)p))>>dec)&0x7FF)*5)/8+860; //value range 860<->2140 -125%<->+125%
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
RX_FLAG_off; //data has been processed
|
RX_FLAG_off; //data has been processed
|
||||||
}
|
}
|
||||||
|
|
||||||
static void module_reset()
|
static void module_reset()
|
||||||
{
|
{
|
||||||
|
if(remote_callback)
|
||||||
|
{ // previous protocol loaded
|
||||||
remote_callback = 0;
|
remote_callback = 0;
|
||||||
switch(prev_protocol)
|
switch(prev_protocol)
|
||||||
{
|
{
|
||||||
@ -554,16 +553,15 @@ static void module_reset()
|
|||||||
case MODE_FRSKYX:
|
case MODE_FRSKYX:
|
||||||
CC2500_Reset();
|
CC2500_Reset();
|
||||||
break;
|
break;
|
||||||
break;
|
|
||||||
case MODE_DSM2:
|
case MODE_DSM2:
|
||||||
case MODE_DEVO:
|
case MODE_DEVO:
|
||||||
CYRF_Reset();
|
CYRF_Reset();
|
||||||
break;
|
break;
|
||||||
default:
|
default: // MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY
|
||||||
// MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY
|
|
||||||
NRF24L01_Reset();
|
NRF24L01_Reset();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel value is converted to 8bit values full scale
|
// Channel value is converted to 8bit values full scale
|
||||||
@ -617,16 +615,6 @@ uint16_t limit_channel_100(uint8_t ch)
|
|||||||
return Servo_data[ch];
|
return Servo_data[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert 32b id to rx_tx_addr
|
|
||||||
static void set_rx_tx_addr(uint32_t id)
|
|
||||||
{ // Used by almost all protocols
|
|
||||||
rx_tx_addr[0] = (id >> 24) & 0xFF;
|
|
||||||
rx_tx_addr[1] = (id >> 16) & 0xFF;
|
|
||||||
rx_tx_addr[2] = (id >> 8) & 0xFF;
|
|
||||||
rx_tx_addr[3] = (id >> 0) & 0xFF;
|
|
||||||
rx_tx_addr[4] = 0xC1; // for YD717: always uses first data port
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(TELEMETRY)
|
#if defined(TELEMETRY)
|
||||||
void Serial_write(uint8_t data)
|
void Serial_write(uint8_t data)
|
||||||
{
|
{
|
||||||
@ -641,21 +629,12 @@ void Serial_write(uint8_t data)
|
|||||||
|
|
||||||
static void Mprotocol_serial_init()
|
static void Mprotocol_serial_init()
|
||||||
{
|
{
|
||||||
#if defined(NUM_SERIAL_CH_8) //8 channels serial protocol
|
|
||||||
#define BAUD 125000
|
|
||||||
#include <util/setbaud.h>
|
|
||||||
UBRR0H = UBRRH_VALUE;
|
|
||||||
UBRR0L = UBRRL_VALUE;
|
|
||||||
//Set frame format to 8 data bits, no parity, 1 stop bit
|
|
||||||
UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
|
|
||||||
#else //16 channels serial protocol
|
|
||||||
#define BAUD 100000
|
#define BAUD 100000
|
||||||
#include <util/setbaud.h>
|
#include <util/setbaud.h>
|
||||||
UBRR0H = UBRRH_VALUE;
|
UBRR0H = UBRRH_VALUE;
|
||||||
UBRR0L = UBRRL_VALUE;
|
UBRR0L = UBRRL_VALUE;
|
||||||
//Set frame format to 8 data bits, even parity, 2 stop bits
|
//Set frame format to 8 data bits, even parity, 2 stop bits
|
||||||
UCSR0C |= (1<<UPM01)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
|
UCSR0C |= (1<<UPM01)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
|
||||||
#endif
|
|
||||||
while ( UCSR0A & (1 << RXC0) )//flush receive buffer
|
while ( UCSR0A & (1 << RXC0) )//flush receive buffer
|
||||||
UDR0;
|
UDR0;
|
||||||
//enable reception and RC complete interrupt
|
//enable reception and RC complete interrupt
|
||||||
@ -663,6 +642,26 @@ static void Mprotocol_serial_init()
|
|||||||
UCSR0B |= (1<<TXEN0);//tx enable
|
UCSR0B |= (1<<TXEN0);//tx enable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PPM_Telemetry_serial_init()
|
||||||
|
{
|
||||||
|
//9600 bauds
|
||||||
|
UBRR0H = 0x00;
|
||||||
|
UBRR0L = 0x67;
|
||||||
|
//Set frame format to 8 data bits, none, 1 stop bit
|
||||||
|
UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
|
||||||
|
UCSR0B |= (1<<TXEN0);//tx enable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert 32b id to rx_tx_addr
|
||||||
|
static void set_rx_tx_addr(uint32_t id)
|
||||||
|
{ // Used by almost all protocols
|
||||||
|
rx_tx_addr[0] = (id >> 24) & 0xFF;
|
||||||
|
rx_tx_addr[1] = (id >> 16) & 0xFF;
|
||||||
|
rx_tx_addr[2] = (id >> 8) & 0xFF;
|
||||||
|
rx_tx_addr[3] = (id >> 0) & 0xFF;
|
||||||
|
rx_tx_addr[4] = 0xC1; // for YD717: always uses first data port
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t random_id(uint16_t adress, uint8_t create_new)
|
static uint32_t random_id(uint16_t adress, uint8_t create_new)
|
||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -694,6 +693,7 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
|
|||||||
/**************************/
|
/**************************/
|
||||||
/**************************/
|
/**************************/
|
||||||
|
|
||||||
|
//PPM
|
||||||
ISR(INT1_vect)
|
ISR(INT1_vect)
|
||||||
{ // Interrupt on PPM pin
|
{ // Interrupt on PPM pin
|
||||||
static int8_t chan=-1;
|
static int8_t chan=-1;
|
||||||
@ -722,53 +722,8 @@ ISR(INT1_vect)
|
|||||||
Prev_TCNT1+=Cur_TCNT1;
|
Prev_TCNT1+=Cur_TCNT1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(TELEMETRY)
|
//Serial RX
|
||||||
ISR(USART_UDRE_vect)
|
#if !defined(POTAR_SELECT)
|
||||||
{ // Transmit interrupt
|
|
||||||
uint8_t t = tx_tail;
|
|
||||||
if(tx_head!=t)
|
|
||||||
{
|
|
||||||
if(++t>=TXBUFFER_SIZE)//head
|
|
||||||
t=0;
|
|
||||||
UDR0=tx_buff[t];
|
|
||||||
tx_tail=t;
|
|
||||||
}
|
|
||||||
if (t == tx_head)
|
|
||||||
UCSR0B &= ~(1<<UDRIE0); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(NUM_SERIAL_CH_8) //8 channels serial protocol
|
|
||||||
ISR(USART_RX_vect)
|
|
||||||
{ // RX interrupt
|
|
||||||
static uint16_t crc = 0;
|
|
||||||
|
|
||||||
if(idx==0)
|
|
||||||
{ // Let's try to sync at this point
|
|
||||||
OCR1B=TCNT1+5000L; // timer for 2500us
|
|
||||||
TIFR1=(1<<OCF1B); // clear OCR1B match flag
|
|
||||||
TIMSK1 |=(1<<OCIE1B); // enable interrupt on compare B match
|
|
||||||
crc=0;
|
|
||||||
}
|
|
||||||
if(idx<RXBUFFER_SIZE-1)
|
|
||||||
{ // Store bytes in buffer and calculate crc as we go
|
|
||||||
rx_buff[idx]=UDR0;
|
|
||||||
crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ rx_buff[idx++]) & 0xFF]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // A frame has been received and needs to be checked before giving it to main
|
|
||||||
TIMSK1 &=~(1<<OCIE1B); // disable interrupt on compare B match
|
|
||||||
if(UDR0==(uint8_t)(crc & 0xFF) && !IS_RX_FLAG_on)
|
|
||||||
{ //Good frame received and main has finished with previous buffer
|
|
||||||
for(idx=0;idx<RXBUFFER_SIZE;idx++)
|
|
||||||
rx_ok_buff[idx]=rx_buff[idx]; // Duplicate the buffer
|
|
||||||
RX_FLAG_on; //flag for main to process servo data
|
|
||||||
LED_ON;
|
|
||||||
}
|
|
||||||
idx=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else //16 channels serial protocol
|
|
||||||
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
|
||||||
@ -807,7 +762,25 @@ ISR(USART_RX_vect)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//Serial timer
|
||||||
ISR(TIMER1_COMPB_vect)
|
ISR(TIMER1_COMPB_vect)
|
||||||
{ // Timer1 compare B interrupt
|
{ // Timer1 compare B interrupt
|
||||||
idx=0;
|
idx=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(TELEMETRY)
|
||||||
|
//Serial TX
|
||||||
|
ISR(USART_UDRE_vect)
|
||||||
|
{ // Transmit interrupt
|
||||||
|
uint8_t t = tx_tail;
|
||||||
|
if(tx_head!=t)
|
||||||
|
{
|
||||||
|
if(++t>=TXBUFFER_SIZE)//head
|
||||||
|
t=0;
|
||||||
|
UDR0=tx_buff[t];
|
||||||
|
tx_tail=t;
|
||||||
|
}
|
||||||
|
if (t == tx_head)
|
||||||
|
UCSR0B &= ~(1<<UDRIE0); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -271,7 +271,7 @@ static const uint8_t xn297_scramble[] = {
|
|||||||
|
|
||||||
static const uint16_t xn297_crc_xorout[] = {
|
static const uint16_t xn297_crc_xorout[] = {
|
||||||
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, // 1st entry is missing, probably never needed
|
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, // 1st entry is missing, probably never needed
|
||||||
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x8148, // it's used for 3-byte address w/ 0 byte payload only
|
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, // it's used for 3-byte address w/ 0 byte payload only
|
||||||
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
|
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
|
||||||
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
|
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
|
||||||
0x2138, 0x129F, 0xB3A0, 0x2988};
|
0x2138, 0x129F, 0xB3A0, 0x2988};
|
||||||
|
@ -31,7 +31,7 @@ enum {
|
|||||||
SLT_DATA3
|
SLT_DATA3
|
||||||
};
|
};
|
||||||
|
|
||||||
static void SLT_init()
|
static void __attribute__((unused)) SLT_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off
|
||||||
@ -47,7 +47,7 @@ static void SLT_init()
|
|||||||
NRF24L01_FlushRx();
|
NRF24L01_FlushRx();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SLT_init2()
|
static void __attribute__((unused)) SLT_init2()
|
||||||
{
|
{
|
||||||
NRF24L01_FlushTx();
|
NRF24L01_FlushTx();
|
||||||
packet_sent = 0;
|
packet_sent = 0;
|
||||||
@ -57,7 +57,7 @@ static void SLT_init2()
|
|||||||
NRF24L01_SetTxRxMode(TX_EN);
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SLT_set_tx_id(void)
|
static void __attribute__((unused)) SLT_set_tx_id(void)
|
||||||
{
|
{
|
||||||
// Frequency hopping sequence generation
|
// Frequency hopping sequence generation
|
||||||
for (uint8_t i = 0; i < 4; ++i)
|
for (uint8_t i = 0; i < 4; ++i)
|
||||||
@ -90,14 +90,14 @@ static void SLT_set_tx_id(void)
|
|||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SLT_wait_radio()
|
static void __attribute__((unused)) SLT_wait_radio()
|
||||||
{
|
{
|
||||||
if (packet_sent)
|
if (packet_sent)
|
||||||
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS))) ;
|
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS))) ;
|
||||||
packet_sent = 0;
|
packet_sent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SLT_send_data(uint8_t *data, uint8_t len)
|
static void __attribute__((unused)) SLT_send_data(uint8_t *data, uint8_t len)
|
||||||
{
|
{
|
||||||
SLT_wait_radio();
|
SLT_wait_radio();
|
||||||
NRF24L01_FlushTx();
|
NRF24L01_FlushTx();
|
||||||
@ -107,7 +107,7 @@ static void SLT_send_data(uint8_t *data, uint8_t len)
|
|||||||
packet_sent = 1;
|
packet_sent = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SLT_build_packet()
|
static void __attribute__((unused)) SLT_build_packet()
|
||||||
{
|
{
|
||||||
// aileron, elevator, throttle, rudder, gear, pitch
|
// aileron, elevator, throttle, rudder, gear, pitch
|
||||||
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
|
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
|
||||||
@ -129,7 +129,7 @@ static void SLT_build_packet()
|
|||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SLT_send_bind_packet()
|
static void __attribute__((unused)) SLT_send_bind_packet()
|
||||||
{
|
{
|
||||||
SLT_wait_radio();
|
SLT_wait_radio();
|
||||||
BIND_IN_PROGRESS; // autobind protocol
|
BIND_IN_PROGRESS; // autobind protocol
|
||||||
|
@ -41,7 +41,7 @@ enum {
|
|||||||
SYMAX_DATA
|
SYMAX_DATA
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t SYMAX_checksum(uint8_t *data)
|
static uint8_t __attribute__((unused)) SYMAX_checksum(uint8_t *data)
|
||||||
{
|
{
|
||||||
uint8_t sum = data[0];
|
uint8_t sum = data[0];
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ static uint8_t SYMAX_checksum(uint8_t *data)
|
|||||||
return sum + ( sub_protocol==SYMAX5C ? 0 : 0x55 );
|
return sum + ( sub_protocol==SYMAX5C ? 0 : 0x55 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SYMAX_read_controls()
|
static void __attribute__((unused)) SYMAX_read_controls()
|
||||||
{
|
{
|
||||||
// Protocol is registered AETRF, that is
|
// Protocol is registered AETRF, that is
|
||||||
// Aileron is channel 1, Elevator - 2, Throttle - 3, Rudder - 4, Flip control - 5
|
// Aileron is channel 1, Elevator - 2, Throttle - 3, Rudder - 4, Flip control - 5
|
||||||
@ -80,7 +80,7 @@ static void SYMAX_read_controls()
|
|||||||
|
|
||||||
#define X5C_CHAN2TRIM(X) ((((X) & 0x80 ? 0xff - (X) : 0x80 + (X)) >> 2) + 0x20)
|
#define X5C_CHAN2TRIM(X) ((((X) & 0x80 ? 0xff - (X) : 0x80 + (X)) >> 2) + 0x20)
|
||||||
|
|
||||||
static void SYMAX_build_packet_x5c(uint8_t bind)
|
static void __attribute__((unused)) SYMAX_build_packet_x5c(uint8_t bind)
|
||||||
{
|
{
|
||||||
if (bind)
|
if (bind)
|
||||||
{
|
{
|
||||||
@ -116,7 +116,7 @@ static void SYMAX_build_packet_x5c(uint8_t bind)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SYMAX_build_packet(uint8_t bind)
|
static void __attribute__((unused)) SYMAX_build_packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
if (bind)
|
if (bind)
|
||||||
{
|
{
|
||||||
@ -146,7 +146,7 @@ static void SYMAX_build_packet(uint8_t bind)
|
|||||||
packet[9] = SYMAX_checksum(packet);
|
packet[9] = SYMAX_checksum(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SYMAX_send_packet(uint8_t bind)
|
static void __attribute__((unused)) SYMAX_send_packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
if (sub_protocol==SYMAX5C)
|
if (sub_protocol==SYMAX5C)
|
||||||
SYMAX_build_packet_x5c(bind);
|
SYMAX_build_packet_x5c(bind);
|
||||||
@ -167,7 +167,7 @@ static void SYMAX_send_packet(uint8_t bind)
|
|||||||
NRF24L01_SetPower(); // Set tx_power
|
NRF24L01_SetPower(); // Set tx_power
|
||||||
}
|
}
|
||||||
|
|
||||||
static void symax_init()
|
static void __attribute__((unused)) symax_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
//
|
//
|
||||||
@ -219,7 +219,7 @@ static void symax_init()
|
|||||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0e); // power on
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0e); // power on
|
||||||
}
|
}
|
||||||
|
|
||||||
static void symax_init1()
|
static void __attribute__((unused)) symax_init1()
|
||||||
{
|
{
|
||||||
// duplicate stock tx sending strange packet (effect unknown)
|
// duplicate stock tx sending strange packet (effect unknown)
|
||||||
uint8_t first_packet[] = {0xf9, 0x96, 0x82, 0x1b, 0x20, 0x08, 0x08, 0xf2, 0x7d, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00};
|
uint8_t first_packet[] = {0xf9, 0x96, 0x82, 0x1b, 0x20, 0x08, 0x08, 0xf2, 0x7d, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00};
|
||||||
@ -247,7 +247,7 @@ static void symax_init1()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// channels determined by last byte of tx address
|
// channels determined by last byte of tx address
|
||||||
static void symax_set_channels(uint8_t address)
|
static void __attribute__((unused)) symax_set_channels(uint8_t address)
|
||||||
{
|
{
|
||||||
static const uint8_t start_chans_1[] = {0x0a, 0x1a, 0x2a, 0x3a};
|
static const uint8_t start_chans_1[] = {0x0a, 0x1a, 0x2a, 0x3a};
|
||||||
static const uint8_t start_chans_2[] = {0x2a, 0x0a, 0x42, 0x22};
|
static const uint8_t start_chans_2[] = {0x2a, 0x0a, 0x42, 0x22};
|
||||||
@ -290,7 +290,7 @@ static void symax_set_channels(uint8_t address)
|
|||||||
*pchans = 0x39194121;
|
*pchans = 0x39194121;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void symax_init2()
|
static void __attribute__((unused)) symax_init2()
|
||||||
{
|
{
|
||||||
uint8_t chans_data_x5c[] = {0x1d, 0x2f, 0x26, 0x3d, 0x15, 0x2b, 0x25, 0x24,
|
uint8_t chans_data_x5c[] = {0x1d, 0x2f, 0x26, 0x3d, 0x15, 0x2b, 0x25, 0x24,
|
||||||
0x27, 0x2c, 0x1c, 0x3e, 0x39, 0x2d, 0x22};
|
0x27, 0x2c, 0x1c, 0x3e, 0x39, 0x2d, 0x22};
|
||||||
|
@ -75,7 +75,7 @@ static const uint8_t freq_hopping[][16] = {
|
|||||||
0x18, 0x2A, 0x21, 0x38, 0x10, 0x26, 0x20, 0x1F } // 03
|
0x18, 0x2A, 0x21, 0x38, 0x10, 0x26, 0x20, 0x1F } // 03
|
||||||
};
|
};
|
||||||
|
|
||||||
static void v202_init()
|
static void __attribute__((unused)) v202_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ static void v202_init()
|
|||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x66\x88\x68\x68\x68", 5);
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x66\x88\x68\x68\x68", 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void V202_init2()
|
static void __attribute__((unused)) V202_init2()
|
||||||
{
|
{
|
||||||
NRF24L01_FlushTx();
|
NRF24L01_FlushTx();
|
||||||
packet_sent = 0;
|
packet_sent = 0;
|
||||||
@ -119,7 +119,7 @@ static void V202_init2()
|
|||||||
//Done by TX_EN??? => NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
|
//Done by TX_EN??? => NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void V2X2_set_tx_id(void)
|
static void __attribute__((unused)) V2X2_set_tx_id(void)
|
||||||
{
|
{
|
||||||
uint8_t sum;
|
uint8_t sum;
|
||||||
sum = rx_tx_addr[1] + rx_tx_addr[2] + rx_tx_addr[3];
|
sum = rx_tx_addr[1] + rx_tx_addr[2] + rx_tx_addr[3];
|
||||||
@ -134,7 +134,7 @@ static void V2X2_set_tx_id(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void V2X2_add_pkt_checksum()
|
static void __attribute__((unused)) V2X2_add_pkt_checksum()
|
||||||
{
|
{
|
||||||
uint8_t sum = 0;
|
uint8_t sum = 0;
|
||||||
for (uint8_t i = 0; i < 15; ++i)
|
for (uint8_t i = 0; i < 15; ++i)
|
||||||
@ -142,7 +142,7 @@ static void V2X2_add_pkt_checksum()
|
|||||||
packet[15] = sum;
|
packet[15] = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void V2X2_send_packet(uint8_t bind)
|
static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
uint8_t flags2=0;
|
uint8_t flags2=0;
|
||||||
if (bind)
|
if (bind)
|
||||||
|
@ -41,7 +41,7 @@ enum {
|
|||||||
YD717_DATA
|
YD717_DATA
|
||||||
};
|
};
|
||||||
|
|
||||||
static void yd717_send_packet(uint8_t bind)
|
static void __attribute__((unused)) yd717_send_packet(uint8_t bind)
|
||||||
{
|
{
|
||||||
uint8_t rudder_trim, elevator_trim, aileron_trim;
|
uint8_t rudder_trim, elevator_trim, aileron_trim;
|
||||||
if (bind)
|
if (bind)
|
||||||
@ -125,7 +125,7 @@ static void yd717_send_packet(uint8_t bind)
|
|||||||
NRF24L01_SetPower(); // Set tx_power
|
NRF24L01_SetPower(); // Set tx_power
|
||||||
}
|
}
|
||||||
|
|
||||||
static void yd717_init()
|
static void __attribute__((unused)) yd717_init()
|
||||||
{
|
{
|
||||||
NRF24L01_Initialize();
|
NRF24L01_Initialize();
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ static void yd717_init()
|
|||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YD717_init1()
|
static void __attribute__((unused)) YD717_init1()
|
||||||
{
|
{
|
||||||
// for bind packets set address to prearranged value known to receiver
|
// for bind packets set address to prearranged value known to receiver
|
||||||
uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65};
|
uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65};
|
||||||
@ -179,7 +179,7 @@ static void YD717_init1()
|
|||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_rx_tx_addr, 5);
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_rx_tx_addr, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YD717_init2()
|
static void __attribute__((unused)) YD717_init2()
|
||||||
{
|
{
|
||||||
// set rx/tx address for data phase
|
// set rx/tx address for data phase
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
|
||||||
|
234
Multiprotocol/_Config.h
Normal file
234
Multiprotocol/_Config.h
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
This project is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Multiprotocol is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Multiprotocol module configuration file ***/
|
||||||
|
|
||||||
|
//Uncomment your TX type
|
||||||
|
#define TARANIS //TARANIS TAER (1100<->1900µs)
|
||||||
|
//#define TX_ER9X //ER9X AETR (988<->2012µs)
|
||||||
|
//#define TX_DEVO7 //DEVO7 EATR (1120<->1920µs)
|
||||||
|
//#define TX_SPEKTRUM //Spektrum TAER (1100<->1900µs)
|
||||||
|
//#define TX_HISKY //HISKY AETR (1100<->1900µs)
|
||||||
|
|
||||||
|
//Uncomment to enable telemetry
|
||||||
|
#define TELEMETRY
|
||||||
|
#define HUB_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 a protocol to exclude it from compilation
|
||||||
|
#define BAYANG_NRF24L01_INO
|
||||||
|
#define CG023_NRF24L01_INO
|
||||||
|
#define CX10_NRF24L01_INO
|
||||||
|
#define DEVO_CYRF6936_INO
|
||||||
|
#define DSM2_CYRF6936_INO
|
||||||
|
#define ESKY_NRF24L01_INO
|
||||||
|
#define FLYSKY_A7105_INO
|
||||||
|
#define FRSKY_CC2500_INO // FRSKY2way
|
||||||
|
//#define FRSKYX_CC2500_INO
|
||||||
|
#define HISKY_NRF24L01_INO
|
||||||
|
#define HUBSAN_A7105_INO
|
||||||
|
#define KN_NRF24L01_INO
|
||||||
|
#define SLT_NRF24L01_INO
|
||||||
|
#define SYMAX_NRF24L01_INO
|
||||||
|
#define V2X2_NRF24L01_INO
|
||||||
|
#define YD717_NRF24L01_INO
|
||||||
|
|
||||||
|
#define H7_NRF24L01_INO
|
||||||
|
//#define HM830_NRF24L01_INO
|
||||||
|
//#define CFlie_NRF24L01_INO
|
||||||
|
|
||||||
|
//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]=
|
||||||
|
{
|
||||||
|
// Protocol , Sub protocol , RX_Num , Power , Auto Bind , Option
|
||||||
|
{MODE_DSM2 , DSM2 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=1
|
||||||
|
{MODE_FLYSKY, Flysky , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=2
|
||||||
|
{MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=3
|
||||||
|
{MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=4
|
||||||
|
{MODE_CG023 , CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=5
|
||||||
|
{MODE_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=6
|
||||||
|
{MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=7
|
||||||
|
{MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=8
|
||||||
|
{MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=9
|
||||||
|
{MODE_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=10
|
||||||
|
{MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=11
|
||||||
|
{MODE_SLT , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=12
|
||||||
|
{MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=13
|
||||||
|
{MODE_SYMAX , SYMAX5C , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=14
|
||||||
|
{MODE_FRSKY , 0 , 0 , P_HIGH , NO_AUTOBIND , 0xD7 }, //Dial=15
|
||||||
|
};
|
||||||
|
/* Available protocols and associated sub protocols:
|
||||||
|
MODE_FLYSKY
|
||||||
|
Flysky
|
||||||
|
V9X9
|
||||||
|
V6X6
|
||||||
|
V912
|
||||||
|
MODE_HUBSAN
|
||||||
|
NONE
|
||||||
|
MODE_FRSKY
|
||||||
|
NONE
|
||||||
|
MODE_HISKY
|
||||||
|
Hisky
|
||||||
|
HK310
|
||||||
|
MODE_V2X2
|
||||||
|
NONE
|
||||||
|
MODE_DSM2
|
||||||
|
DSM2
|
||||||
|
DSMX
|
||||||
|
MODE_DEVO
|
||||||
|
NONE
|
||||||
|
MODE_YD717
|
||||||
|
YD717
|
||||||
|
SKYWLKR
|
||||||
|
SYMAX4
|
||||||
|
XINXUN
|
||||||
|
NIHUI
|
||||||
|
MODE_KN
|
||||||
|
WLTOYS
|
||||||
|
FEILUN
|
||||||
|
MODE_SYMAX
|
||||||
|
SYMAX
|
||||||
|
SYMAX5C
|
||||||
|
MODE_SLT
|
||||||
|
NONE
|
||||||
|
MODE_CX10
|
||||||
|
CX10_GREEN
|
||||||
|
CX10_BLUE
|
||||||
|
DM007
|
||||||
|
Q282
|
||||||
|
JC3015_1
|
||||||
|
JC3015_2
|
||||||
|
MK33041
|
||||||
|
Q242
|
||||||
|
MODE_CG023
|
||||||
|
CG023
|
||||||
|
YD829
|
||||||
|
H8_3D
|
||||||
|
MODE_BAYANG
|
||||||
|
NONE
|
||||||
|
MODE_FRSKYX
|
||||||
|
NONE
|
||||||
|
MODE_ESKY
|
||||||
|
NONE
|
||||||
|
|
||||||
|
RX_Num value between 0 and 15
|
||||||
|
|
||||||
|
Power P_HIGH or P_LOW
|
||||||
|
|
||||||
|
Auto Bind AUTOBIND or NO_AUTOBIND
|
||||||
|
|
||||||
|
Option value between 0 and 255. 0xD7 or 0x00 for Frsky fine tuning.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//******************
|
||||||
|
//TX definitions with timing endpoints and channels order
|
||||||
|
|
||||||
|
// Turnigy PPM and channels
|
||||||
|
#if defined(TX_ER9X)
|
||||||
|
#define PPM_MAX 2140
|
||||||
|
#define PPM_MIN 860
|
||||||
|
#define PPM_MAX_100 2012
|
||||||
|
#define PPM_MIN_100 988
|
||||||
|
#define AETR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Devo PPM and channels
|
||||||
|
#if defined(TX_DEVO7)
|
||||||
|
#define PPM_MAX 2100
|
||||||
|
#define PPM_MIN 900
|
||||||
|
#define PPM_MAX_100 1920
|
||||||
|
#define PPM_MIN_100 1120
|
||||||
|
#define EATR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// SPEKTRUM PPM and channels
|
||||||
|
#if defined(TX_SPEKTRUM) | defined(TARANIS)
|
||||||
|
#define PPM_MAX 2000
|
||||||
|
#define PPM_MIN 1000
|
||||||
|
#define PPM_MAX_100 1900
|
||||||
|
#define PPM_MIN_100 1100
|
||||||
|
#define TAER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// HISKY
|
||||||
|
#if defined(TX_HISKY)
|
||||||
|
#define PPM_MAX 2000
|
||||||
|
#define PPM_MIN 1000
|
||||||
|
#define PPM_MAX_100 1900
|
||||||
|
#define PPM_MIN_100 1100
|
||||||
|
#define AETR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(EATR)
|
||||||
|
enum chan_order{
|
||||||
|
ELEVATOR=0,
|
||||||
|
AILERON,
|
||||||
|
THROTTLE,
|
||||||
|
RUDDER,
|
||||||
|
AUX1,
|
||||||
|
AUX2,
|
||||||
|
AUX3,
|
||||||
|
AUX4,
|
||||||
|
AUX5,
|
||||||
|
AUX6,
|
||||||
|
AUX7,
|
||||||
|
AUX8
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TAER)
|
||||||
|
enum chan_order{
|
||||||
|
THROTTLE=0,
|
||||||
|
AILERON,
|
||||||
|
ELEVATOR,
|
||||||
|
RUDDER,
|
||||||
|
AUX1,
|
||||||
|
AUX2,
|
||||||
|
AUX3,
|
||||||
|
AUX4,
|
||||||
|
AUX5,
|
||||||
|
AUX6,
|
||||||
|
AUX7,
|
||||||
|
AUX8
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(AETR)
|
||||||
|
enum chan_order{
|
||||||
|
AILERON =0,
|
||||||
|
ELEVATOR,
|
||||||
|
THROTTLE,
|
||||||
|
RUDDER,
|
||||||
|
AUX1,
|
||||||
|
AUX2,
|
||||||
|
AUX3,
|
||||||
|
AUX4,
|
||||||
|
AUX5,
|
||||||
|
AUX6,
|
||||||
|
AUX7,
|
||||||
|
AUX8
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PPM_MIN_COMMAND 1250
|
||||||
|
#define PPM_SWITCH 1550
|
||||||
|
#define PPM_MAX_COMMAND 1750
|
@ -16,6 +16,16 @@
|
|||||||
#ifndef _IFACE_CC2500_H_
|
#ifndef _IFACE_CC2500_H_
|
||||||
#define _IFACE_CC2500_H_
|
#define _IFACE_CC2500_H_
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FRSKY_BIND = 0,
|
||||||
|
FRSKY_BIND_DONE = 1000,
|
||||||
|
FRSKY_DATA1,
|
||||||
|
FRSKY_DATA2,
|
||||||
|
FRSKY_DATA3,
|
||||||
|
FRSKY_DATA4,
|
||||||
|
FRSKY_DATA5
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CC2500_00_IOCFG2 = 0x00, // GDO2 output pin configuration
|
CC2500_00_IOCFG2 = 0x00, // GDO2 output pin configuration
|
||||||
CC2500_01_IOCFG1 = 0x01, // GDO1 output pin configuration
|
CC2500_01_IOCFG1 = 0x01, // GDO1 output pin configuration
|
||||||
|
65
Multiprotocol/liste.txt
Normal file
65
Multiprotocol/liste.txt
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
MODE_SERIAL = 0, // Serial / Manche commands
|
||||||
|
MODE_FLYSKY = 1, // =>A7105 { Flysky=0, V9X9=1, V6X6=2, V912=3 };
|
||||||
|
MODE_HUBSAN = 2, // =>A7105
|
||||||
|
MODE_CG023 = 3, // =>NRF24L01 { CG023 = 0, YD829 = 1, H8_3D = 2 };
|
||||||
|
MODE_CX10 = 4, // =>NRF24L01 { CX10_GREEN = 0, DM007=2, CX10_BLUE=1, // also compatible with CX10-A, CX12 };
|
||||||
|
MODE_HISKY = 6, // =>NRF24L01 { Hisky=0, HK310=1 };
|
||||||
|
MODE_DSM2 = 6, // =>CYRF6936 { DSM2=0, DSMX=1};
|
||||||
|
MODE_DEVO =7, // =>CYRF6936
|
||||||
|
MODE_YD717 = 8, // =>NRF24L01 { YD717=0, SKYWLKR=1, SYMAX2=2, XINXUN=3, NIHUI=4 };
|
||||||
|
MODE_KN = 9, // =>NRF24L01
|
||||||
|
MODE_SYMAX = 10, // =>NRF24L01 { SYMAX=0, SYMAX5C=1, };
|
||||||
|
MODE_SLT = 11, // =>NRF24L01
|
||||||
|
MODE_V2X2 = 12, // =>NRF24L01
|
||||||
|
MODE_BAYANG = 13, // =>NRF24L01
|
||||||
|
MODE_FRSKY = 14, // =>CC2500
|
||||||
|
= 15, // =>
|
||||||
|
|
||||||
|
BAYANG
|
||||||
|
AUX1 FLIP
|
||||||
|
AUX2 HEADLESS
|
||||||
|
AUX3 RTH
|
||||||
|
AUX4 SNAPSHOT
|
||||||
|
AUX5 VIDEO
|
||||||
|
|
||||||
|
CG023
|
||||||
|
AUX1 FLIP
|
||||||
|
AUX2 LED
|
||||||
|
AUX3 STILL
|
||||||
|
AUX4 VIDEO
|
||||||
|
AUX5 EASY
|
||||||
|
|
||||||
|
CX10
|
||||||
|
AUX1 FLIP
|
||||||
|
AUX2 mode 1-2-3 (headless on CX-10A)
|
||||||
|
AUX3 SNAPSHOT
|
||||||
|
AUX4 VIDEO
|
||||||
|
AUX5 HEADLESS
|
||||||
|
|
||||||
|
HUBSAN
|
||||||
|
AUX1 FLIP
|
||||||
|
AUX2 LED
|
||||||
|
AUX3 VIDEO
|
||||||
|
|
||||||
|
KN
|
||||||
|
AUX1 Dual rate
|
||||||
|
AUX2 Throttle Hold
|
||||||
|
AUX3 Idle up
|
||||||
|
AUX4 Gyro
|
||||||
|
|
||||||
|
V2X2
|
||||||
|
AUX1 FLIP
|
||||||
|
AUX2 LED
|
||||||
|
AUX3 CAMERA
|
||||||
|
AUX4 VIDEO
|
||||||
|
AUX5 HEADLESS
|
||||||
|
AUX6 MAG_CAL_X
|
||||||
|
AUX7 MAG_CAL_Y
|
||||||
|
|
||||||
|
YD717
|
||||||
|
AUX1 FLIP
|
||||||
|
AUX2 LED
|
||||||
|
AUX3 PICTURE
|
||||||
|
AUX4 VIDEO
|
||||||
|
AUX5 HEADLESS
|
||||||
|
|
91
Multiprotocol/multi.lua
Normal file
91
Multiprotocol/multi.lua
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
-- Multiprotocole Midelic et Pascallanger
|
||||||
|
local debut = 0
|
||||||
|
local tps = 0
|
||||||
|
local tpsact = 1024
|
||||||
|
local mix, mixe
|
||||||
|
local channel
|
||||||
|
|
||||||
|
local inp = {
|
||||||
|
{ "Protocole", VALUE, 1, 26, 2 },
|
||||||
|
{ "Switch", SOURCE }
|
||||||
|
}
|
||||||
|
-- 6 7 8 15 16 17 24 25 26
|
||||||
|
-- 4 5 12 13 14 21 22 23
|
||||||
|
-- 1 2 3 9 10 11 18 19 20
|
||||||
|
local out = { "Bind", "Gaz", "Aile", "Prof", "Dir" }
|
||||||
|
|
||||||
|
local function run_func(proto, sw)
|
||||||
|
-- test mixage lua
|
||||||
|
if debut == 0 then
|
||||||
|
-- passage en lua
|
||||||
|
for channel = 0, 3, 1 do
|
||||||
|
local mix = model.getMix(channel, 0)
|
||||||
|
mix_source = mix["source"]
|
||||||
|
if mix_source < 33 or 1 then
|
||||||
|
model.deleteMix(channel, 0)
|
||||||
|
mix["source"] = channel + 34
|
||||||
|
mix["name"] = "Lua "
|
||||||
|
model.insertMix(channel, 0, mix)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- inter install
|
||||||
|
channel = 4
|
||||||
|
mix = { name="Raz Bind", source=33, weight=100, switch=0, multiplex=REPLACE }
|
||||||
|
count = model.getMixesCount(channel + 0)
|
||||||
|
if count == 0 and inter == 1 then
|
||||||
|
model.insertMix(channel + 0, 0, mix)
|
||||||
|
elseif count == 1 and inter == 0 then
|
||||||
|
mixe = model.getMix(channel, 0)
|
||||||
|
if mixe["name"] == mix["name"] then
|
||||||
|
model.deleteMix(channel, 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- delais init
|
||||||
|
if proto ~= debut then
|
||||||
|
tps = getTime() + 500 -- delai pour mini 12 cycle PPM
|
||||||
|
tpsact = 1024
|
||||||
|
debut = proto
|
||||||
|
end
|
||||||
|
|
||||||
|
local gaz = 1024
|
||||||
|
local ail = 0
|
||||||
|
local dir = 0
|
||||||
|
local pro = 0
|
||||||
|
|
||||||
|
if tpsact == 0 and sw < 200 then
|
||||||
|
-- reprise valeur input
|
||||||
|
pro = getValue(1)
|
||||||
|
ail = getValue(2)
|
||||||
|
gaz = getValue(3)
|
||||||
|
dir = getValue(4)
|
||||||
|
elseif tpsact ~= 0 then
|
||||||
|
-- decallage pour position memo (centre)
|
||||||
|
if proto > 4 then proto = proto + 1 end
|
||||||
|
|
||||||
|
-- calcul position
|
||||||
|
-- decallage pour > 18
|
||||||
|
if proto > 18 then
|
||||||
|
ail = 1024
|
||||||
|
proto = proto - 18
|
||||||
|
end
|
||||||
|
-- decallage pour > 9
|
||||||
|
if proto > 9 then
|
||||||
|
ail = -1024
|
||||||
|
proto = proto - 9
|
||||||
|
end
|
||||||
|
|
||||||
|
if proto < 4 then pro = -1024 end
|
||||||
|
if proto > 6 then pro = 1024 end
|
||||||
|
|
||||||
|
if proto % 3 == 1 then dir = -1024 end
|
||||||
|
if proto % 3 == 0 then dir = 1024 end
|
||||||
|
|
||||||
|
if tps < getTime() then tpsact = 0 end
|
||||||
|
sw = tpsact
|
||||||
|
end
|
||||||
|
|
||||||
|
return sw, gaz, ail, pro, dir
|
||||||
|
end
|
||||||
|
return { run=run_func, input=inp, output=out}
|
@ -28,13 +28,17 @@ enum PROTOCOLS
|
|||||||
MODE_DEVO =7, // =>CYRF6936 / DEVO protocol
|
MODE_DEVO =7, // =>CYRF6936 / DEVO protocol
|
||||||
MODE_YD717 = 8, // =>NRF24L01 / YD717 protocol (CX10 red pcb)
|
MODE_YD717 = 8, // =>NRF24L01 / YD717 protocol (CX10 red pcb)
|
||||||
MODE_KN = 9, // =>NRF24L01 / KN protocol
|
MODE_KN = 9, // =>NRF24L01 / KN protocol
|
||||||
MODE_SYMAX = 10, // =>NRF24L01 / SYMAX protocol (SYMAX4 working)
|
MODE_SYMAX = 10, // =>NRF24L01 / SYMAX protocol
|
||||||
MODE_SLT = 11, // =>NRF24L01 / SLT protocol
|
MODE_SLT = 11, // =>NRF24L01 / SLT protocol
|
||||||
MODE_CX10 = 12, // =>NRF24L01 / CX-10 protocol
|
MODE_CX10 = 12, // =>NRF24L01 / CX-10 protocol
|
||||||
MODE_CG023 = 13, // =>NRF24L01 / CG023 protocol
|
MODE_CG023 = 13, // =>NRF24L01 / CG023 protocol
|
||||||
MODE_BAYANG = 14, // =>NRF24L01 / BAYANG protocol
|
MODE_BAYANG = 14, // =>NRF24L01 / BAYANG protocol
|
||||||
MODE_FRSKYX = 15, // =>CC2500 / FRSKYX protocol
|
MODE_FRSKYX = 15, // =>CC2500 / FRSKYX protocol
|
||||||
MODE_ESKY = 16, // =>NRF24L01 / ESKY protocol
|
MODE_ESKY = 16, // =>NRF24L01 / ESKY protocol
|
||||||
|
// Ajout
|
||||||
|
MODE_H7 = 21, // =>NRF24L01 / EAchine MT99xx (H7, MT9916 ...)
|
||||||
|
// MODE_HM830 =22, // =>NRF24L01 / HM830
|
||||||
|
MODE_CFLIE =23, // =>NRF24L01 / CFlie
|
||||||
};
|
};
|
||||||
enum Flysky
|
enum Flysky
|
||||||
{
|
{
|
||||||
@ -78,7 +82,8 @@ enum CX10
|
|||||||
Q282=3,
|
Q282=3,
|
||||||
JC3015_1=4,
|
JC3015_1=4,
|
||||||
JC3015_2=5,
|
JC3015_2=5,
|
||||||
MK33041=6
|
MK33041=6,
|
||||||
|
Q242=7
|
||||||
};
|
};
|
||||||
enum CG023
|
enum CG023
|
||||||
{
|
{
|
||||||
@ -87,101 +92,22 @@ enum CG023
|
|||||||
H8_3D = 2
|
H8_3D = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
//******************
|
|
||||||
//TX definitions with timing endpoints and channels order
|
|
||||||
//******************
|
|
||||||
|
|
||||||
// Turnigy PPM and channels
|
#define NONE 0
|
||||||
#if defined(TX_ER9X)
|
#define P_HIGH 1
|
||||||
#define PPM_MAX 2140
|
#define P_LOW 0
|
||||||
#define PPM_MIN 860
|
#define AUTOBIND 1
|
||||||
#define PPM_MAX_100 2012
|
#define NO_AUTOBIND 0
|
||||||
#define PPM_MIN_100 988
|
|
||||||
enum chan_order{
|
struct PPM_Parameters
|
||||||
AILERON =0,
|
{
|
||||||
ELEVATOR,
|
uint8_t protocol : 5;
|
||||||
THROTTLE,
|
uint8_t sub_proto : 3;
|
||||||
RUDDER,
|
uint8_t rx_num : 4;
|
||||||
AUX1,
|
uint8_t power : 1;
|
||||||
AUX2,
|
uint8_t autobind : 1;
|
||||||
AUX3,
|
uint8_t option;
|
||||||
AUX4,
|
|
||||||
AUX5,
|
|
||||||
AUX6,
|
|
||||||
AUX7,
|
|
||||||
AUX8
|
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
// Devo PPM and channels
|
|
||||||
#if defined(TX_DEVO7)
|
|
||||||
#define PPM_MAX 2100
|
|
||||||
#define PPM_MIN 900
|
|
||||||
#define PPM_MAX_100 1920
|
|
||||||
#define PPM_MIN_100 1120
|
|
||||||
enum chan_order{
|
|
||||||
ELEVATOR=0,
|
|
||||||
AILERON,
|
|
||||||
THROTTLE,
|
|
||||||
RUDDER,
|
|
||||||
AUX1,
|
|
||||||
AUX2,
|
|
||||||
AUX3,
|
|
||||||
AUX4,
|
|
||||||
AUX5,
|
|
||||||
AUX6,
|
|
||||||
AUX7,
|
|
||||||
AUX8
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// SPEKTRUM PPM and channels
|
|
||||||
#if defined(TX_SPEKTRUM)
|
|
||||||
#define PPM_MAX 2000
|
|
||||||
#define PPM_MIN 1000
|
|
||||||
#define PPM_MAX_100 1900
|
|
||||||
#define PPM_MIN_100 1100
|
|
||||||
enum chan_order{
|
|
||||||
THROTTLE=0,
|
|
||||||
AILERON,
|
|
||||||
ELEVATOR,
|
|
||||||
RUDDER,
|
|
||||||
AUX1,
|
|
||||||
AUX2,
|
|
||||||
AUX3,
|
|
||||||
AUX4,
|
|
||||||
AUX5,
|
|
||||||
AUX6,
|
|
||||||
AUX7,
|
|
||||||
AUX8
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// HISKY
|
|
||||||
#if defined(TX_HISKY)
|
|
||||||
#define PPM_MAX 2000
|
|
||||||
#define PPM_MIN 1000
|
|
||||||
#define PPM_MAX_100 1900
|
|
||||||
#define PPM_MIN_100 1100
|
|
||||||
enum chan_order{
|
|
||||||
AILERON =0,
|
|
||||||
ELEVATOR,
|
|
||||||
THROTTLE,
|
|
||||||
RUDDER,
|
|
||||||
AUX1,
|
|
||||||
AUX2,
|
|
||||||
AUX3,
|
|
||||||
AUX4,
|
|
||||||
AUX5,
|
|
||||||
AUX6,
|
|
||||||
AUX7,
|
|
||||||
AUX8
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PPM_MIN_COMMAND 1250
|
|
||||||
#define PPM_SWITCH 1550
|
|
||||||
#define PPM_MAX_COMMAND 1750
|
|
||||||
|
|
||||||
//*******************
|
//*******************
|
||||||
//*** Pinouts ***
|
//*** Pinouts ***
|
||||||
@ -508,6 +434,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
|||||||
JC3015_1 4
|
JC3015_1 4
|
||||||
JC3015_2 5
|
JC3015_2 5
|
||||||
MK33041 6
|
MK33041 6
|
||||||
|
Q242 7
|
||||||
sub_protocol==CG023
|
sub_protocol==CG023
|
||||||
CG023 0
|
CG023 0
|
||||||
YD829 1
|
YD829 1
|
||||||
@ -523,86 +450,5 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
|||||||
1843 +100%
|
1843 +100%
|
||||||
2047 +125%
|
2047 +125%
|
||||||
Channels bits are concatenated to fit in 22 bytes like in SBUS protocol
|
Channels bits are concatenated to fit in 22 bytes like in SBUS protocol
|
||||||
|
|
||||||
|
|
||||||
**************************
|
|
||||||
8 channels serial protocol
|
|
||||||
**************************
|
|
||||||
Serial: 125000 Baud 8n1 _ xxxx xxxx - ---
|
|
||||||
Channels:
|
|
||||||
Nbr=8
|
|
||||||
10bits=0..1023
|
|
||||||
0 -125%
|
|
||||||
96 -100%
|
|
||||||
512 0%
|
|
||||||
928 +100%
|
|
||||||
1023 +125%
|
|
||||||
Stream[0] = sub_protocol|BindBit|RangeCheckBit|AutoBindBit;
|
|
||||||
sub_protocol is 0..31 (bits 0..4)
|
|
||||||
=> Reserved 0
|
|
||||||
Flysky 1
|
|
||||||
Hubsan 2
|
|
||||||
Frsky 3
|
|
||||||
Hisky 4
|
|
||||||
V2x2 5
|
|
||||||
DSM2 6
|
|
||||||
Devo 7
|
|
||||||
YD717 8
|
|
||||||
KN 9
|
|
||||||
SymaX 10
|
|
||||||
SLT 11
|
|
||||||
CX10 12
|
|
||||||
CG023 13
|
|
||||||
Bayang 14
|
|
||||||
FrskyX 15
|
|
||||||
ESky 16
|
|
||||||
BindBit=> 0x80 1=Bind/0=No
|
|
||||||
AutoBindBit=> 0x40 1=Yes /0=No
|
|
||||||
RangeCheck=> 0x20 1=Yes /0=No
|
|
||||||
Stream[1] = RxNum | Power | Type;
|
|
||||||
RxNum value is 0..15 (bits 0..3)
|
|
||||||
Type is 0..7 <<4 (bit 4..6)
|
|
||||||
sub_protocol==Flysky
|
|
||||||
Flysky 0
|
|
||||||
V9x9 1
|
|
||||||
V6x6 2
|
|
||||||
V912 3
|
|
||||||
sub_protocol==Hisky
|
|
||||||
Hisky 0
|
|
||||||
HK310 1
|
|
||||||
sub_protocol==DSM2
|
|
||||||
DSM2 0
|
|
||||||
DSMX 1
|
|
||||||
sub_protocol==YD717
|
|
||||||
YD717 0
|
|
||||||
SKYWLKR 1
|
|
||||||
SYMAX4 2
|
|
||||||
XINXUN 3
|
|
||||||
NIHUI 4
|
|
||||||
sub_protocol==KN
|
|
||||||
WLTOYS 0
|
|
||||||
FEILUN 1
|
|
||||||
sub_protocol==SYMAX
|
|
||||||
SYMAX 0
|
|
||||||
SYMAX5C 1
|
|
||||||
sub_protocol==CX10
|
|
||||||
CX10_GREEN 0
|
|
||||||
CX10_BLUE 1 // also compatible with CX10-A, CX12
|
|
||||||
DM007 2
|
|
||||||
Q282 3
|
|
||||||
JC3015_1 4
|
|
||||||
JC3015_2 5
|
|
||||||
MK33041 6
|
|
||||||
sub_protocol==CG023
|
|
||||||
CG023 0
|
|
||||||
YD829 1
|
|
||||||
H8_3D 2
|
|
||||||
Power value => 0x80 0=High/1=Low
|
|
||||||
Stream[2] = option_protocol;
|
|
||||||
option_protocol value is -127..127
|
|
||||||
Stream[i+3] = lowByte(channel[i]) // with i[0..7]
|
|
||||||
Stream[11] = highByte(channel[0])<<6 | highByte(channel[1])<<4 | highByte(channel[2])<<2 | highByte(channel[3])
|
|
||||||
Stream[12] = highByte(channel[4])<<6 | highByte(channel[5])<<4 | highByte(channel[6])<<2 | highByte(channel[7])
|
|
||||||
Stream[13] = lowByte(CRC16(Stream[0..12])
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
151
Multiprotocol/nrf24l01_H7.ino
Normal file
151
Multiprotocol/nrf24l01_H7.ino
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
This program 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.
|
||||||
|
|
||||||
|
This program 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. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// EAchine MT99xx (H7, MT9916 ...) TX protocol
|
||||||
|
|
||||||
|
// Auxiliary channels:
|
||||||
|
// CH5: rate (3 pos)
|
||||||
|
// CH6: flip flag
|
||||||
|
// CH7: still camera
|
||||||
|
// CH8: video camera
|
||||||
|
// CH10: elevator trim
|
||||||
|
// CH11: aileron trim
|
||||||
|
|
||||||
|
#if defined(H7_NRF24L01_INO)
|
||||||
|
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
static const uint8_t H7_freq[] = {
|
||||||
|
0x02, 0x48, 0x0C, 0x3e, 0x16, 0x34, 0x20, 0x2A,
|
||||||
|
0x2A, 0x20, 0x34, 0x16, 0x3e, 0x0c, 0x48, 0x02
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t H7_mys_byte[] = {
|
||||||
|
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
|
||||||
|
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
// flags going to packet[6]
|
||||||
|
// H7_FLAG_RATE0, // default rate, no flag
|
||||||
|
#define H7_FLAG_RATE1 0x01
|
||||||
|
#define H7_FLAG_RATE2 0x02
|
||||||
|
#define H7_FLAG_VIDEO 0x10
|
||||||
|
#define H7_FLAG_SNAPSHOT 0x20
|
||||||
|
#define H7_FLAG_FLIP 0x80
|
||||||
|
|
||||||
|
uint8_t H7_tx_addr[5];
|
||||||
|
|
||||||
|
uint8_t checksum_offset;
|
||||||
|
uint8_t channel_offset;
|
||||||
|
|
||||||
|
#define H7_PACKET_PERIOD 2625
|
||||||
|
#define H7_PAYPLOAD_SIZE 9
|
||||||
|
|
||||||
|
void H7_initTXID() {
|
||||||
|
checksum_offset = (rx_tx_addr[0] + rx_tx_addr[1]) & 0xff;
|
||||||
|
channel_offset = (((checksum_offset & 0xf0)>>4) + (checksum_offset & 0x0f)) % 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t H7_init() {
|
||||||
|
H7_initTXID();
|
||||||
|
NRF24L01_Reset();
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
delay(10);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
for(u8 i=0; i<5; i++) { H7_tx_addr[i] = 0xCC; }
|
||||||
|
XN297_SetTXAddr(H7_tx_addr, 5);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // clear data ready, data sent, and retransmit
|
||||||
|
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // no AA
|
||||||
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // enable data pipe 0 only
|
||||||
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes address
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // set RF channel
|
||||||
|
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00);// no auto retransmit
|
||||||
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x09); // rx payload size (unused ?)
|
||||||
|
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
NRF24L01_Activate(0x73);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00);
|
||||||
|
NRF24L01_ReadReg(NRF24L01_1D_FEATURE); // read reg 1D back ?
|
||||||
|
delay(150);
|
||||||
|
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||||
|
delay(100);
|
||||||
|
H7_bind();
|
||||||
|
return H7_PACKET_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void H7_bind() {
|
||||||
|
BIND_IN_PROGRESS;
|
||||||
|
uint8_t counter = 58;
|
||||||
|
packet[0] = 0x20; // fixed (firmware date 2014-03-25 ?)
|
||||||
|
packet[1] = 0x14; // fixed
|
||||||
|
packet[2] = 0x03; // fixed
|
||||||
|
packet[3] = 0x25; // fixed
|
||||||
|
packet[4] = rx_tx_addr[0]; // 1st byte for data phase tx address
|
||||||
|
packet[5] = rx_tx_addr[1]; // 2nd byte for data phase tx address
|
||||||
|
packet[6] = 0x00; // 3rd byte for data phase tx address (always 0x00 ?)
|
||||||
|
packet[7] = checksum_offset; // checksum offset
|
||||||
|
packet[8] = 0xAA; // fixed
|
||||||
|
while(counter--) {
|
||||||
|
for (uint8_t ch = 0; ch < 16; ch++) {
|
||||||
|
delayMicroseconds(5);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS,0x70);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH,H7_freq[ch]);
|
||||||
|
XN297_WritePayload(packet, H7_PAYPLOAD_SIZE); //(bind packet)
|
||||||
|
delayMicroseconds(H7_PACKET_PERIOD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(15);
|
||||||
|
H7_tx_addr[0] = rx_tx_addr[0];
|
||||||
|
H7_tx_addr[1] = rx_tx_addr[1];
|
||||||
|
H7_tx_addr[2] = 0;
|
||||||
|
XN297_SetTXAddr(H7_tx_addr, 5);
|
||||||
|
BIND_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t H7_calcChecksum() {
|
||||||
|
uint8_t result=checksum_offset;
|
||||||
|
for(uint8_t i=0; i<8; i++) { result += packet[i]; }
|
||||||
|
return result & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void H7_WritePacket() {
|
||||||
|
static uint8_t channel=0;
|
||||||
|
packet[0] = map(Servo_data[THROTTLE], PPM_MIN, PPM_MAX, 0xE1, 0x00);
|
||||||
|
packet[1] = map(Servo_data[RUDDER], PPM_MIN, PPM_MAX, 0xE1, 0x00);
|
||||||
|
packet[2] = map(Servo_data[AILERON], PPM_MIN, PPM_MAX, 0x00, 0xE1);
|
||||||
|
packet[3] = map(Servo_data[ELEVATOR], PPM_MIN, PPM_MAX, 0x00, 0xE1);
|
||||||
|
packet[4] = map(Servo_data[AUX7], PPM_MIN, PPM_MAX, 0x3f, 0x00); // elevator trim 0x3f - 0x00
|
||||||
|
packet[5] = map(Servo_data[AUX8], PPM_MIN, PPM_MAX, 0x3f, 0x00); // aileron trim 0x3f - 0x00
|
||||||
|
packet[6] = 0x40; // flags (default is 0x00 on H7, 0x40 on MT9916 stock TX)
|
||||||
|
if(Servo_data[AUX2] > PPM_MAX_COMMAND) { packet[6] |= H7_FLAG_FLIP; }
|
||||||
|
|
||||||
|
if(Servo_data[AUX1] > PPM_MAX_COMMAND) { packet[6] |= H7_FLAG_RATE2; }
|
||||||
|
else if(Servo_data[AUX1] > PPM_MIN_COMMAND) { packet[6] |= H7_FLAG_RATE1; }
|
||||||
|
|
||||||
|
if(Servo_data[AUX5] > PPM_MAX_COMMAND) { packet[6] |= H7_FLAG_SNAPSHOT; }
|
||||||
|
if(Servo_data[AUX6] > PPM_MAX_COMMAND) { packet[6] |= H7_FLAG_VIDEO; }
|
||||||
|
packet[7] = H7_mys_byte[channel]; // looks like this byte has no importance actually
|
||||||
|
packet[8] = H7_calcChecksum();
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, H7_freq[channel]+channel_offset);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
XN297_WritePayload(packet, H7_PAYPLOAD_SIZE);
|
||||||
|
channel++;
|
||||||
|
if(channel > 15) { channel = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t process_H7() {
|
||||||
|
H7_WritePacket();
|
||||||
|
return H7_PACKET_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
321
Multiprotocol/nrf24l01_hm830.ino
Normal file
321
Multiprotocol/nrf24l01_hm830.ino
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
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 protocol is for the HM Hobby HM830 RC Paper Airplane
|
||||||
|
Protocol spec:
|
||||||
|
Channel data:
|
||||||
|
AA BB CC DD EE FF GG
|
||||||
|
AA : Throttle Min=0x00 max =0x64
|
||||||
|
BB :
|
||||||
|
bit 0,1,2: Left/Right magnitude, bit 5 Polarity (set = right)
|
||||||
|
bit 6: Accelerate
|
||||||
|
bit 7: Right button (also the ABC Button)
|
||||||
|
CC : bit 0 seems to be impacted by the Right button
|
||||||
|
DD
|
||||||
|
EE
|
||||||
|
FF : Trim (bit 0-5: Magnitude, bit 6 polarity (set = right)
|
||||||
|
GG : Checksum (CRC8 on bytes AA-FF), init = 0xa5, poly = 0x01
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HM830_NRF24L01_INO
|
||||||
|
|
||||||
|
#include "iface_nrf24l01.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HM830_BIND1A = 0,
|
||||||
|
HM830_BIND2A,
|
||||||
|
HM830_BIND3A,
|
||||||
|
HM830_BIND4A,
|
||||||
|
HM830_BIND5A,
|
||||||
|
HM830_BIND6A,
|
||||||
|
HM830_BIND7A,
|
||||||
|
HM830_DATA1,
|
||||||
|
HM830_DATA2,
|
||||||
|
HM830_DATA3,
|
||||||
|
HM830_DATA4,
|
||||||
|
HM830_DATA5,
|
||||||
|
HM830_DATA6,
|
||||||
|
HM830_DATA7,
|
||||||
|
HM830_BIND1B = 0x80,
|
||||||
|
HM830_BIND2B,
|
||||||
|
HM830_BIND3B,
|
||||||
|
HM830_BIND4B,
|
||||||
|
HM830_BIND5B,
|
||||||
|
HM830_BIND6B,
|
||||||
|
HM830_BIND7B,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t init_vals[][2] = {
|
||||||
|
{NRF24L01_17_FIFO_STATUS, 0x00},
|
||||||
|
{NRF24L01_16_RX_PW_P5, 0x07},
|
||||||
|
{NRF24L01_15_RX_PW_P4, 0x07},
|
||||||
|
{NRF24L01_14_RX_PW_P3, 0x07},
|
||||||
|
{NRF24L01_13_RX_PW_P2, 0x07},
|
||||||
|
{NRF24L01_12_RX_PW_P1, 0x07},
|
||||||
|
{NRF24L01_11_RX_PW_P0, 0x07},
|
||||||
|
{NRF24L01_0F_RX_ADDR_P5, 0xC6},
|
||||||
|
{NRF24L01_0E_RX_ADDR_P4, 0xC5},
|
||||||
|
{NRF24L01_0D_RX_ADDR_P3, 0xC4},
|
||||||
|
{NRF24L01_0C_RX_ADDR_P2, 0xC3},
|
||||||
|
{NRF24L01_09_CD, 0x00},
|
||||||
|
{NRF24L01_08_OBSERVE_TX, 0x00},
|
||||||
|
{NRF24L01_07_STATUS, 0x07},
|
||||||
|
// {NRF24L01_06_RF_SETUP, 0x07},
|
||||||
|
{NRF24L01_05_RF_CH, 0x18},
|
||||||
|
{NRF24L01_04_SETUP_RETR, 0x3F},
|
||||||
|
{NRF24L01_03_SETUP_AW, 0x03},
|
||||||
|
{NRF24L01_02_EN_RXADDR, 0x3F},
|
||||||
|
{NRF24L01_01_EN_AA, 0x3F},
|
||||||
|
{NRF24L01_00_CONFIG, 0x0E},
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t count;
|
||||||
|
static const uint8_t rf_ch[] = {0x08, 0x35, 0x12, 0x3f, 0x1c, 0x49, 0x26};
|
||||||
|
static const uint8_t bind_addr[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xc2};
|
||||||
|
|
||||||
|
static uint8_t crc8(uint32_t result, uint8_t *data, int len) {
|
||||||
|
int polynomial = 0x01;
|
||||||
|
for(int i = 0; i < len; i++) {
|
||||||
|
result = result ^ data[i];
|
||||||
|
for(int j = 0; j < 8; j++) {
|
||||||
|
if(result & 0x80) { result = (result << 1) ^ polynomial; }
|
||||||
|
else { result = result << 1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HM830_init() {
|
||||||
|
NRF24L01_Initialize();
|
||||||
|
for (uint32_t i = 0; i < sizeof(init_vals) / sizeof(init_vals[0]); i++) { NRF24L01_WriteReg(init_vals[i][0], init_vals[i][1]); }
|
||||||
|
|
||||||
|
NRF24L01_SetTxRxMode(TX_EN);
|
||||||
|
NRF24L01_SetBitrate(0);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bind_addr, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, bind_addr+1, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_addr, 5);
|
||||||
|
NRF24L01_Activate(0x73); //Enable FEATURE
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F);
|
||||||
|
//NRF24L01_ReadReg(NRF24L01_07_STATUS) ==> 0x07
|
||||||
|
|
||||||
|
// Check for Beken BK2421/BK2423 chip
|
||||||
|
// It is done by using Beken specific activate code, 0x53 and checking that status register changed appropriately
|
||||||
|
// There is no harm to run it on nRF24L01 because following closing activate command changes state back even if it does something on nRF24L01
|
||||||
|
// For detailed description of what's happening here see : http://www.inhaos.com/uploadfile/otherpic/AN0008-BK2423%20Communication%20In%20250Kbps%20Air%20Rate.pdf
|
||||||
|
NRF24L01_Activate(0x53); // magic for BK2421 bank switch
|
||||||
|
// printf("=>H377 : Trying to switch banks\n");
|
||||||
|
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & 0x80) {
|
||||||
|
// printf("=>H377 : BK2421 detected\n");
|
||||||
|
long nul = 0;
|
||||||
|
// Beken registers don't have such nice names, so we just mention them by their numbers
|
||||||
|
// It's all magic, eavesdropped from real transfer and not even from the data sheet - it has slightly different values
|
||||||
|
NRF24L01_WriteRegisterMulti(0x00, (uint8_t *) "\x40\x4B\x01\xE2", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x01, (uint8_t *) "\xC0\x4B\x00\x00", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x02, (uint8_t *) "\xD0\xFC\x8C\x02", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x03, (uint8_t *) "\xF9\x00\x39\x21", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x04, (uint8_t *) "\xC1\x96\x9A\x1B", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x05, (uint8_t *) "\x24\x06\x7F\xA6", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x06, (uint8_t *) &nul, 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x07, (uint8_t *) &nul, 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x08, (uint8_t *) &nul, 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x09, (uint8_t *) &nul, 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x0A, (uint8_t *) &nul, 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x0B, (uint8_t *) &nul, 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x0C, (uint8_t *) "\x00\x12\x73\x00", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x0D, (uint8_t *) "\x46\xB4\x80\x00", 4);
|
||||||
|
//NRF24L01_WriteRegisterMulti(0x0E, (uint8_t *) "\x41\x10\x04\x82\x20\x08\x08\xF2\x7D\xEF\xFF", 11);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x04, (uint8_t *) "\xC7\x96\x9A\x1B", 4);
|
||||||
|
NRF24L01_WriteRegisterMulti(0x04, (uint8_t *) "\xC1\x96\x9A\x1B", 4);
|
||||||
|
} else { } // printf("=>H377 : nRF24L01 detected\n");
|
||||||
|
//NRF24L01_ReadReg(NRF24L01_07_STATUS) ==> 0x07
|
||||||
|
NRF24L01_Activate(0x53); // switch bank back
|
||||||
|
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
//NRF24L01_ReadReg(NRF24L01_07_STATUS) ==> 0x0e
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x0e);
|
||||||
|
//NRF24L01_ReadReg(NRF24L01_00_CONFIG); ==> 0x0e
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0e);
|
||||||
|
NRF24L01_ReadReg(NRF24L01_01_EN_AA); // No Auto Acknoledgement
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_bind_packet() {
|
||||||
|
for(int i = 0; i < 6; i++) { packet[i] = rx_tx_addr[i]; }
|
||||||
|
packet[6] = crc8(0xa5, packet, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_data_packet() {
|
||||||
|
uint8_t ail_sign = 0, trim_sign = 0;
|
||||||
|
|
||||||
|
throttle = (uint32_t)Servo_data[2] * 50 / PPM_MAX + 50;
|
||||||
|
if (throttle < 0) { throttle = 0; }
|
||||||
|
|
||||||
|
aileron = (uint32_t)Servo_data[0] * 8 / PPM_MAX;
|
||||||
|
if (aileron < 0) { aileron = -aileron; ail_sign = 1; }
|
||||||
|
if (aileron > 7) { aileron = 7; }
|
||||||
|
|
||||||
|
uint8_t turbo = (uint32_t)Servo_data[1] > 0 ? 1 : 0;
|
||||||
|
|
||||||
|
uint8_t trim = ((uint32_t)Servo_data[3] * 0x1f / PPM_MAX);
|
||||||
|
if (trim < 0) { trim = -trim; trim_sign = 1; }
|
||||||
|
if (trim > 0x1f) { trim = 0x1f; }
|
||||||
|
|
||||||
|
uint8_t rbutton = (uint32_t)Channels[4] > 0 ? 1 : 0;
|
||||||
|
packet[0] = throttle;
|
||||||
|
packet[1] = aileron;
|
||||||
|
if (ail_sign) { packet[1] |= 0x20; }
|
||||||
|
if (turbo) { packet[1] |= 0x40; }
|
||||||
|
if (rbutton) { packet[1] |= 0x80; }
|
||||||
|
packet[5] = trim;
|
||||||
|
if (trim_sign) { packet[5] |= 0x20;}
|
||||||
|
packet[6] = crc8(0xa5, packet, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_packet_hm830() {
|
||||||
|
NRF24L01_ReadReg(NRF24L01_17_FIFO_STATUS);
|
||||||
|
NRF24L01_WritePayload(packet, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t handle_binding() {
|
||||||
|
uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||||
|
if (status & 0x20) {
|
||||||
|
//Binding complete
|
||||||
|
phase = HM830_DATA1 + ((phase&0x7F)-HM830_BIND1A);
|
||||||
|
count = 0;
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, rx_tx_addr+1, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
build_data_packet();
|
||||||
|
uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
|
||||||
|
rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
|
||||||
|
send_packet_hm830();
|
||||||
|
return 14000;
|
||||||
|
}
|
||||||
|
switch (phase) {
|
||||||
|
case HM830_BIND1A:
|
||||||
|
//Look for a Rx that is already bound
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, rx_tx_addr+1, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[0]);
|
||||||
|
build_bind_packet();
|
||||||
|
break;
|
||||||
|
case HM830_BIND1B:
|
||||||
|
//Look for a Rx that is not yet bound
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bind_addr, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, bind_addr+1, 5);
|
||||||
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_addr, 5);
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[0]);
|
||||||
|
break;
|
||||||
|
case HM830_BIND2A:
|
||||||
|
case HM830_BIND3A:
|
||||||
|
case HM830_BIND4A:
|
||||||
|
case HM830_BIND5A:
|
||||||
|
case HM830_BIND6A:
|
||||||
|
case HM830_BIND7A:
|
||||||
|
case HM830_BIND2B:
|
||||||
|
case HM830_BIND3B:
|
||||||
|
case HM830_BIND4B:
|
||||||
|
case HM830_BIND5B:
|
||||||
|
case HM830_BIND6B:
|
||||||
|
case HM830_BIND7B:
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[(phase&0x7F)-HM830_BIND1A]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
|
||||||
|
rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
|
||||||
|
send_packet_hm830();
|
||||||
|
phase++;
|
||||||
|
if (phase == HM830_BIND7B+1) { phase = HM830_BIND1A; }
|
||||||
|
else if (phase == HM830_BIND7A+1) { phase = HM830_BIND1B; }
|
||||||
|
return 20000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t handle_data() {
|
||||||
|
uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||||
|
if (count <= 0 || !(status & 0x20)) {
|
||||||
|
if(count < 0 || ! (status & 0x20)) {
|
||||||
|
count = 0;
|
||||||
|
//We didn't get a response on this channel, try the next one
|
||||||
|
phase++;
|
||||||
|
if (phase-HM830_DATA1 > 6) { phase = HM830_DATA1; }
|
||||||
|
|
||||||
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[0]);
|
||||||
|
NRF24L01_FlushTx();
|
||||||
|
build_data_packet();
|
||||||
|
uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
|
||||||
|
rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
|
||||||
|
send_packet_hm830();
|
||||||
|
return 14000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
build_data_packet();
|
||||||
|
count++;
|
||||||
|
if(count == 98) {
|
||||||
|
count = -1;
|
||||||
|
NRF24L01_SetPower();
|
||||||
|
}
|
||||||
|
uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
|
||||||
|
rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
|
||||||
|
NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
|
||||||
|
send_packet_hm830();
|
||||||
|
return 20000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t HM830_callback() {
|
||||||
|
if ((phase & 0x7F) < HM830_DATA1) { return handle_binding(); }
|
||||||
|
else { return handle_data(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t HM830_setup(){
|
||||||
|
count = 0;
|
||||||
|
// initialize_tx_id
|
||||||
|
|
||||||
|
rx_tx_addr[4] = 0xee;
|
||||||
|
rx_tx_addr[5] = 0xc2;
|
||||||
|
HM830_init();
|
||||||
|
phase = HM830_BIND1A;
|
||||||
|
|
||||||
|
return 500;
|
||||||
|
|
||||||
|
// CLOCK_StartTimer(50000, HM830_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
const void *HM830_Cmds(enum ProtoCmds cmd)
|
||||||
|
{
|
||||||
|
switch(cmd) {
|
||||||
|
case PROTOCMD_INIT: initialize(); return 0;
|
||||||
|
case PROTOCMD_DEINIT:
|
||||||
|
case PROTOCMD_RESET:
|
||||||
|
CLOCK_StopTimer();
|
||||||
|
return (void *)(NRF24L01_Reset() ? 1L : -1L);
|
||||||
|
case PROTOCMD_CHECK_AUTOBIND: return (void *)1L; // Always Autobind
|
||||||
|
case PROTOCMD_BIND: initialize(); return 0;
|
||||||
|
case PROTOCMD_NUMCHAN: return (void *) 5L; // T, A, E, R, G
|
||||||
|
case PROTOCMD_DEFAULT_NUMCHAN: return (void *)5L;
|
||||||
|
// TODO: return id correctly
|
||||||
|
case PROTOCMD_CURRENT_ID: return Model.fixed_id ? (void *)((unsigned long)Model.fixed_id) : 0;
|
||||||
|
case PROTOCMD_TELEMETRYSTATE: return (void *)(long)PROTO_TELEM_UNSUPPORTED;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#endif //PROTO_HAS_NRF24L01
|
BIN
Multiprotocol/opentx-multi-2015-24-12.bin
Normal file
BIN
Multiprotocol/opentx-multi-2015-24-12.bin
Normal file
Binary file not shown.
BIN
Multiprotocol/opentx.bin
Normal file
BIN
Multiprotocol/opentx.bin
Normal file
Binary file not shown.
@ -1,24 +1,26 @@
|
|||||||
/*
|
//*************************************
|
||||||
This project is free software: you can redistribute it and/or modify
|
// FrSky Telemetry serial code *
|
||||||
it under the terms of the GNU General Public License as published by
|
// By Midelic on RCG *
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
//*************************************
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Multiprotocol is distributed in the hope that it will be useful,
|
#if defined TELEMETRY
|
||||||
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
|
#define USER_MAX_BYTES 6
|
||||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
#define MAX_PKTX 10
|
||||||
*/
|
uint8_t frame[18];
|
||||||
|
uint8_t pass = 0;
|
||||||
|
uint8_t index;
|
||||||
|
uint8_t prev_index;
|
||||||
|
uint8_t pktx[MAX_PKTX];
|
||||||
|
|
||||||
|
void frskySendStuffed()
|
||||||
static void frskySendStuffed(uint8_t frame[])
|
|
||||||
{
|
{
|
||||||
Serial_write(0x7E);
|
Serial_write(0x7E);
|
||||||
for (uint8_t i = 0; i < 9; i++) {
|
for (uint8_t i = 0; i < 9; i++)
|
||||||
if ((frame[i] == 0x7e) || (frame[i] == 0x7d)) {
|
{
|
||||||
|
|
||||||
|
if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
|
||||||
|
{
|
||||||
Serial_write(0x7D);
|
Serial_write(0x7D);
|
||||||
frame[i] ^= 0x20;
|
frame[i] ^= 0x20;
|
||||||
}
|
}
|
||||||
@ -27,13 +29,19 @@ static void frskySendStuffed(uint8_t frame[])
|
|||||||
Serial_write(0x7E);
|
Serial_write(0x7E);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frskySendFrame()
|
void compute_RSSIdbm(){
|
||||||
{
|
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5);
|
||||||
uint8_t frame[9];
|
if(pktt[len-2] >=128)
|
||||||
|
RSSI_dBm -= 82;
|
||||||
|
else
|
||||||
|
RSSI_dBm += 65;
|
||||||
|
}
|
||||||
|
|
||||||
|
void frsky_link_frame()
|
||||||
|
{
|
||||||
frame[0] = 0xfe;
|
frame[0] = 0xfe;
|
||||||
if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
|
#if defined(FRSKY_CC2500_INO)
|
||||||
{
|
if ((cur_protocol[0]&0x1F)==MODE_FRSKY) {
|
||||||
compute_RSSIdbm();
|
compute_RSSIdbm();
|
||||||
frame[1] = pktt[3];
|
frame[1] = pktt[3];
|
||||||
frame[2] = pktt[4];
|
frame[2] = pktt[4];
|
||||||
@ -41,23 +49,101 @@ static void frskySendFrame()
|
|||||||
frame[4] = pktt[5]*2;//txrssi
|
frame[4] = pktt[5]*2;//txrssi
|
||||||
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
||||||
}
|
}
|
||||||
else
|
#endif
|
||||||
if ((cur_protocol[0]&0x1F)==MODE_HUBSAN)
|
#if defined(HUBSAN_A7105_INO)
|
||||||
{
|
if ((cur_protocol[0]&0x1F)==MODE_HUBSAN) {
|
||||||
frame[1] = v_lipo*2;
|
frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V
|
||||||
frame[2] = 0;
|
frame[2] = frame[1];
|
||||||
frame[3] = 0x5A;//dummy value
|
frame[3] =0X6e;
|
||||||
frame[4] = 2 * 0x5A;//dummy value
|
frame[4] =2*0x6e;
|
||||||
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
||||||
}
|
}
|
||||||
frskySendStuffed(frame);
|
frskySendStuffed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined HUB_TELEMETRY
|
||||||
|
void frsky_user_frame()
|
||||||
|
{
|
||||||
|
uint8_t indexx = 0, c=0, j=8, n=0, i;
|
||||||
|
|
||||||
|
if(pktt[6]>0 && pktt[6]<=MAX_PKTX)
|
||||||
|
{//only valid hub frames
|
||||||
|
frame[0] = 0xFD;
|
||||||
|
frame[1] = 0;
|
||||||
|
frame[2] = pktt[7];
|
||||||
|
|
||||||
|
switch(pass)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
indexx=pktt[6];
|
||||||
|
for(i=0;i<indexx;i++)
|
||||||
|
{
|
||||||
|
if(pktt[j]==0x5E)
|
||||||
|
{
|
||||||
|
if(c++)
|
||||||
|
{
|
||||||
|
c=0;
|
||||||
|
n++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pktx[i]=pktt[j++];
|
||||||
|
}
|
||||||
|
indexx = indexx-n;
|
||||||
|
pass=1;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
index=indexx;
|
||||||
|
prev_index = indexx;
|
||||||
|
if(index<USER_MAX_BYTES)
|
||||||
|
{
|
||||||
|
for(i=0;i<index;i++)
|
||||||
|
frame[i+3]=pktx[i];
|
||||||
|
pktt[6]=0;
|
||||||
|
pass=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = USER_MAX_BYTES;
|
||||||
|
for(i=0;i<index;i++)
|
||||||
|
frame[i+3]=pktx[i];
|
||||||
|
pass=2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
index = prev_index - index;
|
||||||
|
prev_index=0;
|
||||||
|
if(index<MAX_PKTX-USER_MAX_BYTES) //10-6=4
|
||||||
|
for(i=0;i<index;i++)
|
||||||
|
frame[i+3]=pktx[USER_MAX_BYTES+i];
|
||||||
|
pass=0;
|
||||||
|
pktt[6]=0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!index)
|
||||||
|
return;
|
||||||
|
frame[1] = index;
|
||||||
|
frskySendStuffed();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pass=0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void frskyUpdate()
|
void frskyUpdate()
|
||||||
{
|
{
|
||||||
if(telemetry_link)
|
if(telemetry_link)
|
||||||
{
|
{
|
||||||
frskySendFrame();
|
frsky_link_frame();
|
||||||
telemetry_link=0;
|
telemetry_link=0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
#if defined HUB_TELEMETRY
|
||||||
|
if(!telemetry_link)
|
||||||
|
frsky_user_frame();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
97
README.md
97
README.md
@ -1,4 +1,7 @@
|
|||||||
# DIY-Multiprotocol-TX-Module
|
# DIY-Multiprotocol-TX-Module
|
||||||
|
|
||||||
|
Fork for adding PPM select of project https://github.com/pascallanger/DIY-Multiprotocol-TX-Module
|
||||||
|
|
||||||
Multiprotocol is a 2.4GHz transmitter which enables any TX to control lot of different models available on the market.
|
Multiprotocol is a 2.4GHz transmitter which enables any TX to control lot of different models available on the market.
|
||||||
|
|
||||||
The source code is partly based on the Deviation TX project, thanks to all the developpers for their great job on protocols.
|
The source code is partly based on the Deviation TX project, thanks to all the developpers for their great job on protocols.
|
||||||
@ -26,11 +29,22 @@ The source code is partly based on the Deviation TX project, thanks to all the d
|
|||||||
###Using standard PPM output (trainer port)
|
###Using standard PPM output (trainer port)
|
||||||
The multiprotocol TX module can be used on any TX with a trainer port.
|
The multiprotocol TX module can be used on any TX with a trainer port.
|
||||||
|
|
||||||
Channels order is AETR by default but can be changed in the source code.
|
Channels order is AETR by default but can be changed in the _Config.h.
|
||||||
|
|
||||||
The protocol selection is done via a dip switch or a rotary dip switch for access to up to 15 different protocols.
|
The protocol selection is done via a dip switch, rotary dip switch, scsi ID selector or PPM position.
|
||||||
|
|
||||||
|

|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
|
You can access to up to 15 different protocols and associated settings.
|
||||||
|
|
||||||
|
Settings per selection are located in _Config.h:
|
||||||
|
- Protocol and type: many main protocols have variants
|
||||||
|
- RX Num: number your different RXs and make sure only one model will react to the commands
|
||||||
|
- Power: High or low, enables to lower the power setting of your TX (indoor for example).
|
||||||
|
- Option: -127..+127 allowing to set specific protocol options. Like for Hubsan to set the video frequency.
|
||||||
|
- Autobind: Yes or No. At the model selection (or power applied to the TX) a bind sequence will be initiated
|
||||||
|
|
||||||
###Using a serial output
|
###Using a serial output
|
||||||
The multiprotocol TX module takes full advantage of being used on a Turnigy 9X, 9XR, 9XR Pro, Taranis, 9Xtreme, AR9X, ... running [er9x or ersky9X](https://github.com/MikeBland/mbtx/tree/next). (A version for OpenTX is being looked at)
|
The multiprotocol TX module takes full advantage of being used on a Turnigy 9X, 9XR, 9XR Pro, Taranis, 9Xtreme, AR9X, ... running [er9x or ersky9X](https://github.com/MikeBland/mbtx/tree/next). (A version for OpenTX is being looked at)
|
||||||
@ -50,18 +64,31 @@ Options are:
|
|||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- Using this solution does not need any modification of the TX since it uses the TX module slot PPM pin for serial transfer.
|
- Using this solution does not need any modification of the TX since it uses the TX module slot PPM pin for serial transfer.
|
||||||
- There are 2 versions of serial protocol either 8 or 16 channels. 16 channels is the latest version. Make sure to use the right version based on your version of er9x/ersky9x.
|
- There are 2 versions of serial protocol either 8 or 16 channels. 16 channels is the latest and only available version going forward. Make sure to use the right version based on your version of er9x/ersky9x.
|
||||||
- Channels order is AETR by default but can be changed in the source code.
|
- Channels order is AETR by default but can be changed in _Config.h.
|
||||||
|
|
||||||
###Telemetry
|
###Telemetry
|
||||||
Telemetry is available for er9x and ersky9x TXs.
|
|
||||||
There are only 2 protocols so far supporting telemetry: Hubsan and Frsky.
|
There are only 2 protocols so far supporting telemetry: Hubsan and Frsky.
|
||||||
|
|
||||||
To enable telemetry on Turnigy 9X or 9XR you need to modify your TX following one of the Frsky mod like this [one](http://blog.oscarliang.net/turnigy-9x-advance-mod/).
|
Hubsan displays the battery voltage.
|
||||||
|
|
||||||
Enabling telemetry on 9XR PRO and may be other TXs does not require any hardware modifications. The additional required serial pin is already available on the TX back module pins.
|
FRSky displays full telemetry (A0, A1, RSSI, TSSI and Hub).
|
||||||
|
|
||||||
Once the TX is telemetry enabled, it just needs to be configured on the model as usual.
|
### If used in PPM mode
|
||||||
|
|
||||||
|
Telemetry is available as a serial 9600 8 n 1 output on the TX pin of the Atmega328p using the FRSky hub format.
|
||||||
|
|
||||||
|
You can connect it to your TX if it is telemetry enabled or use a bluetooth adapter along with an app on your phone to display telemetry information and setup alerts.
|
||||||
|
|
||||||
|
### If used in Serial mode
|
||||||
|
Telemetry is built in for er9x and ersky9x TXs.
|
||||||
|
|
||||||
|
To enable telemetry on a Turnigy 9X or 9XR you need to modify your TX following one of the Frsky mod like this [one](http://blog.oscarliang.net/turnigy-9x-advance-mod/).
|
||||||
|
|
||||||
|
Enabling telemetry on a 9XR PRO and may be other TXs does not require any hardware modifications. The additional required serial pin is already available on the TX back module pins.
|
||||||
|
|
||||||
|
Once the TX is telemetry enabled, it just needs to be configured on the model (see er9x/ersky9x documentation).
|
||||||
|
|
||||||
##Protocols
|
##Protocols
|
||||||
|
|
||||||
@ -85,31 +112,35 @@ Notes:
|
|||||||
###Protocol selection
|
###Protocol selection
|
||||||
|
|
||||||
####Using the dial for PPM input
|
####Using the dial for PPM input
|
||||||
PPM is only allowing access to a subset of existing protocols & sub_protocols.
|
PPM is only allowing access to a subset of existing protocols.
|
||||||
The default association dial position / protocol is listed below.
|
The default association dial position / protocol is listed below.
|
||||||
|
|
||||||
Dial|Protocol|Sub_protocol|RF Module
|
Dial|Protocol|Sub_protocol|RX Num|Power|Auto Bind|Option|RF Module
|
||||||
----|--------|------------|---------
|
----|--------|------------|------|-----|---------|------|---------
|
||||||
0|Select serial||
|
0|Select PPM||||||
|
||||||
1|FLYSKY|Flysky|A7105
|
1|FLYSKY|Flysky|0|High|No|0|A7105
|
||||||
2|HUBSAN|-|A7105
|
2|HUBSAN|-|0|High|No|0|A7105
|
||||||
3|FRSKY|-|CC2500
|
3|FRSKY|-|0|High|No|-41|CC2500
|
||||||
4|HISKY|Hisky|NRF24L01
|
4|HISKY|Hisky|0|High|No|0|NRF24L01
|
||||||
5|V2X2|-|NRF24L01
|
5|V2X2|-|0|High|No|0|NRF24L01
|
||||||
6|DSM2|DSM2|CYRF6936
|
6|DSM2|DSM2|0|High|No|0|CYRF6936
|
||||||
7|DEVO|-|CYRF6936
|
7|DEVO|-|0|High|No|0|CYRF6936
|
||||||
8|YD717|YD717|NRF24L01
|
8|YD717|YD717|0|High|No|0|NRF24L01
|
||||||
9|KN|WLTOYS|NRF24L01
|
9|KN|WLTOYS|0|High|No|0|NRF24L01
|
||||||
10|SYMAX|SYMAX|NRF24L01
|
10|SYMAX|SYMAX|0|High|No|0|NRF24L01
|
||||||
11|SLT|-|NRF24L01
|
11|SLT|-|0|High|No|0|NRF24L01
|
||||||
12|CX10|CX10_BLUE|NRF24L01
|
12|CX10|CX10_BLUE|0|High|No|0|NRF24L01
|
||||||
13|CG023|CG023|NRF24L01
|
13|CG023|CG023|0|High|No|0|NRF24L01
|
||||||
14|BAYANG|-|NRF24L01
|
14|BAYANG|-|0|High|No|0|NRF24L01
|
||||||
15|SYMAX|SYMAX5C|NRF24L01
|
15|SYMAX|SYMAX5C|0|High|No|0|NRF24L01
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- The dial selection must be done before the power is applied.
|
- The dial selection must be done before the power is applied.
|
||||||
- The protocols and subprotocols accessible by the dial can be personalized by modifying the source code.
|
- The protocols, subprotocols and all other settings can be personalized by modifying the _Config.h file.
|
||||||
|
|
||||||
|
#####Select PPM
|
||||||
|
Calculating the desired protocol with the position of the sleeves during startup or reset. This allows for a choice of 26 protocols. A path is lost in order to have a hardware reset if using "PPM selection".
|
||||||
|
To simplify the memorization, I provided a lua script for OPENTX.
|
||||||
|
|
||||||
####Using serial input with er9x/ersky9x
|
####Using serial input with er9x/ersky9x
|
||||||
Serial is allowing access to all existing protocols & sub_protocols listed below.
|
Serial is allowing access to all existing protocols & sub_protocols listed below.
|
||||||
@ -152,6 +183,7 @@ CX10||NRF24L01
|
|||||||
|JC3015_1
|
|JC3015_1
|
||||||
|JC3015_2
|
|JC3015_2
|
||||||
|MK33041
|
|MK33041
|
||||||
|
|Q242
|
||||||
CG023||NRF24L01
|
CG023||NRF24L01
|
||||||
|CG023
|
|CG023
|
||||||
|YD829
|
|YD829
|
||||||
@ -239,7 +271,7 @@ CH5|CH6|CH7|CH8|CH9
|
|||||||
---|---|---|---|---
|
---|---|---|---|---
|
||||||
FLIP|MODE|PICTURE|VIDEO|HEADLESS
|
FLIP|MODE|PICTURE|VIDEO|HEADLESS
|
||||||
|
|
||||||
#####Sub_protocol CX10_Q282
|
#####Sub_protocol CX10_Q282 and CX10_Q242
|
||||||
|
|
||||||
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
||||||
---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---
|
||||||
@ -308,7 +340,7 @@ BTMBTN|TOPBTN
|
|||||||
####FRSKY
|
####FRSKY
|
||||||
Extended limits supported
|
Extended limits supported
|
||||||
|
|
||||||
Telemetry enabled for A0, A1, RSSI
|
Telemetry enabled for A0, A1, RSSI, TSSI and Hub
|
||||||
|
|
||||||
Option=fine frequency tuning, usually 0 or -41 based on the manufacturer boards
|
Option=fine frequency tuning, usually 0 or -41 based on the manufacturer boards
|
||||||
|
|
||||||
@ -419,11 +451,12 @@ An [Arduino pro mini](http://www.banggood.com/Wholesale-New-Ver-Pro-Mini-ATMEGA3
|
|||||||
Using stripboard:
|
Using stripboard:
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
Using a [home made PCB](http://www.rcgroups.com/forums/showpost.php?p=32645328&postcount=1621):
|
Using a [home made PCB](http://www.rcgroups.com/forums/showpost.php?p=32645328&postcount=1621):
|
||||||
|
|
||||||

|
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
or build your own board using [SMD components](http://www.rcgroups.com/forums/showpost.php?p=31064232&postcount=1020) and an [associated PCB](https://oshpark.com/shared_projects/MaGYDg0y):
|
or build your own board using [SMD components](http://www.rcgroups.com/forums/showpost.php?p=31064232&postcount=1020) and an [associated PCB](https://oshpark.com/shared_projects/MaGYDg0y):
|
||||||
|
|
||||||
@ -455,7 +488,7 @@ Arduino 1.6.5
|
|||||||
|
|
||||||
Compilation of the code posted here works. So if it doesn't for you this is a problem with your setup, please double check everything before asking.
|
Compilation of the code posted here works. So if it doesn't for you this is a problem with your setup, please double check everything before asking.
|
||||||
|
|
||||||
Multiprotocol.ino header can be modified to compile with/without some protocols, change protocols/sub_protocols associated with dial for PPM input, different channel orders, different channels timing, 8 or 16 channels serial protocol, Telemetry or not, ...
|
_Config.h file can be modified to compile with/without some protocols, change protocols/sub_protocols/settings associated with dial for PPM input, different channel orders, different channels timing, Telemetry or not, ...
|
||||||
|
|
||||||
###Upload the code using ISP (In System Programming)
|
###Upload the code using ISP (In System Programming)
|
||||||
It is recommended to use an external programmer like [USBASP](http://www.banggood.com/USBASP-USBISP-3_3-5V-AVR-Downloader-Programmer-With-ATMEGA8-ATMEGA128-p-934425.html) to upload the code in the Atmega328. The programmer should be set to 3.3V or nothing to not supply any over voltage to the multimodule and avoid any damages.
|
It is recommended to use an external programmer like [USBASP](http://www.banggood.com/USBASP-USBISP-3_3-5V-AVR-Downloader-Programmer-With-ATMEGA8-ATMEGA128-p-934425.html) to upload the code in the Atmega328. The programmer should be set to 3.3V or nothing to not supply any over voltage to the multimodule and avoid any damages.
|
||||||
|
BIN
sync.ffs_db
Normal file
BIN
sync.ffs_db
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user