Merge pull request #2 from tipouic/flysky_afhds2a

Flysky afhds2a
This commit is contained in:
tipouic 2016-12-01 19:27:39 +01:00 committed by GitHub
commit 53c5af4bd7
9 changed files with 697 additions and 148 deletions

View File

@ -16,9 +16,14 @@ Multiprotocol is distributed in the hope that it will be useful,
// Last sync with hexfet new_protocols/bayang_nrf24l01.c dated 2015-12-22 // Last sync with hexfet new_protocols/bayang_nrf24l01.c dated 2015-12-22
#if defined(BAYANG_NRF24L01_INO) #if defined(BAYANG_NRF24L01_INO)
#include "iface_nrf24l01.h" #include "iface_nrf24l01.h"
#ifdef ENABLE_BAYANG_TELEMETRY
#define BAYANG_PACKET_PERIOD_TELEM 3200
uint32_t bayang_telemetry_last_rx = 0;
#endif
#define BAYANG_BIND_COUNT 1000 #define BAYANG_BIND_COUNT 1000
#define BAYANG_PACKET_PERIOD 2000 #define BAYANG_PACKET_PERIOD 2000
#define BAYANG_INITIAL_WAIT 500 #define BAYANG_INITIAL_WAIT 500
@ -31,11 +36,24 @@ enum BAYANG_FLAGS {
// flags going to packet[2] // flags going to packet[2]
BAYANG_FLAG_RTH = 0x01, BAYANG_FLAG_RTH = 0x01,
BAYANG_FLAG_HEADLESS = 0x02, BAYANG_FLAG_HEADLESS = 0x02,
#ifdef ENABLE_BAYANG_TELEMETRY
BAYANG_FLAG_TELEMETRY = 0x04,
#endif
BAYANG_FLAG_FLIP = 0x08, BAYANG_FLAG_FLIP = 0x08,
BAYANG_FLAG_VIDEO = 0x10, BAYANG_FLAG_VIDEO = 0x10,
BAYANG_FLAG_PICTURE = 0x20, BAYANG_FLAG_PICTURE = 0x20,
// flags going to packet[3] // flags going to packet[3]
BAYANG_FLAG_INVERTED = 0x80 // inverted flight on Floureon H101 BAYANG_FLAG_INVERTED = 0x80, // inverted flight on Floureon H101
#ifdef ENABLE_BAYANG_TELEMETRY
BAYANG_FLAG_FLIGHT_MODE0 = 0x01,
BAYANG_FLAG_FLIGHT_MODE1 = 0x02,
BAYANG_FLAG_DATA_SELECT0 = 0x04,
BAYANG_FLAG_DATA_SELECT1 = 0x08,
BAYANG_FLAG_DATA_SELECT2 = 0x10,
BAYANG_FLAG_DATA_ADJUST0 = 0x20,
BAYANG_FLAG_DATA_ADJUST1 = 0x40,
#endif
}; };
static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind) static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
@ -53,6 +71,12 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
} }
else else
{ {
int telem_enabled = 0;
#ifdef ENABLE_BAYANG_TELEMETRY
telem_enabled = (sub_protocol == BAYANG_TELEM);
// telem_enabled &= Servo_AUX8; // enable telem with a switch
#endif
uint16_t val; uint16_t val;
packet[0] = 0xA5; packet[0] = 0xA5;
packet[1] = 0xFA; // normal mode is 0xf7, expert 0xfa packet[1] = 0xFA; // normal mode is 0xf7, expert 0xfa
@ -69,11 +93,111 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
packet[2] |= BAYANG_FLAG_VIDEO; packet[2] |= BAYANG_FLAG_VIDEO;
if(Servo_AUX5) if(Servo_AUX5)
packet[2] |= BAYANG_FLAG_HEADLESS; packet[2] |= BAYANG_FLAG_HEADLESS;
#ifdef ENABLE_BAYANG_TELEMETRY
if (telem_enabled)
{
packet[2] |= BAYANG_FLAG_TELEMETRY;
}
#endif
//Flags packet[3] //Flags packet[3]
packet[3] = 0x00; packet[3] = 0x00;
if(Servo_AUX6) if(Servo_AUX6)
packet[3] = BAYANG_FLAG_INVERTED; packet[3] = BAYANG_FLAG_INVERTED;
#ifdef ENABLE_BAYANG_TELEMETRY
if (telem_enabled)
{
static uint8_t dataselect = 2;
uint8_t dataselect_old = dataselect;
uint16_t partitions[4] ={1200,1400,1600,1800}; // 5 options (previous data set, data 1, data 2, data 3, next data set)
for (uint8_t i = 0; i < 4; ++i)
{
int16_t hysteresis = 0;
if (dataselect_old*2 == (i*2+1) - 1)
{
hysteresis = 25;
}
else if (dataselect_old*2 == (i*2+1) + 1)
{
hysteresis = -25;
}
if (Servo_data[AUX7] <= partitions[i] + hysteresis)
{
dataselect = i;
break;
}
else
{
dataselect = i+1;
}
}
// data adjust 1333 1666 - aux 6
static uint8_t dataadjust = 1;
uint8_t dataadjust_old = dataadjust;
partitions[0] = 1333; // three options (decreaes, do nothing, increase)
partitions[1] = 1666;
for (uint8_t i = 0; i < 2; ++i)
{
int16_t hysteresis = 0;
if (dataadjust_old*2 == (i*2+1) - 1)
{
hysteresis = 25;
}
else if (dataadjust_old*2 == (i*2+1) + 1)
{
hysteresis = -25;
}
if (Servo_data[AUX8] <= partitions[i] + hysteresis)
{
dataadjust = i;
break;
}
else
{
dataadjust = i+1;
}
}
static uint8_t flightmode = 0;
// flight mode 1250 1500 1750 - aux 1
uint8_t flightmode_old = flightmode;
partitions[0] = 1250; // 4 flight modes
partitions[1] = 1500;
partitions[2] = 1750;
for (uint8_t i = 0; i < 3; ++i)
{
int16_t hysteresis = 0;
if (flightmode_old*2 == (i*2+1) - 1)
{
hysteresis = 25;
}
else if (flightmode_old*2 == (i*2+1) + 1)
{
hysteresis = -25;
}
if (Servo_data[AUX9] <= partitions[i] + hysteresis)
{
flightmode = i;
break;
}
else
{
flightmode = i+1;
}
}
packet[3] |= (flightmode & 0x3);
packet[3] |= (dataselect & 0x7) << 2;
packet[3] |= (dataadjust & 0x3) << 5;
}
#endif
//Aileron //Aileron
val = convert_channel_10b(AILERON); val = convert_channel_10b(AILERON);
packet[4] = (val>>8) + ((val>>2) & 0xFC); packet[4] = (val>>8) + ((val>>2) & 0xFC);
@ -123,20 +247,43 @@ static void __attribute__((unused)) BAYANG_init()
NRF24L01_FlushRx(); NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit 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_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_PACKET_SIZE); // rx pipe 0
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only 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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_SetPower(); NRF24L01_SetPower();
} }
uint16_t BAYANG_callback() uint16_t BAYANG_callback()
{ {
if(IS_BIND_DONE_on) if(IS_BIND_DONE_on)
{
#ifdef ENABLE_BAYANG_TELEMETRY
if(sub_protocol == BAYANG_TELEM)
{
Bayang_process();
// Return 0 here so that Bayang_process is called as often as possible
// to check for the incomming telemetry data. When telemetry is enabled
// the packet period is handled in the Bayang_process function.
return 0;
}
else
#endif
{
BAYANG_send_packet(0); BAYANG_send_packet(0);
}
}
else else
{ {
if (bind_counter == 0) if (bind_counter == 0)
{ {
XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH); XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
XN297_SetRXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
BIND_DONE; BIND_DONE;
} }
else else
@ -167,4 +314,147 @@ uint16_t initBAYANG(void)
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD; return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;
} }
#ifdef ENABLE_BAYANG_TELEMETRY
extern float telemetry_voltage;
extern uint8_t telemetry_rx_rssi;
extern uint8_t telemetry_tx_rssi;
extern uint8_t telemetry_datamode;
extern float telemetry_data[3]; // pids
extern uint8_t telemetry_dataitem;
extern uint16_t telemetry_uptime;
extern uint16_t telemetry_flighttime;
extern uint8_t telemetry_flightmode;
uint8_t telemetry_tx_rssi_count;
uint8_t telemetry_tx_rssi_next;
uint8_t BAYANG_recv_packet() {
uint8_t received = 0;
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
int sum = 0;
uint16_t roll, pitch, yaw, throttle;
XN297_ReadPayload(packet, BAYANG_PACKET_SIZE);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushRx();
if (packet[0] == 0xA9) {
//serialDebug.print("data packet");
for (int i = 0; i < 14; i++) {
sum += packet[i];
}
if ( (sum & 0xFF) == packet[14] ) {
typedef union {
uint16_t v;
uint8_t bytes[2];
} val;
val v;
v.bytes[0] = packet[1];
v.bytes[1] = packet[2];
telemetry_voltage = v.v / 100.f;
telemetry_rx_rssi = packet[3];
v.bytes[0] = packet[4];
v.bytes[1] = (packet[6] & 0x0F); // 12 bit # shared with flighttime
telemetry_uptime = v.v;
v.bytes[0] = packet[5];
v.bytes[1] = (packet[6] >> 4);
telemetry_flighttime = v.v;
telemetry_flightmode = packet[7] & 0x3; // 0 = level, 1 = acro,
telemetry_datamode = (packet[7] >> 2) & 0xF; // (0=acro yaw, 1=acro roll/acro pitch, 2=level roll/pitch)
telemetry_dataitem = (packet[7] >> 6) & 0x3; // (0=acro yaw, 1=acro roll/acro pitch, 2=level roll/pitch)
v.bytes[0] = packet[8];
v.bytes[1] = packet[9];
telemetry_data[0] = v.v/1000.f;
v.bytes[0] = packet[10];
v.bytes[1] = packet[11];
telemetry_data[1] = v.v/1000.f;
v.bytes[0] = packet[12];
v.bytes[1] = packet[13];
telemetry_data[2] = v.v/1000.f;
}
}
received = 1;
}
return received;
}
typedef enum
{
BAYANG_STATE_IDLE,
BAYANG_STATE_TRANSMITTING,
BAYANG_STATE_RECEIEVING,
} BayangState;
BayangState Bayang_state = BAYANG_STATE_IDLE;
uint32_t Bayang_next_send = 0;
void Bayang_process() {
uint32_t time_micros = micros();
if (BAYANG_STATE_TRANSMITTING == Bayang_state) {
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)) {
// send finished, switch to rx to receive telemetry
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
telemetry_tx_rssi_count++;
Bayang_state = BAYANG_STATE_RECEIEVING;
}
}
else if (BAYANG_STATE_RECEIEVING == Bayang_state) {
// 250us is about the time it takes to read a packet over spi
if (time_micros > (Bayang_next_send-250)) {
// didnt receive telemetry in time
Bayang_state = BAYANG_STATE_IDLE;
// if it's been a while since receiving telemetry data,
// stop sending the telemetry data to the transmitter
if (millis() - bayang_telemetry_last_rx > 1000)
telemetry_lost = 1;
}
else if (BAYANG_recv_packet()) {
telemetry_tx_rssi_next++;
// received telemetry packet
telemetry_lost = 0;
bayang_telemetry_last_rx = millis();
}
else
{
return;
}
if (100 == telemetry_tx_rssi_count)
{
telemetry_tx_rssi = telemetry_tx_rssi_next;
telemetry_tx_rssi_next = 0;
telemetry_tx_rssi_count = 0;
}
Bayang_state = BAYANG_STATE_IDLE;
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_FlushRx();
}
else if (time_micros > Bayang_next_send) {
BAYANG_send_packet(0);
Bayang_state = BAYANG_STATE_TRANSMITTING;
Bayang_next_send = time_micros + BAYANG_PACKET_PERIOD_TELEM;
}
}
#endif //ENABLE_BAYANG_TELEMETRY
#endif #endif

