mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-03 03:57:51 +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,
|
||||
0x01, 0x0f, 0xff
|
||||
};
|
||||
|
||||
#define ID_NORMAL 0x55201041
|
||||
#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_Regs;
|
||||
|
@ -38,7 +38,7 @@ enum BAYANG_FLAGS {
|
||||
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;
|
||||
if (bind)
|
||||
@ -112,7 +112,7 @@ static void BAYANG_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void BAYANG_init()
|
||||
static void __attribute__((unused)) BAYANG_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
@ -148,7 +148,7 @@ uint16_t BAYANG_callback()
|
||||
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...
|
||||
hopping_frequency[0]=0;
|
||||
|
@ -70,7 +70,7 @@ enum H8_3D_FLAGS_2 {
|
||||
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=convert_channel_8b(THROTTLE);
|
||||
@ -205,7 +205,7 @@ static void CG023_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void CG023_init()
|
||||
static void __attribute__((unused)) CG023_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
@ -246,7 +246,7 @@ uint16_t CG023_callback()
|
||||
return H8_3D_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
static void CG023_initialize_txid()
|
||||
static void __attribute__((unused)) CG023_initialize_txid()
|
||||
{
|
||||
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[3] = rx_tx_addr[3] % 0x11;
|
||||
|
||||
hopping_frequency[0] = 0x06 + (rx_tx_addr[0]&0x0f);
|
||||
hopping_frequency[1] = 0x15 + (rx_tx_addr[1]&0x0f);
|
||||
hopping_frequency[2] = 0x24 + (rx_tx_addr[2]&0x0f);
|
||||
hopping_frequency[3] = 0x33 + (rx_tx_addr[3]&0x0f);
|
||||
hopping_frequency[0] = 0x06 + ((rx_tx_addr[0]&0x0f) % 0x0f);
|
||||
hopping_frequency[1] = 0x15 + ((rx_tx_addr[1]&0x0f) % 0x0f);
|
||||
hopping_frequency[2] = 0x24 + ((rx_tx_addr[2]&0x0f) % 0x0f);
|
||||
hopping_frequency[3] = 0x33 + ((rx_tx_addr[3]&0x0f) % 0x0f);
|
||||
}
|
||||
else
|
||||
{ // CG023 and YD829
|
||||
|
@ -46,7 +46,7 @@ enum {
|
||||
CX10_DATA
|
||||
};
|
||||
|
||||
static void CX10_Write_Packet(uint8_t bind)
|
||||
static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
|
||||
{
|
||||
uint8_t offset = 0;
|
||||
if(sub_protocol == CX10_BLUE)
|
||||
@ -90,24 +90,36 @@ static void CX10_Write_Packet(uint8_t bind)
|
||||
if(Servo_AUX4) flags |= 0x08; // Channel 8 - video
|
||||
break;
|
||||
case Q282:
|
||||
case Q242:
|
||||
memcpy(&packet[15], "\x10\x10\xaa\xaa\x00\x00", 6);
|
||||
//FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
|
||||
if(Servo_AUX1) flags2 =0x80; // Channel 5 - FLIP
|
||||
if(Servo_AUX2) flags2|=0x40; // Channel 6 - LED
|
||||
if(Servo_AUX3) flags2|=0x10; // Channel 7 - picture
|
||||
if(Servo_AUX4) // Channel 8 - video
|
||||
{
|
||||
if (!(video_state & 0x20)) video_state ^= 0x21;
|
||||
}
|
||||
else
|
||||
if (video_state & 0x20) video_state &= 0x01;
|
||||
flags2 |= video_state;
|
||||
|
||||
if(Servo_AUX5) flags2|=0x08; // Channel 9 - HEADLESS
|
||||
flags=3;
|
||||
if(sub_protocol==Q282)
|
||||
{
|
||||
if(Servo_AUX3) flags2|=0x10; // Channel 7 - picture
|
||||
if(Servo_AUX4) // Channel 8 - video
|
||||
{
|
||||
if (!(video_state & 0x20)) video_state ^= 0x21;
|
||||
}
|
||||
else
|
||||
if (video_state & 0x20) video_state &= 0x01;
|
||||
flags2 |= video_state;
|
||||
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_AUX7) flags2|=0x04; // Channel 11 - XCAL
|
||||
if(Servo_AUX8) flags2|=0x02; // Channel 12 - YCAL
|
||||
memcpy(&packet[15], "\x10\x10\xaa\xaa\x00\x00", 6);
|
||||
break;
|
||||
case DM007:
|
||||
//FLIP|MODE|PICTURE|VIDEO|HEADLESS
|
||||
@ -154,7 +166,7 @@ static void CX10_Write_Packet(uint8_t bind)
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void CX10_init()
|
||||
static void __attribute__((unused)) CX10_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
@ -199,7 +211,7 @@ uint16_t CX10_callback() {
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
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
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
@ -214,7 +226,7 @@ uint16_t CX10_callback() {
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
static void initialize_txid()
|
||||
static void __attribute__((unused)) initialize_txid()
|
||||
{
|
||||
rx_tx_addr[1]%= 0x30;
|
||||
if(sub_protocol==Q282)
|
||||
@ -225,12 +237,20 @@ static void initialize_txid()
|
||||
hopping_frequency[3] = 0x4c;
|
||||
}
|
||||
else
|
||||
{
|
||||
hopping_frequency[0] = 0x03 + (rx_tx_addr[0] & 0x0F);
|
||||
hopping_frequency[1] = 0x16 + (rx_tx_addr[0] >> 4);
|
||||
hopping_frequency[2] = 0x2D + (rx_tx_addr[1] & 0x0F);
|
||||
hopping_frequency[3] = 0x40 + (rx_tx_addr[1] >> 4);
|
||||
}
|
||||
if(sub_protocol==Q242)
|
||||
{
|
||||
hopping_frequency[0] = 0x48;
|
||||
hopping_frequency[1] = 0x4a;
|
||||
hopping_frequency[2] = 0x4c;
|
||||
hopping_frequency[3] = 0x4e;
|
||||
}
|
||||
else
|
||||
{
|
||||
hopping_frequency[0] = 0x03 + (rx_tx_addr[0] & 0x0F);
|
||||
hopping_frequency[1] = 0x16 + (rx_tx_addr[0] >> 4);
|
||||
hopping_frequency[2] = 0x2D + (rx_tx_addr[1] & 0x0F);
|
||||
hopping_frequency[3] = 0x40 + (rx_tx_addr[1] >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initCX10(void)
|
||||
@ -247,7 +267,7 @@ uint16_t initCX10(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sub_protocol==Q282)
|
||||
if(sub_protocol==Q282||sub_protocol==Q242)
|
||||
packet_length = Q282_PACKET_SIZE;
|
||||
else
|
||||
packet_length = CX10_PACKET_SIZE;
|
||||
|
@ -110,7 +110,6 @@ uint16_t cyrf_state;
|
||||
uint8_t crcidx;
|
||||
uint8_t binding;
|
||||
uint16_t crc;
|
||||
uint8_t model;
|
||||
|
||||
/*
|
||||
#ifdef USE_FIXED_MFGID
|
||||
@ -121,14 +120,14 @@ const uint8_t cyrfmfg_id[6] = {0xd4, 0x62, 0xd6, 0xad, 0xd3, 0xff}; //dx6i
|
||||
#endif
|
||||
*/
|
||||
|
||||
static void build_bind_packet()
|
||||
static void __attribute__((unused)) build_bind_packet()
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t sum = 384 - 0x10;//
|
||||
packet[0] = crc >> 8;
|
||||
packet[1] = crc & 0xff;
|
||||
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[5] = packet[1];
|
||||
packet[6] = packet[2];
|
||||
@ -154,7 +153,23 @@ static void build_bind_packet()
|
||||
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
|
||||
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)
|
||||
{
|
||||
packet[0] = cyrfmfg_id[2];
|
||||
packet[1] = cyrfmfg_id[3] + model;
|
||||
packet[1] = cyrfmfg_id[3] + RX_num;
|
||||
bits=11;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[0] = (0xff ^ cyrfmfg_id[2]);
|
||||
packet[1] = (0xff ^ cyrfmfg_id[3]) + model;
|
||||
packet[1] = (0xff ^ cyrfmfg_id[3]) + RX_num;
|
||||
bits=10;
|
||||
}
|
||||
//
|
||||
@ -252,23 +267,7 @@ static void build_data_packet(uint8_t upper)//
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t 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 uint8_t get_pn_row(uint8_t channel)
|
||||
static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel)
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
static void cyrf_config()
|
||||
static void __attribute__((unused)) cyrf_config()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(init_vals[i][0], init_vals[i][1]);
|
||||
@ -308,7 +307,7 @@ static void cyrf_config()
|
||||
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 };
|
||||
uint8_t data_code[32];
|
||||
@ -342,13 +341,13 @@ const uint8_t data_vals[][2] = {
|
||||
{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++)
|
||||
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]);
|
||||
//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;
|
||||
}
|
||||
|
||||
static void calc_dsmx_channel()
|
||||
static void __attribute__((unused)) calc_dsmx_channel()
|
||||
{
|
||||
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));
|
||||
@ -513,8 +512,6 @@ uint16_t initDsm2()
|
||||
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;//Ok
|
||||
data_col = 7 - sop_col;//ok
|
||||
|
||||
model=MProtocol_id-MProtocol_id_master; // RxNum for serial or 0 for ppm
|
||||
|
||||
CYRF_SetTxRxMode(TX_EN);
|
||||
//
|
||||
if(IS_AUTOBIND_FLAG_on)
|
||||
|
@ -66,7 +66,7 @@ uint8_t ch_idx;
|
||||
uint8_t use_fixed_id;
|
||||
uint8_t failsafe_pkt;
|
||||
|
||||
static void scramble_pkt()
|
||||
static void __attribute__((unused)) scramble_pkt()
|
||||
{
|
||||
#ifdef NO_SCRAMBLE
|
||||
return;
|
||||
@ -77,7 +77,7 @@ static void scramble_pkt()
|
||||
#endif
|
||||
}
|
||||
|
||||
static void add_pkt_suffix()
|
||||
static void __attribute__((unused)) add_pkt_suffix()
|
||||
{
|
||||
uint8_t bind_state;
|
||||
if (use_fixed_id)
|
||||
@ -97,7 +97,7 @@ static void add_pkt_suffix()
|
||||
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);
|
||||
// uint8_t enable = 0;
|
||||
@ -116,7 +116,7 @@ static void build_beacon_pkt(uint8_t upper)
|
||||
add_pkt_suffix();
|
||||
}
|
||||
|
||||
static void build_bind_pkt()
|
||||
static void __attribute__((unused)) build_bind_pkt()
|
||||
{
|
||||
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a;
|
||||
packet[1] = bind_counter & 0xff;
|
||||
@ -136,7 +136,7 @@ static void build_bind_pkt()
|
||||
packet[15] ^= cyrfmfg_id[2];
|
||||
}
|
||||
|
||||
static void build_data_pkt()
|
||||
static void __attribute__((unused)) build_data_pkt()
|
||||
{
|
||||
uint8_t i;
|
||||
packet[0] = (DEVO_NUM_CHANNELS << 4) | (0x0b + ch_idx);
|
||||
@ -161,7 +161,7 @@ static void build_data_pkt()
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
|
||||
static void cyrf_init()
|
||||
static void __attribute__((unused)) cyrf_init()
|
||||
{
|
||||
/* Initialise CYRF chip */
|
||||
CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x39);
|
||||
@ -201,7 +201,7 @@ static void cyrf_init()
|
||||
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
|
||||
}
|
||||
|
||||
static void set_radio_channels()
|
||||
static void __attribute__((unused)) set_radio_channels()
|
||||
{
|
||||
//int i;
|
||||
CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80);
|
||||
@ -217,7 +217,7 @@ static void set_radio_channels()
|
||||
hopping_frequency[4] = hopping_frequency[1];
|
||||
}
|
||||
|
||||
static void DEVO_BuildPacket()
|
||||
static void __attribute__((unused)) DEVO_BuildPacket()
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
@ -302,7 +302,7 @@ uint16_t devo_callback()
|
||||
return 1200;
|
||||
}
|
||||
|
||||
/*static void devo_bind()
|
||||
/*static void __attribute__((unused)) devo_bind()
|
||||
{
|
||||
fixed_id = Model_fixed_id;
|
||||
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){
|
||||
//randomSeed((uint32_t)analogRead(A6)<<10|analogRead(A7));//seed
|
||||
uint8_t txid[4];
|
||||
|
@ -23,14 +23,14 @@
|
||||
#define ESKY_PAYLOAD_SIZE 13
|
||||
#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_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, 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();
|
||||
|
||||
@ -41,8 +41,8 @@ static void ESKY_init(uint8_t bind)
|
||||
if (bind)
|
||||
{
|
||||
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_10_TX_ADDR, (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*)"\x00\x00\x00", 3);
|
||||
}
|
||||
else
|
||||
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
|
||||
}
|
||||
|
||||
static void ESKY_init2()
|
||||
static void __attribute__((unused)) ESKY_init2()
|
||||
{
|
||||
NRF24L01_FlushTx();
|
||||
packet_sent = 0;
|
||||
@ -90,7 +90,7 @@ static void ESKY_init2()
|
||||
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
|
||||
if (bind)
|
||||
|
@ -73,7 +73,7 @@ uint8_t chanrow;
|
||||
uint8_t chancol;
|
||||
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 ?
|
||||
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;
|
||||
//servodata timing range for flysky.
|
||||
|
@ -18,9 +18,11 @@
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
//##########Variables########
|
||||
uint32_t state;
|
||||
uint8_t len;
|
||||
//uint32_t state;
|
||||
//uint8_t len;
|
||||
uint8_t telemetry_counter=0;
|
||||
|
||||
/*
|
||||
enum {
|
||||
FRSKY_BIND = 0,
|
||||
FRSKY_BIND_DONE = 1000,
|
||||
@ -30,114 +32,9 @@ enum {
|
||||
FRSKY_DATA4,
|
||||
FRSKY_DATA5
|
||||
};
|
||||
*/
|
||||
|
||||
uint16_t initFrSky_2way()
|
||||
{
|
||||
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)
|
||||
static void __attribute__((unused)) frsky2way_init(uint8_t bind)
|
||||
{
|
||||
// Configure cc2500 for tx mode
|
||||
CC2500_Reset();
|
||||
@ -151,7 +48,7 @@ static void frsky2way_init(uint8_t bind)
|
||||
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x05);
|
||||
cc2500_writeReg(CC2500_3E_PATABLE, 0xff);
|
||||
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x08);
|
||||
cc2500_writeReg(CC2500_0C_FSCTRL0, fine);
|
||||
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
|
||||
//base freq FREQ = 0x5C7627 (F = 2404MHz)
|
||||
cc2500_writeReg(CC2500_0D_FREQ2, 0x5c);
|
||||
cc2500_writeReg(CC2500_0E_FREQ1, 0x76);
|
||||
@ -196,7 +93,7 @@ static void frsky2way_init(uint8_t bind)
|
||||
//#######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;
|
||||
if(idx == 3 || idx == 23 || idx == 47)
|
||||
@ -206,7 +103,7 @@ static uint8_t get_chan_num(uint16_t idx)
|
||||
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 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;
|
||||
}
|
||||
|
||||
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)
|
||||
//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
|
||||
@ -241,7 +138,8 @@ static void frsky2way_data_frame()
|
||||
packet[1] = rx_tx_addr[3];
|
||||
packet[2] = rx_tx_addr[2];
|
||||
packet[3] = counter;//
|
||||
packet[4] = pkt[6]?(telemetry_counter++)%32:0;
|
||||
packet[4]=telemetry_counter;
|
||||
|
||||
packet[5] = 0x01;
|
||||
//
|
||||
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
|
||||
|
@ -18,21 +18,21 @@
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define BIND_COUNT 1000
|
||||
#define TXID_SIZE 5
|
||||
#define FREQUENCE_NUM 20
|
||||
#define HISKY_BIND_COUNT 1000
|
||||
#define HISKY_TXID_SIZE 5
|
||||
#define HISKY_FREQUENCE_NUM 20
|
||||
//
|
||||
uint8_t bind_buf_arry[4][10];
|
||||
|
||||
// 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
|
||||
// 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;
|
||||
uint32_t rnd = seed;
|
||||
uint32_t rnd = MProtocol_id;
|
||||
|
||||
while (idx < FREQUENCE_NUM)
|
||||
while (idx < HISKY_FREQUENCE_NUM)
|
||||
{
|
||||
uint8_t i;
|
||||
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
|
||||
uint8_t next_ch = ((rnd >> 8) % 73) + 2;
|
||||
// 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;
|
||||
// Check that it's not duplicated and spread uniformly
|
||||
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;
|
||||
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();
|
||||
|
||||
@ -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
|
||||
// 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;
|
||||
uint8_t i,j;
|
||||
@ -144,10 +144,14 @@ uint16_t hisky_cb()
|
||||
NRF24L01_SetPower();
|
||||
phase=2;
|
||||
break;
|
||||
case 3:
|
||||
if (! bind_counter)
|
||||
NRF24L01_WritePayload(packet,10); // 2 packets per 5ms
|
||||
break;
|
||||
case 4:
|
||||
phase=6;
|
||||
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?THROTTLE:AUX3,&packet[2],&packet[3]);
|
||||
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_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
hopping_frequency_no++;
|
||||
if (hopping_frequency_no >= FREQUENCE_NUM)
|
||||
if (hopping_frequency_no >= HISKY_FREQUENCE_NUM)
|
||||
hopping_frequency_no = 0;
|
||||
break;
|
||||
case 7:
|
||||
@ -213,15 +217,19 @@ uint16_t hisky_cb()
|
||||
return 1000; // send 1 binding packet and 1 data packet per 9ms
|
||||
}
|
||||
|
||||
// Generate internal id from TX id and manufacturer id (STM32 unique id)
|
||||
static void initialize_tx_id()
|
||||
static void __attribute__((unused)) initialize_tx_id()
|
||||
{
|
||||
//Generate frequency hopping table
|
||||
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
|
||||
calc_fh_channels(MProtocol_id);
|
||||
calc_fh_channels();
|
||||
}
|
||||
|
||||
uint16_t initHiSky()
|
||||
@ -234,7 +242,7 @@ uint16_t initHiSky()
|
||||
binding_idx = 0;
|
||||
|
||||
if(IS_AUTOBIND_FLAG_on)
|
||||
bind_counter = BIND_COUNT;
|
||||
bind_counter = HISKY_BIND_COUNT;
|
||||
else
|
||||
bind_counter = 0;
|
||||
return 1000;
|
||||
|
@ -12,6 +12,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// compatible with Hubsan H102D, H107/L/C/D and H107P/C+/D+
|
||||
// Last sync with hexfet new_protocols/hubsan_a7105.c dated 2015-12-11
|
||||
|
||||
#if defined(HUBSAN_A7105_INO)
|
||||
@ -55,7 +56,7 @@ enum {
|
||||
};
|
||||
#define WAIT_WRITE 0x80
|
||||
|
||||
static void update_crc()
|
||||
static void __attribute__((unused)) hubsan_update_crc()
|
||||
{
|
||||
uint8_t sum = 0;
|
||||
for(uint8_t i = 0; i < 15; i++)
|
||||
@ -63,7 +64,7 @@ static void update_crc()
|
||||
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;
|
||||
if(phase < BIND_7)
|
||||
@ -98,14 +99,14 @@ static void hubsan_build_bind_packet(uint8_t bind_state)
|
||||
if(phase == BIND_7)
|
||||
packet[2] = handshake_counter++;
|
||||
}
|
||||
update_crc();
|
||||
hubsan_update_crc();
|
||||
}
|
||||
|
||||
//cc : throttle observed range: 0x00 - 0xFF (smaller is down)
|
||||
//ee : rudder observed range: 0x34 - 0xcc (smaller is right)52-204-60%
|
||||
//gg : elevator observed range: 0x3e - 0xbc (smaller is up)62-188 -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;
|
||||
memset(packet, 0, 16);
|
||||
@ -176,7 +177,7 @@ static void hubsan_build_packet()
|
||||
packet_count++;
|
||||
}
|
||||
}
|
||||
update_crc();
|
||||
hubsan_update_crc();
|
||||
}
|
||||
|
||||
#if defined(TELEMETRY)
|
||||
@ -192,8 +193,10 @@ static void hubsan_build_packet()
|
||||
|
||||
uint16_t ReadHubsan()
|
||||
{
|
||||
static uint8_t txState=0;
|
||||
#if defined(TELEMETRY)
|
||||
static uint8_t rfMode=0;
|
||||
#endif
|
||||
static uint8_t txState=0;
|
||||
static uint8_t bind_count=0;
|
||||
uint16_t delay;
|
||||
uint8_t i;
|
||||
@ -276,7 +279,9 @@ uint16_t ReadHubsan()
|
||||
case DATA_4:
|
||||
case DATA_5:
|
||||
if( txState == 0) { // send packet
|
||||
#if defined(TELEMETRY)
|
||||
rfMode = A7105_TX;
|
||||
#endif
|
||||
if( phase == DATA_1)
|
||||
A7105_SetPower(); //Keep transmit power in sync
|
||||
hubsan_build_packet();
|
||||
|
@ -70,6 +70,205 @@ enum {
|
||||
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
|
||||
//================================================================================================
|
||||
@ -145,202 +344,4 @@ uint16_t kn_callback()
|
||||
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
|
||||
|
@ -1,11 +1,11 @@
|
||||
/*********************************************************
|
||||
Multiprotocol Tx code
|
||||
by Midelic and Pascal Langer(hpnuts)
|
||||
http://www.rcgroups.com/forums/showthread.php?t=2165676
|
||||
Multiprotocol Tx code
|
||||
by Midelic and Pascal Langer(hpnuts)
|
||||
http://www.rcgroups.com/forums/showthread.php?t=2165676
|
||||
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/edit/master/README.md
|
||||
|
||||
Thanks to PhracturedBlue
|
||||
Ported from deviation firmware
|
||||
Thanks to PhracturedBlue, Hexfet, Goebish and all protocol developers
|
||||
Ported from deviation firmware
|
||||
|
||||
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
|
||||
@ -23,71 +23,10 @@
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.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"
|
||||
|
||||
//Uncomment to enable 8 channels serial protocol, 16 otherwise
|
||||
//#define NUM_SERIAL_CH_8
|
||||
|
||||
//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
|
||||
//******************************************************
|
||||
//******************************************************
|
||||
|
||||
//Multiprotocol module configuration file
|
||||
#include "_Config.h"
|
||||
|
||||
//Global constants/variables
|
||||
|
||||
@ -126,17 +65,18 @@ uint8_t hopping_frequency_no=0;
|
||||
uint8_t rf_ch_num;
|
||||
uint8_t throttle, rudder, elevator, aileron;
|
||||
uint8_t flags;
|
||||
//
|
||||
uint32_t state;
|
||||
uint8_t len;
|
||||
uint8_t RX_num;
|
||||
|
||||
// Mode_select variables
|
||||
uint8_t mode_select;
|
||||
uint8_t ppm_select;
|
||||
uint8_t protocol_flags=0,protocol_flags2=0;
|
||||
|
||||
// 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
|
||||
#endif
|
||||
#define TXBUFFER_SIZE 12
|
||||
volatile uint8_t rx_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;
|
||||
|
||||
// Telemetry
|
||||
#define MAX_PKT 27
|
||||
uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||
#if defined(TELEMETRY)
|
||||
uint8_t pkt[27];//telemetry receiving packets
|
||||
uint8_t pktt[27];//telemetry receiving packets
|
||||
volatile uint8_t tx_head;
|
||||
volatile uint8_t tx_tail;
|
||||
uint8_t v_lipo;
|
||||
int16_t RSSI_dBm;
|
||||
//const uint8_t RSSI_offset=72;//69 71.72 values db
|
||||
uint8_t telemetry_link=0;
|
||||
#include "telemetry.h"
|
||||
uint8_t pktt[MAX_PKT];//telemetry receiving packets
|
||||
volatile uint8_t tx_head;
|
||||
volatile uint8_t tx_tail;
|
||||
uint8_t v_lipo;
|
||||
int16_t RSSI_dBm;
|
||||
//const uint8_t RSSI_offset=72;//69 71.72 values db
|
||||
uint8_t telemetry_link=0;
|
||||
#include "telemetry.h"
|
||||
#endif
|
||||
|
||||
// Callback
|
||||
@ -183,13 +124,13 @@ void setup()
|
||||
CC25_CSN_on;
|
||||
NRF_CSN_on;
|
||||
CYRF_CSN_on;
|
||||
// Set SPI lines
|
||||
// Set SPI lines
|
||||
SDI_on;
|
||||
SCK_off;
|
||||
|
||||
// Timer1 config
|
||||
TCCR1A = 0;
|
||||
TCCR1B = (1 << CS11); //prescaler8, set timer1 to increment every 0.5us(16Mhz) and start timer
|
||||
TCCR1B = (1 << CS11); //prescaler8, set timer1 to increment every 0.5us(16Mhz) and start timer
|
||||
|
||||
// Set servos positions
|
||||
for(uint8_t i=0;i<NUM_CHN;i++)
|
||||
@ -199,75 +140,80 @@ void setup()
|
||||
|
||||
// Read status of bind button
|
||||
if( (PINB & _BV(5)) == 0x00 )
|
||||
BIND_BUTTON_FLAG_on; // If bind button pressed save the status for protocol id reset under hubsan
|
||||
BIND_BUTTON_FLAG_on; // If bind button pressed save the status for protocol id reset under hubsan
|
||||
|
||||
// Read status of mode select binary switch
|
||||
// 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=14; // here to test PPM
|
||||
//**********************************
|
||||
//**********************************
|
||||
//mode_select=14; // here to test PPM
|
||||
//**********************************
|
||||
|
||||
// Update LED
|
||||
LED_OFF;
|
||||
LED_SET_OUTPUT;
|
||||
|
||||
// Read or create protocol id
|
||||
MProtocol_id=random_id(10,false);
|
||||
MProtocol_id_master=MProtocol_id;
|
||||
MProtocol_id_master=random_id(10,false);
|
||||
|
||||
//Set power transmission flags
|
||||
POWER_FLAG_on; //By default high power for everything
|
||||
//Init RF modules
|
||||
CC2500_Reset();
|
||||
|
||||
//Protocol and interrupts initialization
|
||||
if(mode_select != MODE_SERIAL)
|
||||
{ // PPM
|
||||
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
|
||||
#if !defined(POTAR_SELECT)
|
||||
if(mode_select == MODE_SERIAL)
|
||||
{ // Serial
|
||||
cur_protocol[0]=0;
|
||||
cur_protocol[1]=0;
|
||||
prev_protocol=0;
|
||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||
}
|
||||
else
|
||||
#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
|
||||
void loop()
|
||||
{
|
||||
#if !defined(POTAR_SELECT)
|
||||
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();
|
||||
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
|
||||
{
|
||||
for(uint8_t i=0;i<NUM_CHN;i++)
|
||||
{ // update servo data without interrupts to prevent bad read in protocols
|
||||
cli(); // disable global int
|
||||
cli(); // disable global int
|
||||
Servo_data[i]=PPM_data[i];
|
||||
sei(); // enable global int
|
||||
update_aux_flags();
|
||||
sei(); // enable global int
|
||||
}
|
||||
PPM_FLAG_off; // wait for next frame before update
|
||||
update_aux_flags();
|
||||
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();
|
||||
#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();
|
||||
#endif
|
||||
if (remote_callback != 0)
|
||||
@ -279,7 +225,11 @@ static void update_aux_flags(void)
|
||||
{
|
||||
Servo_AUX=0;
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
if(Servo_data[AUX1+i]>PPM_SWITCH)
|
||||
#if defined(POTAR_SELECT)
|
||||
if(Servo_data[AUX2+i]>PPM_SWITCH)
|
||||
#else
|
||||
if(Servo_data[AUX1+i]>PPM_SWITCH)
|
||||
#endif
|
||||
Servo_AUX|=1<<i;
|
||||
}
|
||||
|
||||
@ -288,21 +238,21 @@ static void update_led_status(void)
|
||||
{
|
||||
if(blink<millis())
|
||||
{
|
||||
if(cur_protocol[0]==0) // No valid serial received at least once
|
||||
blink+=BLINK_SERIAL_TIME; //blink slowly while waiting a valid serial input
|
||||
if(cur_protocol[0]==0) // No valid serial received at least once
|
||||
blink+=BLINK_SERIAL_TIME; //blink slowly while waiting a valid serial input
|
||||
else
|
||||
if(remote_callback == 0)
|
||||
{ // Invalid protocol
|
||||
if(IS_LED_on) //flash to indicate invalid protocol
|
||||
blink+=BLINK_BAD_PROTO_TIME_LOW;
|
||||
else
|
||||
blink+=BLINK_BAD_PROTO_TIME_HIGH;
|
||||
}
|
||||
if(IS_LED_on) //flash to indicate invalid protocol
|
||||
blink+=BLINK_BAD_PROTO_TIME_LOW;
|
||||
else
|
||||
blink+=BLINK_BAD_PROTO_TIME_HIGH;
|
||||
}
|
||||
else
|
||||
if(IS_BIND_DONE_on)
|
||||
LED_OFF; //bind completed -> led on
|
||||
else
|
||||
blink+=BLINK_BIND_TIME; //blink fastly during binding
|
||||
LED_OFF; //bind completed -> led on
|
||||
else
|
||||
blink+=BLINK_BIND_TIME; //blink fastly during binding
|
||||
LED_TOGGLE;
|
||||
}
|
||||
}
|
||||
@ -314,34 +264,35 @@ static void CheckTimer(uint16_t (*cb)(void))
|
||||
uint32_t prev;
|
||||
if( (TIFR1 & (1<<OCF1A)) != 0)
|
||||
{
|
||||
cli(); // disable global int
|
||||
OCR1A=TCNT1; // Callback should already have been called... Use "now" as new sync point.
|
||||
sei(); // enable global int
|
||||
cli(); // disable global int
|
||||
OCR1A=TCNT1; // Callback should already have been called... Use "now" as new sync point.
|
||||
sei(); // enable global int
|
||||
}
|
||||
else
|
||||
while((TIFR1 & (1<<OCF1A)) == 0); // wait before callback
|
||||
prev=micros();
|
||||
while((TIFR1 & (1<<OCF1A)) == 0); // wait before callback
|
||||
prev=micros();
|
||||
next_callback=cb();
|
||||
if(prev+next_callback+50 > micros())
|
||||
{ // Callback did not took more than requested time for next callback
|
||||
if(next_callback>32000)
|
||||
{ // next_callback should not be more than 32767 so we will wait here...
|
||||
delayMicroseconds(next_callback-2000);
|
||||
cli(); // disable global int
|
||||
cli(); // disable global int
|
||||
OCR1A=TCNT1+4000;
|
||||
sei(); // enable global int
|
||||
sei(); // enable global int
|
||||
}
|
||||
else
|
||||
{
|
||||
cli(); // disable global int
|
||||
OCR1A+=next_callback*2; // set compare A for callback
|
||||
sei(); // enable global int
|
||||
cli(); // disable global int
|
||||
OCR1A+=next_callback*2; // set compare A for callback
|
||||
sei(); // enable global int
|
||||
}
|
||||
TIFR1=(1<<OCF1A); // clear compare A=callback flag
|
||||
TIFR1=(1<<OCF1A); // clear compare A=callback flag
|
||||
}
|
||||
}
|
||||
|
||||
static void protocol_init(uint8_t protocol)
|
||||
// Protocol start
|
||||
static void protocol_init()
|
||||
{
|
||||
uint16_t next_callback=0; // Default is immediate call back
|
||||
remote_callback = 0;
|
||||
@ -351,218 +302,265 @@ static void protocol_init(uint8_t protocol)
|
||||
if(IS_BIND_BUTTON_FLAG_on)
|
||||
AUTOBIND_FLAG_on;
|
||||
if(IS_AUTOBIND_FLAG_on)
|
||||
BIND_IN_PROGRESS; // Indicates bind in progress for blinking bind led
|
||||
BIND_IN_PROGRESS; // Indicates bind in progress for blinking bind led
|
||||
else
|
||||
BIND_DONE;
|
||||
|
||||
CTRL1_on; //NRF24L01 antenna RF3 by default
|
||||
CTRL2_off; //NRF24L01 antenna RF3 by default
|
||||
CTRL1_on; //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)
|
||||
case MODE_FLYSKY:
|
||||
CTRL1_off; //antenna RF1
|
||||
next_callback = initFlySky();
|
||||
remote_callback = ReadFlySky;
|
||||
break;
|
||||
case MODE_FLYSKY:
|
||||
CTRL1_off; //antenna RF1
|
||||
next_callback = initFlySky();
|
||||
remote_callback = ReadFlySky;
|
||||
break;
|
||||
#endif
|
||||
#if defined(HUBSAN_A7105_INO)
|
||||
case MODE_HUBSAN:
|
||||
CTRL1_off; //antenna RF1
|
||||
if(IS_BIND_BUTTON_FLAG_on) random_id(10,true); // Generate new ID if bind button is pressed.
|
||||
next_callback = initHubsan();
|
||||
remote_callback = ReadHubsan;
|
||||
break;
|
||||
case MODE_HUBSAN:
|
||||
CTRL1_off; //antenna RF1
|
||||
if(IS_BIND_BUTTON_FLAG_on) random_id(10,true); // Generate new ID if bind button is pressed.
|
||||
next_callback = initHubsan();
|
||||
remote_callback = ReadHubsan;
|
||||
break;
|
||||
#endif
|
||||
#if defined(FRSKY_CC2500_INO)
|
||||
case MODE_FRSKY:
|
||||
CTRL1_off; //antenna RF2
|
||||
CTRL2_on;
|
||||
next_callback = initFrSky_2way();
|
||||
remote_callback = ReadFrSky_2way;
|
||||
break;
|
||||
case MODE_FRSKY:
|
||||
CTRL1_off; //antenna RF2
|
||||
CTRL2_on;
|
||||
next_callback = initFrSky_2way();
|
||||
remote_callback = ReadFrSky_2way;
|
||||
break;
|
||||
#endif
|
||||
#if defined(FRSKYX_CC2500_INO)
|
||||
case MODE_FRSKYX:
|
||||
CTRL1_off; //antenna RF2
|
||||
CTRL2_on;
|
||||
next_callback = initFrSkyX();
|
||||
remote_callback = ReadFrSkyX;
|
||||
break;
|
||||
case MODE_FRSKYX:
|
||||
CTRL1_off; //antenna RF2
|
||||
CTRL2_on;
|
||||
next_callback = initFrSkyX();
|
||||
remote_callback = ReadFrSkyX;
|
||||
break;
|
||||
#endif
|
||||
#if defined(DSM2_CYRF6936_INO)
|
||||
case MODE_DSM2:
|
||||
CTRL2_on; //antenna RF4
|
||||
next_callback = initDsm2();
|
||||
//Servo_data[2]=1500;//before binding
|
||||
remote_callback = ReadDsm2;
|
||||
break;
|
||||
case MODE_DSM2:
|
||||
CTRL2_on; //antenna RF4
|
||||
next_callback = initDsm2();
|
||||
//Servo_data[2]=1500;//before binding
|
||||
remote_callback = ReadDsm2;
|
||||
break;
|
||||
#endif
|
||||
#if defined(DEVO_CYRF6936_INO)
|
||||
case MODE_DEVO:
|
||||
CTRL2_on; //antenna RF4
|
||||
next_callback = DevoInit();
|
||||
remote_callback = devo_callback;
|
||||
break;
|
||||
case MODE_DEVO:
|
||||
CTRL2_on; //antenna RF4
|
||||
next_callback = DevoInit();
|
||||
remote_callback = devo_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(HISKY_NRF24L01_INO)
|
||||
case MODE_HISKY:
|
||||
next_callback=initHiSky();
|
||||
remote_callback = hisky_cb;
|
||||
break;
|
||||
case MODE_HISKY:
|
||||
next_callback=initHiSky();
|
||||
remote_callback = hisky_cb;
|
||||
break;
|
||||
#endif
|
||||
#if defined(V2X2_NRF24L01_INO)
|
||||
case MODE_V2X2:
|
||||
next_callback = initV2x2();
|
||||
remote_callback = ReadV2x2;
|
||||
break;
|
||||
case MODE_V2X2:
|
||||
next_callback = initV2x2();
|
||||
remote_callback = ReadV2x2;
|
||||
break;
|
||||
#endif
|
||||
#if defined(YD717_NRF24L01_INO)
|
||||
case MODE_YD717:
|
||||
next_callback=initYD717();
|
||||
remote_callback = yd717_callback;
|
||||
break;
|
||||
case MODE_YD717:
|
||||
next_callback=initYD717();
|
||||
remote_callback = yd717_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(KN_NRF24L01_INO)
|
||||
case MODE_KN:
|
||||
next_callback = initKN();
|
||||
remote_callback = kn_callback;
|
||||
break;
|
||||
case MODE_KN:
|
||||
next_callback = initKN();
|
||||
remote_callback = kn_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SYMAX_NRF24L01_INO)
|
||||
case MODE_SYMAX:
|
||||
next_callback = initSymax();
|
||||
remote_callback = symax_callback;
|
||||
break;
|
||||
case MODE_SYMAX:
|
||||
next_callback = initSymax();
|
||||
remote_callback = symax_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SLT_NRF24L01_INO)
|
||||
case MODE_SLT:
|
||||
next_callback=initSLT();
|
||||
remote_callback = SLT_callback;
|
||||
break;
|
||||
case MODE_SLT:
|
||||
next_callback=initSLT();
|
||||
remote_callback = SLT_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CX10_NRF24L01_INO)
|
||||
case MODE_CX10:
|
||||
next_callback=initCX10();
|
||||
remote_callback = CX10_callback;
|
||||
break;
|
||||
case MODE_CX10:
|
||||
next_callback=initCX10();
|
||||
remote_callback = CX10_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CG023_NRF24L01_INO)
|
||||
case MODE_CG023:
|
||||
next_callback=initCG023();
|
||||
remote_callback = CG023_callback;
|
||||
break;
|
||||
case MODE_CG023:
|
||||
next_callback=initCG023();
|
||||
remote_callback = CG023_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BAYANG_NRF24L01_INO)
|
||||
case MODE_BAYANG:
|
||||
next_callback=initBAYANG();
|
||||
remote_callback = BAYANG_callback;
|
||||
break;
|
||||
case MODE_BAYANG:
|
||||
next_callback=initBAYANG();
|
||||
remote_callback = BAYANG_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(ESKY_NRF24L01_INO)
|
||||
case MODE_ESKY:
|
||||
next_callback=initESKY();
|
||||
remote_callback = ESKY_callback;
|
||||
break;
|
||||
case MODE_ESKY:
|
||||
next_callback=initESKY();
|
||||
remote_callback = ESKY_callback;
|
||||
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
|
||||
}
|
||||
|
||||
if(next_callback>32000)
|
||||
{ // next_callback should not be more than 32767 so we will wait here...
|
||||
delayMicroseconds(next_callback-2000);
|
||||
next_callback=2000;
|
||||
}
|
||||
cli(); // disable global int
|
||||
OCR1A=TCNT1+next_callback*2; // set compare A for callback
|
||||
sei(); // enable global int
|
||||
TIFR1=(1<<OCF1A); // clear compare A flag
|
||||
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
|
||||
cli(); // disable global int
|
||||
OCR1A=TCNT1+next_callback*2; // set compare A for callback
|
||||
sei(); // enable global int
|
||||
TIFR1=(1<<OCF1A); // clear compare A flag
|
||||
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()
|
||||
{
|
||||
if(rx_ok_buff[0]&0x20) //check range
|
||||
RANGE_FLAG_on;
|
||||
else
|
||||
RANGE_FLAG_off;
|
||||
if(rx_ok_buff[0]&0xC0) //check autobind(0x40) & bind(0x80) together
|
||||
AUTOBIND_FLAG_on;
|
||||
else
|
||||
AUTOBIND_FLAG_off;
|
||||
if(rx_ok_buff[1]&0x80) //if rx_ok_buff[1] ==1,power is low ,0-power high
|
||||
POWER_FLAG_off; //power low
|
||||
else
|
||||
POWER_FLAG_on; //power high
|
||||
if(rx_ok_buff[0]&0x20) //check range
|
||||
RANGE_FLAG_on;
|
||||
else
|
||||
RANGE_FLAG_off;
|
||||
if(rx_ok_buff[0]&0xC0) //check autobind(0x40) & bind(0x80) together
|
||||
AUTOBIND_FLAG_on;
|
||||
else
|
||||
AUTOBIND_FLAG_off;
|
||||
if(rx_ok_buff[1]&0x80) //if rx_ok_buff[1] ==1,power is low ,0-power high
|
||||
POWER_FLAG_off; //power low
|
||||
else
|
||||
POWER_FLAG_on; //power high
|
||||
|
||||
option=rx_ok_buff[2];
|
||||
fine=option; // Update FrSky fine tuning
|
||||
option=rx_ok_buff[2];
|
||||
|
||||
if( ((rx_ok_buff[0]&0x5F) != (cur_protocol[0]&0x5F)) || ( (rx_ok_buff[1]&0x7F) != cur_protocol[1] ) )
|
||||
{ // New model has been selected
|
||||
prev_protocol=cur_protocol[0]&0x1F; //store previous protocol so we can reset the module
|
||||
cur_protocol[1] = rx_ok_buff[1]&0x7F; //store current protocol
|
||||
CHANGE_PROTOCOL_FLAG_on; //change protocol
|
||||
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
|
||||
}
|
||||
prev_protocol=cur_protocol[0]&0x1F; //store previous protocol so we can reset the module
|
||||
cur_protocol[1] = rx_ok_buff[1]&0x7F; //store current protocol
|
||||
CHANGE_PROTOCOL_FLAG_on; //change protocol
|
||||
sub_protocol=(rx_ok_buff[1]>>4)& 0x07; //subprotocol no (0-7) bits 4-6
|
||||
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
|
||||
if( ((rx_ok_buff[0]&0x80)!=0) && ((cur_protocol[0]&0x80)==0) ) // Bind flag has been set
|
||||
CHANGE_PROTOCOL_FLAG_on; //restart protocol with bind
|
||||
cur_protocol[0] = rx_ok_buff[0]; //store current protocol
|
||||
if( ((rx_ok_buff[0]&0x80)!=0) && ((cur_protocol[0]&0x80)==0) ) // Bind flag has been set
|
||||
CHANGE_PROTOCOL_FLAG_on; //restart protocol with bind
|
||||
cur_protocol[0] = rx_ok_buff[0]; //store current protocol
|
||||
|
||||
// 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;
|
||||
uint8_t dec=-3;
|
||||
volatile uint8_t *p=rx_ok_buff+2;
|
||||
uint8_t dec=-3;
|
||||
for(uint8_t i=0;i<NUM_CHN;i++)
|
||||
{
|
||||
dec+=3;
|
||||
dec+=3;
|
||||
if(dec>=8)
|
||||
{
|
||||
dec-=8;
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
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
|
||||
dec-=8;
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
Servo_data[i]=((((*((uint32_t *)p))>>dec)&0x7FF)*5)/8+860; //value range 860<->2140 -125%<->+125%
|
||||
}
|
||||
RX_FLAG_off; //data has been processed
|
||||
}
|
||||
|
||||
static void module_reset()
|
||||
{
|
||||
remote_callback = 0;
|
||||
switch(prev_protocol)
|
||||
{
|
||||
case MODE_FLYSKY:
|
||||
case MODE_HUBSAN:
|
||||
A7105_Reset();
|
||||
break;
|
||||
case MODE_FRSKY:
|
||||
case MODE_FRSKYX:
|
||||
CC2500_Reset();
|
||||
break;
|
||||
break;
|
||||
case MODE_DSM2:
|
||||
case MODE_DEVO:
|
||||
CYRF_Reset();
|
||||
break;
|
||||
default:
|
||||
// MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY
|
||||
NRF24L01_Reset();
|
||||
break;
|
||||
if(remote_callback)
|
||||
{ // previous protocol loaded
|
||||
remote_callback = 0;
|
||||
switch(prev_protocol)
|
||||
{
|
||||
case MODE_FLYSKY:
|
||||
case MODE_HUBSAN:
|
||||
A7105_Reset();
|
||||
break;
|
||||
case MODE_FRSKY:
|
||||
case MODE_FRSKYX:
|
||||
CC2500_Reset();
|
||||
break;
|
||||
case MODE_DSM2:
|
||||
case MODE_DEVO:
|
||||
CYRF_Reset();
|
||||
break;
|
||||
default: // MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY
|
||||
NRF24L01_Reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -612,21 +610,11 @@ uint16_t limit_channel_100(uint8_t ch)
|
||||
if(Servo_data[ch]>PPM_MAX_100)
|
||||
return PPM_MAX_100;
|
||||
else
|
||||
if (Servo_data[ch]<PPM_MIN_100)
|
||||
return PPM_MIN_100;
|
||||
if (Servo_data[ch]<PPM_MIN_100)
|
||||
return PPM_MIN_100;
|
||||
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)
|
||||
void Serial_write(uint8_t data)
|
||||
{
|
||||
@ -641,21 +629,12 @@ void Serial_write(uint8_t data)
|
||||
|
||||
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
|
||||
#include <util/setbaud.h>
|
||||
UBRR0H = UBRRH_VALUE;
|
||||
UBRR0L = UBRRL_VALUE;
|
||||
//Set frame format to 8 data bits, even parity, 2 stop bits
|
||||
UCSR0C |= (1<<UPM01)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
|
||||
#endif
|
||||
while ( UCSR0A & (1 << RXC0) )//flush receive buffer
|
||||
UDR0;
|
||||
//enable reception and RC complete interrupt
|
||||
@ -663,6 +642,26 @@ static void Mprotocol_serial_init()
|
||||
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)
|
||||
{
|
||||
uint32_t id;
|
||||
@ -694,6 +693,7 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
|
||||
/**************************/
|
||||
/**************************/
|
||||
|
||||
//PPM
|
||||
ISR(INT1_vect)
|
||||
{ // Interrupt on PPM pin
|
||||
static int8_t chan=-1;
|
||||
@ -722,53 +722,8 @@ ISR(INT1_vect)
|
||||
Prev_TCNT1+=Cur_TCNT1;
|
||||
}
|
||||
|
||||
#if defined(TELEMETRY)
|
||||
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
|
||||
|
||||
#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
|
||||
//Serial RX
|
||||
#if !defined(POTAR_SELECT)
|
||||
ISR(USART_RX_vect)
|
||||
{ // RX interrupt
|
||||
if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error
|
||||
@ -807,7 +762,25 @@ ISR(USART_RX_vect)
|
||||
}
|
||||
#endif
|
||||
|
||||
//Serial timer
|
||||
ISR(TIMER1_COMPB_vect)
|
||||
{ // Timer1 compare B interrupt
|
||||
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[] = {
|
||||
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,
|
||||
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
|
||||
0x2138, 0x129F, 0xB3A0, 0x2988};
|
||||
|
@ -31,7 +31,7 @@ enum {
|
||||
SLT_DATA3
|
||||
};
|
||||
|
||||
static void SLT_init()
|
||||
static void __attribute__((unused)) SLT_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
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();
|
||||
}
|
||||
|
||||
static void SLT_init2()
|
||||
static void __attribute__((unused)) SLT_init2()
|
||||
{
|
||||
NRF24L01_FlushTx();
|
||||
packet_sent = 0;
|
||||
@ -57,7 +57,7 @@ static void SLT_init2()
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
}
|
||||
|
||||
static void SLT_set_tx_id(void)
|
||||
static void __attribute__((unused)) SLT_set_tx_id(void)
|
||||
{
|
||||
// Frequency hopping sequence generation
|
||||
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);
|
||||
}
|
||||
|
||||
static void SLT_wait_radio()
|
||||
static void __attribute__((unused)) SLT_wait_radio()
|
||||
{
|
||||
if (packet_sent)
|
||||
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS))) ;
|
||||
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();
|
||||
NRF24L01_FlushTx();
|
||||
@ -107,7 +107,7 @@ static void SLT_send_data(uint8_t *data, uint8_t len)
|
||||
packet_sent = 1;
|
||||
}
|
||||
|
||||
static void SLT_build_packet()
|
||||
static void __attribute__((unused)) SLT_build_packet()
|
||||
{
|
||||
// aileron, elevator, throttle, rudder, gear, pitch
|
||||
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;
|
||||
}
|
||||
|
||||
static void SLT_send_bind_packet()
|
||||
static void __attribute__((unused)) SLT_send_bind_packet()
|
||||
{
|
||||
SLT_wait_radio();
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
|
@ -41,7 +41,7 @@ enum {
|
||||
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];
|
||||
|
||||
@ -54,7 +54,7 @@ static uint8_t SYMAX_checksum(uint8_t *data)
|
||||
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
|
||||
// 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)
|
||||
|
||||
static void SYMAX_build_packet_x5c(uint8_t bind)
|
||||
static void __attribute__((unused)) SYMAX_build_packet_x5c(uint8_t 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)
|
||||
{
|
||||
@ -146,7 +146,7 @@ static void SYMAX_build_packet(uint8_t bind)
|
||||
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)
|
||||
SYMAX_build_packet_x5c(bind);
|
||||
@ -167,7 +167,7 @@ static void SYMAX_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void symax_init()
|
||||
static void __attribute__((unused)) symax_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
//
|
||||
@ -219,7 +219,7 @@ static void symax_init()
|
||||
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)
|
||||
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
|
||||
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_2[] = {0x2a, 0x0a, 0x42, 0x22};
|
||||
@ -290,7 +290,7 @@ static void symax_set_channels(uint8_t address)
|
||||
*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,
|
||||
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
|
||||
};
|
||||
|
||||
static void v202_init()
|
||||
static void __attribute__((unused)) v202_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
@ -108,7 +108,7 @@ static void v202_init()
|
||||
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();
|
||||
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));
|
||||
}
|
||||
|
||||
static void V2X2_set_tx_id(void)
|
||||
static void __attribute__((unused)) V2X2_set_tx_id(void)
|
||||
{
|
||||
uint8_t sum;
|
||||
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;
|
||||
for (uint8_t i = 0; i < 15; ++i)
|
||||
@ -142,7 +142,7 @@ static void V2X2_add_pkt_checksum()
|
||||
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;
|
||||
if (bind)
|
||||
|
@ -41,7 +41,7 @@ enum {
|
||||
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;
|
||||
if (bind)
|
||||
@ -125,7 +125,7 @@ static void yd717_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void yd717_init()
|
||||
static void __attribute__((unused)) yd717_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
@ -162,7 +162,7 @@ static void yd717_init()
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
static void YD717_init2()
|
||||
static void __attribute__((unused)) YD717_init2()
|
||||
{
|
||||
// set rx/tx address for data phase
|
||||
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_
|
||||
#define _IFACE_CC2500_H_
|
||||
|
||||
enum {
|
||||
FRSKY_BIND = 0,
|
||||
FRSKY_BIND_DONE = 1000,
|
||||
FRSKY_DATA1,
|
||||
FRSKY_DATA2,
|
||||
FRSKY_DATA3,
|
||||
FRSKY_DATA4,
|
||||
FRSKY_DATA5
|
||||
};
|
||||
|
||||
enum {
|
||||
CC2500_00_IOCFG2 = 0x00, // GDO2 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}
|
@ -21,20 +21,24 @@ enum PROTOCOLS
|
||||
MODE_SERIAL = 0, // Serial commands
|
||||
MODE_FLYSKY = 1, // =>A7105 / FLYSKY protocol
|
||||
MODE_HUBSAN = 2, // =>A7105 / HUBSAN protocol
|
||||
MODE_FRSKY = 3, // =>CC2500 / FRSKY protocol
|
||||
MODE_FRSKY = 3, // =>CC2500 / FRSKY protocol
|
||||
MODE_HISKY = 4, // =>NRF24L01 / HISKY protocol
|
||||
MODE_V2X2 = 5, // =>NRF24L01 / V2x2 protocol
|
||||
MODE_DSM2 = 6, // =>CYRF6936 / DSM2 protocol
|
||||
MODE_DEVO =7, // =>CYRF6936 / DEVO protocol
|
||||
MODE_YD717 = 8, // =>NRF24L01 / YD717 protocol (CX10 red pcb)
|
||||
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_CX10 = 12, // =>NRF24L01 / CX-10 protocol
|
||||
MODE_CG023 = 13, // =>NRF24L01 / CG023 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
|
||||
// Ajout
|
||||
MODE_H7 = 21, // =>NRF24L01 / EAchine MT99xx (H7, MT9916 ...)
|
||||
// MODE_HM830 =22, // =>NRF24L01 / HM830
|
||||
MODE_CFLIE =23, // =>NRF24L01 / CFlie
|
||||
};
|
||||
enum Flysky
|
||||
{
|
||||
@ -78,7 +82,8 @@ enum CX10
|
||||
Q282=3,
|
||||
JC3015_1=4,
|
||||
JC3015_2=5,
|
||||
MK33041=6
|
||||
MK33041=6,
|
||||
Q242=7
|
||||
};
|
||||
enum CG023
|
||||
{
|
||||
@ -87,101 +92,22 @@ enum CG023
|
||||
H8_3D = 2
|
||||
};
|
||||
|
||||
//******************
|
||||
//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
|
||||
enum chan_order{
|
||||
AILERON =0,
|
||||
ELEVATOR,
|
||||
THROTTLE,
|
||||
RUDDER,
|
||||
AUX1,
|
||||
AUX2,
|
||||
AUX3,
|
||||
AUX4,
|
||||
AUX5,
|
||||
AUX6,
|
||||
AUX7,
|
||||
AUX8
|
||||
#define NONE 0
|
||||
#define P_HIGH 1
|
||||
#define P_LOW 0
|
||||
#define AUTOBIND 1
|
||||
#define NO_AUTOBIND 0
|
||||
|
||||
struct PPM_Parameters
|
||||
{
|
||||
uint8_t protocol : 5;
|
||||
uint8_t sub_proto : 3;
|
||||
uint8_t rx_num : 4;
|
||||
uint8_t power : 1;
|
||||
uint8_t autobind : 1;
|
||||
uint8_t option;
|
||||
};
|
||||
#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 ***
|
||||
@ -508,6 +434,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
JC3015_1 4
|
||||
JC3015_2 5
|
||||
MK33041 6
|
||||
Q242 7
|
||||
sub_protocol==CG023
|
||||
CG023 0
|
||||
YD829 1
|
||||
@ -523,86 +450,5 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
1843 +100%
|
||||
2047 +125%
|
||||
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
|
||||
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.
|
||||
//*************************************
|
||||
// FrSky Telemetry serial code *
|
||||
// By Midelic on RCG *
|
||||
//*************************************
|
||||
|
||||
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.
|
||||
#if defined TELEMETRY
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#define USER_MAX_BYTES 6
|
||||
#define MAX_PKTX 10
|
||||
uint8_t frame[18];
|
||||
uint8_t pass = 0;
|
||||
uint8_t index;
|
||||
uint8_t prev_index;
|
||||
uint8_t pktx[MAX_PKTX];
|
||||
|
||||
|
||||
static void frskySendStuffed(uint8_t frame[])
|
||||
void frskySendStuffed()
|
||||
{
|
||||
Serial_write(0x7E);
|
||||
for (uint8_t i = 0; i < 9; i++) {
|
||||
if ((frame[i] == 0x7e) || (frame[i] == 0x7d)) {
|
||||
for (uint8_t i = 0; i < 9; i++)
|
||||
{
|
||||
|
||||
if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
|
||||
{
|
||||
Serial_write(0x7D);
|
||||
frame[i] ^= 0x20;
|
||||
}
|
||||
@ -27,37 +29,121 @@ static void frskySendStuffed(uint8_t frame[])
|
||||
Serial_write(0x7E);
|
||||
}
|
||||
|
||||
static void frskySendFrame()
|
||||
{
|
||||
uint8_t frame[9];
|
||||
void compute_RSSIdbm(){
|
||||
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5);
|
||||
if(pktt[len-2] >=128)
|
||||
RSSI_dBm -= 82;
|
||||
else
|
||||
RSSI_dBm += 65;
|
||||
}
|
||||
|
||||
frame[0] = 0xfe;
|
||||
if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
|
||||
{
|
||||
compute_RSSIdbm();
|
||||
frame[1] = pktt[3];
|
||||
frame[2] = pktt[4];
|
||||
frame[3] = (uint8_t)RSSI_dBm;
|
||||
frame[4] = pktt[5]*2;//txrssi
|
||||
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
||||
}
|
||||
else
|
||||
if ((cur_protocol[0]&0x1F)==MODE_HUBSAN)
|
||||
{
|
||||
frame[1] = v_lipo*2;
|
||||
frame[2] = 0;
|
||||
frame[3] = 0x5A;//dummy value
|
||||
frame[4] = 2 * 0x5A;//dummy value
|
||||
void frsky_link_frame()
|
||||
{
|
||||
frame[0] = 0xfe;
|
||||
#if defined(FRSKY_CC2500_INO)
|
||||
if ((cur_protocol[0]&0x1F)==MODE_FRSKY) {
|
||||
compute_RSSIdbm();
|
||||
frame[1] = pktt[3];
|
||||
frame[2] = pktt[4];
|
||||
frame[3] = (uint8_t)RSSI_dBm;
|
||||
frame[4] = pktt[5]*2;//txrssi
|
||||
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
||||
}
|
||||
frskySendStuffed(frame);
|
||||
#endif
|
||||
#if defined(HUBSAN_A7105_INO)
|
||||
if ((cur_protocol[0]&0x1F)==MODE_HUBSAN) {
|
||||
frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V
|
||||
frame[2] = frame[1];
|
||||
frame[3] =0X6e;
|
||||
frame[4] =2*0x6e;
|
||||
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
||||
}
|
||||
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()
|
||||
{
|
||||
if(telemetry_link)
|
||||
{
|
||||
frskySendFrame();
|
||||
frsky_link_frame();
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
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)
|
||||
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
|
||||
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:
|
||||
- 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.
|
||||
- Channels order is AETR by default but can be changed in the source code.
|
||||
- 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 _Config.h.
|
||||
|
||||
###Telemetry
|
||||
Telemetry is available for er9x and ersky9x TXs.
|
||||
|
||||
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
|
||||
|
||||
@ -85,31 +112,35 @@ Notes:
|
||||
###Protocol selection
|
||||
|
||||
####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.
|
||||
|
||||
Dial|Protocol|Sub_protocol|RF Module
|
||||
----|--------|------------|---------
|
||||
0|Select serial||
|
||||
1|FLYSKY|Flysky|A7105
|
||||
2|HUBSAN|-|A7105
|
||||
3|FRSKY|-|CC2500
|
||||
4|HISKY|Hisky|NRF24L01
|
||||
5|V2X2|-|NRF24L01
|
||||
6|DSM2|DSM2|CYRF6936
|
||||
7|DEVO|-|CYRF6936
|
||||
8|YD717|YD717|NRF24L01
|
||||
9|KN|WLTOYS|NRF24L01
|
||||
10|SYMAX|SYMAX|NRF24L01
|
||||
11|SLT|-|NRF24L01
|
||||
12|CX10|CX10_BLUE|NRF24L01
|
||||
13|CG023|CG023|NRF24L01
|
||||
14|BAYANG|-|NRF24L01
|
||||
15|SYMAX|SYMAX5C|NRF24L01
|
||||
Dial|Protocol|Sub_protocol|RX Num|Power|Auto Bind|Option|RF Module
|
||||
----|--------|------------|------|-----|---------|------|---------
|
||||
0|Select PPM||||||
|
||||
1|FLYSKY|Flysky|0|High|No|0|A7105
|
||||
2|HUBSAN|-|0|High|No|0|A7105
|
||||
3|FRSKY|-|0|High|No|-41|CC2500
|
||||
4|HISKY|Hisky|0|High|No|0|NRF24L01
|
||||
5|V2X2|-|0|High|No|0|NRF24L01
|
||||
6|DSM2|DSM2|0|High|No|0|CYRF6936
|
||||
7|DEVO|-|0|High|No|0|CYRF6936
|
||||
8|YD717|YD717|0|High|No|0|NRF24L01
|
||||
9|KN|WLTOYS|0|High|No|0|NRF24L01
|
||||
10|SYMAX|SYMAX|0|High|No|0|NRF24L01
|
||||
11|SLT|-|0|High|No|0|NRF24L01
|
||||
12|CX10|CX10_BLUE|0|High|No|0|NRF24L01
|
||||
13|CG023|CG023|0|High|No|0|NRF24L01
|
||||
14|BAYANG|-|0|High|No|0|NRF24L01
|
||||
15|SYMAX|SYMAX5C|0|High|No|0|NRF24L01
|
||||
|
||||
Notes:
|
||||
- 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
|
||||
Serial is allowing access to all existing protocols & sub_protocols listed below.
|
||||
@ -152,6 +183,7 @@ CX10||NRF24L01
|
||||
|JC3015_1
|
||||
|JC3015_2
|
||||
|MK33041
|
||||
|Q242
|
||||
CG023||NRF24L01
|
||||
|CG023
|
||||
|YD829
|
||||
@ -239,7 +271,7 @@ CH5|CH6|CH7|CH8|CH9
|
||||
---|---|---|---|---
|
||||
FLIP|MODE|PICTURE|VIDEO|HEADLESS
|
||||
|
||||
#####Sub_protocol CX10_Q282
|
||||
#####Sub_protocol CX10_Q282 and CX10_Q242
|
||||
|
||||
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
||||
---|---|---|---|---|---|---|---
|
||||
@ -308,7 +340,7 @@ BTMBTN|TOPBTN
|
||||
####FRSKY
|
||||
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
|
||||
|
||||
@ -419,11 +451,12 @@ An [Arduino pro mini](http://www.banggood.com/Wholesale-New-Ver-Pro-Mini-ATMEGA3
|
||||
Using stripboard:
|
||||
|
||||

|
||||

|
||||
|
||||
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):
|
||||
|
||||
@ -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.
|
||||
|
||||
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)
|
||||
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