From 02008a8b2e7e838e7f86662740ae2e54a32d347d Mon Sep 17 00:00:00 2001 From: Pascal Langer Date: Thu, 21 May 2020 11:47:51 +0200 Subject: [PATCH] New protocol JJRC345: WIP Work in progress --- Multiprotocol/JJRC345_nrf24l01.ino | 169 +++++++++++++++++++++++++++++ Multiprotocol/Multi_Names.ino | 4 + Multiprotocol/Multiprotocol.h | 3 + Multiprotocol/Multiprotocol.ino | 6 + Multiprotocol/Validate.h | 1 + Multiprotocol/_Config.h | 3 + Protocols_Details.md | 10 +- 7 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 Multiprotocol/JJRC345_nrf24l01.ino diff --git a/Multiprotocol/JJRC345_nrf24l01.ino b/Multiprotocol/JJRC345_nrf24l01.ino new file mode 100644 index 0000000..33ba941 --- /dev/null +++ b/Multiprotocol/JJRC345_nrf24l01.ino @@ -0,0 +1,169 @@ +/* + 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 JJRC345 + +#if defined(JJRC345_NRF24L01_INO) + +#include "iface_nrf24l01.h" + +#define JJRC345_FORCE_ID + +#define JJRC345_PACKET_PERIOD 7450 // Timeout for callback in uSec +#define JJRC345_INITIAL_WAIT 500 +#define JJRC345_PACKET_SIZE 16 +#define JJRC345_RF_BIND_CHANNEL 5 +#define JJRC345_BIND_COUNT 500 +#define JJRC345_NUM_CHANNELS 4 + + +enum JJRC345_FLAGS { + // flags going to packet[8] + //JJRC345_FLAG_FLIP = 0x80, + JJRC345_FLAG_HEADLESS = 0x40, +}; + +static uint8_t __attribute__((unused)) JJRC345_convert_channel(uint8_t num) +{ + uint8_t val=convert_channel_8b(num); + // 7F..01=left, 00=center, 80..FF=right + if(val==0x80) + val=0; // 0 + else + if(val>0x80) + val--; // 80..FE + else + { + val=0x80-val; // 80..01 + if(val==0x80) + val--; // 7F..01 + } + return val; +} + +static void __attribute__((unused)) JJRC345_send_packet() +{ + packet[0] = 0x00; + packet[2] = 0x00; + if (IS_BIND_IN_PROGRESS) + { //00 05 00 0A 46 4A 41 47 00 00 40 46 A5 4A F1 18 + packet[1] = JJRC345_RF_BIND_CHANNEL; + packet[4] = hopping_frequency[0]; + packet[5] = hopping_frequency[1]; + packet[6] = hopping_frequency[2]; + packet[7] = hopping_frequency[3]; + packet[12] = 0xa5; + } + else + { //00 41 00 0A 00 80 80 80 00 00 40 46 00 49 F1 18 + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]); + if (hopping_frequency_no >= JJRC345_NUM_CHANNELS) + hopping_frequency_no = 0; + packet[1] = hopping_frequency[hopping_frequency_no]; // next packet will be sent on this channel + + packet[4] = convert_channel_8b(THROTTLE); // throttle: 00..FF + packet[5] = JJRC345_convert_channel(RUDDER); // rudder: 70..60..41..01, 80 center, 81..C1..E0..F0 + packet[6] = JJRC345_convert_channel(ELEVATOR); // elevator: 70..60..41..01, 80 center, 81..C1..E0..F0 + packet[7] = JJRC345_convert_channel(AILERON); // aileron: 70..60..41..01, 80 center, 81..C1..E0..F0 + packet[12] = 0x02; // Rate: 00-01-02 + } + packet[3] = (packet[4] >= 0xB7) ? 0x0e : 0x0a; // Some throttle flag. 0A when Thr <= B6, 0E when Thr >= B7, sometimes 06 when moving Ele/Ail + + packet[8] = GET_FLAG(CH6_SW,JJRC345_FLAG_HEADLESS); // Headless mode: 00 normal, 40 headless. Rudder trim, 00 when not used, 01..1F when trimmed left, 20..3F + packet[9] = 0; // Elevator trim, 00 when not used, 20..25 when trimmed up, 0..1F when trimmed down + packet[10] = 0x40; // Aileron trim, 40 when not used, 40..5F when trimmed left, 61..7F when trimmed right + + packet[11] = hopping_frequency[0]; // First hopping frequency + + // Checksum + packet[13] = 0xf8; + for (uint8_t i = 0; i < 13; i++) + packet[13] += packet[i]; + + // TX ID + packet[14] = rx_tx_addr[2]; + packet[15] = rx_tx_addr[3]; + + // Power on, TX mode + XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP)); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); + NRF24L01_FlushTx(); + XN297_WritePayload(packet, JJRC345_PACKET_SIZE); + + NRF24L01_SetPower(); // Set tx_power +} + +static void __attribute__((unused)) JJRC345_init() +{ + NRF24L01_Initialize(); + NRF24L01_SetTxRxMode(TX_EN); + XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5); + NRF24L01_WriteReg(NRF24L01_05_RF_CH, JJRC345_RF_BIND_CHANNEL); // Bind channel + NRF24L01_FlushTx(); + NRF24L01_FlushRx(); + 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_02_EN_RXADDR, 0x01); // Enable data pipe 0 only + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1 Mbps + NRF24L01_SetPower(); +} + +uint16_t JJRC345_callback() +{ + #ifdef MULTI_SYNC + telemetry_set_input_sync(JJRC345_PACKET_PERIOD); + #endif + if(IS_BIND_IN_PROGRESS) + { + if (bind_counter) + bind_counter--; + else + BIND_DONE; + } + JJRC345_send_packet(); + return JJRC345_PACKET_PERIOD; +} + +static void __attribute__((unused)) JJRC345_initialize_txid() +{ + calc_fh_channels(4); + + #ifdef JJRC345_FORCE_ID + //TX 1 + rx_tx_addr[2]=0x1B; + rx_tx_addr[3]=0x12; + hopping_frequency[0] = 0x3f; + hopping_frequency[1] = 0x49; + hopping_frequency[2] = 0x47; + hopping_frequency[3] = 0x47; + //TX 2 + rx_tx_addr[2]=0xF1; + rx_tx_addr[3]=0x18; + hopping_frequency[0] = 0x46; + hopping_frequency[1] = 0x4A; + hopping_frequency[2] = 0x41; + hopping_frequency[3] = 0x47; + #endif +} + +uint16_t initJJRC345(void) +{ + BIND_IN_PROGRESS; // autobind protocol + bind_counter = JJRC345_BIND_COUNT; + JJRC345_initialize_txid(); + JJRC345_init(); + return JJRC345_INITIAL_WAIT; +} + +#endif diff --git a/Multiprotocol/Multi_Names.ino b/Multiprotocol/Multi_Names.ino index b73c4b4..80856a2 100644 --- a/Multiprotocol/Multi_Names.ino +++ b/Multiprotocol/Multi_Names.ino @@ -40,6 +40,7 @@ const char STR_SHENQI[] ="Shenqi"; const char STR_FY326[] ="FY326"; const char STR_SFHSS[] ="SFHSS"; const char STR_J6PRO[] ="J6 Pro"; +const char STR_JJRC345[] ="JJRC345"; const char STR_FQ777[] ="FQ777"; const char STR_ASSAN[] ="Assan"; const char STR_FRSKYV[] ="FrSky V"; @@ -273,6 +274,9 @@ const mm_protocol_definition multi_protocols[] = { #if defined(J6PRO_CYRF6936_INO) {PROTO_J6PRO, STR_J6PRO, 0, NO_SUBTYPE, OPTION_NONE }, #endif + #if defined(JJRC345_NRF24L01_INO) + {PROTO_JJRC345, STR_JJRC345, 0, NO_SUBTYPE, OPTION_NONE }, + #endif #if defined(KF606_NRF24L01_INO) {PROTO_KF606, STR_KF606, 0, NO_SUBTYPE, OPTION_RFTUNE }, #endif diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index cf0dc9a..34f6ef5 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -97,6 +97,7 @@ enum PROTOCOLS PROTO_SKYARTEC = 68, // =>CC2500 PROTO_ESKY150V2 = 69, // =>CC2500+NRF24L01 PROTO_DSM_RX = 70, // =>CYRF6936 + PROTO_JJRC345 = 71, // =>NRF24L01 }; enum Flysky @@ -764,6 +765,8 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- FRSKYL 67 SKYARTEC 68 ESKY150V2 69 + DSM_RX 70 + JJRC345 71 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 5993a31..a122589 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -1542,6 +1542,12 @@ static void protocol_init() remote_callback = XN297Dump_callback; break; #endif + #if defined(JJRC345_NRF24L01_INO) + case PROTO_JJRC345: + next_callback=initJJRC345(); + remote_callback = JJRC345_callback; + break; + #endif #endif #ifdef SX1276_INSTALLED #if defined(FRSKYR9_SX1276_INO) diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index c2c1cfe..5e4aaef 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -248,6 +248,7 @@ #undef H8_3D_NRF24L01_INO #undef HISKY_NRF24L01_INO #undef HONTAI_NRF24L01_INO + #undef JJRC345_NRF24L01_INO #undef KF606_NRF24L01_INO #undef KN_NRF24L01_INO #undef MJXQ_NRF24L01_INO diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index 3db2af6..e00a81e 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -212,6 +212,7 @@ #define HISKY_NRF24L01_INO #define HONTAI_NRF24L01_INO #define H8_3D_NRF24L01_INO +#define JJRC345_NRF24L01_INO #define KF606_NRF24L01_INO #define KN_NRF24L01_INO #define MJXQ_NRF24L01_INO @@ -635,6 +636,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { H501 PROTO_J6PRO NONE + PROTO_JJRC345 + NONE PROTO_KF606 NONE PROTO_KN diff --git a/Protocols_Details.md b/Protocols_Details.md index b882735..f758dfb 100644 --- a/Protocols_Details.md +++ b/Protocols_Details.md @@ -106,7 +106,8 @@ CFlie|38|CFlie||||||||NRF24L01| [Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|||||NRF24L01|XN297 [HoTT](Protocols_Details.md#HoTT---57)|57|||||||||CC2500| [Hubsan](Protocols_Details.md#HUBSAN---2)|2|H107|H301|H501||||||A7105| -[J6Pro](Protocols_Details.md#J6Pro---22)|22|J6PRO||||||||CYRF6936| +[J6Pro](Protocols_Details.md#J6Pro---22)|22|||||||||CYRF6936| +[JJRC345](Protocols_Details.md#JJRC345---71)|71|||||||||NRF24L01|XN297 [KF606](Protocols_Details.md#KF606---49)|49|KF606*||||||||NRF24L01|XN297 [KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01| [MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297 @@ -1097,6 +1098,13 @@ ARM| ### Sub_protocol FQ777_951 - *3* +## JJRC345 - *71* +Model: JJRC345 + +CH1|CH2|CH3|CH4|CH5|CH6 +---|---|---|---|---|--- +A|E|T|R||HEADLESS + ## KF606 - *49* Model: KF606