From bc42dbf88ab9b54a626029ecd1307d82371c89a9 Mon Sep 17 00:00:00 2001 From: pascallanger Date: Wed, 20 Jan 2016 10:50:56 +0100 Subject: [PATCH] Core and all protocols have been updated Lot of changes in this new master ChangeLog: - Core: LED flashing when an invalid protocol has been selected - Core: Channels 5 to 12 available as switches for all protocols: code and size optimization - Documentation (readme.md): fully updated, all protocols/sub protocols/channels described, models example, many improvements - All protocols have been updated in some way, here are some highlights: * Bayang: added picture, video and inverted channels * CG023->H8_3D: added light and calibration channels * CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041 * ESky: added new protocol - untested * Hubsan: added compatibility with the new Hubsan Plus protocol * KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN, 11 channels support New version successfully tested on all my models: Flysky RX/F939/V911 protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan, Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol CG023. To access new protocols from er9x/ersky9x, you need to build a version from this github repository https://github.com/pascallanger/mbtx based on the latest er9x r820 and ersky9x r218. --- Multiprotocol/A7105_SPI.ino | 28 +- Multiprotocol/Bayang_nrf24l01.ino | 111 +++---- Multiprotocol/CC2500_SPI.ino | 18 +- Multiprotocol/CG023_nrf24l01.ino | 88 +++--- Multiprotocol/CX10_nrf24l01.ino | 148 ++++++--- Multiprotocol/CYRF6936_SPI.ino | 28 +- Multiprotocol/DSM2_cyrf6936.ino | 18 +- Multiprotocol/Devo_cyrf6936.ino | 24 +- Multiprotocol/ESky_nrf24l01.ino | 171 ++++++++++ Multiprotocol/FlySky_a7105.ino | 40 +-- Multiprotocol/FrSky_cc2500.ino | 21 +- Multiprotocol/Hisky_nrf24l01.ino | 13 +- Multiprotocol/Hubsan_a7105.ino | 192 +++++++---- Multiprotocol/KN_nrf24l01.ino | 510 +++++++++++++++++------------- Multiprotocol/Multiprotocol.ino | 167 ++++------ Multiprotocol/NRF24l01_SPI.ino | 57 +--- Multiprotocol/SLT_nrf24l01.ino | 38 +-- Multiprotocol/Symax_nrf24l01.ino | 58 ++-- Multiprotocol/V2X2_nrf24l01.ino | 46 ++- Multiprotocol/YD717_nrf24l01.ino | 42 ++- Multiprotocol/iface_cyrf6936.h | 8 +- Multiprotocol/multiprotocol.h | 157 ++++++++- Multiprotocol/telemetry.h | 14 +- 23 files changed, 1199 insertions(+), 798 deletions(-) create mode 100644 Multiprotocol/ESky_nrf24l01.ino diff --git a/Multiprotocol/A7105_SPI.ino b/Multiprotocol/A7105_SPI.ino index 50e4f28..1698725 100644 --- a/Multiprotocol/A7105_SPI.ino +++ b/Multiprotocol/A7105_SPI.ino @@ -140,19 +140,18 @@ void A7105_WriteID(uint32_t ida) { CS_on; } -void A7105_SetPower_Value(int power) +/* +static void A7105_SetPower_Value(int power) { - /* - Power amp is ~+16dBm so: - TXPOWER_100uW = -23dBm == PAC=0 TBG=0 - TXPOWER_300uW = -20dBm == PAC=0 TBG=1 - TXPOWER_1mW = -16dBm == PAC=0 TBG=2 - TXPOWER_3mW = -11dBm == PAC=0 TBG=4 - TXPOWER_10mW = -6dBm == PAC=1 TBG=5 - TXPOWER_30mW = 0dBm == PAC=2 TBG=7 - TXPOWER_100mW = 1dBm == PAC=3 TBG=7 - TXPOWER_150mW = 1dBm == PAC=3 TBG=7 - */ + //Power amp is ~+16dBm so: + //TXPOWER_100uW = -23dBm == PAC=0 TBG=0 + //TXPOWER_300uW = -20dBm == PAC=0 TBG=1 + //TXPOWER_1mW = -16dBm == PAC=0 TBG=2 + //TXPOWER_3mW = -11dBm == PAC=0 TBG=4 + //TXPOWER_10mW = -6dBm == PAC=1 TBG=5 + //TXPOWER_30mW = 0dBm == PAC=2 TBG=7 + //TXPOWER_100mW = 1dBm == PAC=3 TBG=7 + //TXPOWER_150mW = 1dBm == PAC=3 TBG=7 uint8_t pac, tbg; switch(power) { case 0: pac = 0; tbg = 0; break; @@ -167,6 +166,7 @@ void A7105_SetPower_Value(int power) }; A7105_WriteReg(0x28, (pac << 3) | tbg); } +*/ void A7105_SetPower() { @@ -196,6 +196,8 @@ 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 void A7105_Init(uint8_t protocol) { void *A7105_Regs; @@ -207,7 +209,7 @@ void A7105_Init(uint8_t protocol) } else { - A7105_WriteID(0x55201041); + A7105_WriteID(ID_NORMAL); A7105_Regs=(void *)HUBSAN_A7105_regs; } for (uint8_t i = 0; i < 0x33; i++){ diff --git a/Multiprotocol/Bayang_nrf24l01.ino b/Multiprotocol/Bayang_nrf24l01.ino index bafcb3c..782d3ad 100644 --- a/Multiprotocol/Bayang_nrf24l01.ino +++ b/Multiprotocol/Bayang_nrf24l01.ino @@ -4,7 +4,7 @@ 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, +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. @@ -12,7 +12,8 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ -// compatible with EAchine H8 mini, H10, BayangToys X6/X7/X9, JJRC JJ850 ... +// Compatible with EAchine H8 mini, H10, BayangToys X6/X7/X9, JJRC JJ850 ... +// Last sync with hexfet new_protocols/bayang_nrf24l01.c dated 2015-12-22 #if defined(BAYANG_NRF24L01_INO) @@ -30,15 +31,14 @@ enum BAYANG_FLAGS { // flags going to packet[2] BAYANG_FLAG_RTH = 0x01, BAYANG_FLAG_HEADLESS = 0x02, - BAYANG_FLAG_FLIP = 0x08 + BAYANG_FLAG_FLIP = 0x08, + BAYANG_FLAG_VIDEO = 0x10, + BAYANG_FLAG_PICTURE = 0x20, + // flags going to packet[3] + BAYANG_FLAG_INVERTED = 0x80 // inverted flight on Floureon H101 }; -enum BAYANG_PHASES { - BAYANG_BIND = 0, - BAYANG_DATA -}; - -void BAYANG_send_packet(uint8_t bind) +static void BAYANG_send_packet(uint8_t bind) { uint8_t i; if (bind) @@ -48,8 +48,8 @@ void BAYANG_send_packet(uint8_t bind) packet[i+1]=rx_tx_addr[i]; for(i=0;i<4;i++) packet[i+6]=hopping_frequency[i]; - packet[10] = rx_tx_addr[0]; - packet[11] = rx_tx_addr[1]; + packet[10] = rx_tx_addr[0]; // txid[0] + packet[11] = rx_tx_addr[1]; // txid[1] } else { @@ -57,16 +57,22 @@ void BAYANG_send_packet(uint8_t bind) packet[0] = 0xA5; packet[1] = 0xFA; // normal mode is 0xf7, expert 0xfa - //Flags - packet[2] =0x00; - if(Servo_data[AUX1] > PPM_SWITCH) - packet[2] |= BAYANG_FLAG_FLIP; - if(Servo_data[AUX2] > PPM_SWITCH) - packet[2] |= BAYANG_FLAG_HEADLESS; - if(Servo_data[AUX3] > PPM_SWITCH) + //Flags packet[2] + packet[2] = 0x00; + if(Servo_AUX1) + packet[2] = BAYANG_FLAG_FLIP; + if(Servo_AUX2) packet[2] |= BAYANG_FLAG_RTH; - + if(Servo_AUX3) + packet[2] |= BAYANG_FLAG_PICTURE; + if(Servo_AUX4) + packet[2] |= BAYANG_FLAG_VIDEO; + if(Servo_AUX5) + packet[2] |= BAYANG_FLAG_HEADLESS; + //Flags packet[3] packet[3] = 0x00; + if(Servo_AUX6) + packet[3] = BAYANG_FLAG_INVERTED; //Aileron val = convert_channel_10b(AILERON); @@ -85,7 +91,7 @@ void BAYANG_send_packet(uint8_t bind) packet[10] = (val>>8) + (val>>2 & 0xFC); packet[11] = val & 0xFF; } - packet[12] = rx_tx_addr[2]; + packet[12] = rx_tx_addr[2]; // txid[2] packet[13] = 0x0A; packet[14] = 0; for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++) @@ -95,10 +101,7 @@ void BAYANG_send_packet(uint8_t bind) // Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); - if (bind) - NRF24L01_WriteReg(NRF24L01_05_RF_CH, BAYANG_RF_BIND_CHANNEL); - else - NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]); + NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? BAYANG_RF_BIND_CHANNEL:hopping_frequency[hopping_frequency_no++]); hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS; // clear packet status bits and TX FIFO @@ -109,7 +112,7 @@ void BAYANG_send_packet(uint8_t bind) NRF24L01_SetPower(); // Set tx_power } -void BAYANG_init() +static void BAYANG_init() { NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); @@ -118,49 +121,40 @@ void BAYANG_init() NRF24L01_FlushTx(); NRF24L01_FlushRx(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes - NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only - NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); - NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits - NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps - NRF24L01_SetPower(); - - NRF24L01_Activate(0x73); // Activate feature register - NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes - NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); - NRF24L01_Activate(0x73); + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps + NRF24L01_SetPower(); } uint16_t BAYANG_callback() { - switch (phase) + if(IS_BIND_DONE_on) + BAYANG_send_packet(0); + else { - case BAYANG_BIND: - if (bind_counter == 0) - { - XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH); - phase = BAYANG_DATA; - BIND_DONE; - } - else - { - BAYANG_send_packet(1); - bind_counter--; - } - break; - case BAYANG_DATA: - BAYANG_send_packet(0); - break; + if (bind_counter == 0) + { + XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH); + BIND_DONE; + } + else + { + BAYANG_send_packet(1); + bind_counter--; + } } return BAYANG_PACKET_PERIOD; } -void BAYANG_initialize_txid() +static void BAYANG_initialize_txid() { - // Strange txid, rx_tx_addr and rf_channels could be anything so I will use on rx_tx_addr for all of them... - // Strange also that there is no check of duplicated rf channels... I think we need to implement that later... - for(uint8_t i=0; i. */ +// compatible with EAchine 3D X4, CG023/CG031, Attop YD-822/YD-829/YD-829C and H8_3D/JJRC H20/H22 // Merged CG023 and H8_3D protocols -// compatible with EAchine 3D X4, CG023/CG031, Attop YD-822/YD-829/YD-829C and H8_3D/JJRC H20 +// Last sync with hexfet new_protocols/cg023_nrf24l01.c dated 2015-10-03 +// Last sync with hexfet new_protocols/h8_3d_nrf24l01.c dated 2015-11-18 #if defined(CG023_NRF24L01_INO) @@ -58,8 +60,9 @@ enum H8_3D_FLAGS { H8_3D_FLAG_FLIP = 0x01, H8_3D_FLAG_RATE_MID = 0x02, H8_3D_FLAG_RATE_HIGH = 0x04, - H8_3D_FLAG_HEADLESS = 0x10, // RTH + headless on H8, headless on JJRC H20 - H8_3D_FLAG_RTH = 0x40, // 360 flip mode on H8 3D, RTH on JJRC H20 + H8_3D_FLAG_LIGTH = 0x08, // Light on H22 + H8_3D_FLAG_HEADLESS = 0x10, // RTH + headless on H8, headless on JJRC H20, RTH on H22 + H8_3D_FLAG_RTH = 0x20, // 360 flip mode on H8 3D and H22, RTH on JJRC H20 }; enum H8_3D_FLAGS_2 { @@ -67,12 +70,7 @@ enum H8_3D_FLAGS_2 { H8_3D_FLAG_CALIBRATE = 0x20, // accelerometer calibration }; -enum CG023_PHASES { - CG023_BIND = 0, - CG023_DATA -}; - -void CG023_send_packet(uint8_t bind) +static void CG023_send_packet(uint8_t bind) { // throttle : 0x00 - 0xFF throttle=convert_channel_8b(THROTTLE); @@ -92,7 +90,7 @@ void CG023_send_packet(uint8_t bind) packet[0] = 0x13; packet[3] = rx_tx_addr[2]; packet[4] = rx_tx_addr[3]; - packet[8] = (rx_tx_addr[0]+rx_tx_addr[1]+rx_tx_addr[2]+rx_tx_addr[3]) & 0xff; // txid checksum + packet[8] = rx_tx_addr[0]+rx_tx_addr[1]+rx_tx_addr[2]+rx_tx_addr[3]; // txid checksum memset(&packet[9], 0, 10); if (bind) { @@ -115,15 +113,15 @@ void CG023_send_packet(uint8_t bind) packet[15] = 0x20; packet[16] = 0x20; packet[17] = H8_3D_FLAG_RATE_HIGH; - if(Servo_data[AUX1] > PPM_SWITCH) + if(Servo_AUX1) packet[17] |= H8_3D_FLAG_FLIP; - if(Servo_data[AUX2] > PPM_SWITCH) + if(Servo_AUX2) + packet[17] |= H8_3D_FLAG_LIGTH; //H22 light + if(Servo_AUX3) packet[17] |= H8_3D_FLAG_HEADLESS; - if(Servo_data[AUX3] > PPM_SWITCH) + if(Servo_AUX4) packet[17] |= H8_3D_FLAG_RTH; // 180/360 flip mode on H8 3D - - // both sticks bottom left: calibrate acc - if(packet[9] <= 0x05 && packet[10] >= 0xa7 && packet[11] <= 0x57 && packet[12] >= 0xa7) + if(Servo_AUX5) packet[18] = H8_3D_FLAG_CALIBRATE; } uint8_t sum = packet[9]; @@ -156,15 +154,15 @@ void CG023_send_packet(uint8_t bind) // rate packet[13] = CG023_FLAG_RATE_HIGH; // flags - if(Servo_data[AUX1] > PPM_SWITCH) + if(Servo_AUX1) packet[13] |= CG023_FLAG_FLIP; - if(Servo_data[AUX2] > PPM_SWITCH) + if(Servo_AUX2) packet[13] |= CG023_FLAG_LED_OFF; - if(Servo_data[AUX3] > PPM_SWITCH) + if(Servo_AUX3) packet[13] |= CG023_FLAG_STILL; - if(Servo_data[AUX4] > PPM_SWITCH) + if(Servo_AUX4) packet[13] |= CG023_FLAG_VIDEO; - if(Servo_data[AUX5] > PPM_SWITCH) + if(Servo_AUX5) packet[13] |= CG023_FLAG_EASY; } else @@ -172,13 +170,13 @@ void CG023_send_packet(uint8_t bind) // rate packet[13] = YD829_FLAG_RATE_HIGH; // flags - if(Servo_data[AUX1] > PPM_SWITCH) + if(Servo_AUX1) packet[13] |= YD829_FLAG_FLIP; - if(Servo_data[AUX3] > PPM_SWITCH) + if(Servo_AUX3) packet[13] |= YD829_FLAG_STILL; - if(Servo_data[AUX4] > PPM_SWITCH) + if(Servo_AUX4) packet[13] |= YD829_FLAG_VIDEO; - if(Servo_data[AUX5] > PPM_SWITCH) + if(Servo_AUX5) packet[13] |= YD829_FLAG_HEADLESS; } packet[14] = 0; @@ -207,7 +205,7 @@ void CG023_send_packet(uint8_t bind) NRF24L01_SetPower(); // Set tx_power } -void CG023_init() +static void CG023_init() { NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); @@ -227,24 +225,19 @@ void CG023_init() uint16_t CG023_callback() { - switch (phase) + if(IS_BIND_DONE_on) + CG023_send_packet(0); + else { - case CG023_BIND: - if (bind_counter == 0) - { - phase = CG023_DATA; - BIND_DONE; - } - else - { - CG023_send_packet(1); - bind_counter--; - } - break; - case CG023_DATA: - CG023_send_packet(0); - break; + if (bind_counter == 0) + BIND_DONE; + else + { + CG023_send_packet(1); + bind_counter--; + } } + if(sub_protocol==CG023) return CG023_PACKET_PERIOD; else @@ -253,7 +246,7 @@ uint16_t CG023_callback() return H8_3D_PACKET_PERIOD; } -void CG023_initialize_txid() +static void CG023_initialize_txid() { if(sub_protocol==H8_3D) { @@ -262,10 +255,10 @@ 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]>>8) + (rx_tx_addr[0]&0x0f)) % 0x0f); - hopping_frequency[1] = 0x15 + (((rx_tx_addr[1]>>8) + (rx_tx_addr[1]&0x0f)) % 0x0f); - hopping_frequency[2] = 0x24 + (((rx_tx_addr[2]>>8) + (rx_tx_addr[2]&0x0f)) % 0x0f); - hopping_frequency[3] = 0x33 + (((rx_tx_addr[3]>>8) + (rx_tx_addr[3]&0x0f)) % 0x0f); + 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); } else { // CG023 and YD829 @@ -282,7 +275,6 @@ uint16_t initCG023(void) bind_counter = CG023_BIND_COUNT; CG023_initialize_txid(); CG023_init(); - phase=CG023_BIND; if(sub_protocol==CG023) return CG023_INITIAL_WAIT+CG023_PACKET_PERIOD; else diff --git a/Multiprotocol/CX10_nrf24l01.ino b/Multiprotocol/CX10_nrf24l01.ino index 4525b7d..10b9437 100644 --- a/Multiprotocol/CX10_nrf24l01.ino +++ b/Multiprotocol/CX10_nrf24l01.ino @@ -13,6 +13,7 @@ along with Multiprotocol. If not, see . */ // compatible with Cheerson CX-10 blue & newer red pcb, CX-10A, CX11, CX-10 green pcb, DM007, Floureon FX-10, CX-Stars +// Last sync with hexfet new_protocols/cx10_nrf24l01.c dated 2015-11-26 #if defined(CX10_NRF24L01_INO) @@ -21,6 +22,7 @@ #define CX10_BIND_COUNT 4360 // 6 seconds #define CX10_PACKET_SIZE 15 #define CX10A_PACKET_SIZE 19 // CX10 blue board packets have 19-byte payload +#define Q282_PACKET_SIZE 21 #define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec #define CX10A_PACKET_PERIOD 6000 @@ -39,13 +41,12 @@ #define NUM_RF_CHANNELS 4 enum { - CX10_INIT1 = 0, - CX10_BIND1, + CX10_BIND1 = 0, CX10_BIND2, CX10_DATA }; -void CX10_Write_Packet(uint8_t bind) +static void CX10_Write_Packet(uint8_t bind) { uint8_t offset = 0; if(sub_protocol == CX10_BLUE) @@ -66,32 +67,74 @@ void CX10_Write_Packet(uint8_t bind) packet[12+offset]= highByte(Servo_data[RUDDER]); // Channel 5 - flip flag - if(Servo_data[AUX1] > PPM_SWITCH) + if(Servo_AUX1) packet[12+offset] |= CX10_FLAG_FLIP; // flip flag - // Channel 6 - mode - if(Servo_data[AUX2] > PPM_MAX_COMMAND) // mode 3 / headless on CX-10A - packet[13+offset] = 0x02; + //flags=0; // packet 13 + uint8_t flags2=0; // packet 14 + + // Channel 6 - rate mode is 2 lsb of packet 13 + if(Servo_data[AUX2] > PPM_MAX_COMMAND) // rate 3 / headless on CX-10A + flags = 0x02; else if(Servo_data[AUX2] < PPM_MIN_COMMAND) - packet[13+offset] = 0x00; // mode 1 + flags = 0x00; // rate 1 else - packet[13+offset] = 0x01; // mode 2 + flags = 0x01; // rate 2 - flags=0; - if(sub_protocol == DM007) + uint8_t video_state=packet[14] & 0x21; + switch(sub_protocol) { - // Channel 7 - snapshot - if(Servo_data[AUX3] > PPM_SWITCH) - flags |= CX10_FLAG_SNAPSHOT; - // Channel 8 - video - if(Servo_data[AUX4] > PPM_SWITCH) - flags |= CX10_FLAG_VIDEO; - // Channel 9 - headless - if(Servo_data[AUX5] > PPM_SWITCH) - packet[13+offset] |= CX10_FLAG_HEADLESS; + case CX10_BLUE: + if(Servo_AUX3) flags |= 0x10; // Channel 7 - picture + if(Servo_AUX4) flags |= 0x08; // Channel 8 - video + break; + case Q282: + //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(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 + if(Servo_AUX3) flags2 = CX10_FLAG_SNAPSHOT; // Channel 7 - picture + if(Servo_AUX4) flags2|= CX10_FLAG_VIDEO; // Channel 8 - video + if(Servo_AUX5) flags |= CX10_FLAG_HEADLESS; // Channel 9 - headless + break; + case JC3015_1: + //FLIP|MODE|PICTURE|VIDEO + if(Servo_AUX3) flags2 = _BV(3); // Channel 7 - picture + if(Servo_AUX4) flags2|= _BV(4); // Channel 8 - video + break; + case JC3015_2: + //FLIP|MODE|LED|DFLIP + if(Servo_AUX3) flags2 = _BV(3); // Channel 7 - LED + if(Servo_AUX4) flags2|= _BV(4); // Channel 8 - DFLIP + break; + case MK33041: + //FLIP|MODE|PICTURE|VIDEO|HEADLESS|RTH + if(Servo_AUX3) flags |= _BV(7); // Channel 7 - picture + if(Servo_AUX4) flags2 = _BV(0); // Channel 8 - video + if(Servo_AUX5) flags2|= _BV(5); // Channel 9 - headless + if(Servo_AUX6) flags |= _BV(2); // Channel 10 - rth + break; } - packet[14+offset] = flags; + packet[13+offset]=flags; + packet[14+offset]=flags2; // Power on, TX mode, 2byte CRC // Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing @@ -111,7 +154,7 @@ void CX10_Write_Packet(uint8_t bind) NRF24L01_SetPower(); } -void CX10_init() +static void CX10_init() { NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); @@ -130,9 +173,6 @@ void CX10_init() uint16_t CX10_callback() { switch (phase) { - case CX10_INIT1: - phase = bind_phase; - break; case CX10_BIND1: if (bind_counter == 0) { @@ -174,41 +214,51 @@ uint16_t CX10_callback() { return packet_period; } -void initialize_txid() +static void initialize_txid() { rx_tx_addr[1]%= 0x30; - 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==Q282) + { + hopping_frequency[0] = 0x46; + hopping_frequency[1] = 0x48; + hopping_frequency[2] = 0x4a; + 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); + } } uint16_t initCX10(void) { - switch(sub_protocol) + if(sub_protocol==CX10_BLUE) { - case CX10_GREEN: - case DM007: - packet_length = CX10_PACKET_SIZE; - packet_period = CX10_PACKET_PERIOD; - bind_phase = CX10_BIND1; - bind_counter = CX10_BIND_COUNT; - break; - case CX10_BLUE: - packet_length = CX10A_PACKET_SIZE; - packet_period = CX10A_PACKET_PERIOD; - bind_phase = CX10_BIND2; - bind_counter=0; - for(uint8_t i=0; i<4; i++) - packet[5+i] = 0xff; // clear aircraft id - packet[9] = 0; - break; + packet_length = CX10A_PACKET_SIZE; + packet_period = CX10A_PACKET_PERIOD; + phase = CX10_BIND2; + bind_counter=0; + for(uint8_t i=0; i<4; i++) + packet[5+i] = 0xff; // clear aircraft id + packet[9] = 0; + } + else + { + if(sub_protocol==Q282) + packet_length = Q282_PACKET_SIZE; + else + packet_length = CX10_PACKET_SIZE; + packet_period = CX10_PACKET_PERIOD; + phase = CX10_BIND1; + bind_counter = CX10_BIND_COUNT; } initialize_txid(); CX10_init(); - phase = CX10_INIT1; BIND_IN_PROGRESS; // autobind protocol - return INITIAL_WAIT; + return INITIAL_WAIT+packet_period; } #endif diff --git a/Multiprotocol/CYRF6936_SPI.ino b/Multiprotocol/CYRF6936_SPI.ino index a45101d..9880233 100644 --- a/Multiprotocol/CYRF6936_SPI.ino +++ b/Multiprotocol/CYRF6936_SPI.ino @@ -14,7 +14,7 @@ */ #include "iface_cyrf6936.h" -void cyrf_spi_write(uint8_t command) +static void cyrf_spi_write(uint8_t command) { uint8_t n=8; SCK_off;//SCK start low @@ -32,7 +32,7 @@ void cyrf_spi_write(uint8_t command) SDI_on; } -uint8_t cyrf_spi_read() +static uint8_t cyrf_spi_read() { uint8_t result; uint8_t i; @@ -59,7 +59,7 @@ void CYRF_WriteRegister(uint8_t address, uint8_t data) CYRF_CSN_on; } -void CYRF_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t length) +static void CYRF_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t length) { uint8_t i; @@ -70,7 +70,7 @@ void CYRF_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t leng CYRF_CSN_on; } -void CYRF_ReadRegisterMulti(uint8_t address, uint8_t data[], uint8_t length) +static void CYRF_ReadRegisterMulti(uint8_t address, uint8_t data[], uint8_t length) { uint8_t i; @@ -149,11 +149,13 @@ void CYRF_ConfigRFChannel(uint8_t ch) CYRF_WriteRegister(CYRF_00_CHANNEL,ch); } -void CYRF_SetPower_Value(uint8_t power) +/* +static void CYRF_SetPower_Value(uint8_t power) { uint8_t val = CYRF_ReadRegister(CYRF_03_TX_CFG) & 0xF8; CYRF_WriteRegister(CYRF_03_TX_CFG, val | (power & 0x07)); } +*/ void CYRF_SetPower(uint8_t val) { @@ -203,22 +205,22 @@ void CYRF_WritePreamble(uint32_t preamble) /* * */ -void CYRF_StartReceive() +static void CYRF_StartReceive() { CYRF_WriteRegister(CYRF_05_RX_CTRL,0x87); } -void CYRF_ReadDataPacket(uint8_t dpbuffer[]) +/*static void CYRF_ReadDataPacket(uint8_t dpbuffer[]) { CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, 0x10); } - -void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length) +*/ +/*static void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length) { ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, length); } - -void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len) +*/ +static void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len) { CYRF_WriteRegister(CYRF_01_TX_LENGTH, len); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40); @@ -231,7 +233,7 @@ void CYRF_WriteDataPacket(const uint8_t dpbuffer[]) CYRF_WriteDataPacketLen(dpbuffer, 16); } -uint8_t CYRF_ReadRSSI(uint8_t dodummyread) +/*static uint8_t CYRF_ReadRSSI(uint8_t dodummyread) { uint8_t result; if(dodummyread) @@ -241,7 +243,7 @@ uint8_t CYRF_ReadRSSI(uint8_t dodummyread) result = CYRF_ReadRegister(CYRF_13_RSSI); return (result & 0x0F); } - +*/ //NOTE: This routine will reset the CRC Seed void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uint8_t min, uint8_t max) { diff --git a/Multiprotocol/DSM2_cyrf6936.ino b/Multiprotocol/DSM2_cyrf6936.ino index fd4e0f9..66b582a 100644 --- a/Multiprotocol/DSM2_cyrf6936.ino +++ b/Multiprotocol/DSM2_cyrf6936.ino @@ -121,7 +121,7 @@ const uint8_t cyrfmfg_id[6] = {0xd4, 0x62, 0xd6, 0xad, 0xd3, 0xff}; //dx6i #endif */ -void build_bind_packet() +static void build_bind_packet() { uint8_t i; uint16_t sum = 384 - 0x10;// @@ -154,7 +154,7 @@ void build_bind_packet() packet[15] = sum & 0xff; } -void build_data_packet(uint8_t upper)// +static void build_data_packet(uint8_t upper)// { #if DSM2_NUM_CHANNELS==4 const uint8_t ch_map[] = {0, 1, 2, 3, 0xff, 0xff, 0xff}; //Guess @@ -252,7 +252,7 @@ void build_data_packet(uint8_t upper)// } } -uint8_t PROTOCOL_SticksMoved(uint8_t init) +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; @@ -268,7 +268,7 @@ uint8_t PROTOCOL_SticksMoved(uint8_t init) return ((ele_diff + ail_diff) > STICK_MOVEMENT);// } -uint8_t get_pn_row(uint8_t channel) +static uint8_t get_pn_row(uint8_t channel) { return (sub_protocol == DSMX ? (channel - 2) % 5 : channel % 5); } @@ -300,7 +300,7 @@ const uint8_t init_vals[][2] = { {CYRF_01_TX_LENGTH, 0x10}, //16byte packet }; -void cyrf_config() +static void 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 +308,7 @@ void cyrf_config() CYRF_ConfigRFChannel(0x61); } -void initialize_bind_state() +static void initialize_bind_state() { const uint8_t pn_bind[] = { 0xc6,0x94,0x22,0xfe,0x48,0xe6,0x57,0x4e }; uint8_t data_code[32]; @@ -342,13 +342,13 @@ const uint8_t data_vals[][2] = { {CYRF_10_FRAMING_CFG, 0xea}, }; -void cyrf_configdata() +static void cyrf_configdata() { for(uint8_t i = 0; i < sizeof(data_vals) / 2; i++) CYRF_WriteRegister(data_vals[i][0], data_vals[i][1]); } -void set_sop_data_crc() +static void 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 +363,7 @@ void set_sop_data_crc() crcidx = !crcidx; } -void calc_dsmx_channel() +static void 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)); diff --git a/Multiprotocol/Devo_cyrf6936.ino b/Multiprotocol/Devo_cyrf6936.ino index bfc08a8..3e8ec7a 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; -void scramble_pkt() +static void scramble_pkt() { #ifdef NO_SCRAMBLE return; @@ -77,7 +77,7 @@ void scramble_pkt() #endif } -void add_pkt_suffix() +static void add_pkt_suffix() { uint8_t bind_state; if (use_fixed_id) @@ -97,7 +97,7 @@ void add_pkt_suffix() packet[15] = (fixed_id >> 16) & 0xff; } -void build_beacon_pkt(uint8_t upper) +static void build_beacon_pkt(uint8_t upper) { packet[0] = ((DEVO_NUM_CHANNELS << 4) | 0x07); // uint8_t enable = 0; @@ -116,7 +116,7 @@ void build_beacon_pkt(uint8_t upper) add_pkt_suffix(); } -void build_bind_pkt() +static void build_bind_pkt() { packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a; packet[1] = bind_counter & 0xff; @@ -136,7 +136,7 @@ void build_bind_pkt() packet[15] ^= cyrfmfg_id[2]; } -void build_data_pkt() +static void build_data_pkt() { uint8_t i; packet[0] = (DEVO_NUM_CHANNELS << 4) | (0x0b + ch_idx); @@ -161,7 +161,7 @@ void build_data_pkt() add_pkt_suffix(); } -void cyrf_set_bound_sop_code() +static void 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 @@ void cyrf_set_bound_sop_code() CYRF_SetPower(0x08); } -void cyrf_init() +static void cyrf_init() { /* Initialise CYRF chip */ CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x39); @@ -201,7 +201,7 @@ void cyrf_init() CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28); } -void set_radio_channels() +static void set_radio_channels() { //int i; CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80); @@ -217,7 +217,7 @@ void set_radio_channels() hopping_frequency[4] = hopping_frequency[1]; } -void DEVO_BuildPacket() +static void DEVO_BuildPacket() { switch(phase) { @@ -302,7 +302,7 @@ uint16_t devo_callback() return 1200; } -void devo_bind() +/*static void devo_bind() { fixed_id = Model_fixed_id; bind_counter = DEVO_BIND_COUNT; @@ -310,8 +310,8 @@ void devo_bind() //PROTOCOL_SetBindState(0x1388 * 2400 / 1000); //msecs 12000ms } -/* -void generate_fixed_id_bind(){ + +static void 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 new file mode 100644 index 0000000..77452a3 --- /dev/null +++ b/Multiprotocol/ESky_nrf24l01.ino @@ -0,0 +1,171 @@ +/* + 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 . + */ +// Last sync with hexfet new_protocols/esky_nrf24l01.c dated 2015-02-13 + +#if defined(ESKY_NRF24L01_INO) + +#include "iface_nrf24l01.h" + +#define ESKY_BIND_COUNT 1000 +#define ESKY_PACKET_PERIOD 3333 +#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() +{ + 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) +{ + NRF24L01_Initialize(); + + // 2-bytes CRC, radio off + NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); + NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 + 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); + } + else + ESKY_set_data_address(); + NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // No auto retransmission + NRF24L01_WriteReg(NRF24L01_05_RF_CH, 50); // Channel 50 for bind packets + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps + NRF24L01_SetPower(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit + NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, ESKY_PAYLOAD_SIZE); // bytes of data payload for pipe 0 + NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, ESKY_PAYLOAD_SIZE); + NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, ESKY_PAYLOAD_SIZE); + NRF24L01_WriteReg(NRF24L01_14_RX_PW_P3, ESKY_PAYLOAD_SIZE); + NRF24L01_WriteReg(NRF24L01_15_RX_PW_P4, ESKY_PAYLOAD_SIZE); + NRF24L01_WriteReg(NRF24L01_16_RX_PW_P5, ESKY_PAYLOAD_SIZE); + NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here +} + +static void ESKY_init2() +{ + NRF24L01_FlushTx(); + packet_sent = 0; + hopping_frequency_no = 0; + uint16_t channel_ord = rx_tx_addr[0] % 74; + hopping_frequency[12] = 10 + (uint8_t)channel_ord; //channel_code + uint8_t channel1, channel2; + channel1 = 10 + (uint8_t)((37 + channel_ord*5) % 74); + channel2 = 10 + (uint8_t)(( channel_ord*5) % 74) ; + + hopping_frequency[0] = channel1; + hopping_frequency[1] = channel1; + hopping_frequency[2] = channel1; + hopping_frequency[3] = channel2; + hopping_frequency[4] = channel2; + hopping_frequency[5] = channel2; + + //end_bytes + hopping_frequency[6] = 6; + hopping_frequency[7] = channel1*2; + hopping_frequency[8] = channel2*2; + hopping_frequency[9] = 6; + hopping_frequency[10] = channel1*2; + hopping_frequency[11] = channel2*2; + + // Turn radio power on + NRF24L01_SetTxRxMode(TX_EN); +} + +static void ESKY_send_packet(uint8_t bind) +{ + uint8_t rf_ch = 50; // bind channel + if (bind) + { + // Bind packet + packet[0] = rx_tx_addr[2]; + packet[1] = rx_tx_addr[1]; + packet[2] = rx_tx_addr[0]; + packet[3] = hopping_frequency[12]; // channel_code encodes pair of channels to transmit on + packet[4] = 0x18; + packet[5] = 0x29; + packet[6] = 0; + packet[7] = 0; + packet[8] = 0; + packet[9] = 0; + packet[10] = 0; + packet[11] = 0; + packet[12] = 0; + } + else + { + // Regular packet + // Each data packet is repeated 3 times on one channel, and 3 times on another channel + // For arithmetic simplicity, channels are repeated in rf_channels array + if (hopping_frequency_no == 0) + { + const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2}; + for (uint8_t i = 0; i < 6; i++) + { + packet[i*2] = Servo_data[ch[i]]>>8; //high byte of servo timing(1000-2000us) + packet[i*2+1] = Servo_data[ch[i]]&0xFF; //low byte of servo timing(1000-2000us) + } + } + rf_ch = hopping_frequency[hopping_frequency_no]; + packet[12] = hopping_frequency[hopping_frequency_no+6]; // end_bytes + hopping_frequency_no++; + if (hopping_frequency_no > 6) hopping_frequency_no = 0; + } + NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch); + NRF24L01_FlushTx(); + NRF24L01_WritePayload(packet, ESKY_PAYLOAD_SIZE); + packet_sent = 1; + if (! rf_ch_num) + NRF24L01_SetPower(); //Keep transmit power updated +} + +uint16_t ESKY_callback() +{ + if(IS_BIND_DONE_on) + { + if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) + return ESKY_PACKET_CHKTIME; + ESKY_send_packet(0); + } + else + { + if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) + return ESKY_PACKET_CHKTIME; + ESKY_send_packet(1); + if (--bind_counter == 0) + { + ESKY_set_data_address(); + BIND_DONE; + } + } + return ESKY_PACKET_PERIOD; +} + +uint16_t initESKY(void) +{ + bind_counter = ESKY_BIND_COUNT; + rx_tx_addr[3] = 0xBB; + ESKY_init(IS_AUTOBIND_FLAG_on); + ESKY_init2(); + return 50000; +} + +#endif \ No newline at end of file diff --git a/Multiprotocol/FlySky_a7105.ino b/Multiprotocol/FlySky_a7105.ino index eb3be83..452b5ff 100644 --- a/Multiprotocol/FlySky_a7105.ino +++ b/Multiprotocol/FlySky_a7105.ino @@ -12,6 +12,7 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// Last sync with hexfet new_protocols/flysky_a7105.c dated 2015-09-28 #if defined(FLYSKY_A7105_INO) @@ -72,44 +73,45 @@ uint8_t chanrow; uint8_t chancol; uint8_t chanoffset; -void flysky_apply_extension_flags() +static void 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, }; static uint8_t seq_counter; - switch(sub_protocol) { + switch(sub_protocol) + { case V9X9: - if(Servo_data[AUX1] > PPM_SWITCH) + if(Servo_AUX1) packet[12] |= FLAG_V9X9_UNK; - if(Servo_data[AUX2] > PPM_SWITCH) + if(Servo_AUX2) packet[12] |= FLAG_V9X9_LED; - if(Servo_data[AUX3] > PPM_SWITCH) + if(Servo_AUX3) packet[10] |= FLAG_V9X9_CAMERA; - if(Servo_data[AUX4] > PPM_SWITCH) + if(Servo_AUX4) packet[10] |= FLAG_V9X9_VIDEO; break; case V6X6: packet[13] = 0x03; // 3 = 100% rate (0=40%, 1=60%, 2=80%) packet[14] = 0x00; - if(Servo_data[AUX1] > PPM_SWITCH) + if(Servo_AUX1) packet[14] |= FLAG_V6X6_FLIP; - if(Servo_data[AUX2] > PPM_SWITCH) + if(Servo_AUX2) packet[14] |= FLAG_V6X6_LED; - if(Servo_data[AUX3] > PPM_SWITCH) + if(Servo_AUX3) packet[14] |= FLAG_V6X6_CAMERA; - if(Servo_data[AUX4] > PPM_SWITCH) + if(Servo_AUX4) packet[14] |= FLAG_V6X6_VIDEO; - if(Servo_data[AUX5] > PPM_SWITCH) + if(Servo_AUX5) { packet[13] |= FLAG_V6X6_HLESS1; packet[14] |= FLAG_V6X6_HLESS2; } - if(Servo_data[AUX6] > PPM_SWITCH) //use option to manipulate these bytes + if(Servo_AUX6) //use option to manipulate these bytes packet[14] |= FLAG_V6X6_RTH; - if(Servo_data[AUX7] > PPM_SWITCH) + if(Servo_AUX7) packet[14] |= FLAG_V6X6_XCAL; - if(Servo_data[AUX8] > PPM_SWITCH) + if(Servo_AUX8) packet[14] |= FLAG_V6X6_YCAL; packet[15] = 0x10; // unknown packet[16] = 0x10; // unknown @@ -126,9 +128,9 @@ void flysky_apply_extension_flags() packet[12] |= 0x20; // bit 6 is always set ? packet[13] = 0x00; // unknown packet[14] = 0x00; - if(Servo_data[AUX1] > PPM_SWITCH) - packet[14] |= FLAG_V912_BTMBTN; - if(Servo_data[AUX2] > PPM_SWITCH) + if(Servo_AUX1) + packet[14] = FLAG_V912_BTMBTN; + if(Servo_AUX2) packet[14] |= FLAG_V912_TOPBTN; packet[15] = 0x27; // [15] and [16] apparently hold an analog channel with a value lower than 1000 packet[16] = 0x03; // maybe it's there for a pitch channel for a CP copter ? @@ -146,7 +148,7 @@ void flysky_apply_extension_flags() } } -void flysky_build_packet(uint8_t init) +static void flysky_build_packet(uint8_t init) { uint8_t i; //servodata timing range for flysky. @@ -159,7 +161,7 @@ void flysky_build_packet(uint8_t init) packet[2] = rx_tx_addr[2]; packet[3] = rx_tx_addr[1]; packet[4] = rx_tx_addr[0]; - uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4}; + const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4}; for(i = 0; i < 8; i++) { packet[5+2*i]=lowByte(Servo_data[ch[i]]); //low byte of servo timing(1000-2000us) diff --git a/Multiprotocol/FrSky_cc2500.ino b/Multiprotocol/FrSky_cc2500.ino index 44899fe..035383e 100644 --- a/Multiprotocol/FrSky_cc2500.ino +++ b/Multiprotocol/FrSky_cc2500.ino @@ -111,7 +111,7 @@ uint16_t ReadFrSky_2way() } #if defined(TELEMETRY) -void check_telemetry(uint8_t *pkt,uint8_t len) +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 @@ -128,17 +128,16 @@ void check_telemetry(uint8_t *pkt,uint8_t len) } void compute_RSSIdbm(){ -if(pktt[len-2] >=128){ -RSSI_dBm =(((uint16_t)(pktt[len-2])*18)>>5)- 82; -} -else{ - RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5)+65; - } + RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5); + if(pktt[len-2] >=128) + RSSI_dBm -= 82; + else + RSSI_dBm += 65; } #endif -void frsky2way_init(uint8_t bind) +static void frsky2way_init(uint8_t bind) { // Configure cc2500 for tx mode CC2500_Reset(); @@ -197,7 +196,7 @@ void frsky2way_init(uint8_t bind) //#######END INIT######## } -uint8_t get_chan_num(uint16_t idx) +static uint8_t get_chan_num(uint16_t idx) { uint8_t ret = (idx * 0x1e) % 0xeb; if(idx == 3 || idx == 23 || idx == 47) @@ -207,7 +206,7 @@ uint8_t get_chan_num(uint16_t idx) return ret; } -void frsky2way_build_bind_packet() +static void 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 @@ -234,7 +233,7 @@ void frsky2way_build_bind_packet() uint8_t telemetry_counter=0; -void frsky2way_data_frame() +static void 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 diff --git a/Multiprotocol/Hisky_nrf24l01.ino b/Multiprotocol/Hisky_nrf24l01.ino index 5555a81..d7a3fde 100644 --- a/Multiprotocol/Hisky_nrf24l01.ino +++ b/Multiprotocol/Hisky_nrf24l01.ino @@ -12,6 +12,7 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// Last sync with hexfet new_protocols/hisky_nrf24l01.c dated 2015-03-27 #if defined(HISKY_NRF24L01_INO) @@ -26,7 +27,7 @@ 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] -void calc_fh_channels(uint32_t seed) +static void calc_fh_channels(uint32_t seed) { uint8_t idx = 0; uint32_t rnd = seed; @@ -60,7 +61,7 @@ void calc_fh_channels(uint32_t seed) } } -void build_binding_packet(void) +static void build_binding_packet(void) { uint8_t i; uint16_t sum=0; @@ -94,7 +95,7 @@ void build_binding_packet(void) } } -void hisky_init() +static void hisky_init() { NRF24L01_Initialize(); @@ -115,11 +116,11 @@ 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 -void build_ch_data() +static void build_ch_data() { uint16_t temp; uint8_t i,j; - uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4}; + const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4}; for (i = 0; i< 8; i++) { j=ch[i]; temp=map(limit_channel_100(j),PPM_MIN_100,PPM_MAX_100,0,1000); @@ -213,7 +214,7 @@ uint16_t hisky_cb() } // Generate internal id from TX id and manufacturer id (STM32 unique id) -void initialize_tx_id() +static void initialize_tx_id() { //Generate frequency hopping table if(sub_protocol==HK310) diff --git a/Multiprotocol/Hubsan_a7105.ino b/Multiprotocol/Hubsan_a7105.ino index 68c9869..402e61a 100644 --- a/Multiprotocol/Hubsan_a7105.ino +++ b/Multiprotocol/Hubsan_a7105.ino @@ -12,19 +12,31 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// Last sync with hexfet new_protocols/hubsan_a7105.c dated 2015-12-11 #if defined(HUBSAN_A7105_INO) #include "iface_a7105.h" enum{ - HUBSAN_FLAG_VIDEO = 0x01, // record video - HUBSAN_FLAG_FLIP = 0x08, - HUBSAN_FLAG_LIGHT = 0x04 + // flags going to packet[9] (Normal) + HUBSAN_FLAG_VIDEO= 0x01, // record video + HUBSAN_FLAG_FLIP = 0x08, // enable flips + HUBSAN_FLAG_LED = 0x04 // enable LEDs }; -uint32_t sessionid; -const uint32_t txid = 0xdb042679; +enum{ + // flags going to packet[9] (Plus series) + HUBSAN_FLAG_HEADLESS = 0x08, // headless mode +}; + +enum{ + // flags going to packet[13] (Plus series) + HUBSAN_FLAG_SNAPSHOT = 0x01, + HUBSAN_FLAG_FLIP_PLUS = 0x80, +}; + +uint32_t sessionid,id_data; enum { BIND_1, @@ -43,7 +55,7 @@ enum { }; #define WAIT_WRITE 0x80 -void update_crc() +static void update_crc() { uint8_t sum = 0; for(uint8_t i = 0; i < 15; i++) @@ -51,23 +63,41 @@ void update_crc() packet[15] = (256 - (sum % 256)) & 0xFF; } -void hubsan_build_bind_packet(uint8_t state) +static void hubsan_build_bind_packet(uint8_t bind_state) { - packet[0] = state; + static uint8_t handshake_counter; + if(phase < BIND_7) + handshake_counter = 0; + memset(packet, 0, 16); + packet[0] = bind_state; packet[1] = channel; packet[2] = (sessionid >> 24) & 0xFF; packet[3] = (sessionid >> 16) & 0xFF; packet[4] = (sessionid >> 8) & 0xFF; packet[5] = (sessionid >> 0) & 0xFF; - packet[6] = 0x08; - packet[7] = 0xe4; - packet[8] = 0xea; - packet[9] = 0x9e; - packet[10] = 0x50; - packet[11] = (txid >> 24) & 0xFF; - packet[12] = (txid >> 16) & 0xFF; - packet[13] = (txid >> 8) & 0xFF; - packet[14] = (txid >> 0) & 0xFF; + if(id_data == ID_NORMAL) + { + packet[6] = 0x08; + packet[7] = 0xe4; + packet[8] = 0xea; + packet[9] = 0x9e; + packet[10] = 0x50; + //const uint32_t txid = 0xdb042679; + packet[11] = 0xDB; + packet[12] = 0x04; + packet[13] = 0x26; + packet[14] = 0x79; + } + else + { //ID_PLUS + if(phase >= BIND_3) + { + packet[7] = 0x62; + packet[8] = 0x16; + } + if(phase == BIND_7) + packet[2] = handshake_counter++; + } update_crc(); } @@ -75,69 +105,111 @@ void hubsan_build_bind_packet(uint8_t state) //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% -void hubsan_build_packet() +static void hubsan_build_packet() { static uint8_t vtx_freq = 0; memset(packet, 0, 16); if(vtx_freq != option || packet_count==100) // set vTX frequency (H107D) { vtx_freq = option; - packet[0] = 0x40; - packet[1] = (option>0xF2)?0x17:0x16; - packet[2] = option+0x0D; // 5645 - 5900 MHz + packet[0] = 0x40; // vtx data packet + packet[1] = (vtx_freq>0xF2)?0x17:0x16; + packet[2] = vtx_freq+0x0D; // 5645 - 5900 MHz packet[3] = 0x82; packet_count++; } else //20 00 00 00 80 00 7d 00 84 02 64 db 04 26 79 7b { - packet[0] = 0x20; - packet[2] = convert_channel_8b(THROTTLE);//throtle + packet[0] = 0x20; // normal data packet + packet[2] = convert_channel_8b(THROTTLE); //Throtle } - packet[4] = 0xFF - convert_channel_8b(RUDDER);//Rudder is reversed - packet[6] = 0xFF - convert_channel_8b(ELEVATOR); //Elevator is reversed - packet[8] = convert_channel_8b(AILERON);//aileron - if( packet_count < 100) { - packet[9] = 0x02 | HUBSAN_FLAG_LIGHT | HUBSAN_FLAG_FLIP; - packet_count++; + packet[4] = 0xFF - convert_channel_8b(RUDDER); //Rudder is reversed + packet[6] = 0xFF - convert_channel_8b(ELEVATOR); //Elevator is reversed + packet[8] = convert_channel_8b(AILERON); //Aileron + if(id_data == ID_NORMAL) + { + if( packet_count < 100) + { + packet[9] = 0x02 | HUBSAN_FLAG_LED | HUBSAN_FLAG_FLIP; // sends default value for the 100 first packets + packet_count++; + } + else + { + packet[9] = 0x02; + // Channel 5 + if(Servo_AUX1) packet[9] |= HUBSAN_FLAG_FLIP; + // Channel 6 + if(Servo_AUX2) packet[9] |= HUBSAN_FLAG_LED; + // Channel 8 + if(Servo_AUX4) packet[9] |= HUBSAN_FLAG_VIDEO; // H102D + } + packet[10] = 0x64; + //const uint32_t txid = 0xdb042679; + packet[11] = 0xDB; + packet[12] = 0x04; + packet[13] = 0x26; + packet[14] = 0x79; } else - { - packet[9] = 0x02; - // Channel 5 - if( Servo_data[AUX1] >= PPM_SWITCH) - packet[9] |= HUBSAN_FLAG_FLIP; - // Channel 6 - if( Servo_data[AUX2] >= PPM_SWITCH) - packet[9] |= HUBSAN_FLAG_LIGHT; - // Channel 8 - if( Servo_data[AUX4] > PPM_SWITCH) - packet[9] |= HUBSAN_FLAG_VIDEO; + { //ID_PLUS + packet[3] = 0x64; + packet[5] = 0x64; + packet[7] = 0x64; + packet[9] = 0x06; + //FLIP|LIGHT|PICTURE|VIDEO|HEADLESS + if(Servo_AUX4) packet[9] |= HUBSAN_FLAG_VIDEO; + if(Servo_AUX5) packet[9] |= HUBSAN_FLAG_HEADLESS; + packet[10]= 0x19; + packet[12]= 0x5C; // ghost channel ? + packet[13] = 0; + if(Servo_AUX3) packet[13] = HUBSAN_FLAG_SNAPSHOT; + if(Servo_AUX1) packet[13] |= HUBSAN_FLAG_FLIP_PLUS; + packet[14]= 0x49; // ghost channel ? + if(packet_count < 100) + { // set channels to neutral for first 100 packets + packet[2] = 0x80; // throttle neutral is at mid stick on plus series + packet[4] = 0x80; + packet[6] = 0x80; + packet[8] = 0x80; + packet[9] = 0x06; + packet[13]= 0x00; + packet_count++; + } } - packet[10] = 0x64; - packet[11] = (txid >> 24) & 0xFF; - packet[12] = (txid >> 16) & 0xFF; - packet[13] = (txid >> 8) & 0xFF; - packet[14] = (txid >> 0) & 0xFF; update_crc(); } -uint8_t hubsan_check_integrity() +#if defined(TELEMETRY) +/*static uint8_t hubsan_check_integrity() { - uint8_t sum = 0; - for(int i = 0; i < 15; i++) + int sum = 0; + for(uint8_t i = 0; i < 15; i++) sum += packet[i]; return packet[15] == ((256 - (sum % 256)) & 0xFF); } +*/ +#endif uint16_t ReadHubsan() { static uint8_t txState=0; static uint8_t rfMode=0; + static uint8_t bind_count=0; uint16_t delay; uint8_t i; switch(phase) { case BIND_1: + bind_count++; + if(bind_count >= 20) + { + if(id_data == ID_NORMAL) + id_data = ID_PLUS; + else + id_data = ID_NORMAL; + A7105_WriteID(id_data); + bind_count = 0; + } case BIND_3: case BIND_5: case BIND_7: @@ -151,13 +223,22 @@ uint16_t ReadHubsan() case BIND_5 | WAIT_WRITE: case BIND_7 | WAIT_WRITE: //wait for completion - for(i = 0; i< 20; i++) { + for(i = 0; i< 20; i++) if(! (A7105_ReadReg(A7105_00_MODE) & 0x01)) break; - } A7105_SetTxRxMode(RX_EN); A7105_Strobe(A7105_RX); phase &= ~WAIT_WRITE; + if(id_data == ID_PLUS) + { + if(state == BIND_7 && packet[2] == 9) + { + state = DATA_1; + A7105_WriteReg(A7105_1F_CODE_I, 0x0F); + BIND_DONE; + return 4500; + } + } phase++; return 4500; //7.5msec elapsed since last write case BIND_2: @@ -180,7 +261,7 @@ uint16_t ReadHubsan() return 15000; //22.5msec elapsed since last write } A7105_ReadData(); - if(packet[1] == 9) { + if(packet[1] == 9 && id_data == ID_NORMAL) { phase = DATA_1; A7105_WriteReg(A7105_1F_CODE_I, 0x0F); BIND_DONE; @@ -200,7 +281,7 @@ uint16_t ReadHubsan() A7105_SetPower(); //Keep transmit power in sync hubsan_build_packet(); A7105_Strobe(A7105_STANDBY); - A7105_WriteData(16, phase == DATA_5 ? channel + 0x23 : channel); + A7105_WriteData(16, phase == DATA_5 && id_data == ID_NORMAL ? channel + 0x23 : channel); if (phase == DATA_5) phase = DATA_1; else @@ -249,13 +330,18 @@ uint16_t initHubsan() { const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82}; A7105_Init(INIT_HUBSAN); //hubsan_init(); - randomSeed((uint32_t)analogRead(A0) << 10 | analogRead(A4)); + randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7)); sessionid = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16); channel = allowed_ch[random(0xfefefefe) % sizeof(allowed_ch)]; BIND_IN_PROGRESS; // autobind protocol phase = BIND_1; packet_count=0; + id_data=ID_NORMAL; +#if defined(TELEMETRY) + v_lipo=0; + telemetry_link=0; +#endif return 10000; } diff --git a/Multiprotocol/KN_nrf24l01.ino b/Multiprotocol/KN_nrf24l01.ino index 2a315e9..6c89ff1 100644 --- a/Multiprotocol/KN_nrf24l01.ino +++ b/Multiprotocol/KN_nrf24l01.ino @@ -12,53 +12,248 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// Last sync with hexfet new_protocols/KN_nrf24l01.c dated 2015-11-09 #if defined(KN_NRF24L01_INO) #include "iface_nrf24l01.h" -#define KN_BIND_COUNT 1000 // for KN 2sec every 2ms - 1000 packets -// Timeout for callback in uSec, 2ms=2000us for KN -#define KN_PACKET_PERIOD 2000 -#define KN_PACKET_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short) +// Wait for RX chip stable - 10ms +#define KN_INIT_WAIT_MS 10000 -//#define PAYLOADSIZE 16 -#define NFREQCHANNELS 4 -#define KN_TXID_SIZE 4 +//Payload(16 bytes) plus overhead(10 bytes) is 208 bits, takes about 0.4ms or 0.2ms +//to send for the rate of 500kb/s and 1Mb/s respectively. +// Callback timeout period for sending bind packets, minimum 250 +#define KN_BINDING_PACKET_PERIOD 1000 + +// Timeout for sending data packets, in uSec, KN protocol requires 2ms +#define KN_WL_SENDING_PACKET_PERIOD 2000 +// Timeout for sending data packets, in uSec, KNFX protocol requires 1.2 ms +#define KN_FX_SENDING_PACKET_PERIOD 1200 + +// packets to be sent during binding, last 0.5 seconds in WL Toys and 0.2 seconds in Feilun +#define KN_WL_BIND_COUNT 500 +#define KN_FX_BIND_COUNT 200 + +#define KN_PAYLOADSIZE 16 + +//24L01 has 126 RF channels, can we use all of them? +#define KN_MAX_RF_CHANNEL 73 + +//KN protocol for WL Toys changes RF frequency every 10 ms, repeats with only 4 channels. +//Feilun variant uses only 2 channels, so we will just repeat the hopping channels later +#define KN_RF_CH_COUNT 4 + +//KN protocol for WL Toys sends 4 data packets every 2ms per frequency, plus a 2ms gap. +#define KN_WL_PACKET_SEND_COUNT 5 +//KN protocol for Feilun sends 8 data packets every 1.2ms per frequency, plus a 0.3ms gap. +#define KN_FX_PACKET_SEND_COUNT 8 + +#define KN_TX_ADDRESS_SIZE 5 enum { - KN_FLAG_DR = 0x01, // Dual Rate - KN_FLAG_TH = 0x02, // Throttle Hold - KN_FLAG_IDLEUP = 0x04, // Idle up + KN_PHASE_PRE_BIND, + KN_PHASE_BINDING, + KN_PHASE_PRE_SEND, + KN_PHASE_SENDING, +}; + +enum { + KN_FLAG_DR = 0x01, // Dual Rate: 1 - full range + KN_FLAG_TH = 0x02, // Throttle Hold: 1 - hold + KN_FLAG_IDLEUP = 0x04, // Idle up: 1 - 3D KN_FLAG_RES1 = 0x08, KN_FLAG_RES2 = 0x10, KN_FLAG_RES3 = 0x20, - KN_FLAG_GYRO3 = 0x40, // 00 - 6G mode, 01 - 3G mode + KN_FLAG_GYRO3 = 0x40, // 0 - 6G mode, 1 - 3G mode KN_FLAG_GYROR = 0x80 // Always 0 so far }; -// -enum { - KN_INIT2 = 0, - KN_INIT2_NO_BIND, - KN_BIND, - KN_DATA -}; - -/*enum { - USE1MBPS_NO = 0, - USE1MBPS_YES = 1, -};*/ - -// 2-bytes CRC -#define CRC_CONFIG (BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)) - -void kn_init() +//================================================================================================ +// Private Functions +//================================================================================================ +uint16_t initKN() { + if(sub_protocol==WLTOYS) + { + packet_period = KN_WL_SENDING_PACKET_PERIOD; + bind_counter = KN_WL_BIND_COUNT; + packet_count = KN_WL_PACKET_SEND_COUNT; + } + else + { + packet_period = KN_FX_SENDING_PACKET_PERIOD; + bind_counter = KN_FX_BIND_COUNT; + packet_count = KN_FX_PACKET_SEND_COUNT; + } + kn_init(); + phase = IS_AUTOBIND_FLAG_on ? KN_PHASE_PRE_BIND : KN_PHASE_PRE_SEND; + + return KN_INIT_WAIT_MS; +} + +uint16_t kn_callback() +{ + switch (phase) + { + case KN_PHASE_PRE_BIND: + kn_bind_init(); + phase=KN_PHASE_BINDING; + //Do once, no break needed + case KN_PHASE_BINDING: + if(bind_counter>0) + { + bind_counter--; + NRF24L01_WritePayload(packet, KN_PAYLOADSIZE); + return KN_BINDING_PACKET_PERIOD; + } + BIND_DONE; + //Continue + case KN_PHASE_PRE_SEND: + packet_sent = 0; + hopping_frequency_no = 0; + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, KN_TX_ADDRESS_SIZE); + phase = KN_PHASE_SENDING; + //Do once, no break needed + case KN_PHASE_SENDING: + if(packet_sent >= packet_count) + { + packet_sent = 0; + hopping_frequency_no++; + if(hopping_frequency_no >= KN_RF_CH_COUNT) hopping_frequency_no = 0; + kn_update_packet_control_data(); + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); + } + else + { + // Update sending count and RF channel index. + // The protocol sends 4 data packets every 2ms per frequency, plus a 2ms gap. + // Each data packet need a packet number and RF channel index + packet[13] = 0x00; + if(sub_protocol==WLTOYS) + packet[13] = (packet_sent << 5) | (hopping_frequency_no << 2); + } + NRF24L01_WritePayload(packet, KN_PAYLOADSIZE); + packet_sent++; + return packet_period; + } //switch + + //Bad things happened, reset + packet_sent = 0; + phase = KN_PHASE_PRE_SEND; + 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, CRC_CONFIG); + 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 @@ -68,207 +263,84 @@ void kn_init() NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // bytes of data payload for pipe 0 - NRF24L01_Activate(0x73); // Activate feature register + NRF24L01_Activate(0x73); NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0 - // Enable: Dynamic Payload Length, Payload with ACK , W_TX_PAYLOAD_NOACK - NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL) | BV(NRF2401_1D_EN_ACK_PAY) | BV(NRF2401_1D_EN_DYN_ACK)); - NRF24L01_Activate(0x73); -} + // Enable: Dynamic Payload Length to enable PCF + NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL)); + + NRF24L01_SetPower(); -uint16_t kn_init2() -{ NRF24L01_FlushTx(); - NRF24L01_FlushRx(); - packet_sent = 0; - packet_count = 0; - hopping_frequency_no = 0; - // Turn radio power on - NRF24L01_SetTxRxMode(TX_EN); - NRF24L01_WriteReg(NRF24L01_00_CONFIG, CRC_CONFIG | BV(NRF24L01_00_PWR_UP)); - return 150; + NRF24L01_SetTxRxMode(TX_EN); + NRF24L01_SetBitrate(NRF24L01_BR_1M); //USE1MBPS_YES ? NRF24L01_BR_1M : NRF24L01_BR_250K; } -void set_tx_for_bind() +//------------------------------------------------------------------------------------------------- +// 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() { - NRF24L01_WriteReg(NRF24L01_05_RF_CH, 83); - NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps for binding - NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *) "KNDZK", 5); -} - -void set_tx_for_data() -{ - NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5); -} - -void kn_calc_fh_channels(uint32_t seed) -{ - uint8_t idx = 0; - uint32_t rnd = seed; - while (idx < NFREQCHANNELS) { - 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) % 73) + 2; - // Keep the distance 2 between the channels - either odd or even - if (((next_ch ^ seed) & 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; - } -} - -void kn_initialize_tx_id() -{ - rx_tx_addr[4] = 'K'; - kn_calc_fh_channels(MProtocol_id); -} - -#define PACKET_COUNT_SHIFT 5 -#define RF_CHANNEL_SHIFT 2 -void kn_send_packet(uint8_t bind) -{ - uint8_t rf_ch; - if (bind) { - rf_ch = 83; - packet[0] = 'K'; - packet[1] = 'N'; - packet[2] = 'D'; - packet[3] = 'Z'; - packet[4] = rx_tx_addr[0]; - packet[5] = rx_tx_addr[1]; - packet[6] = rx_tx_addr[2]; - packet[7] = rx_tx_addr[3]; - packet[8] = hopping_frequency[0]; - packet[9] = hopping_frequency[1]; - packet[10] = hopping_frequency[2]; - packet[11] = hopping_frequency[3]; - packet[12] = 0x00; - packet[13] = 0x00; - packet[14] = 0x00; - packet[15] = 0x01; //mode_bitrate == USE1MBPS_YES ? 0x01 : 0x00; - } else { - rf_ch = hopping_frequency[hopping_frequency_no]; - - // Each packet is repeated 4 times on the same channel - // We're not strictly repeating them, rather we - // send new packet on the same frequency, so the - // receiver gets the freshest command. As receiver - // hops to a new frequency as soon as valid packet - // received it does not matter that the packet is - // not the same one repeated twice - nobody checks this - - // NB! packet_count overflow is handled and used in - // callback. - if (++packet_count == 4) - hopping_frequency_no = (hopping_frequency_no + 1) & 0x03; - - uint16_t kn_throttle, kn_rudder, kn_elevator, kn_aileron; - kn_throttle = convert_channel_10b(THROTTLE); - kn_aileron = convert_channel_10b(AILERON); - kn_elevator = convert_channel_10b(ELEVATOR); - kn_rudder = convert_channel_10b(RUDDER); - packet[0] = (kn_throttle >> 8) & 0xFF; - packet[1] = kn_throttle & 0xFF; - packet[2] = (kn_aileron >> 8) & 0xFF; - packet[3] = kn_aileron & 0xFF; - packet[4] = (kn_elevator >> 8) & 0xFF; - packet[5] = kn_elevator & 0xFF; - packet[6] = (kn_rudder >> 8) & 0xFF; - packet[7] = kn_rudder & 0xFF; - // Trims, middle is 0x64 (100) 0-200 - packet[8] = 0x64; // T - packet[9] = 0x64; // A - packet[10] = 0x64; // E - packet[11] = 0x64; // R - - if (Servo_data[AUX1] > PPM_SWITCH) - flags |= KN_FLAG_DR; - else - flags=0; - 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] = (packet_count << PACKET_COUNT_SHIFT) | (hopping_frequency_no << RF_CHANNEL_SHIFT); - - packet[14] = 0x00; - packet[15] = 0x00; - } - - packet_sent = 0; - NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch); - NRF24L01_FlushTx(); - NRF24L01_WritePayload(packet, 16); - //++total_packets; - packet_sent = 1; - - if (! hopping_frequency_no) { - //Keep transmit power updated - NRF24L01_SetPower(); - } -} - -uint16_t kn_callback() -{ - uint16_t timeout = KN_PACKET_PERIOD; - switch (phase) + if(sub_protocol==FEILUN) { - case KN_INIT2: - bind_counter = KN_BIND_COUNT; - timeout = kn_init2(); - phase = KN_BIND; - set_tx_for_bind(); - break; - case KN_INIT2_NO_BIND: - timeout = kn_init2(); - phase = KN_DATA; - set_tx_for_data(); - break; - case KN_BIND: - if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) - return KN_PACKET_CHKTIME; - kn_send_packet(1); - if (--bind_counter == 0) { - phase = KN_DATA; - set_tx_for_data(); - BIND_DONE; - } - break; - case KN_DATA: - if (packet_count == 4) - packet_count = 0; - else { - if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) - return KN_PACKET_CHKTIME; - kn_send_packet(0); - } - break; + 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; } - return timeout; + //The 5th byte is a constant, must be 'K' + rx_tx_addr[4] = 'K'; } -uint16_t initKN(){ - //total_packets = 0; - //mode_bitrate=USE1MBPS_YES; - kn_init(); - phase = IS_AUTOBIND_FLAG_on ? KN_INIT2 : KN_INIT2_NO_BIND; - kn_initialize_tx_id(); +//------------------------------------------------------------------------------------------------- +// 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 - // Call callback in 50ms - return 50000; + // 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 1d1d866..678de5c 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -24,14 +24,17 @@ #include #include -#include "multiprotocol.h" - +//****************************************************** //****************************************************** // Multiprotocol module configuration starts here -//Uncomment the TX type -#define ER9X -//#define DEVO7 +//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 @@ -39,12 +42,13 @@ //Uncomment to enable telemetry #define TELEMETRY -//Protocols to include in compilation, comment to exclude +//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 @@ -65,7 +69,7 @@ static const uint8_t PPM_prot[15][2]= { {MODE_FLYSKY , Flysky }, //Dial=1 {MODE_DSM2 , DSM2 }, //Dial=6 {MODE_DEVO , 0 }, //Dial=7 {MODE_YD717 , YD717 }, //Dial=8 - {MODE_KN , 0 }, //Dial=9 + {MODE_KN , WLTOYS }, //Dial=9 {MODE_SYMAX , SYMAX }, //Dial=10 {MODE_SLT , 0 }, //Dial=11 {MODE_CX10 , CX10_BLUE }, //Dial=12 @@ -74,54 +78,6 @@ static const uint8_t PPM_prot[15][2]= { {MODE_FLYSKY , Flysky }, //Dial=1 {MODE_SYMAX , SYMAX5C } //Dial=15 }; -// -//TX definitions with timing endpoints and channels order -// - -// Turnigy PPM and channels -#if defined(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 -}; -#endif - -// Devo PPM and channels -#if defined(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 - //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 @@ -130,6 +86,7 @@ uint8_t fine = 0xd7; //* 215=-41 * // Multiprotocol module configuration ends here //****************************************************** +//****************************************************** //Global constants/variables @@ -148,6 +105,7 @@ uint8_t packet[40]; #define NUM_CHN 16 // Servo data uint16_t Servo_data[NUM_CHN]; +uint8_t Servo_AUX; // PPM variable volatile uint16_t PPM_data[NUM_CHN]; @@ -171,7 +129,7 @@ uint8_t flags; // Mode_select variables uint8_t mode_select; -uint8_t protocol_flags; +uint8_t protocol_flags=0,protocol_flags2=0; // Serial variables #if defined(NUM_SERIAL_CH_8) //8 channels serial protocol @@ -207,7 +165,7 @@ uint8_t telemetry_link=0; // Callback typedef uint16_t (*void_function_t) (void);//pointer to a function with no parameters which return an uint16_t integer void_function_t remote_callback = 0; -void CheckTimer(uint16_t (*cb)(void)); +static void CheckTimer(uint16_t (*cb)(void)); // Init void setup() @@ -251,7 +209,7 @@ void setup() //********************************** // Update LED - LED_OFF; + LED_OFF; LED_SET_OUTPUT; // Read or create protocol id @@ -287,6 +245,7 @@ void loop() if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received { update_serial_data(); // Update protocol and data + update_aux_flags(); if(IS_CHANGE_PROTOCOL_FLAG_on) { // Protocol needs to be changed LED_OFF; //led off during protocol init @@ -302,6 +261,7 @@ void loop() cli(); // disable global int Servo_data[i]=PPM_data[i]; sei(); // enable global int + update_aux_flags(); } PPM_FLAG_off; // wait for next frame before update } @@ -314,33 +274,41 @@ void loop() CheckTimer(remote_callback); } -// Update led status based on binding and serial -void update_led_status(void) +// Update Servo_AUX flags based on servo AUX positions +static void update_aux_flags(void) { - if(cur_protocol[0]==0) - { // serial without valid protocol - if(blinkPPM_SWITCH) + Servo_AUX|=1< led on + if(remote_callback == 0) + { // Invalid protocol + if(IS_LED_on) //flash to indicate invalid protocol + blink+=BLINK_BAD_PROTO_TIME_LOW; + else + blink+=BLINK_BAD_PROTO_TIME_HIGH; + } else - if(blink led on + else + blink+=BLINK_BIND_TIME; //blink fastly during binding + LED_TOGGLE; + } } // Protocol scheduler -void CheckTimer(uint16_t (*cb)(void)) +static void CheckTimer(uint16_t (*cb)(void)) { uint16_t next_callback; uint32_t prev; @@ -373,13 +341,13 @@ void CheckTimer(uint16_t (*cb)(void)) } } -void protocol_init(uint8_t protocol) +static void protocol_init(uint8_t protocol) { - uint16_t next_callback=100; // Default is immediate call back + uint16_t next_callback=0; // Default is immediate call back remote_callback = 0; set_rx_tx_addr(MProtocol_id); - blink=millis()+BLINK_BIND_TIME; + blink=millis(); if(IS_BIND_BUTTON_FLAG_on) AUTOBIND_FLAG_on; if(IS_AUTOBIND_FLAG_on) @@ -387,8 +355,8 @@ void protocol_init(uint8_t protocol) else BIND_DONE; - CTRL1_on; //antenna RF3 by default - CTRL2_off; //antenna RF3 by default + CTRL1_on; //NRF24L01 antenna RF3 by default + CTRL2_off; //NRF24L01 antenna RF3 by default switch(protocol) // Init the requested protocol { @@ -491,6 +459,12 @@ void protocol_init(uint8_t protocol) next_callback=initBAYANG(); remote_callback = BAYANG_callback; break; +#endif +#if defined(ESKY_NRF24L01_INO) + case MODE_ESKY: + next_callback=initESKY(); + remote_callback = ESKY_callback; + break; #endif } @@ -506,7 +480,7 @@ void protocol_init(uint8_t protocol) BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change } -void update_serial_data() +static void update_serial_data() { if(rx_ok_buff[0]&0x20) //check range RANGE_FLAG_on; @@ -567,7 +541,7 @@ void update_serial_data() RX_FLAG_off; //data has been processed } -void module_reset() +static void module_reset() { remote_callback = 0; switch(prev_protocol) @@ -580,19 +554,15 @@ void module_reset() case MODE_FRSKYX: CC2500_Reset(); break; - case MODE_HISKY: - case MODE_V2X2: - case MODE_YD717: - case MODE_KN: - case MODE_SYMAX: - case MODE_SLT: - case MODE_CX10: - NRF24L01_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; } } @@ -648,7 +618,7 @@ uint16_t limit_channel_100(uint8_t ch) } // Convert 32b id to rx_tx_addr -void set_rx_tx_addr(uint32_t id) +static void set_rx_tx_addr(uint32_t id) { // Used by almost all protocols rx_tx_addr[0] = (id >> 24) & 0xFF; rx_tx_addr[1] = (id >> 16) & 0xFF; @@ -669,7 +639,7 @@ void Serial_write(uint8_t data) } #endif -void Mprotocol_serial_init() +static void Mprotocol_serial_init() { #if defined(NUM_SERIAL_CH_8) //8 channels serial protocol #define BAUD 125000 @@ -742,9 +712,10 @@ ISR(INT1_vect) else if(chan!=-1) // need to wait for start of frame { //servo values between 500us and 2420us will end up here - PPM_data[chan] = Cur_TCNT1/2; - if(PPM_data[chan]PPM_MAX) PPM_data[chan]=PPM_MAX; + uint16_t a = Cur_TCNT1>>2; + if(aPPM_MAX) a=PPM_MAX; + PPM_data[chan]=a; if(chan++>=NUM_CHN) chan=-1; // don't accept any new channels } diff --git a/Multiprotocol/NRF24l01_SPI.ino b/Multiprotocol/NRF24l01_SPI.ino index c37953f..200365e 100644 --- a/Multiprotocol/NRF24l01_SPI.ino +++ b/Multiprotocol/NRF24l01_SPI.ino @@ -19,7 +19,7 @@ //--------------------------- #include "iface_nrf24l01.h" -void nrf_spi_write(uint8_t command) +static void nrf_spi_write(uint8_t command) { uint8_t n=8; @@ -39,7 +39,7 @@ void nrf_spi_write(uint8_t command) } //VARIANT 2 -uint8_t nrf_spi_read(void) +static uint8_t nrf_spi_read(void) { uint8_t result; uint8_t i; @@ -106,7 +106,7 @@ uint8_t NRF24L01_ReadReg(uint8_t reg) return data; } -void NRF24L01_ReadRegisterMulti(uint8_t reg, uint8_t * data, uint8_t length) +/*static void NRF24L01_ReadRegisterMulti(uint8_t reg, uint8_t * data, uint8_t length) { NRF_CSN_off; nrf_spi_write(R_REGISTER | (REGISTER_MASK & reg)); @@ -114,8 +114,8 @@ void NRF24L01_ReadRegisterMulti(uint8_t reg, uint8_t * data, uint8_t length) data[i] = nrf_spi_read(); NRF_CSN_on; } - -void NRF24L01_ReadPayload(uint8_t * data, uint8_t length) +*/ +static void NRF24L01_ReadPayload(uint8_t * data, uint8_t length) { NRF_CSN_off; nrf_spi_write(R_RX_PAYLOAD); @@ -124,7 +124,7 @@ void NRF24L01_ReadPayload(uint8_t * data, uint8_t length) NRF_CSN_on; } -void NRF24L01_Strobe(uint8_t state) +static void NRF24L01_Strobe(uint8_t state) { NRF_CSN_off; nrf_spi_write(state); @@ -161,7 +161,8 @@ void NRF24L01_SetBitrate(uint8_t bitrate) NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup); } -void NRF24L01_SetPower_Value(uint8_t power) +/* + static void NRF24L01_SetPower_Value(uint8_t power) { uint8_t nrf_power = 0; switch(power) { @@ -179,7 +180,7 @@ void NRF24L01_SetPower_Value(uint8_t power) rf_setup = (rf_setup & 0xF9) | ((nrf_power & 0x03) << 1); NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup); } - +*/ void NRF24L01_SetPower() { uint8_t power=NRF_BIND_POWER; @@ -254,42 +255,6 @@ uint8_t NRF24L01_packet_ack() return PKT_PENDING; } - - -//--------------------------- -/* -void NRF24L01_spi_test(void) -{ -unsigned long errors = 0; -unsigned long test = 0; -unsigned long time; -uint8_t test_data_r[5]; -uint8_t test_data_w[5] = {0x01,0x02,0x03,0x04,0x05}; - -time = micros(); -Serial.println("Testing SPI"); - for(test=0; test < 2775600 ; test++) // should run for X mins. - { - NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, test_data_w, 5); - NRF24L01_ReadRegisterMulti(NRF24L01_0B_RX_ADDR_P1, test_data_r, 5); - if(0 != memcmp(test_data_r, test_data_w, sizeof(test_data_r))) errors++; - test_data_w[0] ++; - test_data_w[1] ++; - test_data_w[2] ++; - test_data_w[3] ++; - test_data_w[4] ++; - } -Serial.print("test "); Serial.print(test, HEX); Serial.print("\n"); -Serial.print("errors "); Serial.print(errors, HEX); Serial.print("\n"); -Serial.print("time "); Serial.print(micros()- time, DEC); Serial.print("\n"); - -// 124211960 -// 90899216 -} -*/ -//--------------------------- - - /////////////// // XN297 emulation layer uint8_t xn297_addr_len; @@ -311,7 +276,7 @@ static const uint16_t xn297_crc_xorout[] = { 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, 0x2138, 0x129F, 0xB3A0, 0x2988}; -uint8_t bit_reverse(uint8_t b_in) +static uint8_t bit_reverse(uint8_t b_in) { uint8_t b_out = 0; for (uint8_t i = 0; i < 8; ++i) @@ -322,7 +287,7 @@ uint8_t bit_reverse(uint8_t b_in) return b_out; } -uint16_t crc16_update(uint16_t crc, uint8_t a) +static uint16_t crc16_update(uint16_t crc, uint8_t a) { static const uint16_t polynomial = 0x1021; diff --git a/Multiprotocol/SLT_nrf24l01.ino b/Multiprotocol/SLT_nrf24l01.ino index c096f87..5219d21 100644 --- a/Multiprotocol/SLT_nrf24l01.ino +++ b/Multiprotocol/SLT_nrf24l01.ino @@ -12,6 +12,7 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// Last sync with hexfet new_protocols/slt_nrf24l01.c dated 2015-02-13 #if defined(SLT_NRF24L01_INO) @@ -30,7 +31,7 @@ enum { SLT_DATA3 }; -void SLT_init() +static void SLT_init() { NRF24L01_Initialize(); NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off @@ -56,7 +57,7 @@ static void SLT_init2() NRF24L01_SetTxRxMode(TX_EN); } -void SLT_set_tx_id(void) +static void SLT_set_tx_id(void) { // Frequency hopping sequence generation for (uint8_t i = 0; i < 4; ++i) @@ -67,7 +68,7 @@ void SLT_set_tx_id(void) hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base; hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base; if (i*4 + 3 < SLT_NFREQCHANNELS) // guard for 16 channel - hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base; + hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base; } // unique @@ -89,16 +90,16 @@ void SLT_set_tx_id(void) NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4); } -void wait_radio() +static void SLT_wait_radio() { if (packet_sent) while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS))) ; packet_sent = 0; } -void send_data(uint8_t *data, uint8_t len) +static void SLT_send_data(uint8_t *data, uint8_t len) { - wait_radio(); + SLT_wait_radio(); NRF24L01_FlushTx(); NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_RX_DR) | BV(NRF24L01_07_MAX_RT)); NRF24L01_WritePayload(data, len); @@ -106,11 +107,11 @@ void send_data(uint8_t *data, uint8_t len) packet_sent = 1; } -void SLT_build_packet() +static void SLT_build_packet() { // aileron, elevator, throttle, rudder, gear, pitch uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed - uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER}; + const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER}; for (uint8_t i = 0; i < 4; ++i) { uint16_t v = convert_channel_10b(ch[i]); packet[i] = v; @@ -128,19 +129,20 @@ void SLT_build_packet() hopping_frequency_no = 0; } -static void send_bind_packet() +static void SLT_send_bind_packet() { - wait_radio(); - + SLT_wait_radio(); + BIND_IN_PROGRESS; // autobind protocol NRF24L01_SetPower(); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x7E\xB8\x63\xA9", 4); NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x50); - send_data(rx_tx_addr, 4); + SLT_send_data(rx_tx_addr, 4); // NB: we should wait until the packet's sent before changing TX address! - wait_radio(); + SLT_wait_radio(); + BIND_DONE; NRF24L01_SetPower(); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4); } @@ -156,24 +158,23 @@ uint16_t SLT_callback() delay_us = 150; break; case SLT_BIND: - send_bind_packet(); + SLT_send_bind_packet(); phase = SLT_DATA1; delay_us = 19000; - BIND_DONE; break; case SLT_DATA1: SLT_build_packet(); - send_data(packet, 7); + SLT_send_data(packet, 7); phase = SLT_DATA2; delay_us = 1000; break; case SLT_DATA2: - send_data(packet, 7); + SLT_send_data(packet, 7); phase = SLT_DATA3; delay_us = 1000; break; case SLT_DATA3: - send_data(packet, 7); + SLT_send_data(packet, 7); if (++counter >= 100) { counter = 0; @@ -196,7 +197,6 @@ uint16_t initSLT() SLT_init(); phase = SLT_INIT2; SLT_set_tx_id(); - BIND_IN_PROGRESS; // autobind protocol return 50000; } diff --git a/Multiprotocol/Symax_nrf24l01.ino b/Multiprotocol/Symax_nrf24l01.ino index e6599b6..a146098 100644 --- a/Multiprotocol/Symax_nrf24l01.ino +++ b/Multiprotocol/Symax_nrf24l01.ino @@ -12,16 +12,13 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// compatible with Syma X5C-1, X11, X11C, X12 and for sub protocol X5C Syma X5C (original), X2 +// Last sync with hexfet new_protocols/cx10_nrf24l01.c dated 2015-09-28 #if defined(SYMAX_NRF24L01_INO) #include "iface_nrf24l01.h" -/*** - Main protocol compatible with Syma X5C-1, X11, X11C, X12. - SymaX5C protocol option compatible with Syma X5C (original) and X2. -***/ - #define SYMAX_BIND_COUNT 345 // 1.5 seconds #define SYMAX_FIRST_PACKET_DELAY 12000 #define SYMAX_PACKET_PERIOD 4000 // Timeout for callback in uSec @@ -44,16 +41,7 @@ enum { SYMAX_DATA }; -/* -http://www.deviationtx.com/forum/protocol-development/3768-syma-x5c-1-x11-x12?start=140 - TX address Channel Sequence -S1 3B B6 00 00 A2 15 35 1D 3D -D1 9A E9 02 00 A2 14 34 1C 3C - -D2 46 18 00 00 A2 11 21 31 41 -*/ - -uint8_t SYMAX_checksum(uint8_t *data) +static uint8_t SYMAX_checksum(uint8_t *data) { uint8_t sum = data[0]; @@ -66,7 +54,7 @@ uint8_t SYMAX_checksum(uint8_t *data) return sum + ( sub_protocol==SYMAX5C ? 0 : 0x55 ); } -void SYMAX_read_controls() +static void SYMAX_read_controls() { // Protocol is registered AETRF, that is // Aileron is channel 1, Elevator - 2, Throttle - 3, Rudder - 4, Flip control - 5 @@ -75,25 +63,24 @@ void SYMAX_read_controls() throttle = convert_channel_8b(THROTTLE); rudder = convert_channel_s8b(RUDDER); + flags=0; // Channel 5 - if (Servo_data[AUX1] > PPM_SWITCH) + if (Servo_AUX1) flags = SYMAX_FLAG_FLIP; - else - flags=0; // Channel 7 - if (Servo_data[AUX3] > PPM_SWITCH) + if (Servo_AUX3) flags |= SYMAX_FLAG_PICTURE; // Channel 8 - if (Servo_data[AUX4] > PPM_SWITCH) + if (Servo_AUX4) flags |= SYMAX_FLAG_VIDEO; // Channel 9 - if (Servo_data[AUX5] > PPM_SWITCH) + if (Servo_AUX5) flags |= SYMAX_FLAG_HEADLESS; } #define X5C_CHAN2TRIM(X) ((((X) & 0x80 ? 0xff - (X) : 0x80 + (X)) >> 2) + 0x20) -void SYMAX_build_packet_x5c(uint8_t bind) +static void SYMAX_build_packet_x5c(uint8_t bind) { if (bind) { @@ -124,12 +111,12 @@ void SYMAX_build_packet_x5c(uint8_t bind) packet[14] = (flags & SYMAX_FLAG_VIDEO ? 0x10 : 0x00) | (flags & SYMAX_FLAG_PICTURE ? 0x08 : 0x00) | (flags & SYMAX_FLAG_FLIP ? 0x01 : 0x00) - | 0x04;// (flags & SYMAX_FLAG_RATES ? 0x04 : 0x00); + | 0x04;// always high rates (bit 3 is rate control) packet[15] = SYMAX_checksum(packet); } } -void SYMAX_build_packet(uint8_t bind) +static void SYMAX_build_packet(uint8_t bind) { if (bind) { @@ -151,7 +138,7 @@ void SYMAX_build_packet(uint8_t bind) packet[2] = rudder; packet[3] = aileron; packet[4] = (flags & SYMAX_FLAG_VIDEO ? 0x80 : 0x00) | (flags & SYMAX_FLAG_PICTURE ? 0x40 : 0x00); - packet[5] = (elevator >> 2) | 0xc0; //always high rates (bit 7 is rate control) (flags & SYMAX_FLAG_RATES ? 0x80 : 0x00) | 0x40; // use trims to extend controls + packet[5] = (elevator >> 2) | 0xc0; //always high rates (bit 7 is rate control) packet[6] = (rudder >> 2) | (flags & SYMAX_FLAG_FLIP ? 0x40 : 0x00); packet[7] = (aileron >> 2) | (flags & SYMAX_FLAG_HEADLESS ? 0x80 : 0x00); packet[8] = 0x00; @@ -159,7 +146,7 @@ void SYMAX_build_packet(uint8_t bind) packet[9] = SYMAX_checksum(packet); } -void SYMAX_send_packet(uint8_t bind) +static void SYMAX_send_packet(uint8_t bind) { if (sub_protocol==SYMAX5C) SYMAX_build_packet_x5c(bind); @@ -232,7 +219,7 @@ static void symax_init() NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0e); // power on } -void symax_init1() +static void 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}; @@ -240,13 +227,6 @@ void symax_init1() uint8_t chans_bind_x5c[] = {0x27, 0x1b, 0x39, 0x28, 0x24, 0x22, 0x2e, 0x36, 0x19, 0x21, 0x29, 0x14, 0x1e, 0x12, 0x2d, 0x18}; - //uint8_t data_rx_tx_addr[] = {0x3b,0xb6,0x00,0x00,0xa2}; - //uint8_t data_rx_tx_addr[] = {0x9A,0xe9,0x03,0x00,0xa2};//<<---- is ok - //uint8_t data_rx_tx_addr[] = {0x3b,0xb6,0x00,0x00,0xa2};//<<--- is ok - //uint8_t data_rx_tx_addr[] = {0x9A,0xe9,0x00,0x00,0xa2}; - //uint8_t data_rx_tx_addr[] = {0x9A,0xe9,0x03,0x00,0xa2};//<<---- is ok - //uint8_t data_rx_tx_addr[] = {0x46,0x18,0x00,0x00,0xa2}; - NRF24L01_FlushTx(); NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x08); NRF24L01_WritePayload(first_packet, 15); @@ -267,14 +247,12 @@ void symax_init1() } // channels determined by last byte of tx address -void symax_set_channels(uint8_t address) +static void 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}; static const uint8_t start_chans_3[] = {0x1a, 0x3a, 0x12, 0x32}; - //static const uint8_t start_chans_4[] = {0x15, 0x35, 0x1d, 0x3d}; - //static const uint8_t start_chans_5[] = {0x14, 0x34, 0x1c, 0x3c}; - //static const uint8_t start_chans_6[] = {0x11, 0x21, 0x31, 0x41}; + uint8_t laddress = address & 0x1f; uint8_t i; uint32_t *pchans = (uint32_t *)hopping_frequency; // avoid compiler warning @@ -312,7 +290,7 @@ void symax_set_channels(uint8_t address) *pchans = 0x39194121; } -void symax_init2() +static void 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 fed869d..35796b1 100644 --- a/Multiprotocol/V2X2_nrf24l01.ino +++ b/Multiprotocol/V2X2_nrf24l01.ino @@ -12,10 +12,11 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// compatible with WLToys V2x2, JXD JD38x, JD39x, JJRC H6C, Yizhan Tarantula X6 ... +// Last sync with hexfet new_protocols/v202_nrf24l01.c dated 2015-03-15 #if defined(V2X2_NRF24L01_INO) -// compatible with WLToys V2x2, JXD JD38x, JD39x, JJRC H6C, Yizhan Tarantula X6 ... #include "iface_nrf24l01.h" @@ -73,9 +74,8 @@ static const uint8_t freq_hopping[][16] = { { 0x22, 0x27, 0x17, 0x39, 0x34, 0x28, 0x2B, 0x1D, 0x18, 0x2A, 0x21, 0x38, 0x10, 0x26, 0x20, 0x1F } // 03 }; -//static uint8_t hopping_frequency[16]; -void v202_init() +static void v202_init() { NRF24L01_Initialize(); @@ -103,14 +103,12 @@ void v202_init() NRF24L01_WriteReg(NRF24L01_15_RX_PW_P4, V2X2_PAYLOADSIZE); NRF24L01_WriteReg(NRF24L01_16_RX_PW_P5, V2X2_PAYLOADSIZE); NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here - uint8_t v2x2_rx_tx_addr[] = {0x66, 0x88, 0x68, 0x68, 0x68}; - uint8_t rx_p1_addr[] = {0x88, 0x66, 0x86, 0x86, 0x86}; - NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, v2x2_rx_tx_addr, 5); - NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, rx_p1_addr, 5); - NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, v2x2_rx_tx_addr, 5); + NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x66\x88\x68\x68\x68", 5); + NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, (uint8_t *)"\x88\x66\x86\x86\x86", 5); + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x66\x88\x68\x68\x68", 5); } -void V202_init2() +static void V202_init2() { NRF24L01_FlushTx(); packet_sent = 0; @@ -121,7 +119,7 @@ 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)); } -void set_tx_id(void) +static void V2X2_set_tx_id(void) { uint8_t sum; sum = rx_tx_addr[1] + rx_tx_addr[2] + rx_tx_addr[3]; @@ -136,7 +134,7 @@ void set_tx_id(void) } } -void add_pkt_checksum() +static void V2X2_add_pkt_checksum() { uint8_t sum = 0; for (uint8_t i = 0; i < 15; ++i) @@ -144,7 +142,7 @@ void add_pkt_checksum() packet[15] = sum; } -void send_packet(uint8_t bind) +static void V2X2_send_packet(uint8_t bind) { uint8_t flags2=0; if (bind) @@ -170,18 +168,15 @@ void send_packet(uint8_t bind) packet[6] = 0x40; // roll //Flags + flags=0; // Channel 5 - if (Servo_data[AUX1] > PPM_SWITCH) - flags |= V2X2_FLAG_FLIP; + if (Servo_AUX1) flags = V2X2_FLAG_FLIP; // Channel 6 - if (Servo_data[AUX2] > PPM_SWITCH) - flags |= V2X2_FLAG_LIGHT; + if (Servo_AUX2) flags |= V2X2_FLAG_LIGHT; // Channel 7 - if (Servo_data[AUX3] > PPM_SWITCH) - flags |= V2X2_FLAG_CAMERA; + if (Servo_AUX3) flags |= V2X2_FLAG_CAMERA; // Channel 8 - if (Servo_data[AUX4] > PPM_SWITCH) - flags |= V2X2_FLAG_VIDEO; + if (Servo_AUX4) flags |= V2X2_FLAG_VIDEO; //Flags2 // Channel 9 @@ -205,7 +200,7 @@ void send_packet(uint8_t bind) packet[13] = 0x00; // packet[14] = flags; - add_pkt_checksum(); + V2X2_add_pkt_checksum(); packet_sent = 0; uint8_t rf_ch = hopping_frequency[hopping_frequency_no >> 1]; @@ -213,7 +208,6 @@ void send_packet(uint8_t bind) NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch); NRF24L01_FlushTx(); NRF24L01_WritePayload(packet, V2X2_PAYLOADSIZE); - ++packet_counter; packet_sent = 1; if (! hopping_frequency_no) @@ -237,7 +231,7 @@ uint16_t ReadV2x2() if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) { return PACKET_CHKTIME; } - send_packet(1); + V2X2_send_packet(1); if (--counter == 0) { phase = V202_DATA; BIND_DONE; @@ -247,7 +241,7 @@ uint16_t ReadV2x2() if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) { return PACKET_CHKTIME; } - send_packet(0); + V2X2_send_packet(0); break; } // Packet every 4ms @@ -256,8 +250,6 @@ uint16_t ReadV2x2() uint16_t initV2x2() { - flags=0; - packet_counter = 0; v202_init(); // if (IS_AUTOBIND_FLAG_on) @@ -267,7 +259,7 @@ uint16_t initV2x2() } else phase = V202_INIT2_NO_BIND; - set_tx_id(); + V2X2_set_tx_id(); return 50000; } diff --git a/Multiprotocol/YD717_nrf24l01.ino b/Multiprotocol/YD717_nrf24l01.ino index ed43851..d2a3f1a 100644 --- a/Multiprotocol/YD717_nrf24l01.ino +++ b/Multiprotocol/YD717_nrf24l01.ino @@ -12,6 +12,7 @@ You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see . */ +// Last sync with hexfet new_protocols/yd717_nrf24l01.c dated 2015-09-28 #if defined(YD717_NRF24L01_INO) @@ -23,7 +24,7 @@ #define YD717_PACKET_CHKTIME 500 // Time to wait if packet not yet acknowledged or timed out // Stock tx fixed frequency is 0x3C. Receiver only binds on this freq. -#define RF_CHANNEL 0x3C +#define YD717_RF_CHANNEL 0x3C #define YD717_FLAG_FLIP 0x0F #define YD717_FLAG_LIGHT 0x80 @@ -32,7 +33,6 @@ #define YD717_FLAG_HEADLESS 0x10 #define YD717_PAYLOADSIZE 8 // receive data pipes set to this size, but unused -//#define YD717_MAX_PACKET_SIZE 9 // YD717 packets have 8-byte payload, Syma X4 is 9 enum { YD717_INIT1 = 0, @@ -41,7 +41,7 @@ enum { YD717_DATA }; -void yd717_send_packet(uint8_t bind) +static void yd717_send_packet(uint8_t bind) { uint8_t rudder_trim, elevator_trim, aileron_trim; if (bind) @@ -93,23 +93,17 @@ void yd717_send_packet(uint8_t bind) packet[6] = aileron_trim; } // Flags + flags=0; // Channel 5 - if (Servo_data[AUX1] > PPM_SWITCH) - flags = YD717_FLAG_FLIP; - else - flags=0; + if (Servo_AUX1) flags = YD717_FLAG_FLIP; // Channel 6 - if (Servo_data[AUX2] > PPM_SWITCH) - flags |= YD717_FLAG_LIGHT; + if (Servo_AUX2) flags |= YD717_FLAG_LIGHT; // Channel 7 - if (Servo_data[AUX3] > PPM_SWITCH) - flags |= YD717_FLAG_PICTURE; + if (Servo_AUX3) flags |= YD717_FLAG_PICTURE; // Channel 8 - if (Servo_data[AUX4] > PPM_SWITCH) - flags |= YD717_FLAG_VIDEO; + if (Servo_AUX4) flags |= YD717_FLAG_VIDEO; // Channel 9 - if (Servo_data[AUX5] > PPM_SWITCH) - flags |= YD717_FLAG_HEADLESS; + if (Servo_AUX5) flags |= YD717_FLAG_HEADLESS; packet[7] = flags; } @@ -123,7 +117,7 @@ void yd717_send_packet(uint8_t bind) { packet[8] = packet[0]; // checksum for(uint8_t i=1; i < 8; i++) - packet[8] += packet[i]; + packet[8] += packet[i]; packet[8] = ~packet[8]; NRF24L01_WritePayload(packet, 9); } @@ -131,7 +125,7 @@ void yd717_send_packet(uint8_t bind) NRF24L01_SetPower(); // Set tx_power } -void yd717_init() +static void yd717_init() { NRF24L01_Initialize(); @@ -142,7 +136,7 @@ void yd717_init() NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x1A); // 500uS retransmit t/o, 10 tries - NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_CHANNEL); // Channel 3C + NRF24L01_WriteReg(NRF24L01_05_RF_CH, YD717_RF_CHANNEL); // Channel 3C NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps NRF24L01_SetPower(); NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit @@ -168,23 +162,24 @@ void yd717_init() NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5); } -void YD717_init1() +static void YD717_init1() { // for bind packets set address to prearranged value known to receiver uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65}; - if( sub_protocol==SYMAX2 ) - for(uint8_t i=0; i < 5; i++) + uint8_t i; + if( sub_protocol==SYMAX4 ) + for(i=0; i < 5; i++) bind_rx_tx_addr[i] = 0x60; else if( sub_protocol==NIHUI ) - for(uint8_t i=0; i < 5; i++) + for(i=0; i < 5; i++) bind_rx_tx_addr[i] = 0x64; NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bind_rx_tx_addr, 5); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_rx_tx_addr, 5); } -void YD717_init2() +static void YD717_init2() { // set rx/tx address for data phase NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5); @@ -244,7 +239,6 @@ uint16_t yd717_callback() uint16_t initYD717() { rx_tx_addr[4] = 0xC1; // always uses first data port - flags = 0; yd717_init(); phase = YD717_INIT1; BIND_IN_PROGRESS; // autobind protocol diff --git a/Multiprotocol/iface_cyrf6936.h b/Multiprotocol/iface_cyrf6936.h index 567014b..cf96f2c 100644 --- a/Multiprotocol/iface_cyrf6936.h +++ b/Multiprotocol/iface_cyrf6936.h @@ -83,13 +83,13 @@ void CYRF_SetTxRxMode(enum TXRX_State); void CYRF_ConfigRFChannel(u8 ch); void CYRF_SetPower(u8 power); void CYRF_ConfigCRCSeed(u16 crc); -void CYRF_StartReceive(); +static void CYRF_StartReceive(); void CYRF_ConfigSOPCode(const u8 *sopcodes); void CYRF_ConfigDataCode(const u8 *datacodes, u8 len); -u8 CYRF_ReadRSSI(u32 dodummyread); -void CYRF_ReadDataPacket(u8 dpbuffer[]); +static u8 CYRF_ReadRSSI(u32 dodummyread); +static void CYRF_ReadDataPacket(u8 dpbuffer[]); void CYRF_WriteDataPacket(const u8 dpbuffer[]); -void CYRF_WriteDataPacketLen(const u8 dpbuffer[], u8 len); +static void CYRF_WriteDataPacketLen(const u8 dpbuffer[], u8 len); void CYRF_WriteRegister(u8 address, u8 data); u8 CYRF_ReadRegister(u8 address); void CYRF_WritePreamble(u32 preamble); diff --git a/Multiprotocol/multiprotocol.h b/Multiprotocol/multiprotocol.h index 69bd2bf..3fab255 100644 --- a/Multiprotocol/multiprotocol.h +++ b/Multiprotocol/multiprotocol.h @@ -13,6 +13,8 @@ along with Multiprotocol. If not, see . */ +//****************** +// Protocols //****************** enum PROTOCOLS { @@ -32,6 +34,7 @@ enum PROTOCOLS MODE_CG023 = 13, // =>NRF24L01 / CG023 protocol MODE_BAYANG = 14, // =>NRF24L01 / BAYANG protocol MODE_FRSKYX = 15, // =>CC2500 / FRSKYX protocol + MODE_ESKY = 16, // =>NRF24L01 / ESKY protocol }; enum Flysky { @@ -53,28 +56,129 @@ enum YD717 { YD717=0, SKYWLKR=1, - SYMAX2=2, + SYMAX4=2, XINXUN=3, NIHUI=4 }; +enum KN +{ + WLTOYS=0, + FEILUN=1 +}; enum SYMAX { SYMAX=0, - SYMAX5C=1, + SYMAX5C=1 }; - -enum CX10 { +enum CX10 +{ CX10_GREEN = 0, - CX10_BLUE, // also compatible with CX10-A, CX12 - DM007 + CX10_BLUE=1, // also compatible with CX10-A, CX12 + DM007=2, + Q282=3, + JC3015_1=4, + JC3015_2=5, + MK33041=6 }; - -enum CG023 { +enum CG023 +{ CG023 = 0, YD829 = 1, 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 +}; +#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 @@ -143,6 +247,7 @@ enum CG023 { #define LED_OFF PORTB &= ~_BV(5) #define LED_TOGGLE PORTB ^= _BV(5) #define LED_SET_OUTPUT DDRB |= _BV(5) +#define IS_LED_on ( (PORTB & _BV(5)) != 0x00 ) // Macros #define NOP() __asm__ __volatile__("nop") @@ -183,8 +288,24 @@ enum CG023 { #define BIND_DONE protocol_flags |= _BV(7) #define IS_BIND_DONE_on ( ( protocol_flags & _BV(7) ) !=0 ) +#define BAD_PROTO_off protocol_flags2 &= ~_BV(0) +#define BAD_PROTO_on protocol_flags2 |= _BV(0) +#define IS_BAD_PROTO_on ( ( protocol_flags2 & _BV(0) ) !=0 ) + #define BLINK_BIND_TIME 100 #define BLINK_SERIAL_TIME 500 +#define BLINK_BAD_PROTO_TIME_LOW 1000 +#define BLINK_BAD_PROTO_TIME_HIGH 50 + +//AUX flags definition +#define Servo_AUX1 Servo_AUX & _BV(0) +#define Servo_AUX2 Servo_AUX & _BV(1) +#define Servo_AUX3 Servo_AUX & _BV(2) +#define Servo_AUX4 Servo_AUX & _BV(3) +#define Servo_AUX5 Servo_AUX & _BV(4) +#define Servo_AUX6 Servo_AUX & _BV(5) +#define Servo_AUX7 Servo_AUX & _BV(6) +#define Servo_AUX8 Servo_AUX & _BV(7) //************************ //*** Power settings *** @@ -349,6 +470,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- 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 @@ -369,9 +491,12 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- sub_protocol==YD717 YD717 0 SKYWLKR 1 - SYMAX2 2 + SYMAX4 2 XINXUN 3 NIHUI 4 + sub_protocol==KN + WLTOYS 0 + FEILUN 1 sub_protocol==SYMAX SYMAX 0 SYMAX5C 1 @@ -379,6 +504,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- 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 @@ -426,6 +555,7 @@ Serial: 125000 Baud 8n1 _ xxxx xxxx - --- 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 @@ -446,9 +576,12 @@ Serial: 125000 Baud 8n1 _ xxxx xxxx - --- sub_protocol==YD717 YD717 0 SKYWLKR 1 - SYMAX2 2 + SYMAX4 2 XINXUN 3 NIHUI 4 + sub_protocol==KN + WLTOYS 0 + FEILUN 1 sub_protocol==SYMAX SYMAX 0 SYMAX5C 1 @@ -456,6 +589,10 @@ Serial: 125000 Baud 8n1 _ xxxx xxxx - --- 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 diff --git a/Multiprotocol/telemetry.h b/Multiprotocol/telemetry.h index adcdc12..b305cd7 100644 --- a/Multiprotocol/telemetry.h +++ b/Multiprotocol/telemetry.h @@ -14,9 +14,8 @@ */ -void frskySendStuffed(uint8_t frame[]) +static void frskySendStuffed(uint8_t frame[]) { - Serial_write(0x7E); for (uint8_t i = 0; i < 9; i++) { if ((frame[i] == 0x7e) || (frame[i] == 0x7d)) { @@ -28,9 +27,7 @@ void frskySendStuffed(uint8_t frame[]) Serial_write(0x7E); } - - -void frskySendFrame() +static void frskySendFrame() { uint8_t frame[9]; @@ -54,16 +51,13 @@ void frskySendFrame() frame[5] = frame[6] = frame[7] = frame[8] = 0; } frskySendStuffed(frame); - } - - void frskyUpdate() { -if(telemetry_link){ + if(telemetry_link) + { frskySendFrame(); telemetry_link=0; - } }