From e4f4d278a832723e2cf8988253fb073509cad452 Mon Sep 17 00:00:00 2001 From: Pascal Langer Date: Thu, 30 Nov 2017 20:12:23 +0100 Subject: [PATCH] Hubsan protocol Added subprotocol H107 (0) Added subprotocol H301 (1) Added subprotocol H501 (2) --- Multiprotocol/A7105_SPI.ino | 2 + Multiprotocol/Hubsan_a7105.ino | 210 +++++++++++++++++++++--------- Multiprotocol/Multi.txt | 2 +- Multiprotocol/Multiprotocol.h | 12 +- Multiprotocol/_Config.h | 10 +- Multiprotocol/_MyConfig.h.example | 14 +- Protocols_Details.md | 22 +++- 7 files changed, 204 insertions(+), 68 deletions(-) diff --git a/Multiprotocol/A7105_SPI.ino b/Multiprotocol/A7105_SPI.ino index 7db0bbf..a8da2ad 100644 --- a/Multiprotocol/A7105_SPI.ino +++ b/Multiprotocol/A7105_SPI.ino @@ -294,6 +294,8 @@ void A7105_Init(void) A7105_SetTxRxMode(TX_EN); A7105_SetPower(); + A7105_AdjustLOBaseFreq(A7105_FREQ_OFFSET); + A7105_Strobe(A7105_STANDBY); } #endif \ No newline at end of file diff --git a/Multiprotocol/Hubsan_a7105.ino b/Multiprotocol/Hubsan_a7105.ino index 755e817..0a1cfda 100644 --- a/Multiprotocol/Hubsan_a7105.ino +++ b/Multiprotocol/Hubsan_a7105.ino @@ -20,24 +20,48 @@ #include "iface_a7105.h" enum{ - // flags going to packet[9] (Normal) - HUBSAN_FLAG_VIDEO= 0x01, // record video - HUBSAN_FLAG_FLIP = 0x08, // enable flips - HUBSAN_FLAG_LED = 0x04 // enable LEDs + // flags going to packet[9] (H107) + HUBSAN_FLAG_VIDEO= 0x01, // record video + HUBSAN_FLAG_FLIP = 0x08, // enable flips + HUBSAN_FLAG_LED = 0x04 // enable LEDs }; enum{ - // flags going to packet[9] (Plus series) - HUBSAN_FLAG_HEADLESS = 0x08, // headless mode + // flags going to packet[9] (H107 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, + // flags going to packet[9] (H301) + FLAG_H301_VIDEO = 0x01, + FLAG_H301_STAB = 0x02, + FLAG_H301_LED = 0x10, + FLAG_H301_RTH = 0x40, }; -uint32_t sessionid,id_data; +enum{ + // flags going to packet[13] (H107 Plus series) + HUBSAN_FLAG_SNAPSHOT = 0x01, + HUBSAN_FLAG_FLIP_PLUS = 0x80, +}; + +enum{ + // flags going to packet[9] (H501S) + FLAG_H501_VIDEO = 0x01, + FLAG_H501_LED = 0x04, + FLAG_H501_RTH = 0x20, + FLAG_H501_HEADLESS1 = 0x40, + FLAG_H501_GPS_HOLD = 0x80, + }; + + enum{ + // flags going to packet[13] (H501S) + FLAG_H501_SNAPSHOT = 0x01, + FLAG_H501_HEADLESS2 = 0x02, + FLAG_H501_ALT_HOLD = 0x08, +}; + +uint32_t hubsan_id_data; enum { BIND_1, @@ -54,7 +78,7 @@ enum { DATA_4, DATA_5, }; -#define WAIT_WRITE 0x80 +#define HUBSAN_WAIT_WRITE 0x80 static void __attribute__((unused)) hubsan_update_crc() { @@ -72,11 +96,11 @@ static void __attribute__((unused)) hubsan_build_bind_packet(uint8_t bind_state) 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; - if(id_data == ID_NORMAL) + packet[2] = (MProtocol_id >> 24) & 0xFF; + packet[3] = (MProtocol_id >> 16) & 0xFF; + packet[4] = (MProtocol_id >> 8) & 0xFF; + packet[5] = (MProtocol_id >> 0) & 0xFF; + if(hubsan_id_data == ID_NORMAL && sub_protocol != H501) { packet[6] = 0x08; packet[7] = 0xe4; @@ -108,7 +132,7 @@ static void __attribute__((unused)) hubsan_build_bind_packet(uint8_t bind_state) //ii : aileron observed range: 0x45 - 0xc3 (smaller is right)69-195-50% static void __attribute__((unused)) hubsan_build_packet() { - static uint8_t vtx_freq = 0; + static uint8_t vtx_freq = 0, h501_packet = 0; memset(packet, 0, 16); if(vtx_freq != option || packet_count==100) // set vTX frequency (H107D) { @@ -127,8 +151,8 @@ static void __attribute__((unused)) hubsan_build_packet() 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(hubsan_id_data == ID_NORMAL && sub_protocol==H107) + {// H107/L/C/D, H102D if( packet_count < 100) { packet[9] = 0x02 | HUBSAN_FLAG_LED | HUBSAN_FLAG_FLIP; // sends default value for the 100 first packets @@ -150,22 +174,56 @@ static void __attribute__((unused)) hubsan_build_packet() packet[12] = 0x04; packet[13] = 0x26; packet[14] = 0x79; + } else if(sub_protocol==H301) + {// H301 + if( packet_count < 100) + { + packet[9] = FLAG_H301_STAB; // sends default value for the 100 first packets + packet_count++; + } + else + { + packet[9] = GET_FLAG(Servo_AUX2, FLAG_H301_LED) + | GET_FLAG(Servo_AUX3, FLAG_H301_STAB) + | GET_FLAG(Servo_AUX4, FLAG_H301_VIDEO) + | GET_FLAG(Servo_AUX1, FLAG_H301_RTH); + } + packet[10] = 0x18; // ? + packet[12] = 0x5c; // ? + packet[14] = 0xf6; // ? } else - { //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 ? + { //ID_PLUS && H501 + packet[3] = sub_protocol==H501 ? 0x00:0x64; + packet[5] = sub_protocol==H501 ? 0x00:0x64; + packet[7] = sub_protocol==H501 ? 0x00:0x64; + + if(sub_protocol==H501) + { // H501S + packet[9] = 0x02 + | GET_FLAG(Servo_AUX2, FLAG_H501_LED) + | GET_FLAG(Servo_AUX4, FLAG_H501_VIDEO) + | GET_FLAG(Servo_AUX1, FLAG_H501_RTH) + | GET_FLAG(Servo_AUX7, FLAG_H501_GPS_HOLD) + | GET_FLAG(Servo_AUX5, FLAG_H501_HEADLESS1); + //packet[10]= 0x1A; + packet[13] = GET_FLAG(Servo_AUX6, FLAG_H501_HEADLESS2) + | GET_FLAG(Servo_AUX8, FLAG_H501_ALT_HOLD) + | GET_FLAG(Servo_AUX3, FLAG_H501_SNAPSHOT); + } + else + { // H107P/C+/D+ + 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 @@ -176,6 +234,21 @@ static void __attribute__((unused)) hubsan_build_packet() packet[13]= 0x00; packet_count++; } + if(sub_protocol==H501) + { // H501S + h501_packet++; + if(h501_packet == 10) + { + memset(packet, 0, 16); + packet[0] = 0xe8; + } + else if(h501_packet == 20) + { + memset(packet, 0, 16); + packet[0] = 0xe9; + } + if(h501_packet >= 20) h501_packet = 0; + } } hubsan_update_crc(); } @@ -198,41 +271,42 @@ uint16_t ReadHubsan() static uint8_t rfMode=0; #endif static uint8_t txState=0; - static uint8_t bind_count=0; uint16_t delay; uint8_t i; - switch(phase) { + switch(phase) + { case BIND_1: - bind_count++; - if(bind_count >= 20) + bind_phase++; + if(bind_phase >= 20 && sub_protocol != H501) { - if(id_data == ID_NORMAL) - id_data = ID_PLUS; + if(hubsan_id_data == ID_NORMAL) + hubsan_id_data = ID_PLUS; else - id_data = ID_NORMAL; - A7105_WriteID(id_data); - bind_count = 0; + hubsan_id_data = ID_NORMAL; + A7105_WriteID(hubsan_id_data); + bind_phase = 0; } case BIND_3: case BIND_5: case BIND_7: hubsan_build_bind_packet(phase == BIND_7 ? 9 : (phase == BIND_5 ? 1 : phase + 1 - BIND_1)); + A7105_Strobe(A7105_STANDBY); A7105_WriteData(16, channel); - phase |= WAIT_WRITE; + phase |= HUBSAN_WAIT_WRITE; return 3000; - case BIND_1 | WAIT_WRITE: - case BIND_3 | WAIT_WRITE: - case BIND_5 | WAIT_WRITE: - case BIND_7 | WAIT_WRITE: + case BIND_1 | HUBSAN_WAIT_WRITE: + case BIND_3 | HUBSAN_WAIT_WRITE: + case BIND_5 | HUBSAN_WAIT_WRITE: + case BIND_7 | HUBSAN_WAIT_WRITE: //wait for completion 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) + phase &= ~HUBSAN_WAIT_WRITE; + if(hubsan_id_data == ID_PLUS) { if(phase == BIND_7 && packet[2] == 9) { @@ -264,7 +338,7 @@ uint16_t ReadHubsan() return 15000; //22.5msec elapsed since last write } A7105_ReadData(16); - if(packet[1] == 9 && id_data == ID_NORMAL) { + if(packet[1] == 9 && hubsan_id_data == ID_NORMAL) { phase = DATA_1; A7105_WriteReg(A7105_1F_CODE_I, 0x0F); BIND_DONE; @@ -285,7 +359,13 @@ uint16_t ReadHubsan() if( phase == DATA_1) A7105_SetPower(); //Keep transmit power in sync hubsan_build_packet(); - A7105_WriteData(16, phase == DATA_5 && id_data == ID_NORMAL ? channel + 0x23 : channel); + A7105_Strobe(A7105_STANDBY); + uint8_t ch; + if((phase == DATA_5 && hubsan_id_data == ID_NORMAL) && sub_protocol == H107) + ch = channel + 0x23; + else + ch = channel; + A7105_WriteData(16, ch); if (phase == DATA_5) phase = DATA_1; else @@ -340,20 +420,30 @@ uint16_t ReadHubsan() return 0; } -uint16_t initHubsan() { +uint16_t initHubsan() +{ const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82}; A7105_Init(); - sessionid = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16); - channel = allowed_ch[random(0xfefefefe) % sizeof(allowed_ch)]; + channel = allowed_ch[MProtocol_id % sizeof(allowed_ch)]; + hubsan_id_data=ID_NORMAL; - BIND_IN_PROGRESS; // autobind protocol - phase = BIND_1; + if(IS_AUTOBIND_FLAG_on || sub_protocol==H107) + { + BIND_IN_PROGRESS; // autobind protocol + phase = BIND_1; + } + else + { + phase = DATA_1; + A7105_WriteID(MProtocol_id); + A7105_WriteReg(A7105_1F_CODE_I, 0x0F); + } packet_count=0; - id_data=ID_NORMAL; -#ifdef HUBSAN_HUB_TELEMETRY - init_frskyd_link_telemetry(); -#endif + bind_phase=0; + #ifdef HUBSAN_HUB_TELEMETRY + init_frskyd_link_telemetry(); + #endif return 10000; } diff --git a/Multiprotocol/Multi.txt b/Multiprotocol/Multi.txt index e8cec95..46e03fd 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -1,5 +1,5 @@ 1,Flysky,Flysky,V9x9,V6x6,V912,CX20 -2,Hubsan +2,Hubsan,H107,H301,H501 3,FrskyD 4,Hisky,Hisky,HK310 5,V2x2,V2x2,JXD506 diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index e5d2572..a16757c 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -19,7 +19,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 1 #define VERSION_REVISION 6 -#define VERSION_PATCH_LEVEL 35 +#define VERSION_PATCH_LEVEL 36 //****************** // Protocols //****************** @@ -72,6 +72,12 @@ enum Flysky V912 = 3, CX20 = 4 }; +enum Hubsan +{ + H107 = 0, + H301 = 1, + H501 = 2, +}; enum AFHDS2A { PWM_IBUS = 0, @@ -555,6 +561,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- V6x6 2 V912 3 CX20 4 + sub_protocol==Hubsan + H107 0 + H301 1 + H501 2 sub_protocol==Hisky Hisky 0 HK310 1 diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index f59474e..08506a7 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -77,6 +77,10 @@ //#define CC2500_ENABLE_LOW_POWER //#define NRF24L01_ENABLE_LOW_POWER +//Fine tune of the A7105 LO base frequency +// This is required for some A7105 modules and/or RXs with inaccurate crystal oscillator. +// The offset is in +/-kHz. Default value is 0. +#define A7105_FREQ_OFFSET 0 /*****************/ /*** GLOBAL ID ***/ @@ -272,7 +276,7 @@ const int8_t AFHDS2AFailsafe[14]= { const PPM_Parameters PPM_prot[15]= { // Dial Protocol Sub protocol RX_Num Power Auto Bind Option /* 1 */ {MODE_FLYSKY, Flysky , 0 , P_HIGH , NO_AUTOBIND , 0 }, -/* 2 */ {MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, +/* 2 */ {MODE_HUBSAN, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 3 */ {MODE_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning /* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 5 */ {MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, @@ -295,7 +299,9 @@ const PPM_Parameters PPM_prot[15]= { V912 CX20 MODE_HUBSAN - NONE + H107 + H301 + H501 MODE_FRSKYV NONE MODE_FRSKYD diff --git a/Multiprotocol/_MyConfig.h.example b/Multiprotocol/_MyConfig.h.example index 80ac6af..f14a2e4 100644 --- a/Multiprotocol/_MyConfig.h.example +++ b/Multiprotocol/_MyConfig.h.example @@ -1,7 +1,19 @@ +/* + This file is meant to keep your settings after an upgrade of the multi source. + If you know parameters you want for sure to be enabled or disabled in future + then just force their values here. + To enable a setting use #define + To disable a setting use #undef +*/ + //#define FORCE_GLOBAL_ID 0x12345678 +//Force bootloader +#define CHECK_FOR_BOOTLOADER + #if not defined STM32_BOARD -// Atmega328p board list of unwanted protocols to fit in flash +// Everything here will only apply to Multi Atmega328p boards +// Add or remove unwanted protocols to fit in flash #undef AFHDS2A_A7105_INO #undef DEVO_CYRF6936_INO diff --git a/Protocols_Details.md b/Protocols_Details.md index 16471b3..4638474 100644 --- a/Protocols_Details.md +++ b/Protocols_Details.md @@ -106,18 +106,34 @@ Note that the RX ouput will be AETR. ### Sub_protocol PPM_SBUS - *3* ## HUBSAN - *2* -Models: Hubsan H102D, H107/L/C/D and Hubsan H107P/C+/D+ - -Autobind protocol Telemetry enabled for battery voltage and TX RSSI Option=vTX frequency (H107D) 5645 - 5900 MHz +### Sub_protocol H107 - *0* +Autobind protocol + +Models: Hubsan H102D, H107/L/C/D and H107P/C+/D+ + CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9 ---|---|---|---|---|---|---|---|--- A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS +### Sub_protocol H301 - *1* +Models: Hubsan H301 + +CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8 +---|---|---|---|---|---|---|--- +A|E|T|R|RTH|LIGHT|STAB|VIDEO + +### Sub_protocol H501 - *1* +Models: Hubsan H501S + +CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 +---|---|---|---|---|---|---|---|---|---|---|--- +A|E|T|R|RTH|LIGHT|PICTURE|VIDEO|HEADLESS1|HEADLESS2|GPS_HOLD|ALT_HOLD + *** # CC2500 RF Module