Compare commits

...

18 Commits

Author SHA1 Message Date
pascallanger
835facd2c3 XK2 Gyro off 2025-03-12 07:45:05 +01:00
pascallanger
9e20e47c5a FX/QF012 details 2 2025-03-12 07:34:47 +01:00
pascallanger
a916275f0d FX/QF012 details 2025-03-12 07:31:32 +01:00
rdba2k
9beade33de Add FX_QF012 subprotocol (#1091) 2025-03-12 07:17:08 +01:00
pascallanger
5ba70c3571 Update Protocols_Details.md 2025-03-10 17:40:46 +01:00
pascallanger
168aa89c57 New SFC protocol WL91x 2025-03-10 17:38:37 +01:00
pascallanger
fa055e991c ASF try 1 2025-02-27 16:56:58 +01:00
pascallanger
5437d88642 DSMR SR6200 test 1 2025-02-26 21:12:34 +01:00
pascallanger
d800f2c333 SLT2 final 2025-02-26 11:31:26 +01:00
pascallanger
78f6af6448 SLT2 last trial? 2025-02-26 00:00:49 +01:00
pascallanger
b04d4a54f7 SLT2 trial 3 2025-02-25 22:08:50 +01:00
pascallanger
ed65c81add SLT2 trial 2 2025-02-25 20:31:46 +01:00
pascallanger
9bdc24c42a SLT2 trial 2025-02-25 15:39:16 +01:00
pascallanger
7107d46d29 SHENQI2 new protocol 2025-02-24 17:04:07 +01:00
pascallanger
825f560cbb Update Protocols_Details.md 2025-02-22 11:51:55 +01:00
pascallanger
ccaec304d5 KAMTOM telemetry 2025-02-22 11:48:03 +01:00
pascallanger
22d45349cc Update Compiling.md (#1078) 2025-02-22 11:36:23 +01:00
pascallanger
5f26d624ad Update Compiling.md 2025-02-22 11:23:49 +01:00
16 changed files with 520 additions and 86 deletions

View File

@@ -91,6 +91,7 @@
58,1,FX,620,1 58,1,FX,620,1
58,2,FX,9630,1,Rate,Gyro,TrimR,TrimA,TrimE 58,2,FX,9630,1,Rate,Gyro,TrimR,TrimA,TrimE
58,3,FX,Q560,1,FLIP,Gyro,LEDs 58,3,FX,Q560,1,FLIP,Gyro,LEDs
58,4,FX,QF012,1,FLIP,Gyro,Invert,Reset
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib 20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert 23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
@@ -138,9 +139,9 @@
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess 17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess 17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
17,5,MT99XX,A180,0,3D_6G 17,5,MT99XX,A180,0,3D_6G,Rate,3D_6G
17,6,MT99XX,Dragon,0,Mode,RTH 17,6,MT99XX,Dragon,0,Mode,RTH
17,7,MT99XX,F949G,0,6G_3D,Light 17,7,MT99XX,F949G,0,6G_3D,Light,Rates,Unk1,Unk2
44,0,NCC1701,Std,1,Warp 44,0,NCC1701,Std,1,Warp
77,0,OMP,M2,0,THold,IdleUp,6G_3D 77,0,OMP,M2,0,THold,IdleUp,6G_3D
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
@@ -232,3 +233,5 @@
102,1,JIABAILE,Gyro,0,Speed,Light,Flash,ST_Tr 102,1,JIABAILE,Gyro,0,Speed,Light,Flash,ST_Tr
103,0,H36,Std,1,Flip,HLess,RTH 103,0,H36,Std,1,Flip,HLess,RTH
104,0,KAMTOM,Std,0,ST_Tr,TH_Tr,TH_DR 104,0,KAMTOM,Std,0,ST_Tr,TH_Tr,TH_DR
105,0,Shenqi2,Std,1
106,0,WL91x,Std,0

View File

@@ -462,7 +462,7 @@ uint16_t DSM_callback()
else else
return DSM2_SFC_PERIOD - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY; return DSM2_SFC_PERIOD - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
} }
return 11000 - DSM_WRITE_DELAY - DSM_READ_DELAY; return 10900 - DSM_WRITE_DELAY - DSM_READ_DELAY; //Was 11000 but the SR6200A needs 10900 to report telemetry correctly
} }
#endif #endif
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY; return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
@@ -470,12 +470,15 @@ uint16_t DSM_callback()
case DSM_CH2_READ_B: case DSM_CH2_READ_B:
//Read telemetry //Read telemetry
rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
debug("ST1:%02X ",rx_phase);
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing) if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
debug("ST2:%02X ",rx_phase);
if((rx_phase & 0x07) == 0x02) if((rx_phase & 0x07) == 0x02)
{ // good data (complete with no errors) { // good data (complete with no errors)
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
length=CYRF_ReadRegister(CYRF_09_RX_COUNT); length=CYRF_ReadRegister(CYRF_09_RX_COUNT);
debug("RX(%d)",length);
if(length>TELEMETRY_BUFFER_SIZE-2) if(length>TELEMETRY_BUFFER_SIZE-2)
length=TELEMETRY_BUFFER_SIZE-2; length=TELEMETRY_BUFFER_SIZE-2;
CYRF_ReadDataPacketLen(packet_in+1, length); CYRF_ReadDataPacketLen(packet_in+1, length);
@@ -489,8 +492,11 @@ uint16_t DSM_callback()
} }
#endif #endif
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
//for(uint8_t i=0;i<length+1;i++)
// debug(" %02X", packet_in[i]);
telemetry_link=1; telemetry_link=1;
} }
debugln("");
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_1F || sub_protocol==DSMX_1F) && num_ch < 8) // 22ms mode if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_1F || sub_protocol==DSMX_1F) && num_ch < 8) // 22ms mode
{ {

View File

@@ -62,7 +62,7 @@ static void __attribute__((unused)) FX_send_packet()
trim_ch++; trim_ch++;
if(trim_ch > 3) trim_ch = 0; if(trim_ch > 3) trim_ch = 0;
} }
else // FX_Q560 else // FX_Q560, QF012
trim_ch = 0; trim_ch = 0;
} }
} }
@@ -85,12 +85,16 @@ static void __attribute__((unused)) FX_send_packet()
val = trim_ch==0 ? 0x20 : (convert_channel_8b(trim_ch + CH6) >> 2); // no trim on Throttle val = trim_ch==0 ? 0x20 : (convert_channel_8b(trim_ch + CH6) >> 2); // no trim on Throttle
packet[4] = val; // Trim for channel x 0C..20..34 packet[4] = val; // Trim for channel x 0C..20..34
packet[5] = (trim_ch << 4) // channel x << 4 packet[5] = (trim_ch << 4) // channel x << 4
| GET_FLAG(CH5_SW, 0x01) // DR toggle swich: 0 small throw, 1 large throw / Q560 acrobatic | GET_FLAG(CH5_SW, (sub_protocol == FX_QF012 ? 0x08 : 0x01)) // DR toggle swich: 0 small throw, 1 large throw / Q560 acrobatic / QF012 Special effects
// FX9630 =>0:6G small throw, 1:6G large throw, 2:3D // FX9630 =>0:6G small throw, 1:6G large throw, 2:3D
// QIDI-550=>0:3D, 1:6G, 2:Torque // QIDI-550=>0:3D, 1:6G, 2:Torque
// QF012=>0:beginner(6G), 1:mid(3D), 2:expert(Gyro off)
| (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x00 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x04 : 0x02)); | (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x00 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x04 : 0x02));
if(sub_protocol == FX_Q560) if(sub_protocol == FX_Q560)
packet[5] |= GET_FLAG(CH7_SW, 0x18); // Q560 LED flag 0x10 conflicting with trim_ch... Corrected on new boards using 0x08 instead packet[5] |= GET_FLAG(CH7_SW, 0x18); // Q560 LED flag 0x10 conflicting with trim_ch... Corrected on new boards using 0x08 instead
else if (sub_protocol == FX_QF012)
packet[5] |= GET_FLAG(CH7_SW, 0x40) // QF012 invert flight
| GET_FLAG(CH8_SW, 0x80); // QF012 Restore fine tunning midpoint
} }
else // FX816 and FX620 else // FX816 and FX620
{ {

View File

@@ -136,10 +136,13 @@ uint16_t KAMTOM_callback()
{ {
BIND_DONE; BIND_DONE;
if(packet_in[0] == 0xA0 && packet_in[14] == rx_tx_addr[2] && packet_in[15] == rx_tx_addr[3]) if(packet_in[0] == 0xA0 && packet_in[14] == rx_tx_addr[2] && packet_in[15] == rx_tx_addr[3])
{ {//Good packet with our TXID
rx_tx_addr[0] = packet_in[9]; rx_tx_addr[0] = packet_in[9];
rx_tx_addr[1] = packet_in[10]; rx_tx_addr[1] = packet_in[10];
//if(packet_in[1] == 0x03) // low voltage #ifdef KAMTOM_HUB_TELEMETRY
v_lipo1 = packet_in[1] == 0x03 ? 0x00:0xFF; // low voltage
telemetry_link = 1;
#endif
} }
#if 0 #if 0
for(uint8_t i=0; i < KAMTOM_PAYLOAD_SIZE; i++) for(uint8_t i=0; i < KAMTOM_PAYLOAD_SIZE; i++)
@@ -174,6 +177,9 @@ void KAMTOM_init()
bind_counter = KAMTOM_BIND_COUNT; bind_counter = KAMTOM_BIND_COUNT;
phase = KAMTOM_DATA; phase = KAMTOM_DATA;
hopping_frequency_no = 0; hopping_frequency_no = 0;
#ifdef KAMTOM_HUB_TELEMETRY
RX_RSSI = 100; // Dummy value
#endif
} }
#endif #endif

View File

@@ -112,7 +112,10 @@ void KYOSHO3_init()
debugln("RF CH: %02X",hopping_frequency[0]); debugln("RF CH: %02X",hopping_frequency[0]);
#endif #endif
CYRF_ConfigRFChannel(hopping_frequency[0]); if(IS_BIND_IN_PROGRESS)
CYRF_ConfigRFChannel(0x04);
else
CYRF_ConfigRFChannel(hopping_frequency[0]);
bind_counter = 8217; bind_counter = 8217;
phase = 0; phase = 0;

View File

@@ -55,7 +55,7 @@
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM 55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
56,AFHDS2A_RX,Multi,CPPM 56,AFHDS2A_RX,Multi,CPPM
57,HoTT,Sync,No_Sync 57,HoTT,Sync,No_Sync
58,FX,816,620,9630,Q560 58,FX,816,620,9630,Q560,QF012
59,Bayang_RX,Multi,CPPM 59,Bayang_RX,Multi,CPPM
60,Pelikan,Pro,Lite,SCX24 60,Pelikan,Pro,Lite,SCX24
61,EazyRC 61,EazyRC
@@ -99,4 +99,6 @@
100,YuXiang 100,YuXiang
102,JIABAILE,STD,GYRO 102,JIABAILE,STD,GYRO
103,H36 103,H36
104,KAMTOM 104,KAMTOM
105,Shenqi2
106,WL91x

View File

@@ -36,6 +36,7 @@ const char STR_MT99XX[] ="MT99XX";
const char STR_MT99XX2[] ="MT99XX2"; const char STR_MT99XX2[] ="MT99XX2";
const char STR_MJXQ[] ="MJXq"; const char STR_MJXQ[] ="MJXq";
const char STR_SHENQI[] ="Shenqi"; const char STR_SHENQI[] ="Shenqi";
const char STR_SHENQI2[] ="Shenqi2";
const char STR_FY326[] ="FY326"; const char STR_FY326[] ="FY326";
const char STR_FUTABA[] ="Futaba"; const char STR_FUTABA[] ="Futaba";
const char STR_J6PRO[] ="J6 Pro"; const char STR_J6PRO[] ="J6 Pro";
@@ -116,6 +117,7 @@ const char STR_YUXIANG[] ="YuXiang";
const char STR_UDIRC[] ="UDIRC"; const char STR_UDIRC[] ="UDIRC";
const char STR_JIABAILE[] ="JIABAILE"; const char STR_JIABAILE[] ="JIABAILE";
const char STR_KAMTOM[] ="KAMTOM"; const char STR_KAMTOM[] ="KAMTOM";
const char STR_WL91X[] ="WL91x";
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20"; const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501"; const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
@@ -185,7 +187,7 @@ const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
const char STR_SUBTYPE_MOULDKG[] = "\x06""Analog""Digit\0"; const char STR_SUBTYPE_MOULDKG[] = "\x06""Analog""Digit\0";
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0"; const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0";
const char STR_SUBTYPE_E129[] = "\x04""E129""C186"; const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
const char STR_SUBTYPE_FX[] = "\x04""816\0""620\0""9630""Q560"; const char STR_SUBTYPE_FX[] = "\x05""816\0 ""620\0 ""9630\0""Q560\0""QF012";
const char STR_SUBTYPE_SGF22[] = "\x04""F22\0""F22S""J20\0"; const char STR_SUBTYPE_SGF22[] = "\x04""F22\0""F22S""J20\0";
const char STR_SUBTYPE_JIABAILE[] = "\x04""Std\0""Gyro"; const char STR_SUBTYPE_JIABAILE[] = "\x04""Std\0""Gyro";
#define NO_SUBTYPE nullptr #define NO_SUBTYPE nullptr
@@ -342,7 +344,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback }, {PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
#endif #endif
#if defined(FX_NRF24L01_INO) #if defined(FX_NRF24L01_INO)
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 4, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback }, {PROTO_FX, STR_FX, STR_SUBTYPE_FX, 5, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
#endif #endif
#if defined(FY326_NRF24L01_INO) #if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback }, {PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
@@ -476,6 +478,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(SHENQI_NRF24L01_INO) #if defined(SHENQI_NRF24L01_INO)
{PROTO_SHENQI, STR_SHENQI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI_init, SHENQI_callback }, {PROTO_SHENQI, STR_SHENQI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI_init, SHENQI_callback },
#endif #endif
#if defined(SHENQI2_NRF24L01_INO)
{PROTO_SHENQI2, STR_SHENQI2, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI2_init, SHENQI2_callback },
#endif
#if defined(SKYARTEC_CC2500_INO) #if defined(SKYARTEC_CC2500_INO)
{PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback }, {PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback },
#endif #endif
@@ -500,9 +505,6 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(V911S_CCNRF_INO) #if defined(V911S_CCNRF_INO)
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback }, {PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },
#endif #endif
#if defined(WK2x01_CYRF6936_INO)
{PROTO_WK2x01, STR_WK2x01, STR_SUBTYPE_WK2x01, 6, OPTION_NONE, 1, 1, SW_CYRF, WK_init, WK_callback },
#endif
#if defined(WFLY_CYRF6936_INO) #if defined(WFLY_CYRF6936_INO)
{PROTO_WFLY, STR_WFLY, STR_SUBTYPE_WFLY, 1, OPTION_NONE, 1, 0, SW_CYRF, WFLY_init, WFLY_callback }, {PROTO_WFLY, STR_WFLY, STR_SUBTYPE_WFLY, 1, OPTION_NONE, 1, 0, SW_CYRF, WFLY_init, WFLY_callback },
#endif #endif
@@ -510,6 +512,13 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_OPTION, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback }, {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_OPTION, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },
// {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_WBUS, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },// crash OpenTX... // {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_WBUS, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },// crash OpenTX...
#endif #endif
#if defined(WK2x01_CYRF6936_INO)
{PROTO_WK2x01, STR_WK2x01, STR_SUBTYPE_WK2x01, 6, OPTION_NONE, 1, 1, SW_CYRF, WK_init, WK_callback },
#endif
#if defined(WL91X_CCNRF_INO)
{PROTO_WL91X, STR_WL91X, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, WL91X_init, WL91X_callback },
#endif
#if defined(XERALL_NRF24L01_INO) #if defined(XERALL_NRF24L01_INO)
{PROTO_XERALL, STR_XERALL, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, XERALL_init, XERALL_callback }, {PROTO_XERALL, STR_XERALL, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, XERALL_init, XERALL_callback },
#endif #endif