View File

@ -22,7 +22,7 @@
#define CX10_BIND_COUNT 4360 // 6 seconds #define CX10_BIND_COUNT 4360 // 6 seconds
#define CX10_PACKET_SIZE 15 #define CX10_PACKET_SIZE 15
#define CX10A_PACKET_SIZE 19 // CX10 blue board packets have 19-byte payload #define CX10A_PACKET_SIZE 19 // CX10 blue board packets have 19-byte payload
#define Q282_PACKET_SIZE 21 #define Q2X2_PACKET_SIZE 21
#define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec #define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec
#define CX10A_PACKET_PERIOD 6000 #define CX10A_PACKET_PERIOD 6000
@ -57,21 +57,14 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
packet[3] = rx_tx_addr[2]; packet[3] = rx_tx_addr[2];
packet[4] = rx_tx_addr[3]; packet[4] = rx_tx_addr[3];
// packet[5] to [8] (aircraft id) is filled during bind for blue board // packet[5] to [8] (aircraft id) is filled during bind for blue board
packet[5+offset] = lowByte(Servo_data[AILERON]); uint16_t aileron=Servo_data[AILERON];
packet[6+offset]= highByte(Servo_data[AILERON]); uint16_t elevator=3000-Servo_data[ELEVATOR];
packet[7+offset]= lowByte(Servo_data[ELEVATOR]); uint16_t rudder=3000-Servo_data[RUDDER];
packet[8+offset]= highByte(Servo_data[ELEVATOR]);
packet[9+offset]= lowByte(Servo_data[THROTTLE]); packet[9+offset]= lowByte(Servo_data[THROTTLE]);
packet[10+offset]= highByte(Servo_data[THROTTLE]); packet[10+offset]= highByte(Servo_data[THROTTLE]);
packet[11+offset]= lowByte(Servo_data[RUDDER]);
packet[12+offset]= highByte(Servo_data[RUDDER]);
// Channel 5 - flip flag // Channel 5 - flip flag
if(Servo_AUX1) packet[12+offset] = GET_FLAG(Servo_AUX1,CX10_FLAG_FLIP); // flip flag applied on rudder
packet[12+offset] |= CX10_FLAG_FLIP; // flip flag
//flags=0; // packet 13
uint8_t flags2=0; // packet 14
// Channel 6 - rate mode is 2 lsb of packet 13 // Channel 6 - rate mode is 2 lsb of packet 13
if(Servo_data[AUX2] > PPM_MAX_COMMAND) // rate 3 / headless on CX-10A if(Servo_data[AUX2] > PPM_MAX_COMMAND) // rate 3 / headless on CX-10A
@ -81,6 +74,7 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
flags = 0x00; // rate 1 flags = 0x00; // rate 1
else else
flags = 0x01; // rate 2 flags = 0x01; // rate 2
uint8_t flags2=0; // packet 14
uint8_t video_state=packet[14] & 0x21; uint8_t video_state=packet[14] & 0x21;
switch(sub_protocol) switch(sub_protocol)
@ -91,6 +85,9 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
break; break;
case Q282: case Q282:
case Q242: case Q242:
case Q222:
aileron = 3000 - aileron;
rudder = 3000 - rudder;
memcpy(&packet[15], "\x10\x10\xaa\xaa\x00\x00", 6); memcpy(&packet[15], "\x10\x10\xaa\xaa\x00\x00", 6);
//FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL //FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
flags2 = GET_FLAG(Servo_AUX1, 0x80) // Channel 5 - FLIP flags2 = GET_FLAG(Servo_AUX1, 0x80) // Channel 5 - FLIP
@ -111,7 +108,7 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
flags2 |= video_state flags2 |= video_state
|GET_FLAG(Servo_AUX3,0x10); // Channel 7 - picture |GET_FLAG(Servo_AUX3,0x10); // Channel 7 - picture
} }
else else if(sub_protocol==Q242)
{ {
flags=2; flags=2;
flags2|= GET_FLAG(Servo_AUX3,0x01) // Channel 7 - picture flags2|= GET_FLAG(Servo_AUX3,0x01) // Channel 7 - picture
@ -119,15 +116,22 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
packet[17]=0x00; packet[17]=0x00;
packet[18]=0x00; packet[18]=0x00;
} }
else
{ // Q222
flags=0;
}
if(Servo_AUX6) flags |=0x80; // Channel 10 - RTH if(Servo_AUX6) flags |=0x80; // Channel 10 - RTH
break; break;
case DM007: case DM007:
aileron = 3000 - aileron;
//FLIP|MODE|PICTURE|VIDEO|HEADLESS //FLIP|MODE|PICTURE|VIDEO|HEADLESS
flags2= GET_FLAG(Servo_AUX3,CX10_FLAG_SNAPSHOT) // Channel 7 - picture flags2= GET_FLAG(Servo_AUX3,CX10_FLAG_SNAPSHOT) // Channel 7 - picture
|GET_FLAG(Servo_AUX4,CX10_FLAG_VIDEO); // Channel 8 - video |GET_FLAG(Servo_AUX4,CX10_FLAG_VIDEO); // Channel 8 - video
if(Servo_AUX5) flags |= CX10_FLAG_HEADLESS; // Channel 9 - headless if(Servo_AUX5) flags |= CX10_FLAG_HEADLESS; // Channel 9 - headless
break; break;
case JC3015_2: case JC3015_2:
aileron = 3000 - aileron;
elevator = 3000 - elevator;
//FLIP|MODE|LED|DFLIP //FLIP|MODE|LED|DFLIP
if(Servo_AUX4) packet[12] &= ~CX10_FLAG_FLIP; if(Servo_AUX4) packet[12] &= ~CX10_FLAG_FLIP;
case JC3015_1: case JC3015_1:
@ -136,6 +140,7 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
|GET_FLAG(Servo_AUX4,_BV(4)); // Channel 8 |GET_FLAG(Servo_AUX4,_BV(4)); // Channel 8
break; break;
case MK33041: case MK33041:
elevator = 3000 - elevator;
//FLIP|MODE|PICTURE|VIDEO|HEADLESS|RTH //FLIP|MODE|PICTURE|VIDEO|HEADLESS|RTH
flags|=GET_FLAG(Servo_AUX3,_BV(7)) // Channel 7 - picture flags|=GET_FLAG(Servo_AUX3,_BV(7)) // Channel 7 - picture
|GET_FLAG(Servo_AUX6,_BV(2)); // Channel 10 - rth |GET_FLAG(Servo_AUX6,_BV(2)); // Channel 10 - rth
@ -143,6 +148,12 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
|GET_FLAG(Servo_AUX5,_BV(5)); // Channel 9 - headless |GET_FLAG(Servo_AUX5,_BV(5)); // Channel 9 - headless
break; break;
} }
packet[5+offset] = lowByte(aileron);
packet[6+offset]= highByte(aileron);
packet[7+offset]= lowByte(elevator);
packet[8+offset]= highByte(elevator);
packet[11+offset]= lowByte(rudder);
packet[12+offset]|= highByte(rudder);
packet[13+offset]=flags; packet[13+offset]=flags;
packet[14+offset]=flags2; packet[14+offset]=flags2;
@ -233,20 +244,15 @@ uint16_t CX10_callback()
static void __attribute__((unused)) CX10_initialize_txid() static void __attribute__((unused)) CX10_initialize_txid()
{ {
rx_tx_addr[1]%= 0x30; rx_tx_addr[1]%= 0x30;
if(sub_protocol==Q282) if(sub_protocol&0x08) //Q2X2 protocols
{ {
hopping_frequency[0] = 0x46; uint8_t offset=0; //Q282
hopping_frequency[1] = 0x48;
hopping_frequency[2] = 0x4a;
hopping_frequency[3] = 0x4c;
}
else
if(sub_protocol==Q242) if(sub_protocol==Q242)
{ offset=2;
hopping_frequency[0] = 0x48; if(sub_protocol==Q222)
hopping_frequency[1] = 0x4a; offset=3;
hopping_frequency[2] = 0x4c; for(uint8_t i=0;i<4;i++)
hopping_frequency[3] = 0x4e; hopping_frequency[i]=0x46+2*i+offset;
} }
else else
{ {
@ -272,8 +278,8 @@ uint16_t initCX10(void)
} }
else else
{ {
if(sub_protocol==Q282||sub_protocol==Q242) if(sub_protocol&0x08) //Q2X2 protocols
packet_length = Q282_PACKET_SIZE; packet_length = Q2X2_PACKET_SIZE;
else else
packet_length = CX10_PACKET_SIZE; packet_length = CX10_PACKET_SIZE;
packet_period = CX10_PACKET_PERIOD; packet_period = CX10_PACKET_PERIOD;

View File

@ -54,7 +54,7 @@
//Global constants/variables //Global constants/variables
uint32_t MProtocol_id;//tx id, uint32_t MProtocol_id;//tx id,
uint32_t MProtocol_id_master; uint32_t MProtocol_id_master;
uint32_t blink=0; uint32_t blink=0,last_signal=0;
// //
uint16_t counter; uint16_t counter;
uint8_t channel; uint8_t channel;
@ -482,7 +482,11 @@ void Update_All()
} }
#endif //ENABLE_PPM #endif //ENABLE_PPM
#if defined(TELEMETRY) #if defined(TELEMETRY)
if((protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM) ) if((protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM)
#ifdef ENABLE_BAYANG_TELEMETRY
|| (protocol==MODE_BAYANG)
#endif
)
TelemetryUpdate(); TelemetryUpdate();
#endif #endif
update_led_status(); update_led_status();
@ -848,6 +852,8 @@ static void protocol_init()
break; break;
#endif #endif
#if defined(CX10_NRF24L01_INO) #if defined(CX10_NRF24L01_INO)
case MODE_Q2X2:
sub_protocol|=0x08; // Increase the number of sub_protocols for CX-10
case MODE_CX10: case MODE_CX10:
next_callback=initCX10(); next_callback=initCX10();
remote_callback = CX10_callback; remote_callback = CX10_callback;
@ -1069,7 +1075,11 @@ void Mprotocol_serial_init()
{ {
if( (protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) ) if( (protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) )
initTXSerial( SPEED_9600 ) ; initTXSerial( SPEED_9600 ) ;
if(protocol==MODE_FRSKYX) if(protocol==MODE_FRSKYX
#ifdef ENABLE_BAYANG_TELEMETRY
|| protocol==MODE_BAYANG
#endif
)
initTXSerial( SPEED_57600 ) ; initTXSerial( SPEED_57600 ) ;
if(protocol==MODE_DSM) if(protocol==MODE_DSM)
initTXSerial( SPEED_125K ) ; initTXSerial( SPEED_125K ) ;

View File

@ -2,7 +2,7 @@
#include "iface_nrf24l01.h" #include "iface_nrf24l01.h"
#define Q303_BIND_COUNT 1200 #define Q303_BIND_COUNT 2335
#define Q303_PACKET_SIZE 10 #define Q303_PACKET_SIZE 10
#define Q303_PACKET_PERIOD 1500 // Timeout for callback in uSec #define Q303_PACKET_PERIOD 1500 // Timeout for callback in uSec
@ -12,6 +12,15 @@
static uint8_t tx_addr[5]; static uint8_t tx_addr[5];
static uint8_t current_chan; static uint8_t current_chan;
/*
static const struct {
u8 txid[sizeof(txid)];
u8 rfchan[NUM_RF_CHANNELS];
} q303_tx_rf_map[] = {
{{0xb8, 0x69, 0x64, 0x67}, {0x48, 0x4a, 0x4c, 0x46}}, // tx2
{{0xAE, 0x89, 0x97, 0x87}, {0x4A, 0x4C, 0x4E, 0x48}}
}; // tx1
*/
uint8_t txid[4] = {0xAE, 0x89, 0x97, 0x87}; uint8_t txid[4] = {0xAE, 0x89, 0x97, 0x87};
static uint8_t rf_chans[4] = {0x4A, 0x4C, 0x4E, 0x48}; static uint8_t rf_chans[4] = {0x4A, 0x4C, 0x4E, 0x48};
@ -44,10 +53,10 @@ static void send_packet(uint8_t bind)
memset(&packet[5], 0, 5); memset(&packet[5], 0, 5);
} }
else { else {
aileron = map(Servo_data[AILERON], 1000, 2000, 0, 1000); aileron = 1000 - map(Servo_data[AILERON], 1000, 2000, 0, 1000);
elevator = 1000 - map(Servo_data[ELEVATOR], 1000, 2000, 0, 1000); elevator = 1000 - map(Servo_data[ELEVATOR], 1000, 2000, 0, 1000);
throttle = map(Servo_data[THROTTLE], 1000, 2000, 0, 1000); throttle = map(Servo_data[THROTTLE], 1000, 2000, 0, 1000);
rudder = 1000 - map(Servo_data[RUDDER], 1000, 2000, 0, 1000); rudder = map(Servo_data[RUDDER], 1000, 2000, 0, 1000);
packet[0] = 0x55; packet[0] = 0x55;
packet[1] = aileron >> 2 ; // 8 bits packet[1] = aileron >> 2 ; // 8 bits
@ -125,20 +134,21 @@ static uint16_t q303_init()
NRF24L01_Initialize(); NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
XN297_SetTXAddr((uint8_t *) "\xCC\xCC\xCC\xCC\xCC", 5); XN297_SetTXAddr((uint8_t *) "\xCC\xCC\xCC\xCC\xCC", 5);
NRF24L01_FlushTx(); NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit 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_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_05_RF_CH, Q303_RF_BIND_CHANNEL); NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
NRF24L01_SetBitrate(NRF24L01_BR_250K); NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits NRF24L01_SetBitrate(NRF24L01_BR_250K);
NRF24L01_SetPower(); NRF24L01_SetPower();
// this sequence necessary for module from stock tx
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_Activate(0x73); // Activate feature register NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00); // Set feature bits on NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
NRF24L01_Activate(0x73);
NRF24L01_Activate(0x53); // switch bank back NRF24L01_Activate(0x53); // switch bank back
BIND_IN_PROGRESS; BIND_IN_PROGRESS;

View File

@ -20,15 +20,20 @@
// For code readability // For code readability
#define SLT_PAYLOADSIZE 7 #define SLT_PAYLOADSIZE 7
#define SLT_VISTA_PAYLOADSIZE 11
#define SLT_NFREQCHANNELS 15 #define SLT_NFREQCHANNELS 15
#define SLT_TXID_SIZE 4 #define SLT_TXID_SIZE 4
enum { enum {
SLT_BUILD=0, // flags going to packet[6]
SLT_DATA1, SLT_VISTA_FLAG_FLIP = 0x04,
SLT_DATA2, SLT_VISTA_FLAG_MODE = 0x20
SLT_DATA3, };
SLT_BIND
enum {
SLT_BIND=0,
SLT_BUILD,
SLT_DATA,
}; };
static void __attribute__((unused)) SLT_init() static void __attribute__((unused)) SLT_init()
@ -103,25 +108,38 @@ static void __attribute__((unused)) SLT_send_data(uint8_t *data, uint8_t len)
static void __attribute__((unused)) SLT_build_packet() static void __attribute__((unused)) SLT_build_packet()
{ {
// Set radio channel - once per packet batch
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
// aileron, elevator, throttle, rudder, gear, pitch // aileron, elevator, throttle, rudder, gear, pitch
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
for (uint8_t i = 0; i < 4; ++i) for (uint8_t i = 0; i < 4; ++i)
{ {
uint16_t v = convert_channel_10b(CH_AETR[i]); uint16_t v = convert_channel_10b(CH_AETR[i]);
if(sub_protocol==VISTA && CH_AETR[i]==THROTTLE)
v = (uint16_t) map(limit_channel_100(THROTTLE),servo_min_100,servo_max_100,850,150); // Throttel is between 850=0% and 150=100%
packet[i] = v; packet[i] = v;
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0); e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
} }
// Extra bits for AETR // Extra bits for AETR
packet[4] = e; packet[4] = e;
if(sub_protocol==SLT)
{
// 8-bit channels // 8-bit channels
packet[5] = convert_channel_8b(AUX1); packet[5] = convert_channel_8b(AUX1);
packet[6] = convert_channel_8b(AUX2); packet[6] = convert_channel_8b(AUX2);
} }
else
{ // VISTA
packet[5] = 0xA6;
packet[6] = 0x00;
if(Servo_AUX1)
packet[6] = SLT_VISTA_FLAG_FLIP;
if(Servo_AUX2)
packet[6] |= SLT_VISTA_FLAG_MODE;
packet[7] = 0x00;
packet[8] = 0x7F;
packet[9] = 0xAA;
packet[10] = 0x00;
}
}
static void __attribute__((unused)) SLT_send_bind_packet() static void __attribute__((unused)) SLT_send_bind_packet()
{ {
@ -144,47 +162,83 @@ uint16_t SLT_callback()
{ {
switch (phase) switch (phase)
{ {
case SLT_BUILD:
SLT_build_packet();
phase++;
return 1000;
case SLT_DATA1:
SLT_send_data(packet, SLT_PAYLOADSIZE);
phase++;
return 1000;
case SLT_DATA2:
SLT_send_data(packet, SLT_PAYLOADSIZE);
phase++;
return 1000;
case SLT_DATA3:
SLT_send_data(packet, SLT_PAYLOADSIZE);
if (++packet_count >= 100)
{
packet_count = 0;
phase++;
return 1000;
}
else
{
NRF24L01_SetPower(); // Set tx_power
phase = SLT_BUILD;
return 19000;
}
case SLT_BIND: case SLT_BIND:
bind_phase = 0;
SLT_send_bind_packet(); SLT_send_bind_packet();
phase = SLT_BUILD; if(sub_protocol == VISTA)
{
phase=SLT_DATA;
return 1000;
}
phase++; // SLT_BUILD
return 18000; return 18000;
case SLT_BUILD:
if(sub_protocol==SLT)
{ // Set radio channel - once per packet batch
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
}
SLT_build_packet();
packet_count=0;
phase++; // SLT_DATA
return 1000;
case SLT_DATA:
if(sub_protocol==VISTA)
{ // Change radio channel every 9 packets
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
rf_ch_num++;
if(rf_ch_num>=9)
{
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
rf_ch_num=0;
}
}
SLT_send_data(packet, sub_protocol == VISTA?SLT_VISTA_PAYLOADSIZE:SLT_PAYLOADSIZE);
packet_count++;
if(packet_count >= (sub_protocol == VISTA?5:3))
{ // repeat the same data packet 3(SLT) or 5(VISTA) times
bind_phase++;
NRF24L01_SetPower(); // Set tx_power
phase = SLT_BUILD; // Refresh data
if(sub_protocol == VISTA)
return 1000;
else
if(bind_phase>=100)
{ //SLT sends bind packet every 2.2s
phase=SLT_BIND;
return 1000;
} }
return 19000; return 19000;
} }
if(sub_protocol == VISTA)
{ //VISTA sends bind packet every 1.5s
if(bind_phase>=150)
phase=SLT_BIND;
else
return 2000;
}
return 1000;
}
return 1000;
}
uint16_t initSLT() uint16_t initSLT()
{ {
packet_count = 0; packet_count = 0;
packet_sent = 0; packet_sent = 0;
rf_ch_num=0;
hopping_frequency_no = 0; hopping_frequency_no = 0;
if(sub_protocol == VISTA)
{
memcpy(rx_tx_addr,"\x00\x00\x23\x00",SLT_TXID_SIZE);
memcpy(hopping_frequency,"\x03\x0A\x11\x18\x1F\x26\x13\x0F\x0B\x10\x08\x16\x1D\x24\x06",15);
}
else
SLT_set_freq(); SLT_set_freq();
SLT_init(); SLT_init();
SLT_build_packet();
phase = SLT_BIND; phase = SLT_BIND;
return 50000; return 50000;
} }

View File

@ -18,12 +18,21 @@
#if defined TELEMETRY #if defined TELEMETRY
#if defined SPORT_TELEMETRY #if defined SPORT_TELEMETRY
float telemetry_voltage = 0.f;
uint8_t telemetry_rx_rssi = 100;
#ifdef ENABLE_BAYANG_TELEMETRY
uint8_t telemetry_tx_rssi = 100;
uint8_t telemetry_datamode = 0;
uint8_t telemetry_dataitem = 0;
float telemetry_data[3] = {0};
uint16_t telemetry_uptime = 0;
uint16_t telemetry_flighttime = 0;
uint8_t telemetry_flightmode = 0;
#endif
#define SPORT_TIME 12000 #define SPORT_TIME 12000
#define FRSKY_SPORT_PACKET_SIZE 8 #define FRSKY_SPORT_PACKET_SIZE 8
uint32_t last = 0; uint32_t last = 0;
uint8_t sport_counter=0; uint8_t sport_counter=0;
uint8_t RxBt = 0;
uint8_t rssi;
uint8_t sport = 0; uint8_t sport = 0;
#endif #endif
#if defined HUB_TELEMETRY #if defined HUB_TELEMETRY
@ -319,19 +328,150 @@ void sportIdle()
void sportSendFrame() void sportSendFrame()
{ {
uint8_t i; uint8_t i;
#ifdef ENABLE_BAYANG_TELEMETRY
uint32_t temp;
uint16_t temp16;
uint8_t* bytes;
#endif
sport_counter = (sport_counter + 1) %36; sport_counter = (sport_counter + 1) %36;
if(telemetry_lost) if(telemetry_lost)
{ {
sportIdle(); sportIdle();
return; return;
} }
if(sport_counter<6)
uint8_t num_frames = 6;
#ifdef ENABLE_BAYANG_TELEMETRY
if (protocol == MODE_BAYANG) { num_frames = 14; }
#endif
if(sport_counter<num_frames)
{ {
frame[0] = 0x98; frame[0] = 0x98;
frame[1] = 0x10; frame[1] = 0x10;
for (i=5;i<8;i++) for (i=5;i<8;i++)
frame[i]=0; frame[i]=0;
} }
#ifdef ENABLE_BAYANG_TELEMETRY
if (protocol == MODE_BAYANG) {
switch (sport_counter)
{
case 0:
frame[2] = 0x05;
frame[3] = 0xf1;
frame[4] = 0x02 ;//dummy values if swr 20230f00
frame[5] = 0x23;
frame[6] = 0x0F;
break;
case 1: // RSSI
frame[2] = 0x01;
frame[3] = 0xf1;
frame[4] = telemetry_rx_rssi;
break;
case 2: //BATT
frame[2] = 0x04;
frame[3] = 0xf1;
if (protocol == MODE_BAYANG)
frame[4] = telemetry_voltage/4.f * 255.f/3.3f;//a1;
else
frame[4] = telemetry_voltage;
break;
case 3: //FCS VOLTAGE
frame[2] = 0x10;
frame[3] = 0x02;
temp = (uint32_t)(telemetry_voltage * 100);
bytes = (uint8_t *) &temp;
frame[4] = bytes[0];
frame[5] = bytes[1];
frame[6] = bytes[2];
frame[7] = bytes[3];
break;
case 4: //RPM (use this as vTX frequency)
frame[2] = 0x00;
frame[3] = 0x05;
frame[4] = 0;
frame[5] = 0;
frame[6] = 0;
frame[7] = 0;
//frskySerial.sendData(0x0500,temp);
break;
case 5: // xjt accx
frame[2] = 0x24;
frame[3] = 0x00;
temp16 = (uint16_t)(telemetry_data[0]*1000);
bytes = (uint8_t *) &temp16;
frame[4] = bytes[0];
frame[5] = bytes[1];
break;
case 6: // xjt accy
frame[2] = 0x25;
frame[3] = 0x00;
temp16 = (uint16_t)(telemetry_data[1]*1000);
bytes = (uint8_t *) &temp16;
frame[4] = bytes[0];
frame[5] = bytes[1];
break;
case 7: // xjt accz
frame[2] = 0x26;
frame[3] = 0x00;
temp16 = (uint16_t)(telemetry_data[2]*1000);
bytes = (uint8_t *) &temp16;
frame[4] = bytes[0];
frame[5] = bytes[1];
break;
case 8: // xjt gps hour minute
frame[2] = 0x17;
frame[3] = 0x00;
temp16 = telemetry_dataitem; // hours
temp16 |= (telemetry_uptime / 60) << 8; // minutes
bytes = (uint8_t *) &temp16;
frame[4] = bytes[0];
frame[5] = bytes[1];
break;
case 9: // xjt gps seconds
frame[2] = 0x18;
frame[3] = 0x00;
frame[4] = telemetry_uptime % 60;
break;
case 10: // xjt gps day/month
frame[2] = 0x15;
frame[3] = 0x00;
frame[4] = telemetry_flighttime / 60;
frame[5] = telemetry_flighttime % 60;
break;
case 11: // xjt gps year
frame[2] = 0x16;
frame[3] = 0x00;
frame[4] = telemetry_flightmode;
break;
case 12: // xjt t1
frame[2] = 0x02;
frame[3] = 0x00;
frame[4] = 0;
break;
case 13: // xjt t2
frame[2] = 0x05;
frame[3] = 0x00;
frame[4] = 0;
break;
default:
if(sport)
{
for (i=0;i<FRSKY_SPORT_PACKET_SIZE;i++)
frame[i]=pktx1[i];
sport=0;
break;
}
else
{
sportIdle();
return;
}
}
}
else
#endif
{
switch (sport_counter) switch (sport_counter)
{ {
case 0: case 0:
@ -344,7 +484,7 @@ void sportSendFrame()
case 2: // RSSI case 2: // RSSI
frame[2] = 0x01; frame[2] = 0x01;
frame[3] = 0xf1; frame[3] = 0xf1;
frame[4] = rssi; frame[4] = telemetry_rx_rssi;
break; break;
case 4: //BATT case 4: //BATT
frame[2] = 0x04; frame[2] = 0x04;
@ -365,6 +505,7 @@ void sportSendFrame()
return; return;
} }
} }
}
sportSend(frame); sportSend(frame);
} }
@ -460,14 +601,18 @@ void TelemetryUpdate()
#endif #endif
#if defined SPORT_TELEMETRY #if defined SPORT_TELEMETRY
if (protocol==MODE_FRSKYX) if (protocol==MODE_FRSKYX
#ifdef ENABLE_BAYANG_TELEMETRY
|| protocol == MODE_BAYANG
#endif
)
{ // FrSkyX { // FrSkyX
if(telemetry_link) if(telemetry_link)
{ {
if(pktt[4] & 0x80) if(pktt[4] & 0x80)
rssi=pktt[4] & 0x7F ; telemetry_rx_rssi=pktt[4] & 0x7F ;
else else
RxBt = (pktt[4]<<1) + 1 ; telemetry_voltage = (pktt[4]<<1) + 1 ;
if(pktt[6]<=6) if(pktt[6]<=6)
for (uint8_t i=0; i < pktt[6]; i++) for (uint8_t i=0; i < pktt[6]; i++)
proces_sport_data(pktt[7+i]); proces_sport_data(pktt[7+i]);

View File

@ -128,6 +128,7 @@
#define SPORT_TELEMETRY #define SPORT_TELEMETRY
#define HUB_TELEMETRY #define HUB_TELEMETRY
#define AFHDS2A_TELEMETRY #define AFHDS2A_TELEMETRY
// #define ENABLE_BAYANG_TELEMETRY // uncomment to enable bayang telemtry for H101 acro firmware - https://github.com/bikemike/H101-acro/tree/telemetry
/****************************/ /****************************/
/*** SERIAL MODE SETTINGS ***/ /*** SERIAL MODE SETTINGS ***/
@ -233,11 +234,16 @@ const PPM_Parameters PPM_prot[15]= {
CX10_GREEN CX10_GREEN
CX10_BLUE CX10_BLUE
DM007 DM007
Q282
JC3015_1 JC3015_1
JC3015_2 JC3015_2
MK33041 MK33041
MODE_Q2X2
Q222
Q242 Q242
Q282
MODE_SLT
SLT
VISTA
MODE_CG023 MODE_CG023
CG023 CG023
YD829 YD829
@ -281,7 +287,10 @@ const PPM_Parameters PPM_prot[15]= {
FORMAT_X5C1 FORMAT_X5C1
FQ777-951 FQ777-951
MODE_AFHDS2A MODE_AFHDS2A
NONE PWM_IBUS
PPM_IBUS
PWM_SBUS
PPM_SBUS
*/ */
// RX_Num is used for model match. Using RX_Num values different for each receiver will prevent starting a model with the false config loaded... // RX_Num is used for model match. Using RX_Num values different for each receiver will prevent starting a model with the false config loaded...

View File

@ -64,6 +64,7 @@ enum PROTOCOLS
MODE_HONTAI = 26, // =>NRF24L01 MODE_HONTAI = 26, // =>NRF24L01
MODE_OPENLRS = 27, // =>OpenLRS hardware MODE_OPENLRS = 27, // =>OpenLRS hardware
MODE_AFHDS2A = 28, // =>A7105 MODE_AFHDS2A = 28, // =>A7105
MODE_Q2X2 = 29, // =>NRF24L01, extension of CX-10 protocol
}; };
enum Flysky enum Flysky
{ {
@ -110,16 +111,25 @@ enum SYMAX
SYMAX=0, SYMAX=0,
SYMAX5C=1 SYMAX5C=1
}; };
enum SLT
{
SLT = 0,
VISTA = 1
};
enum CX10 enum CX10
{ {
CX10_GREEN = 0, CX10_GREEN = 0,
CX10_BLUE=1, // also compatible with CX10-A, CX12 CX10_BLUE=1, // also compatible with CX10-A, CX12
DM007=2, DM007=2,
Q282=3,
JC3015_1=4, JC3015_1=4,
JC3015_2=5, JC3015_2=5,
MK33041=6, MK33041=6,
Q242=7 };
enum Q2X2
{
Q222 = 8,
Q242 = 9,
Q282 = 10,
}; };
enum CG023 enum CG023
{ {
@ -156,6 +166,11 @@ enum HONTAI
FORMAT_FQ777 = 3 FORMAT_FQ777 = 3
}; };
enum BAYANG
{
BAYANG = 0,
BAYANG_TELEM = 1
};
enum HUBSAN enum HUBSAN
{ {
H107 = 0, H107 = 0,
@ -448,6 +463,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
HONTAI 26 HONTAI 26
OpenLRS 27 OpenLRS 27
AFHDS2A 28 AFHDS2A 28
Q2X2 29
BindBit=> 0x80 1=Bind/0=No BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No RangeCheck=> 0x20 1=Yes /0=No
@ -484,11 +500,17 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
CX10_GREEN 0 CX10_GREEN 0
CX10_BLUE 1 // also compatible with CX10-A, CX12 CX10_BLUE 1 // also compatible with CX10-A, CX12
DM007 2 DM007 2
Q282 3 --- 3
JC3015_1 4 JC3015_1 4
JC3015_2 5 JC3015_2 5
MK33041 6 MK33041 6
Q242 7 sub_protocol==Q2X2
Q222 0
Q242 1
Q282 2
sub_protocol==SLT
SLT 0
VISTA 1
sub_protocol==CG023 sub_protocol==CG023
CG023 0 CG023 0
YD829 1 YD829 1
@ -515,6 +537,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
FORMAT_JJRCX1 1 FORMAT_JJRCX1 1
FORMAT_X5C1 2 FORMAT_X5C1 2
FQ777-521 3 FQ777-521 3
sub_protocol==BAYANG
BAYANG 0
BAYANG_TELEM 1
sub_protocol==AFHDS2A sub_protocol==AFHDS2A
PWM_IBUS 0 PWM_IBUS 0
PPM_IBUS 1 PPM_IBUS 1

Binary file not shown.