|
|
|
|
@@ -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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|