View File

@@ -19,7 +19,7 @@
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 3 #define VERSION_MINOR 3
#define VERSION_REVISION 4 #define VERSION_REVISION 4
#define VERSION_PATCH_LEVEL 34 #define VERSION_PATCH_LEVEL 44
#define MODE_SERIAL 0 #define MODE_SERIAL 0
@@ -132,6 +132,8 @@ enum PROTOCOLS
PROTO_JIABAILE = 102, // =>NRF24L01 PROTO_JIABAILE = 102, // =>NRF24L01
PROTO_H36 = 103, // =>NRF24L01 PROTO_H36 = 103, // =>NRF24L01
PROTO_KAMTOM = 104, // =>NRF24L01 PROTO_KAMTOM = 104, // =>NRF24L01
PROTO_SHENQI2 = 105, // =>NRF24L01
PROTO_WL91X = 106, // =>CC2500 & NRF24L01
PROTO_NANORF = 126, // =>NRF24L01 PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500 PROTO_TEST = 127, // =>CC2500
@@ -489,6 +491,7 @@ enum FX
FX620 = 1, FX620 = 1,
FX9630 = 2, FX9630 = 2,
FX_Q560 = 3, FX_Q560 = 3,
FX_QF012 = 4,
}; };
enum SGF22 enum SGF22
{ {

View File

@@ -0,0 +1,232 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#if defined(SHENQI2_NRF24L01_INO)
#include "iface_xn297.h"
//#define FORCE_SHENQI2_ORIGINAL_ID
#define SHENQI2_PAYLOAD_SIZE 8
#define SHENQI2_RF_NUM_CHANNELS 16
#define SHENQI2_BIND_COUNT 2000
#define SHENQI2_WRITE_TIME 650
#define SHENQI2_BIND_CHANNEL 44
#define SHENQI2_PACKET_PERIOD 8210
enum {
SHENQI2_BIND = 0,
SHENQI2_BIND_RX,
SHENQI2_DATA,
};
static void __attribute__((unused)) SHENQI2_send_packet()
{
if(bind_counter)
{
bind_counter--;
if(!bind_counter)
BIND_DONE;
}
memset(packet, 0x00, SHENQI2_PAYLOAD_SIZE);
packet_count &= 0x0F;
packet[0] = packet_count;
memcpy(&packet[1],rx_tx_addr,5);
if(IS_BIND_DONE)
{//Normal
uint8_t val = convert_channel_8b(CH2);
if(val < 0x70)
val = 0x30;
else if(val < 0x80)
val = 0x00;
else
{
val &= 0x7F;
val >>= 2;
}
if(Channel_data[CH1] > 1024+50)
val |= 0x40;
else if(Channel_data[CH1] < 1024-50)
val |= 0x80;
packet[6] = val;
//packet[7] = 0x00; // ??
}
else
packet[0] |= 0x30;
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, SHENQI2_PAYLOAD_SIZE, false);
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < SHENQI2_PAYLOAD_SIZE; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) SHENQI2_initialize_txid()
{
#ifdef FORCE_SHENQI2_ORIGINAL_ID
//TXID
rx_tx_addr[0] = 0x51;
rx_tx_addr[1] = 0x70;
rx_tx_addr[2] = 0x02;
//RXID
rx_tx_addr[3] = 0x46;
rx_tx_addr[4] = 0xBE;
#endif
rx_tx_addr[3] = 0x00;
rx_tx_addr[4] = 0x00;
//Freq
memcpy(hopping_frequency,(uint8_t*)"\x05\x09\x0E\x0F\x17\x1C\x21\x27\x2A\x2C\x33\x39\x3D\x42\x48\x4C",16);
}
static void __attribute__((unused)) SHENQI2_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
//Address
XN297_SetTXAddr((uint8_t*)"\x74\xD1\x3A\xF5\x6C", 5);
XN297_SetRXAddr((uint8_t*)"\x74\xD1\x3A\xF5\x6C", SHENQI2_PAYLOAD_SIZE);
XN297_RFChannel(SHENQI2_BIND_CHANNEL);
}
uint16_t SHENQI2_callback()
{
static bool rx=false;
switch(phase)
{
case SHENQI2_BIND:
rx = XN297_IsRX();
XN297_SetTxRxMode(TXRX_OFF);
SHENQI2_send_packet();
packet_count++;
if(rx)
{
uint8_t val=XN297_ReadEnhancedPayload(packet_in, SHENQI2_PAYLOAD_SIZE);
if(val == SHENQI2_PAYLOAD_SIZE)
{
if(memcmp(rx_tx_addr, packet_in, 3) == 0)
{//Good packet with our TXID
BIND_DONE;
rx_tx_addr[3] = packet_in[3];
rx_tx_addr[4] = packet_in[4];
packet_count = 0;
phase = SHENQI2_DATA;
}
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < SHENQI2_PAYLOAD_SIZE; i++)
debug(" %02X", packet_in[i]);
debugln();
#endif
}
}
phase++;
return SHENQI2_WRITE_TIME;
case SHENQI2_BIND_RX:
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase = SHENQI2_BIND;
return SHENQI2_PACKET_PERIOD - SHENQI2_WRITE_TIME;
default: //SHENQI2_DATA
//Since I don't know the order of the channels, I'm hopping on all the channels quickly
//Refresh rate from the motorcycle perspective is 32ms instead of 8ms...
XN297_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= 0x0F;
SHENQI2_send_packet();
if(hopping_frequency_no%4 == 0)
packet_count++;
return SHENQI2_PACKET_PERIOD/4;
}
return 0;
}
void SHENQI2_init()
{
BIND_IN_PROGRESS;
SHENQI2_initialize_txid();
SHENQI2_RF_init();
bind_counter = SHENQI2_BIND_COUNT;
phase = SHENQI2_BIND;
hopping_frequency_no = 0;
}
#endif
/*
XN297 1Mb Enhanced,Acked,Scrambled
Bind
---
RX on channel: 44, Time: 2890us P: 34 51 70 02 00 00 00 00
RX on channel: 44, Time: 1780us P: 34 51 70 02 00 00 00 00
RX on channel: 44, Time: 1773us P: 34 51 70 02 00 00 00 00
RX on channel: 44, Time: 1772us P: 34 51 70 02 00 00 00 00
RX on channel: 44, Time: 2889us P: 35 51 70 02 00 00 00 00
RX on channel: 44, Time: 1769us P: 35 51 70 02 00 00 00 00
RX on channel: 44, Time: 1774us P: 35 51 70 02 00 00 00 00
RX on channel: 44, Time: 1771us P: 35 51 70 02 00 00 00 00
RX on channel: 44, Time: 2894us P: 36 51 70 02 00 00 00 00
A= 74 D1 3A F5 6C
RF:44
Timing: 1772µs between the same 4 packets, 2892µs to the next packet, 8208µs between 2 packets
Request ack, if no ack repeat the packet 4 times
P[0] = counter 00..0F | 30 bind
P[1] = TXID[0]
P[2] = TXID[1]
P[3] = TXID[2]
P[4] = RXID[0]
P[5] = RXID[1]
P[6] = TH 00..1F, Break 30, 40 ST_right, 80 ST_left
P[7] = 00?
Answer from motorcycle:
P: 51 70 02 46 BE 00 00 00
P[0] = TXID[0]
P[1] = TXID[1]
P[2] = TXID[2]
P[3] = RXID[0]
P[4] = RXID[1]
P[5] = 00
P[6] = 00
P[7] = 00
Normal packets
---
A= 74 D1 3A F5 6C
RF:5,9,14,15,23,28,33,39,42,44,51,57,61,66,72,76
RF:\x05\x09\x0E\x0F\x17\x1C\x21\x27\x2A\x2C\x33\x39\x3D\x42\x48\x4C
- order of the channels is unknown and vary over time
- send 16 times on each channel and switch (counter 00..0F)
Timing:1772µs between the same 4 packets, 2892µs to the next packet, 8208µs between 2 packets
Timing:8208 between packets if acked
P: 00 51 70 02 46 BE 00 00
P[0] = counter 00..0F
P[1] = TXID[0]
P[2] = TXID[1]
P[3] = TXID[2]
P[4] = RXID[0]
P[5] = RXID[1]
P[6] = TH 00..1F, Break 30, 40 ST_right, 80 ST_left
P[7] = 00?
*/

