From 0a5b97a17756ed7ae073e2ced01b2dcacd1204aa Mon Sep 17 00:00:00 2001 From: Pascal Langer Date: Fri, 3 Apr 2020 19:36:05 +0200 Subject: [PATCH] New Protocol: PROPEL Compatible model: PROPEL 74-Z Speeder Bike Protcol: PROPEL (66) Sub protocol: none Autobind protocol Extended limits not supported Telemetry supported 14 channels in use due to many features --- Multiprotocol/FrSkyX_cc2500.ino | 4 - Multiprotocol/Multi.txt | 1 + Multiprotocol/Multi_Names.ino | 7 +- Multiprotocol/Multiprotocol.h | 4 +- Multiprotocol/Multiprotocol.ino | 10 +- Multiprotocol/Propel_nrf24l01.ino | 328 ++++++++++++++++++++++++++++++ Multiprotocol/Telemetry.ino | 4 +- Multiprotocol/Validate.h | 1 + Multiprotocol/_Config.h | 3 + Protocols_Details.md | 14 +- 10 files changed, 365 insertions(+), 11 deletions(-) create mode 100644 Multiprotocol/Propel_nrf24l01.ino diff --git a/Multiprotocol/FrSkyX_cc2500.ino b/Multiprotocol/FrSkyX_cc2500.ino index d204045..6c00054 100644 --- a/Multiprotocol/FrSkyX_cc2500.ino +++ b/Multiprotocol/FrSkyX_cc2500.ino @@ -256,10 +256,6 @@ static void __attribute__((unused)) FrSkyX_build_packet() uint16_t ReadFrSkyX() { - #ifdef DEBUG_SERIAL - static uint16_t fr_time=0; - #endif - switch(state) { default: diff --git a/Multiprotocol/Multi.txt b/Multiprotocol/Multi.txt index 6d80d43..59e0da2 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -63,3 +63,4 @@ 63,XN_DUMP,250K,1M,2M,AUTO 64,FrskyX2,CH_16,CH_8,EU_16,EU_8 65,FrSkyR9,915MHz,868MHz,915_8ch,868_8ch +66,PROPEL,74-Z diff --git a/Multiprotocol/Multi_Names.ino b/Multiprotocol/Multi_Names.ino index 0819026..29e7a6b 100644 --- a/Multiprotocol/Multi_Names.ino +++ b/Multiprotocol/Multi_Names.ino @@ -79,6 +79,7 @@ const char STR_TIGER[] ="Tiger"; const char STR_XK[] ="XK"; const char STR_XN297DUMP[] ="XN297DP"; const char STR_FRSKYR9[] ="FrSkyR9"; +const char STR_PROPEL[] ="PROPEL"; const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20"; const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501"; @@ -121,6 +122,7 @@ const char STR_SUBTYPE_V911S[] = "\x05""V911S""E119\0"; const char STR_SUBTYPE_XK[] = "\x04""X450""X420"; const char STR_SUBTYPE_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch"; const char STR_SUBTYPE_ESKY[] = "\x03""Std""ET4"; +const char STR_SUBTYPE_PROPEL[] = "\x04""74-Z"; enum { @@ -327,7 +329,10 @@ const mm_protocol_definition multi_protocols[] = { {PROTO_XN297DUMP, STR_XN297DUMP, 4, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN }, #endif #if defined(FRSKYR9_SX1276_INO) - {PROTO_FRSKY_R9, STR_FRSKYR9, 4, STR_SUBTYPE_FRSKYR9, OPTION_NONE }, + {PROTO_FRSKY_R9, STR_FRSKYR9, 4, STR_SUBTYPE_FRSKYR9, OPTION_NONE }, +#endif +#if defined(PROPEL_NRF24L01_INO) + {PROTO_PROPEL, STR_PROPEL, 4, STR_SUBTYPE_PROPEL, OPTION_NONE }, #endif {0x00, nullptr, 0, nullptr, 0 } }; diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index 7cdd826..ab072b2 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -19,7 +19,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 3 #define VERSION_REVISION 0 -#define VERSION_PATCH_LEVEL 79 +#define VERSION_PATCH_LEVEL 80 //****************** // Protocols @@ -92,6 +92,7 @@ enum PROTOCOLS PROTO_XN297DUMP = 63, // =>NRF24L01 PROTO_FRSKYX2 = 64, // =>CC2500 PROTO_FRSKY_R9 = 65, // =>SX1276 + PROTO_PROPEL = 66, // =>NRF24L01 }; enum Flysky @@ -727,6 +728,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- XN297DUMP 63 FRSKYX2 64 FRSKY_R9 65 + PROPEL 66 BindBit=> 0x80 1=Bind/0=No AutoBindBit=> 0x40 1=Yes /0=No RangeCheck=> 0x20 1=Yes /0=No diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 18bc127..c557464 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -737,7 +737,7 @@ bool Update_All() update_led_status(); #if defined(TELEMETRY) #if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) ) - if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_FRSKYX2)) + if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_PROPEL)) #endif if(IS_DISABLE_TELEM_off) TelemetryUpdate(); @@ -1485,6 +1485,12 @@ static void protocol_init() remote_callback = XK_callback; break; #endif + #if defined(PROPEL_NRF24L01_INO) + case PROTO_PROPEL: + next_callback=initPROPEL(); + remote_callback = PROPEL_callback; + break; + #endif #if defined(XN297DUMP_NRF24L01_INO) case PROTO_XN297DUMP: next_callback=initXN297Dump(); @@ -2067,7 +2073,7 @@ void pollBoot() #if defined(TELEMETRY) void PPM_Telemetry_serial_init() { - if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) + if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) #ifdef TELEMETRY_FRSKYX_TO_FRSKYD || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) #endif diff --git a/Multiprotocol/Propel_nrf24l01.ino b/Multiprotocol/Propel_nrf24l01.ino new file mode 100644 index 0000000..3d3b8ae --- /dev/null +++ b/Multiprotocol/Propel_nrf24l01.ino @@ -0,0 +1,328 @@ +/* + 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 . + */ +// Compatible with PROPEL 74-Z Speeder Bike. + +#if defined(PROPEL_NRF24L01_INO) + +#include "iface_nrf24l01.h" + +//#define PROPEL_FORCE_ID + +#define PROPEL_INITIAL_WAIT 500 +#define PROPEL_PACKET_PERIOD 10000 +#define PROPEL_BIND_RF_CHANNEL 0x23 +#define PROPEL_PAYLOAD_SIZE 16 +#define PROPEL_SEARCH_PERIOD 50 //*10ms +#define PROPEL_BIND_PERIOD 1500 +#define PROPEL_PACKET_SIZE 14 +#define PROPEL_RF_NUM_CHANNELS 4 +#define PROPEL_ADDRESS_LENGTH 5 +#define PROPEL_DEFAULT_PERIOD 20 + +enum { + PROPEL_BIND1 = 0, + PROPEL_BIND2, + PROPEL_BIND3, + PROPEL_DATA1, +}; + +static uint16_t __attribute__((unused)) PROPEL_checksum() +{ + typedef union { + struct { + uint8_t h:1; + uint8_t g:1; + uint8_t f:1; + uint8_t e:1; + uint8_t d:1; + uint8_t c:1; + uint8_t b:1; + uint8_t a:1; + } bits; + uint8_t byte:8; + } byte_bits_t; + + uint8_t sum = packet[0]; + for (uint8_t i = 1; i < PROPEL_PACKET_SIZE - 2; i++) + sum += packet[i]; + + byte_bits_t in = { .byte = sum }; + byte_bits_t out = { .byte = sum }; + out.byte ^= 0x0a; + out.bits.d = !(in.bits.d ^ in.bits.h); + out.bits.c = (!in.bits.c && !in.bits.d && in.bits.g) + || (in.bits.c && !in.bits.d && !in.bits.g) + || (!in.bits.c && in.bits.g && !in.bits.h) + || (in.bits.c && !in.bits.g && !in.bits.h) + || (in.bits.c && in.bits.d && in.bits.g && in.bits.h) + || (!in.bits.c && in.bits.d && !in.bits.g && in.bits.h); + out.bits.b = (!in.bits.b && !in.bits.c && !in.bits.d) + || (in.bits.b && in.bits.c && in.bits.g) + || (!in.bits.b && !in.bits.c && !in.bits.g) + || (!in.bits.b && !in.bits.d && !in.bits.g) + || (!in.bits.b && !in.bits.c && !in.bits.h) + || (!in.bits.b && !in.bits.g && !in.bits.h) + || (in.bits.b && in.bits.c && in.bits.d && in.bits.h) + || (in.bits.b && in.bits.d && in.bits.g && in.bits.h); + out.bits.a = (in.bits.a && !in.bits.b) + || (in.bits.a && !in.bits.c && !in.bits.d) + || (in.bits.a && !in.bits.c && !in.bits.g) + || (in.bits.a && !in.bits.d && !in.bits.g) + || (in.bits.a && !in.bits.c && !in.bits.h) + || (in.bits.a && !in.bits.g && !in.bits.h) + || (!in.bits.a && in.bits.b && in.bits.c && in.bits.g) + || (!in.bits.a && in.bits.b && in.bits.c && in.bits.d && in.bits.h) + || (!in.bits.a && in.bits.b && in.bits.d && in.bits.g && in.bits.h); + + return (sum << 8) | (out.byte & 0xff); +} + +static void __attribute__((unused)) PROPEL_bind_packet(bool valid_rx_id) +{ + memset(packet, 0, PROPEL_PACKET_SIZE); + + packet[0] = 0xD0; + memcpy(&packet[1], rx_tx_addr, 4); // only 4 bytes sent of 5-byte address + if (valid_rx_id) memcpy(&packet[5], rx_id, 4); + packet[9] = rf_ch_num; // hopping table to be used when switching to normal mode + packet[11] = 0x05; // unknown, 0x01 on TX2?? + + uint16_t check = PROPEL_checksum(); + packet[12] = check >> 8; + packet[13] = check & 0xff; + + NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))); + NRF24L01_FlushTx(); + NRF24L01_FlushRx(); + NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE); +} + +static void __attribute__((unused)) PROPEL_data_packet() +{ + memset(packet, 0, PROPEL_PACKET_SIZE); + + packet[0] = 0xC0; + packet[1] = convert_channel_16b_limit(THROTTLE, 0x2f, 0xcf); + packet[2] = convert_channel_16b_limit(RUDDER , 0xcf, 0x2f); + packet[3] = convert_channel_16b_limit(ELEVATOR, 0x2f, 0xcf); + packet[4] = convert_channel_16b_limit(AILERON , 0xcf, 0x2f); + packet[5] = 0x40; //might be trims but unsused + packet[6] = 0x40; //might be trims but unsused + packet[7] = 0x40; //might be trims but unsused + packet[8] = 0x40; //might be trims but unsused + if (bind_phase) + {//need to send a couple of default packets after bind + bind_phase--; + packet[10] = 0x80; // LEDs + } + else + { + packet[9] = 0x02 // Always fast speed, slow=0x00, medium=0x01, fast=0x02, 0x03=flight training mode + | GET_FLAG( CH14_SW, 0x03) // Flight training mode + | GET_FLAG( CH10_SW, 0x04) // Calibrate + | GET_FLAG( CH12_SW, 0x08) // Take off + | GET_FLAG( CH8_SW, 0x10) // Fire + | GET_FLAG( CH11_SW, 0x20) // Altitude hold=0x20 + | GET_FLAG( CH6_SW, 0x40) // Roll CW + | GET_FLAG( CH7_SW, 0x80); // Roll CCW + packet[10] = GET_FLAG( CH13_SW, 0x20) // Land + | GET_FLAG( CH9_SW, 0x40) // Weapon system activted=0x40 + | GET_FLAG(!CH5_SW, 0x80); // LEDs + } + packet[11] = 5; // unknown, 0x01 on TX2?? + + uint16_t check = PROPEL_checksum(); + packet[12] = check >> 8; + packet[13] = check & 0xff; + + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]); + hopping_frequency_no &= 0x03; + NRF24L01_SetPower(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))); + NRF24L01_FlushTx(); + NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE); +} + +static void __attribute__((unused)) PROPEL_init() +{ + NRF24L01_Initialize(); + NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f); + NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes + NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address + NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps + NRF24L01_SetPower(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // ?? match protocol capture + NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address + NRF24L01_WriteReg(NRF24L01_05_RF_CH, PROPEL_BIND_RF_CHANNEL); + NRF24L01_Activate(0x73); // Activate feature register + NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length + NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features + // Beken 2425 register bank 1 initialized here in stock tx capture + // Hopefully won't matter for nRF compatibility + NRF24L01_FlushTx(); + NRF24L01_SetTxRxMode(TX_EN); +} + +const uint8_t PROGMEM PROPEL_hopping []= { 0x47,0x36,0x27,0x44,0x33,0x0D,0x3C,0x2E,0x1B,0x39,0x2A,0x18 }; +static void __attribute__((unused)) PROPEL_initialize_txid() +{ + //address last byte + rx_tx_addr[4]=0x11; + + //random hopping channel table + rf_ch_num=random(0xfefefefe)&0x03; + for(uint8_t i=0; i<3; i++) + hopping_frequency[i]=pgm_read_byte_near( &PROPEL_hopping[i + 3*rf_ch_num] ); + hopping_frequency[3]=0x23; + +#ifdef PROPEL_FORCE_ID + if(RX_num&1) + memcpy(rx_tx_addr, (uint8_t *)"\x73\xd3\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX1: 73 d3 31 30 11 + else + memcpy(rx_tx_addr, (uint8_t *)"\x94\xc5\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX2: 94 c5 31 30 11 + rf_ch_num = 0x03; //TX1 + memcpy(hopping_frequency,(uint8_t *)"\x39\x2A\x18\x23",PROPEL_RF_NUM_CHANNELS); //TX1: 57,42,24,35 + rf_ch_num = 0x00; //TX2 + memcpy(hopping_frequency,(uint8_t *)"\x47\x36\x27\x23",PROPEL_RF_NUM_CHANNELS); //TX2: 71,54,39,35 + rf_ch_num = 0x01; // Manual search + memcpy(hopping_frequency,(uint8_t *)"\x44\x33\x0D\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 68,51,13,35 + rf_ch_num = 0x02; // Manual search + memcpy(hopping_frequency,(uint8_t *)"\x3C\x2E\x1B\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 60,46,27,35 +#endif +} + +uint16_t PROPEL_callback() +{ + uint8_t status; + + switch (phase) + { + case PROPEL_BIND1: + PROPEL_bind_packet(false); //rx_id unknown + phase++; //BIND2 + return PROPEL_BIND_PERIOD; + + case PROPEL_BIND2: + status=NRF24L01_ReadReg(NRF24L01_07_STATUS); + if (status & _BV(NRF24L01_07_MAX_RT)) + {// Max retry (6) reached + phase = PROPEL_BIND1; + return PROPEL_BIND_PERIOD; + } + if (!(_BV(NRF24L01_07_RX_DR) & status)) + return PROPEL_BIND_PERIOD; // nothing received + // received frame, got rx_id, save it + NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE); + memcpy(rx_id, &packet_in[1], 4); + PROPEL_bind_packet(true); //send bind packet with rx_id + phase++; //BIND3 + break; + + case PROPEL_BIND3: + if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS)) + { + NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE); + if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,4)==0) + {//confirmation from the model + phase++; //PROPEL_DATA1 + bind_phase=PROPEL_DEFAULT_PERIOD; + packet_count=0; + BIND_DONE; + break; + } + } + NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, PROPEL_ADDRESS_LENGTH); + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, PROPEL_ADDRESS_LENGTH); + PROPEL_bind_packet(true); //send bind packet with rx_id + break; + + case PROPEL_DATA1: + if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS)) + {// data received from the model + NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE); + if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,4)==0) + { + telemetry_counter++; //LQI + v_lipo1=packet[5]; //number of life left? + if(telemetry_lost==0) + telemetry_link=1; + } + } + PROPEL_data_packet(); + packet_count++; + if(packet_count>=100) + {//LQI calculation + packet_count=0; + TX_LQI=telemetry_counter; + RX_RSSI=telemetry_counter; + telemetry_counter = 0; + telemetry_lost=0; + } + break; + } + return PROPEL_PACKET_PERIOD; +} + +uint16_t initPROPEL() +{ + BIND_IN_PROGRESS; // autobind protocol + PROPEL_initialize_txid(); + PROPEL_init(); + hopping_frequency_no = 0; + phase=PROPEL_BIND1; + return PROPEL_INITIAL_WAIT; +} + +#endif +// equations for checksum check byte from truth table +// (1) z = a && !b +// || a && !c && !d +// || a && !c && !g +// || a && !d && !g +// || a && !c && !h +// || a && !g && !h +// || !a && b && c && g +// || !a && b && c && d && h +// || !a && b && d && g && h; +// +// (2) y = !b && !c && !d +// || b && c && g +// || !b && !c && !g +// || !b && !d && !g +// || !b && !c && !h +// || !b && !g && !h +// || b && c && d && h +// || b && d && g && h; +// +// (3) x = !c && !d && g +// || c && !d && !g +// || !c && g && !h +// || c && !g && !h +// || c && d && g && h +// || !c && d && !g && h; +// +// (4) w = d && h +// || !d && !h; +// +// (5) v = !e; +// +// (6) u = f; +// +// (7) t = !g; +// +// (8) s = h; \ No newline at end of file diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index 4d4bb39..3fa4b86 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -514,7 +514,7 @@ void frsky_link_frame() telemetry_link |= 2 ; // Send hub if available } else - {//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2 + {//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL frame[1] = v_lipo1; frame[2] = v_lipo2; frame[3] = RX_RSSI; @@ -935,7 +935,7 @@ void TelemetryUpdate() #endif if( telemetry_link & 1 ) - { // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + { // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL // FrSkyX telemetry if in PPM frsky_link_frame(); return; diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index d68f744..383baec 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -250,6 +250,7 @@ #undef BAYANG_RX_NRF24L01_INO #undef TIGER_NRF24L01_INO #undef XK_NRF24L01_INO + #undef PROPEL_NRF24L01_INO #endif #if not defined(STM32_BOARD) #undef SX1276_INSTALLED diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index 3a9cda6..1815d58 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -212,6 +212,7 @@ #define MT99XX_NRF24L01_INO #define NCC1701_NRF24L01_INO #define POTENSIC_NRF24L01_INO +#define PROPEL_NRF24L01_INO #define Q303_NRF24L01_INO #define SHENQI_NRF24L01_INO #define SLT_NRF24L01_INO @@ -638,6 +639,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { NONE PROTO_POTENSIC NONE + PROTO_PROPEL + NONE PROTO_Q2X2 Q222 Q242 diff --git a/Protocols_Details.md b/Protocols_Details.md index 7a790e2..be727c5 100644 --- a/Protocols_Details.md +++ b/Protocols_Details.md @@ -112,6 +112,7 @@ CFlie|38|CFlie||||||||NRF24L01| [OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None| [Pelikan](Protocols_Details.md#Pelikan---60)|60|||||||||A7105| [Potensic](Protocols_Details.md#Potensic---51)|51|A20||||||||NRF24L01|XN297 +[PROPEL](Protocols_Details.md#PROPEL---66)|66|74-Z||||||||NRF24L01| [Q2X2](Protocols_Details.md#Q2X2---29)|29|Q222|Q242|Q282||||||NRF24L01| [Q303](Protocols_Details.md#Q303---31)|31|Q303|CX35|CX10D|CX10WD|||||NRF24L01|XN297 [Redpine](Protocols_Details.md#Redpine---50)|50|FAST|SLOW|||||||NRF24L01| @@ -1107,7 +1108,7 @@ CH1|CH2|CH3|CH4|CH5 A|E|T|R|Warp ## Potensic - *51* -Models: Potensic A20 +Model: Potensic A20 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8 ---|---|---|---|---|---|---|--- @@ -1121,6 +1122,17 @@ MODE: Beginner -100%, Medium 0%, Advanced +100% HEADLESS: Off -100%, On +100% +## PROPEL - *66* +Model: PROPEL 74-Z Speeder Bike + +Autobind protocol + +Telemetry: RSSI is equal to TX_LQI which indicates how well the TX receives the RX (0-100%). A1 voltage should indicate the numbers of life remaining (not tested). + +CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14 +---|---|---|---|---|---|---|---|---|----|----|----|----|---- +A|E|T|R|LEDs|RollCW|RollCCW|Fire|Weapons|Calib|Alt_Hold|Take_off|Land|Training + ## Q2X2 - *29* ### Sub_protocol Q222 - *0* Models: Q222 v1 and V686 v2