Hubsan protocol

Added subprotocol H107 (0)
Added subprotocol H301 (1)
Added subprotocol H501 (2)
This commit is contained in:
Pascal Langer 2017-11-30 20:12:23 +01:00
parent 28868e4c78
commit e4f4d278a8
7 changed files with 204 additions and 68 deletions

View File

@ -294,6 +294,8 @@ void A7105_Init(void)
A7105_SetTxRxMode(TX_EN); A7105_SetTxRxMode(TX_EN);
A7105_SetPower(); A7105_SetPower();
A7105_AdjustLOBaseFreq(A7105_FREQ_OFFSET);
A7105_Strobe(A7105_STANDBY); A7105_Strobe(A7105_STANDBY);
} }
#endif #endif

View File

@ -20,24 +20,48 @@
#include "iface_a7105.h" #include "iface_a7105.h"
enum{ enum{
// flags going to packet[9] (Normal) // flags going to packet[9] (H107)
HUBSAN_FLAG_VIDEO= 0x01, // record video HUBSAN_FLAG_VIDEO= 0x01, // record video
HUBSAN_FLAG_FLIP = 0x08, // enable flips HUBSAN_FLAG_FLIP = 0x08, // enable flips
HUBSAN_FLAG_LED = 0x04 // enable LEDs HUBSAN_FLAG_LED = 0x04 // enable LEDs
}; };
enum{ enum{
// flags going to packet[9] (Plus series) // flags going to packet[9] (H107 Plus series)
HUBSAN_FLAG_HEADLESS = 0x08, // headless mode HUBSAN_FLAG_HEADLESS = 0x08, // headless mode
}; };
enum{ enum{
// flags going to packet[13] (Plus series) // flags going to packet[9] (H301)
FLAG_H301_VIDEO = 0x01,
FLAG_H301_STAB = 0x02,
FLAG_H301_LED = 0x10,
FLAG_H301_RTH = 0x40,
};
enum{
// flags going to packet[13] (H107 Plus series)
HUBSAN_FLAG_SNAPSHOT = 0x01, HUBSAN_FLAG_SNAPSHOT = 0x01,
HUBSAN_FLAG_FLIP_PLUS = 0x80, HUBSAN_FLAG_FLIP_PLUS = 0x80,
}; };
uint32_t sessionid,id_data; 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 { enum {
BIND_1, BIND_1,
@ -54,7 +78,7 @@ enum {
DATA_4, DATA_4,
DATA_5, DATA_5,
}; };
#define WAIT_WRITE 0x80 #define HUBSAN_WAIT_WRITE 0x80
static void __attribute__((unused)) hubsan_update_crc() 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); memset(packet, 0, 16);
packet[0] = bind_state; packet[0] = bind_state;
packet[1] = channel; packet[1] = channel;
packet[2] = (sessionid >> 24) & 0xFF; packet[2] = (MProtocol_id >> 24) & 0xFF;
packet[3] = (sessionid >> 16) & 0xFF; packet[3] = (MProtocol_id >> 16) & 0xFF;
packet[4] = (sessionid >> 8) & 0xFF; packet[4] = (MProtocol_id >> 8) & 0xFF;
packet[5] = (sessionid >> 0) & 0xFF; packet[5] = (MProtocol_id >> 0) & 0xFF;
if(id_data == ID_NORMAL) if(hubsan_id_data == ID_NORMAL && sub_protocol != H501)
{ {
packet[6] = 0x08; packet[6] = 0x08;
packet[7] = 0xe4; 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% //ii : aileron observed range: 0x45 - 0xc3 (smaller is right)69-195-50%
static void __attribute__((unused)) hubsan_build_packet() 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); memset(packet, 0, 16);
if(vtx_freq != option || packet_count==100) // set vTX frequency (H107D) 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[4] = 0xFF - convert_channel_8b(RUDDER); //Rudder is reversed
packet[6] = 0xFF - convert_channel_8b(ELEVATOR); //Elevator is reversed packet[6] = 0xFF - convert_channel_8b(ELEVATOR); //Elevator is reversed
packet[8] = convert_channel_8b(AILERON); //Aileron 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) if( packet_count < 100)
{ {
packet[9] = 0x02 | HUBSAN_FLAG_LED | HUBSAN_FLAG_FLIP; // sends default value for the 100 first packets packet[9] = 0x02 | HUBSAN_FLAG_LED | HUBSAN_FLAG_FLIP; // sends default value for the 100 first packets
@ -150,12 +174,45 @@ static void __attribute__((unused)) hubsan_build_packet()
packet[12] = 0x04; packet[12] = 0x04;
packet[13] = 0x26; packet[13] = 0x26;
packet[14] = 0x79; 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 else
{ //ID_PLUS {
packet[3] = 0x64; packet[9] = GET_FLAG(Servo_AUX2, FLAG_H301_LED)
packet[5] = 0x64; | GET_FLAG(Servo_AUX3, FLAG_H301_STAB)
packet[7] = 0x64; | 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 && 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; packet[9] = 0x06;
//FLIP|LIGHT|PICTURE|VIDEO|HEADLESS //FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
if(Servo_AUX4) packet[9] |= HUBSAN_FLAG_VIDEO; if(Servo_AUX4) packet[9] |= HUBSAN_FLAG_VIDEO;
@ -166,6 +223,7 @@ static void __attribute__((unused)) hubsan_build_packet()
if(Servo_AUX3) packet[13] = HUBSAN_FLAG_SNAPSHOT; if(Servo_AUX3) packet[13] = HUBSAN_FLAG_SNAPSHOT;
if(Servo_AUX1) packet[13] |= HUBSAN_FLAG_FLIP_PLUS; if(Servo_AUX1) packet[13] |= HUBSAN_FLAG_FLIP_PLUS;
packet[14]= 0x49; // ghost channel ? packet[14]= 0x49; // ghost channel ?
}
if(packet_count < 100) if(packet_count < 100)
{ // set channels to neutral for first 100 packets { // set channels to neutral for first 100 packets
packet[2] = 0x80; // throttle neutral is at mid stick on plus series 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[13]= 0x00;
packet_count++; 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(); hubsan_update_crc();
} }
@ -198,41 +271,42 @@ uint16_t ReadHubsan()
static uint8_t rfMode=0; static uint8_t rfMode=0;
#endif #endif
static uint8_t txState=0; static uint8_t txState=0;
static uint8_t bind_count=0;
uint16_t delay; uint16_t delay;
uint8_t i; uint8_t i;
switch(phase) { switch(phase)
case BIND_1:
bind_count++;
if(bind_count >= 20)
{ {
if(id_data == ID_NORMAL) case BIND_1:
id_data = ID_PLUS; bind_phase++;
if(bind_phase >= 20 && sub_protocol != H501)
{
if(hubsan_id_data == ID_NORMAL)
hubsan_id_data = ID_PLUS;
else else
id_data = ID_NORMAL; hubsan_id_data = ID_NORMAL;
A7105_WriteID(id_data); A7105_WriteID(hubsan_id_data);
bind_count = 0; bind_phase = 0;
} }
case BIND_3: case BIND_3:
case BIND_5: case BIND_5:
case BIND_7: case BIND_7:
hubsan_build_bind_packet(phase == BIND_7 ? 9 : (phase == BIND_5 ? 1 : phase + 1 - BIND_1)); hubsan_build_bind_packet(phase == BIND_7 ? 9 : (phase == BIND_5 ? 1 : phase + 1 - BIND_1));
A7105_Strobe(A7105_STANDBY);
A7105_WriteData(16, channel); A7105_WriteData(16, channel);
phase |= WAIT_WRITE; phase |= HUBSAN_WAIT_WRITE;
return 3000; return 3000;
case BIND_1 | WAIT_WRITE: case BIND_1 | HUBSAN_WAIT_WRITE:
case BIND_3 | WAIT_WRITE: case BIND_3 | HUBSAN_WAIT_WRITE:
case BIND_5 | WAIT_WRITE: case BIND_5 | HUBSAN_WAIT_WRITE:
case BIND_7 | WAIT_WRITE: case BIND_7 | HUBSAN_WAIT_WRITE:
//wait for completion //wait for completion
for(i = 0; i< 20; i++) for(i = 0; i< 20; i++)
if(! (A7105_ReadReg(A7105_00_MODE) & 0x01)) if(! (A7105_ReadReg(A7105_00_MODE) & 0x01))
break; break;
A7105_SetTxRxMode(RX_EN); A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX); A7105_Strobe(A7105_RX);
phase &= ~WAIT_WRITE; phase &= ~HUBSAN_WAIT_WRITE;
if(id_data == ID_PLUS) if(hubsan_id_data == ID_PLUS)
{ {
if(phase == BIND_7 && packet[2] == 9) if(phase == BIND_7 && packet[2] == 9)
{ {
@ -264,7 +338,7 @@ uint16_t ReadHubsan()
return 15000; //22.5msec elapsed since last write return 15000; //22.5msec elapsed since last write
} }
A7105_ReadData(16); A7105_ReadData(16);
if(packet[1] == 9 && id_data == ID_NORMAL) { if(packet[1] == 9 && hubsan_id_data == ID_NORMAL) {
phase = DATA_1; phase = DATA_1;
A7105_WriteReg(A7105_1F_CODE_I, 0x0F); A7105_WriteReg(A7105_1F_CODE_I, 0x0F);
BIND_DONE; BIND_DONE;
@ -285,7 +359,13 @@ uint16_t ReadHubsan()
if( phase == DATA_1) if( phase == DATA_1)
A7105_SetPower(); //Keep transmit power in sync A7105_SetPower(); //Keep transmit power in sync
hubsan_build_packet(); hubsan_build_packet();
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) if (phase == DATA_5)
phase = DATA_1; phase = DATA_1;
else else
@ -340,17 +420,27 @@ uint16_t ReadHubsan()
return 0; 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}; const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82};
A7105_Init(); A7105_Init();
sessionid = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16); channel = allowed_ch[MProtocol_id % sizeof(allowed_ch)];
channel = allowed_ch[random(0xfefefefe) % sizeof(allowed_ch)]; hubsan_id_data=ID_NORMAL;
if(IS_AUTOBIND_FLAG_on || sub_protocol==H107)
{
BIND_IN_PROGRESS; // autobind protocol BIND_IN_PROGRESS; // autobind protocol
phase = BIND_1; phase = BIND_1;
}
else
{
phase = DATA_1;
A7105_WriteID(MProtocol_id);
A7105_WriteReg(A7105_1F_CODE_I, 0x0F);
}
packet_count=0; packet_count=0;
id_data=ID_NORMAL; bind_phase=0;
#ifdef HUBSAN_HUB_TELEMETRY #ifdef HUBSAN_HUB_TELEMETRY
init_frskyd_link_telemetry(); init_frskyd_link_telemetry();
#endif #endif

View File

@ -1,5 +1,5 @@
1,Flysky,Flysky,V9x9,V6x6,V912,CX20 1,Flysky,Flysky,V9x9,V6x6,V912,CX20
2,Hubsan 2,Hubsan,H107,H301,H501
3,FrskyD 3,FrskyD
4,Hisky,Hisky,HK310 4,Hisky,Hisky,HK310
5,V2x2,V2x2,JXD506 5,V2x2,V2x2,JXD506

View File

@ -19,7 +19,7 @@
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 1 #define VERSION_MINOR 1
#define VERSION_REVISION 6 #define VERSION_REVISION 6
#define VERSION_PATCH_LEVEL 35 #define VERSION_PATCH_LEVEL 36
//****************** //******************
// Protocols // Protocols
//****************** //******************
@ -72,6 +72,12 @@ enum Flysky
V912 = 3, V912 = 3,
CX20 = 4 CX20 = 4
}; };
enum Hubsan
{
H107 = 0,
H301 = 1,
H501 = 2,
};
enum AFHDS2A enum AFHDS2A
{ {
PWM_IBUS = 0, PWM_IBUS = 0,
@ -555,6 +561,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
V6x6 2 V6x6 2
V912 3 V912 3
CX20 4 CX20 4
sub_protocol==Hubsan
H107 0
H301 1
H501 2
sub_protocol==Hisky sub_protocol==Hisky
Hisky 0 Hisky 0
HK310 1 HK310 1

View File

@ -77,6 +77,10 @@
//#define CC2500_ENABLE_LOW_POWER //#define CC2500_ENABLE_LOW_POWER
//#define NRF24L01_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 ***/ /*** GLOBAL ID ***/
@ -272,7 +276,7 @@ const int8_t AFHDS2AFailsafe[14]= {
const PPM_Parameters PPM_prot[15]= { const PPM_Parameters PPM_prot[15]= {
// Dial Protocol Sub protocol RX_Num Power Auto Bind Option // Dial Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {MODE_FLYSKY, Flysky , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 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 /* 3 */ {MODE_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 5 */ {MODE_V2X2 , 0 , 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 V912
CX20 CX20
MODE_HUBSAN MODE_HUBSAN
NONE H107
H301
H501
MODE_FRSKYV MODE_FRSKYV
NONE NONE
MODE_FRSKYD MODE_FRSKYD

View File

@ -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 <setting name>
To disable a setting use #undef <setting name>
*/
//#define FORCE_GLOBAL_ID 0x12345678 //#define FORCE_GLOBAL_ID 0x12345678
//Force bootloader
#define CHECK_FOR_BOOTLOADER
#if not defined STM32_BOARD #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 AFHDS2A_A7105_INO
#undef DEVO_CYRF6936_INO #undef DEVO_CYRF6936_INO

View File

@ -106,18 +106,34 @@ Note that the RX ouput will be AETR.
### Sub_protocol PPM_SBUS - *3* ### Sub_protocol PPM_SBUS - *3*
## HUBSAN - *2* ## HUBSAN - *2*
Models: Hubsan H102D, H107/L/C/D and Hubsan H107P/C+/D+
Autobind protocol
Telemetry enabled for battery voltage and TX RSSI Telemetry enabled for battery voltage and TX RSSI
Option=vTX frequency (H107D) 5645 - 5900 MHz 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 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS 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 # CC2500 RF Module