View File

@@ -19,6 +19,7 @@
#include "iface_nrf250k.h" #include "iface_nrf250k.h"
//#define SLT_Q200_FORCE_ID //#define SLT_Q200_FORCE_ID
//#define SLT_V1_4_FORCE_ID
// For code readability // For code readability
#define SLT_PAYLOADSIZE_V1 7 #define SLT_PAYLOADSIZE_V1 7
@@ -73,12 +74,12 @@ static void __attribute__((unused)) SLT_set_freq(void)
} }
// Unique freq // Unique freq
uint8_t max_freq=0x50; //V1 and V2 uint8_t max_freq = 0x50; //V1 and V2
if(sub_protocol==Q200) if(sub_protocol == Q200)
max_freq=45; max_freq=45;
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i) for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
{ {
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq) if(sub_protocol == Q200 && hopping_frequency[i] >= max_freq)
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03; hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
uint8_t done = 0; uint8_t done = 0;
while (!done) while (!done)
@@ -94,15 +95,15 @@ static void __attribute__((unused)) SLT_set_freq(void)
} }
} }
} }
#if 0 #ifdef DEBUG_SERIAL
debug("CH:"); debug("CH:");
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i) for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
debug(" %02X", hopping_frequency[i]); debug(" %02X(%d)", hopping_frequency[i], hopping_frequency[i]);
debugln(); debugln();
#endif #endif
//Bind channel //Bind channel
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL; hopping_frequency[SLT_NFREQCHANNELS] = SLT_BIND_CHANNEL;
//Calib all channels //Calib all channels
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1); NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
@@ -153,35 +154,38 @@ static void __attribute__((unused)) SLT_build_packet()
//->V1 stops here //->V1 stops here
if(sub_protocol==Q200) if(sub_protocol == Q200)
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE) packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP) |GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON) |GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF); |GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
else if(sub_protocol==MR100 || sub_protocol==Q100) else if(sub_protocol == MR100 || sub_protocol == Q100)
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE) packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP) |GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but... |GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but... |GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
packet[7]=convert_channel_8b(CH7); packet[7] = convert_channel_8b(CH7);
packet[8]=convert_channel_8b(CH8); packet[8] = convert_channel_8b(CH8);
if(sub_protocol==RF_SIM) { if(sub_protocol == RF_SIM)
packet[9]=convert_channel_8b(CH9); {
packet[10]=convert_channel_8b(CH10); packet[9] = convert_channel_8b(CH9);
} else { packet[10] = convert_channel_8b(CH10);
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
}
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
{//Calibrate
packet[9]=0x77; //enter calibration
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
packet[10]=0x20; //launch calibration
calib_counter++;
if(calib_counter>250) calib_counter=250;
} }
else else
calib_counter=0; {
packet[9] = 0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
packet[10] = 0x00; //normal mode for Q100/Q200, unknown for V2/MR100
}
if((sub_protocol == Q100 || sub_protocol == Q200) && CH13_SW)
{//Calibrate
packet[9] = 0x77; //enter calibration
if(calib_counter >= 20 && calib_counter <= 25) // 7 packets for Q100 / 3 packets for Q200
packet[10] = 0x20; //launch calibration
calib_counter++;
if(calib_counter > 250) calib_counter = 250;
}
else
calib_counter = 0;
} }
static void __attribute__((unused)) SLT_send_bind_packet() static void __attribute__((unused)) SLT_send_bind_packet()
@@ -192,8 +196,8 @@ static void __attribute__((unused)) SLT_send_bind_packet()
NRF250K_SetPower(); NRF250K_SetPower();
BIND_DONE; BIND_DONE;
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE); NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE); memcpy((void*)packet, (void*)rx_tx_addr, SLT_TXID_SIZE);
if(phase==SLT_BIND2) if(phase == SLT_BIND2)
SLT_send_packet(SLT_TXID_SIZE); SLT_send_packet(SLT_TXID_SIZE);
else // SLT_BIND1 else // SLT_BIND1
SLT_send_packet(SLT_PAYLOADSIZE_V2); SLT_send_packet(SLT_PAYLOADSIZE_V2);
@@ -224,9 +228,9 @@ uint16_t SLT_callback()
case SLT_DATA2: case SLT_DATA2:
phase++; phase++;
SLT_send_packet(packet_length); SLT_send_packet(packet_length);
if(sub_protocol==SLT_V1) if(sub_protocol == SLT_V1)
return SLT_V1_TIMING_PACKET; return SLT_V1_TIMING_PACKET;
if(sub_protocol==SLT_V1_4) if(sub_protocol == SLT_V1_4)
{ {
phase++; //Packets are sent two times only phase++; //Packets are sent two times only
return SLT_V1_4_TIMING_PACKET; return SLT_V1_4_TIMING_PACKET;
@@ -238,24 +242,24 @@ uint16_t SLT_callback()
if (++packet_count >= 100) if (++packet_count >= 100)
{// Send bind packet {// Send bind packet
packet_count = 0; packet_count = 0;
if(sub_protocol==SLT_V1||sub_protocol==SLT_V1_4) if(sub_protocol == SLT_V1 || sub_protocol == SLT_V1_4)
{ {
phase=SLT_BIND2; phase = SLT_BIND2;
return SLT_V1_TIMING_BIND2; return SLT_V1_TIMING_BIND2;
} }
//V2 //V2
phase=SLT_BIND1; phase = SLT_BIND1;
return SLT_V2_TIMING_BIND1; return SLT_V2_TIMING_BIND1;
} }
else else
{// Continue to send normal packets {// Continue to send normal packets
phase = SLT_BUILD; phase = SLT_BUILD;
if(sub_protocol==SLT_V1) if(sub_protocol == SLT_V1)
return 20000-SLT_TIMING_BUILD; return 20000 - SLT_TIMING_BUILD;
if(sub_protocol==SLT_V1_4) if(sub_protocol==SLT_V1_4)
return 18000-SLT_TIMING_BUILD-SLT_V1_4_TIMING_PACKET; return 18000 - SLT_TIMING_BUILD - SLT_V1_4_TIMING_PACKET;
//V2 //V2
return 13730-SLT_TIMING_BUILD; return 13730 - SLT_TIMING_BUILD;
} }
case SLT_BIND1: case SLT_BIND1:
SLT_send_bind_packet(); SLT_send_bind_packet();
@@ -264,12 +268,12 @@ uint16_t SLT_callback()
case SLT_BIND2: case SLT_BIND2:
SLT_send_bind_packet(); SLT_send_bind_packet();
phase = SLT_BUILD; phase = SLT_BUILD;
if(sub_protocol==SLT_V1) if(sub_protocol == SLT_V1)
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2; return 20000 - SLT_TIMING_BUILD - SLT_V1_TIMING_BIND2;
if(sub_protocol==SLT_V1_4) if(sub_protocol == SLT_V1_4)
return 18000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2-SLT_V1_4_TIMING_PACKET; return 18000 - SLT_TIMING_BUILD - SLT_V1_TIMING_BIND2 - SLT_V1_4_TIMING_PACKET;
//V2 //V2
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2; return 13730 - SLT_TIMING_BUILD - SLT_V2_TIMING_BIND1 - SLT_V2_TIMING_BIND2;
} }
return 19000; return 19000;
} }
@@ -280,35 +284,26 @@ void SLT_init()
packet_count = 0; packet_count = 0;
packet_sent = 0; packet_sent = 0;
hopping_frequency_no = 0; hopping_frequency_no = 0;
if(sub_protocol==Q200)
{ //Q200: Force high part of the ID otherwise it won't bind if(sub_protocol == SLT_V1)
rx_tx_addr[0]=0x01;
rx_tx_addr[1]=0x02;
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
#endif
}
SLT_RF_init();
SLT_set_freq();
phase = SLT_BUILD;
if(sub_protocol==SLT_V1)
{ {
packet_length = SLT_PAYLOADSIZE_V1; packet_length = SLT_PAYLOADSIZE_V1;
#ifdef MULTI_SYNC #ifdef MULTI_SYNC
packet_period = 20000+2*SLT_V1_TIMING_PACKET; //22ms packet_period = 20000+2*SLT_V1_TIMING_PACKET; //22ms
#endif #endif
} }
else if(sub_protocol==SLT_V1_4) else if(sub_protocol == SLT_V1_4)
{ {
packet_length = SLT_PAYLOADSIZE_V1_4; packet_length = SLT_PAYLOADSIZE_V1_4;
#ifdef MULTI_SYNC #ifdef MULTI_SYNC
packet_period = 18000; //18ms packet_period = 18000; //18ms
#endif #endif
//Test IDs //Force high part of the ID otherwise the RF frequencies do not match, only tested the 2 last bytes...
MProtocol_id = MProtocol_id_master ^ (1<<RX_num); rx_tx_addr[0]=0xF4;
set_rx_tx_addr(MProtocol_id); rx_tx_addr[1]=0x71;
debugln("Try ID: %lx", MProtocol_id); #ifdef SLT_V1_4_FORCE_ID // ID taken from TX dumps
memcpy(rx_tx_addr,"\xF4\x71\x8D\x01",SLT_TXID_SIZE);
#endif
} }
else //V2 else //V2
{ {
@@ -317,6 +312,21 @@ void SLT_init()
packet_period = 13730+2*SLT_V2_TIMING_PACKET; //~18ms packet_period = 13730+2*SLT_V2_TIMING_PACKET; //~18ms
#endif #endif
} }
if(sub_protocol == Q200)
{ //Q200: Force high part of the ID otherwise it won't bind
rx_tx_addr[0]=0x01;
rx_tx_addr[1]=0x02;
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
#endif
}
SLT_RF_init();
SLT_set_freq();
phase = SLT_BUILD;
} }
#endif #endif

