|
| 1 | +/* |
| 2 | + This project is free software: you can redistribute it and/or modify |
| 3 | + it under the terms of the GNU General Public License as published by |
| 4 | + the Free Software Foundation, either version 3 of the License, or |
| 5 | + (at your option) any later version. |
| 6 | +
|
| 7 | + Multiprotocol is distributed in the hope that it will be useful, |
| 8 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | + GNU General Public License for more details. |
| 11 | +
|
| 12 | + You should have received a copy of the GNU General Public License |
| 13 | + along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. |
| 14 | + */ |
| 15 | +// compatible with JJRC345 |
| 16 | + |
| 17 | +#if defined(JJRC345_NRF24L01_INO) |
| 18 | + |
| 19 | +#include "iface_nrf24l01.h" |
| 20 | + |
| 21 | +#define JJRC345_FORCE_ID |
| 22 | + |
| 23 | +#define JJRC345_PACKET_PERIOD 7450 // Timeout for callback in uSec |
| 24 | +#define JJRC345_INITIAL_WAIT 500 |
| 25 | +#define JJRC345_PACKET_SIZE 16 |
| 26 | +#define JJRC345_RF_BIND_CHANNEL 5 |
| 27 | +#define JJRC345_BIND_COUNT 500 |
| 28 | +#define JJRC345_NUM_CHANNELS 4 |
| 29 | + |
| 30 | + |
| 31 | +enum JJRC345_FLAGS { |
| 32 | + // flags going to packet[8] |
| 33 | + //JJRC345_FLAG_FLIP = 0x80, |
| 34 | + JJRC345_FLAG_HEADLESS = 0x40, |
| 35 | +}; |
| 36 | + |
| 37 | +static uint8_t __attribute__((unused)) JJRC345_convert_channel(uint8_t num) |
| 38 | +{ |
| 39 | + uint8_t val=convert_channel_8b(num); |
| 40 | + // 7F..01=left, 00=center, 80..FF=right |
| 41 | + if(val==0x80) |
| 42 | + val=0; // 0 |
| 43 | + else |
| 44 | + if(val>0x80) |
| 45 | + val--; // 80..FE |
| 46 | + else |
| 47 | + { |
| 48 | + val=0x80-val; // 80..01 |
| 49 | + if(val==0x80) |
| 50 | + val--; // 7F..01 |
| 51 | + } |
| 52 | + return val; |
| 53 | +} |
| 54 | + |
| 55 | +static void __attribute__((unused)) JJRC345_send_packet() |
| 56 | +{ |
| 57 | + packet[0] = 0x00; |
| 58 | + packet[2] = 0x00; |
| 59 | + if (IS_BIND_IN_PROGRESS) |
| 60 | + { //00 05 00 0A 46 4A 41 47 00 00 40 46 A5 4A F1 18 |
| 61 | + packet[1] = JJRC345_RF_BIND_CHANNEL; |
| 62 | + packet[4] = hopping_frequency[0]; |
| 63 | + packet[5] = hopping_frequency[1]; |
| 64 | + packet[6] = hopping_frequency[2]; |
| 65 | + packet[7] = hopping_frequency[3]; |
| 66 | + packet[12] = 0xa5; |
| 67 | + } |
| 68 | + else |
| 69 | + { //00 41 00 0A 00 80 80 80 00 00 40 46 00 49 F1 18 |
| 70 | + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]); |
| 71 | + if (hopping_frequency_no >= JJRC345_NUM_CHANNELS) |
| 72 | + hopping_frequency_no = 0; |
| 73 | + packet[1] = hopping_frequency[hopping_frequency_no]; // next packet will be sent on this channel |
| 74 | + |
| 75 | + packet[4] = convert_channel_8b(THROTTLE); // throttle: 00..FF |
| 76 | + packet[5] = JJRC345_convert_channel(RUDDER); // rudder: 70..60..41..01, 80 center, 81..C1..E0..F0 |
| 77 | + packet[6] = JJRC345_convert_channel(ELEVATOR); // elevator: 70..60..41..01, 80 center, 81..C1..E0..F0 |
| 78 | + packet[7] = JJRC345_convert_channel(AILERON); // aileron: 70..60..41..01, 80 center, 81..C1..E0..F0 |
| 79 | + packet[12] = 0x02; // Rate: 00-01-02 |
| 80 | + } |
| 81 | + packet[3] = (packet[4] >= 0xB7) ? 0x0e : 0x0a; // Some throttle flag. 0A when Thr <= B6, 0E when Thr >= B7, sometimes 06 when moving Ele/Ail |
| 82 | + |
| 83 | + 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 |
| 84 | + packet[9] = 0; // Elevator trim, 00 when not used, 20..25 when trimmed up, 0..1F when trimmed down |
| 85 | + packet[10] = 0x40; // Aileron trim, 40 when not used, 40..5F when trimmed left, 61..7F when trimmed right |
| 86 | + |
| 87 | + packet[11] = hopping_frequency[0]; // First hopping frequency |
| 88 | + |
| 89 | + // Checksum |
| 90 | + packet[13] = 0xf8; |
| 91 | + for (uint8_t i = 0; i < 13; i++) |
| 92 | + packet[13] += packet[i]; |
| 93 | + |
| 94 | + // TX ID |
| 95 | + packet[14] = rx_tx_addr[2]; |
| 96 | + packet[15] = rx_tx_addr[3]; |
| 97 | + |
| 98 | + // Power on, TX mode |
| 99 | + XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP)); |
| 100 | + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); |
| 101 | + NRF24L01_FlushTx(); |
| 102 | + XN297_WritePayload(packet, JJRC345_PACKET_SIZE); |
| 103 | + |
| 104 | + NRF24L01_SetPower(); // Set tx_power |
| 105 | +} |
| 106 | + |
| 107 | +static void __attribute__((unused)) JJRC345_init() |
| 108 | +{ |
| 109 | + NRF24L01_Initialize(); |
| 110 | + NRF24L01_SetTxRxMode(TX_EN); |
| 111 | + XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5); |
| 112 | + NRF24L01_WriteReg(NRF24L01_05_RF_CH, JJRC345_RF_BIND_CHANNEL); // Bind channel |
| 113 | + NRF24L01_FlushTx(); |
| 114 | + NRF24L01_FlushRx(); |
| 115 | + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit |
| 116 | + NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes |
| 117 | + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only |
| 118 | + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1 Mbps |
| 119 | + NRF24L01_SetPower(); |
| 120 | +} |
| 121 | + |
| 122 | +uint16_t JJRC345_callback() |
| 123 | +{ |
| 124 | + #ifdef MULTI_SYNC |
| 125 | + telemetry_set_input_sync(JJRC345_PACKET_PERIOD); |
| 126 | + #endif |
| 127 | + if(IS_BIND_IN_PROGRESS) |
| 128 | + { |
| 129 | + if (bind_counter) |
| 130 | + bind_counter--; |
| 131 | + else |
| 132 | + BIND_DONE; |
| 133 | + } |
| 134 | + JJRC345_send_packet(); |
| 135 | + return JJRC345_PACKET_PERIOD; |
| 136 | +} |
| 137 | + |
| 138 | +static void __attribute__((unused)) JJRC345_initialize_txid() |
| 139 | +{ |
| 140 | + calc_fh_channels(4); |
| 141 | + |
| 142 | + #ifdef JJRC345_FORCE_ID |
| 143 | + //TX 1 |
| 144 | + rx_tx_addr[2]=0x1B; |
| 145 | + rx_tx_addr[3]=0x12; |
| 146 | + hopping_frequency[0] = 0x3f; |
| 147 | + hopping_frequency[1] = 0x49; |
| 148 | + hopping_frequency[2] = 0x47; |
| 149 | + hopping_frequency[3] = 0x47; |
| 150 | + //TX 2 |
| 151 | + rx_tx_addr[2]=0xF1; |
| 152 | + rx_tx_addr[3]=0x18; |
| 153 | + hopping_frequency[0] = 0x46; |
| 154 | + hopping_frequency[1] = 0x4A; |
| 155 | + hopping_frequency[2] = 0x41; |
| 156 | + hopping_frequency[3] = 0x47; |
| 157 | + #endif |
| 158 | +} |
| 159 | + |
| 160 | +uint16_t initJJRC345(void) |
| 161 | +{ |
| 162 | + BIND_IN_PROGRESS; // autobind protocol |
| 163 | + bind_counter = JJRC345_BIND_COUNT; |
| 164 | + JJRC345_initialize_txid(); |
| 165 | + JJRC345_init(); |
| 166 | + return JJRC345_INITIAL_WAIT; |
| 167 | +} |
| 168 | + |
| 169 | +#endif |
0 commit comments