diff --git a/Multiprotocol/A7105_SPI.ino b/Multiprotocol/A7105_SPI.ino index 1698725..e3b59d1 100644 --- a/Multiprotocol/A7105_SPI.ino +++ b/Multiprotocol/A7105_SPI.ino @@ -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; diff --git a/Multiprotocol/Bayang_nrf24l01.ino b/Multiprotocol/Bayang_nrf24l01.ino index 782d3ad..84907b4 100644 --- a/Multiprotocol/Bayang_nrf24l01.ino +++ b/Multiprotocol/Bayang_nrf24l01.ino @@ -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; diff --git a/Multiprotocol/CG023_nrf24l01.ino b/Multiprotocol/CG023_nrf24l01.ino index 7236dd0..6810652 100644 --- a/Multiprotocol/CG023_nrf24l01.ino +++ b/Multiprotocol/CG023_nrf24l01.ino @@ -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 diff --git a/Multiprotocol/CX10_nrf24l01.ino b/Multiprotocol/CX10_nrf24l01.ino index 10b9437..044c20c 100644 --- a/Multiprotocol/CX10_nrf24l01.ino +++ b/Multiprotocol/CX10_nrf24l01.ino @@ -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; diff --git a/Multiprotocol/DSM2_cyrf6936.ino b/Multiprotocol/DSM2_cyrf6936.ino index 66b582a..e6769a6 100644 --- a/Multiprotocol/DSM2_cyrf6936.ino +++ b/Multiprotocol/DSM2_cyrf6936.ino @@ -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) diff --git a/Multiprotocol/Devo_cyrf6936.ino b/Multiprotocol/Devo_cyrf6936.ino index 3e8ec7a..e569cb9 100644 --- a/Multiprotocol/Devo_cyrf6936.ino +++ b/Multiprotocol/Devo_cyrf6936.ino @@ -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]; diff --git a/Multiprotocol/ESky_nrf24l01.ino b/Multiprotocol/ESky_nrf24l01.ino index 77452a3..1ed7d3d 100644 --- a/Multiprotocol/ESky_nrf24l01.ino +++ b/Multiprotocol/ESky_nrf24l01.ino @@ -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) diff --git a/Multiprotocol/FlySky_a7105.ino b/Multiprotocol/FlySky_a7105.ino index 452b5ff..8c5f956 100644 --- a/Multiprotocol/FlySky_a7105.ino +++ b/Multiprotocol/FlySky_a7105.ino @@ -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. diff --git a/Multiprotocol/FrSky_cc2500.ino b/Multiprotocol/FrSky_cc2500.ino index 035383e..449f954 100644 --- a/Multiprotocol/FrSky_cc2500.ino +++ b/Multiprotocol/FrSky_cc2500.ino @@ -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>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;i0) + 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 diff --git a/Multiprotocol/Hisky_nrf24l01.ino b/Multiprotocol/Hisky_nrf24l01.ino index d7a3fde..c6edabe 100644 --- a/Multiprotocol/Hisky_nrf24l01.ino +++ b/Multiprotocol/Hisky_nrf24l01.ino @@ -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. */ +// 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(); diff --git a/Multiprotocol/KN_nrf24l01.ino b/Multiprotocol/KN_nrf24l01.ino index 6c89ff1..53e902d 100644 --- a/Multiprotocol/KN_nrf24l01.ino +++ b/Multiprotocol/KN_nrf24l01.ino @@ -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 diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index c10128d..d075ec1 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -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 #include #include - -//****************************************************** -//****************************************************** -// 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,91 +124,96 @@ 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>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_OFF; LED_SET_OUTPUT; // Read or create protocol id - MProtocol_id=random_id(10,false); - MProtocol_id_master=MProtocol_id; - - //Set power transmission flags - POWER_FLAG_on; //By default high power for everything + MProtocol_id_master=random_id(10,false); + + //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<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< 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< 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<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<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 - - option=rx_ok_buff[2]; - fine=option; // Update FrSky fine tuning + 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]; 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=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]> 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 - UBRR0H = UBRRH_VALUE; - UBRR0L = UBRRL_VALUE; - //Set frame format to 8 data bits, no parity, 1 stop bit - UCSR0C |= (1< + #include UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; //Set frame format to 8 data bits, even parity, 2 stop bits UCSR0C |= (1<> 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<>8) ^ rx_buff[idx++]) & 0xFF]); - } - else - { // A frame has been received and needs to be checked before giving it to main - TIMSK1 &=~(1<=TXBUFFER_SIZE)//head + t=0; + UDR0=tx_buff[t]; + tx_tail=t; + } + if (t == tx_head) + UCSR0B &= ~(1<> 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}; diff --git a/Multiprotocol/V2X2_nrf24l01.ino b/Multiprotocol/V2X2_nrf24l01.ino index 35796b1..d761c57 100644 --- a/Multiprotocol/V2X2_nrf24l01.ino +++ b/Multiprotocol/V2X2_nrf24l01.ino @@ -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) diff --git a/Multiprotocol/YD717_nrf24l01.ino b/Multiprotocol/YD717_nrf24l01.ino index d2a3f1a..1d9ffbe 100644 --- a/Multiprotocol/YD717_nrf24l01.ino +++ b/Multiprotocol/YD717_nrf24l01.ino @@ -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); diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h new file mode 100644 index 0000000..4c58806 --- /dev/null +++ b/Multiprotocol/_Config.h @@ -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 . + */ + +/** 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 diff --git a/Multiprotocol/iface_cc2500.h b/Multiprotocol/iface_cc2500.h index 8bcd506..cb7b623 100644 --- a/Multiprotocol/iface_cc2500.h +++ b/Multiprotocol/iface_cc2500.h @@ -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 diff --git a/Multiprotocol/liste.txt b/Multiprotocol/liste.txt new file mode 100644 index 0000000..3b9583e --- /dev/null +++ b/Multiprotocol/liste.txt @@ -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 + diff --git a/Multiprotocol/multi.lua b/Multiprotocol/multi.lua new file mode 100644 index 0000000..4b18f5e --- /dev/null +++ b/Multiprotocol/multi.lua @@ -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} diff --git a/Multiprotocol/multiprotocol.h b/Multiprotocol/multiprotocol.h index 3fab255..ab72a2f 100644 --- a/Multiprotocol/multiprotocol.h +++ b/Multiprotocol/multiprotocol.h @@ -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]) */ diff --git a/Multiprotocol/nrf24l01_H7.ino b/Multiprotocol/nrf24l01_H7.ino new file mode 100644 index 0000000..e2c9e75 --- /dev/null +++ b/Multiprotocol/nrf24l01_H7.ino @@ -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 . + */ + +// 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 diff --git a/Multiprotocol/nrf24l01_hm830.ino b/Multiprotocol/nrf24l01_hm830.ino new file mode 100644 index 0000000..0243695 --- /dev/null +++ b/Multiprotocol/nrf24l01_hm830.ino @@ -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 . + */ + +/* 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 diff --git a/Multiprotocol/opentx-multi-2015-24-12.bin b/Multiprotocol/opentx-multi-2015-24-12.bin new file mode 100644 index 0000000..fe1836e Binary files /dev/null and b/Multiprotocol/opentx-multi-2015-24-12.bin differ diff --git a/Multiprotocol/opentx.bin b/Multiprotocol/opentx.bin new file mode 100644 index 0000000..8e886c4 Binary files /dev/null and b/Multiprotocol/opentx.bin differ diff --git a/Multiprotocol/telemetry.h b/Multiprotocol/telemetry.h index b305cd7..126549f 100644 --- a/Multiprotocol/telemetry.h +++ b/Multiprotocol/telemetry.h @@ -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 . - */ +#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; + } + #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(frame); + frskySendStuffed(); } +#if defined HUB_TELEMETRY +void frsky_user_frame() +{ + uint8_t indexx = 0, c=0, j=8, n=0, i; + + if(pktt[6]>0 && pktt[6]<=MAX_PKTX) + {//only valid hub frames + frame[0] = 0xFD; + frame[1] = 0; + frame[2] = pktt[7]; + + switch(pass) + { + case 0: + indexx=pktt[6]; + for(i=0;i