View File

@@ -337,6 +337,7 @@
#undef REALACC_NRF24L01_INO #undef REALACC_NRF24L01_INO
#undef SGF22_NRF24L01_INO #undef SGF22_NRF24L01_INO
#undef SHENQI_NRF24L01_INO #undef SHENQI_NRF24L01_INO
#undef SHENQI2_NRF24L01_INO
#undef SYMAX_NRF24L01_INO #undef SYMAX_NRF24L01_INO
#undef V2X2_NRF24L01_INO #undef V2X2_NRF24L01_INO
#undef V761_NRF24L01_INO #undef V761_NRF24L01_INO
@@ -358,6 +359,7 @@
#undef SLT_CCNRF_INO #undef SLT_CCNRF_INO
#undef UDIRC_CCNRF_INO #undef UDIRC_CCNRF_INO
#undef V911S_CCNRF_INO #undef V911S_CCNRF_INO
#undef WL91X_CCNRF_INO
#undef XK_CCNRF_INO #undef XK_CCNRF_INO
#undef XK2_CCNRF_INO #undef XK2_CCNRF_INO
#endif #endif
@@ -392,9 +394,11 @@
#undef KYOSHO3_CYRF6936_INO #undef KYOSHO3_CYRF6936_INO
#undef MOULDKG_NRF24L01_INO #undef MOULDKG_NRF24L01_INO
#undef SHENQI_NRF24L01_INO #undef SHENQI_NRF24L01_INO
#undef SHENQI2_NRF24L01_INO
#undef JIABAILE_NRF24L01_INO #undef JIABAILE_NRF24L01_INO
#undef UDIRC_CCNRF_INO #undef UDIRC_CCNRF_INO
#undef KAMTOM_NRF24L01_INO #undef KAMTOM_NRF24L01_INO
#undef WL91X_CCNRF_INO
#endif #endif
#ifdef MULTI_SURFACE #ifdef MULTI_SURFACE
@@ -490,6 +494,7 @@
#undef PROPEL_HUB_TELEMETRY #undef PROPEL_HUB_TELEMETRY
#undef OMP_HUB_TELEMETRY #undef OMP_HUB_TELEMETRY
#undef V761_HUB_TELEMETRY #undef V761_HUB_TELEMETRY
#undef KAMTOM_HUB_TELEMETRY
#undef YUXIANG_HUB_TELEMETRY #undef YUXIANG_HUB_TELEMETRY
#undef RLINK_HUB_TELEMETRY #undef RLINK_HUB_TELEMETRY
#undef DSM_RX_CYRF6936_INO #undef DSM_RX_CYRF6936_INO
@@ -529,6 +534,9 @@
#if not defined(V761_NRF24L01_INO) #if not defined(V761_NRF24L01_INO)
#undef V761_HUB_TELEMETRY #undef V761_HUB_TELEMETRY
#endif #endif
#if not defined(KAMTOM_NRF24L01_INO)
#undef KAMTOM_HUB_TELEMETRY
#endif
#if not defined(YUXIANG_NRF24L01_INO) #if not defined(YUXIANG_NRF24L01_INO)
#undef YUXIANG_HUB_TELEMETRY #undef YUXIANG_HUB_TELEMETRY
#endif #endif
@@ -589,7 +597,7 @@
//protocols using FRSKYD user frames //protocols using FRSKYD user frames
#undef HUB_TELEMETRY #undef HUB_TELEMETRY
#endif #endif
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY) && not defined(V761_HUB_TELEMETRY) && not defined(YUXIANG_HUB_TELEMETRY) && not defined(WFLY2_HUB_TELEMETRY) && not defined(LOLI_HUB_TELEMETRY) && not defined(MLINK_HUB_TELEMETRY) && not defined(MLINK_FW_TELEMETRY) && not defined(MT99XX_HUB_TELEMETRY) && not defined(MULTI_CONFIG_INO) #if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY) && not defined(V761_HUB_TELEMETRY) && not defined(KAMTOM_HUB_TELEMETRY) && not defined(YUXIANG_HUB_TELEMETRY) && not defined(WFLY2_HUB_TELEMETRY) && not defined(LOLI_HUB_TELEMETRY) && not defined(MLINK_HUB_TELEMETRY) && not defined(MLINK_FW_TELEMETRY) && not defined(MT99XX_HUB_TELEMETRY) && not defined(MULTI_CONFIG_INO)
#undef TELEMETRY #undef TELEMETRY
#undef INVERT_TELEMETRY #undef INVERT_TELEMETRY
#undef MULTI_TELEMETRY #undef MULTI_TELEMETRY

View File

@@ -0,0 +1,96 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#if defined(WL91X_CCNRF_INO)
#include "iface_xn297.h"
//#define FORCE_WL91X_ORIGINAL_ID
#define WL91X_PAYLOAD_SIZE 9
#define WL91X_RF_NUM_CHANNELS 3
#define WL91X_PACKET_PERIOD 2594
static void __attribute__((unused)) WL91X_send_packet()
{
uint8_t val;
//RF freq
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no %= WL91X_RF_NUM_CHANNELS;
//Sticks
val = convert_channel_16b_limit(CH2,0x21,0xE0); //THR forward 00..5F, backward 80..DF
if(val < 128) val = 127 - val;
packet[0] = val - 0x80;
val = convert_channel_s8b(CH1); //ST right 00..7F, left 80..FF
packet[1] = val - 0x80;
//Trims
val = convert_channel_s8b(CH3); //ST_Trim centered=80, increment/decrement=4, right 04..7C, left 84..FC
packet[2] = val - 0x80;
packet[3] = convert_channel_16b_limit(CH4,0x00,0x70); //TH_Trim increment/decrement=3, 00..39..6F
//TX_ID
memcpy(&packet[4], rx_tx_addr, 4);
//Checksum
val = 0;
for(uint8_t i=0; i<WL91X_PAYLOAD_SIZE-1; i++)
val += packet[i];
packet[8] = val;
//Send
XN297_SetPower();
XN297_SetFreqOffset();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, WL91X_PAYLOAD_SIZE);
#ifdef DEBUG_SERIAL
for(uint8_t i=0; i < WL91X_PAYLOAD_SIZE; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) WL91X_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_UNSCRAMBLED, XN297_250K);
XN297_HoppingCalib(WL91X_RF_NUM_CHANNELS);
XN297_SetTXAddr((uint8_t*)"\x46\x14\x7B\x08", 4);
}
static void __attribute__((unused)) WL91X_initialize_txid()
{
#ifdef FORCE_WL91X_ORIGINAL_ID
memcpy(rx_tx_addr, (uint8_t*)"\x00\x1E\x33\x02",4);
#endif
memcpy(hopping_frequency, (uint8_t*)"\x1A\x3B\x3B",3); //26,59,59
}
uint16_t WL91X_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(WL91X_PACKET_PERIOD);
#endif
WL91X_send_packet();
return WL91X_PACKET_PERIOD;
}
void WL91X_init()
{
BIND_DONE; //No bind for this protocol
WL91X_initialize_txid();
WL91X_RF_init();
hopping_frequency_no = 0;
}
#endif

View File

@@ -71,9 +71,13 @@ static void __attribute__((unused)) XK2_send_packet()
} }
//Flags //Flags
packet[5] = GET_FLAG(CH5_SW, 0x01) //Rate packet[5] = GET_FLAG(CH5_SW, 0x01) //Rate
| GET_FLAG(CH6_SW, 0x08) //Mode
| GET_FLAG(CH7_SW, 0x20) //Hover | GET_FLAG(CH7_SW, 0x20) //Hover
| GET_FLAG(CH8_SW, 0x40); //Light | GET_FLAG(CH8_SW, 0x40); //Light
if(CH6_SW)
packet[5] |= 0x10; //Gyro off (senior mode)
else if(Channel_data[CH6] > CHANNEL_MIN_COMMAND)
packet[5] |= 0x08; //3D
//Telemetry not received=00, Telemetry received=01 but sometimes switch to 1 even if telemetry is not there... //Telemetry not received=00, Telemetry received=01 but sometimes switch to 1 even if telemetry is not there...
packet[6] = 0x00; packet[6] = 0x00;
//RXID checksum //RXID checksum
@@ -200,7 +204,7 @@ uint16_t XK2_callback()
} }
return 1000; return 1000;
case XK2_DATA_PREP: case XK2_DATA_PREP:
crc8=eeprom_read_byte((EE_ADDR)(XK2_EEPROM_OFFSET+RX_num)); crc8 = eeprom_read_byte((EE_ADDR)(XK2_EEPROM_OFFSET+RX_num));
debugln("R:RX_ID=%02X",crc8); debugln("R:RX_ID=%02X",crc8);
XN297_SetTxRxMode(TXRX_OFF); XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TX_EN); XN297_SetTxRxMode(TX_EN);

View File

@@ -257,6 +257,7 @@
#define REALACC_NRF24L01_INO #define REALACC_NRF24L01_INO
#define SGF22_NRF24L01_INO #define SGF22_NRF24L01_INO
#define SHENQI_NRF24L01_INO #define SHENQI_NRF24L01_INO
#define SHENQI2_NRF24L01_INO
#define SYMAX_NRF24L01_INO #define SYMAX_NRF24L01_INO
#define V2X2_NRF24L01_INO #define V2X2_NRF24L01_INO
#define V761_NRF24L01_INO #define V761_NRF24L01_INO
@@ -276,6 +277,7 @@
#define SLT_CCNRF_INO #define SLT_CCNRF_INO
#define UDIRC_CCNRF_INO #define UDIRC_CCNRF_INO
#define V911S_CCNRF_INO #define V911S_CCNRF_INO
#define WL91X_CCNRF_INO
#define XK_CCNRF_INO #define XK_CCNRF_INO
#define XK2_CCNRF_INO #define XK2_CCNRF_INO
@@ -351,6 +353,7 @@
#define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define OMP_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define OMP_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define V761_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define V761_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define KAMTOM_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define YUXIANG_HUB_TELEMETRY #define YUXIANG_HUB_TELEMETRY
#define PROPEL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define PROPEL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
@@ -697,6 +700,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
FX620 FX620
FX9630 FX9630
Q560 Q560
QF012
PROTO_FY326 PROTO_FY326
FY326 FY326
FY319 FY319
@@ -834,6 +838,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
J20 J20
PROTO_SHENQI PROTO_SHENQI
NONE NONE
PROTO_SHENQI2
NONE
PROTO_SKYARTEC PROTO_SKYARTEC
NONE NONE
PROTO_SLT PROTO_SLT

View File

@@ -99,7 +99,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[FrskyX2](Protocols_Details.md#FRSKYX2---64)|64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500| [FrskyX2](Protocols_Details.md#FRSKYX2---64)|64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|Multi|CloneTX|EraseTX|CPPM|||||CC2500| [Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|Multi|CloneTX|EraseTX|CPPM|||||CC2500|
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||CC2500| [Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||CC2500|
[FX](Protocols_Details.md#FX---58)|28|816|620|9630|Q560|||||NRF24L01| [FX](Protocols_Details.md#FX---58)|28|816|620|9630|Q560|QF012||||NRF24L01|
[FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01| [FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01|
[GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L [GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
[GW008](Protocols_Details.md#GW008---32)|32|||||||||NRF24L01|XN297 [GW008](Protocols_Details.md#GW008---32)|32|||||||||NRF24L01|XN297
@@ -115,6 +115,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[JIABAILE](Protocols_Details.md#JIABAILE---102)|102|Std|Gyro|||||||NRF24L01|XN297 [JIABAILE](Protocols_Details.md#JIABAILE---102)|102|Std|Gyro|||||||NRF24L01|XN297
[JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297 [JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
[JOYSWAY](Protocols_Details.md#JOYSWAY---84)|84|||||||||NRF24L01|XN297 [JOYSWAY](Protocols_Details.md#JOYSWAY---84)|84|||||||||NRF24L01|XN297
[KAMTOM](Protocols_Details.md#KAMTOM---104)|104|||||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|ZCZ50||||||NRF24L01|XN297 [KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|ZCZ50||||||NRF24L01|XN297
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01| [KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105| [Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
@@ -143,6 +144,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[Scorpio](Protocols_Details.md#Scorpio---94)|94|||||||||CYRF6936| [Scorpio](Protocols_Details.md#Scorpio---94)|94|||||||||CYRF6936|
[SGF22](Protocols_Details.md#SGF22---97)|97|F22|F22S|J20||||||NRF24L01|XN297 [SGF22](Protocols_Details.md#SGF22---97)|97|F22|F22S|J20||||||NRF24L01|XN297
[Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01|LT8900 [Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01|LT8900
[Shenqi2](Protocols_Details.md#Shenqi2---105)|105|Shenqi2||||||||NRF24L01|XN297
[Skyartec](Protocols_Details.md#Skyartec---68)|68|||||||||CC2500|CC2500 [Skyartec](Protocols_Details.md#Skyartec---68)|68|||||||||CC2500|CC2500
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100|V1_4CH|RF_SIM||NRF24L01|CC2500 [SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100|V1_4CH|RF_SIM||NRF24L01|CC2500
[SymaX](Protocols_Details.md#Symax---10)|10|SYMAX|SYMAX5C|||||||NRF24L01| [SymaX](Protocols_Details.md#Symax---10)|10|SYMAX|SYMAX5C|||||||NRF24L01|
@@ -153,6 +155,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936| [WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936|
[WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105| [WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105|
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936| [WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936|
[WL91X](Protocols_Details.md#WL91X---106)|106|||||||||NRF24L011&CC2500|XN297
[XERALL](Protocols_Details.md#XERALL---91)|91|Tank||||||||NRF24L01|XN297 [XERALL](Protocols_Details.md#XERALL---91)|91|Tank||||||||NRF24L01|XN297
[XK](Protocols_Details.md#XK---62)|62|X450|X420|Cars||||||NRF24L011&CC2500|XN297 [XK](Protocols_Details.md#XK---62)|62|X450|X420|Cars||||||NRF24L011&CC2500|XN297
[XK2](Protocols_Details.md#XK2---99)|99|X4|P10|||||||NRF24L01&CC2500|XN297 [XK2](Protocols_Details.md#XK2---99)|99|X4|P10|||||||NRF24L01&CC2500|XN297
@@ -1439,11 +1442,14 @@ FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (re
MODE: -100% level, +100% acro MODE: -100% level, +100% acro
### Sub_protocol V1_4CH - *5* ### Sub_protocol V1_4CH - *5*
Transmitters: SLT2 and SLT2 DLC, Receivers: SPMXSE2825RX, SPMXSBER1025G, SPMXSE4510RX, ...
CH1|CH2|CH3|CH4 CH1|CH2|CH3|CH4
---|---|---|--- ---|---|---|---
CH1|CH2|CH3|CH4 CH1|CH2|CH3|CH4
CH4 is used for DSC settings: -35% off to +15% full
### Sub_protocol RF_SIM - *6* ### Sub_protocol RF_SIM - *6*
Models: the SLT-dongle included in RealFlight 7.5 Models: the SLT-dongle included in RealFlight 7.5
@@ -1481,6 +1487,14 @@ A|E|T|R|CALIB|RATE|6G_3D|6GSENIOR|LIGHT
A280 -> 6GSENIOR: -100% - 6G, +100% - Senior mode (turn off gyro), LIGHT: cycle the light through on-flash-off when the CH9 value is changed from -100% to 100% A280 -> 6GSENIOR: -100% - 6G, +100% - Senior mode (turn off gyro), LIGHT: cycle the light through on-flash-off when the CH9 value is changed from -100% to 100%
## WL91X - *106*
Models: WLtoys WL911, WL913, WL915 and may be others...
CH1|CH2|CH3|CH4
---|---|---|---
ST|TH|ST_TR|TH_TR
## XK - *62* ## XK - *62*
CC2500: only X450 is supported. CC2500: only X450 is supported.
@@ -1532,6 +1546,8 @@ The plane does not need to be bound each time if it is powered on **after** the
The rudder trim is driven from the rudder channel to increase the range (Original TX rudder has no range once the motor has been turned on...). The rudder trim is driven from the rudder channel to increase the range (Original TX rudder has no range once the motor has been turned on...).
Mode: -100%=6G, 0%=3D, +100%=Gyro off (Senior mode)
### Sub_protocol X4 - *0* ### Sub_protocol X4 - *0*
Transmitter: XK X4-A160, X5S, model: XK A160S, XK A280, XK A300 Transmitter: XK X4-A160, X5S, model: XK A160S, XK A280, XK A300
@@ -1785,18 +1801,22 @@ FMODE and AUX7 have 4 positions: -100%..-50%=>0, -50%..5%=>1, 5%..50%=>2, 50%..1
## FX - *58* ## FX - *58*
FEI XIONG FEI XIONG
CH1|CH2|CH3|CH4
---|---|---|---
A|-|T|-
### Sub_protocol 816 - *0* ### Sub_protocol 816 - *0*
Model: FX816 P38, B17 Model: FX816 P38, B17
Only 8 TX IDs available Only 8 TX IDs available
CH1|CH2|CH3|CH4
---|---|---|---
A|-|T|-
### Sub_protocol 620 - *1* ### Sub_protocol 620 - *1*
Model: FX620 SU35 Model: FX620 SU35
CH1|CH2|CH3|CH4
---|---|---|---
A|-|T|-
### Sub_protocol 9630 - *2* ### Sub_protocol 9630 - *2*
Model: FX9630, FX9603, QIDI-550 Model: FX9630, FX9603, QIDI-550
@@ -1819,6 +1839,19 @@ FLIP is a toggle channel meaning that -100% to +100% is a command and +100% to -
Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D
### Sub_protocol QF012 - *4*
Model: QF012 SBD Dauntless
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|FLIP|GYRO|Invert|Reset
FLIP is a toggle channel meaning that -100% to +100% is a command and +100% to -100% is also a command
Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D
Reset: Restore fine tunning midpoint
## FY326 - *20* ## FY326 - *20*
### Sub_protocol FY326 - *0* ### Sub_protocol FY326 - *0*
@@ -1982,13 +2015,13 @@ Model: DF-Models SkyTumbler
RTH not supported RTH not supported
## KAMTOM - *104* ## KAMTOM - *104*
Models: KAMTOM KM24xx (KM32xx?), Pinecone SG-24xx Models: KAMTOM RC Racing KM24xx (KM32xx?), Pinecone SG-24xx
CH1|CH2|CH3|CH4|CH5|CH6|CH7 CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|--- ---|---|---|---|---|---|---
ST|TH|UNK1|UNK2|ST_TR|TH_TR|TH_DR ST|TH|UNK1|UNK2|ST_TR|TH_TR|TH_DR
Low batt telemetry is not yet added. Low battery telemetry in A1 with 0 = low batt
## KYOSHO2 - *93* ## KYOSHO2 - *93*
Model: TX KT-17, Minium Edge 540, Minium Citabria Model: TX KT-17, Minium Edge 540, Minium Citabria
@@ -2160,6 +2193,15 @@ CH1|CH2|CH3|CH4
Throttle +100%=full forward,0%=stop,-100%=full backward. Throttle +100%=full forward,0%=stop,-100%=full backward.
## Shenqi2 - *105*
Autobind protocol
Model: Shenqiwei 1/20 Mini Motorcycle
CH1|CH2
---|---
ST|TH
## Symax - *10* ## Symax - *10*
Autobind protocol Autobind protocol

View File

@@ -108,7 +108,7 @@ The images below indicate the pin layout and the location of the ground pin on t
|:---:|:---:|:---:| |:---:|:---:|:---:|
<img src="images/V2b_ISP.jpeg" width="189" height="200" /> | <img src="images/MPTM_PCB_2.3d_ISP.png" width="486" height="201" /> | <img src="images/ProMini_ISP.png" width="195" height="200" /> | <img src="images/V2b_ISP.jpeg" width="189" height="200" /> | <img src="images/MPTM_PCB_2.3d_ISP.png" width="486" height="201" /> | <img src="images/ProMini_ISP.png" width="195" height="200" /> |
You are now ready to plug in the USB programmer to the computer. If you are looking for a good working USBasp Windows driver, [use this one](http://www.protostack.com/download/USBasp-win-driver-x86-x64-v3.0.7.zip). You are now ready to plug in the USB programmer to the computer. If you are looking for a good working USBasp Windows driver, [use this one](https://protostack.com.au/download/USBasp-win-driver-x86-x64-v3.0.7.zip).
### Burn bootloader and set fuses ### Burn bootloader and set fuses
The bootloader only needs to be burned once, unless you decide to switch from one option to the other (or it is accidentally erased). If you have already burned the bootloader / set the fuses you can skip this step. The bootloader only needs to be burned once, unless you decide to switch from one option to the other (or it is accidentally erased). If you have already burned the bootloader / set the fuses you can skip this step.