Traxxas TQ 1st gen: try 5
[DIY-Multiprotocol-TX-Module.git] / Multiprotocol / NCC1701_nrf24l01.ino
blobfa4e635bcf0ab8d1941e9541e2cac7d60475fe2f
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.
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.
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  */
16 #if defined(NCC1701_NRF24L01_INO)
18 #include "iface_nrf24l01.h"
20 #define NCC_WRITE_WAIT      2000
21 #define NCC_PACKET_INTERVAL 10333
22 #define NCC_TX_PACKET_LEN       16
23 #define NCC_RX_PACKET_LEN       13
25 enum {
26         NCC_BIND_TX1=0,
27         NCC_BIND_RX1,
28         NCC_BIND_TX2,
29         NCC_BIND_RX2,
30         NCC_TX3,
31         NCC_RX3,
34 static void __attribute__((unused)) NCC_RF_init()
36         NRF24L01_Initialize();
38         NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
39         NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR,    (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
40         
41         NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, NCC_RX_PACKET_LEN);                     // Enable rx pipe 0
42         NRF24L01_SetBitrate(NRF24L01_BR_250K);                                                          // NRF24L01_BR_1M, NRF24L01_BR_2M, NRF24L01_BR_250K
43         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)         // switch to TX mode and disable CRC
44                                                                                 | (1 << NRF24L01_00_CRCO)
45                                                                                 | (1 << NRF24L01_00_PWR_UP)
46                                                                                 | (0 << NRF24L01_00_PRIM_RX));
49 const uint8_t NCC_xor[]={0x80, 0x44, 0x64, 0x75, 0x6C, 0x71, 0x2A, 0x36, 0x7C, 0xF1, 0x6E, 0x52, 0x09, 0x9D};
50 static void __attribute__((unused)) NCC_Crypt_Packet()
52         crc=0;
53         for(uint8_t i=0; i< NCC_TX_PACKET_LEN-2; i++)
54         {
55                 packet[i]^=NCC_xor[i];
56                 crc16_update(packet[i], 8);
57         }
58         crc^=0x60DE;
59         packet[NCC_TX_PACKET_LEN-2]=crc>>8;
60         packet[NCC_TX_PACKET_LEN-1]=crc;
62 static boolean __attribute__((unused)) NCC_Decrypt_Packet()
64         crc=0;
65         debug("RX: ");
66         for(uint8_t i=0; i< NCC_RX_PACKET_LEN-2; i++)
67         {
68                 crc16_update( packet[i], 8);
69                 packet[i]^=NCC_xor[i];
70                 debug("%02X ",packet[i]);
71         }
72         crc^=0xA950;
73         if( (crc>>8)==packet[NCC_RX_PACKET_LEN-2] && (crc&0xFF)==packet[NCC_RX_PACKET_LEN-1] )
74         {// CRC match
75                 debugln("OK");
76                 return true;
77         }
78         debugln("NOK");
79         return false;
82 static void __attribute__((unused)) NCC_Write_Packet()
84         packet[0]=0xAA;
85         packet[1]=rx_tx_addr[0];
86         packet[2]=rx_tx_addr[1];
87         packet[3]=rx_id[0];
88         packet[4]=rx_id[1];
89         packet[5]=convert_channel_8b(THROTTLE)>>2;      // 00-3D
90         packet[6]=convert_channel_8b(ELEVATOR);         // original: 61-80-9F but works with 00-80-FF
91         packet[7]=convert_channel_8b(AILERON );         // original: 61-80-9F but works with 00-80-FF
92         packet[8]=convert_channel_8b(RUDDER  );         // original: 61-80-9F but works with 00-80-FF
93         packet[9]=rx_id[2];
94         packet[10]=rx_id[3];
95         packet[11]=rx_id[4];
96         packet[12]=GET_FLAG(CH5_SW, 0x02);                      // Warp:0x00 -> 0x02
97         packet[13]=packet[5]+packet[6]+packet[7]+packet[8]+packet[12];
98         if(phase==NCC_BIND_TX1)
99         {
100                 packet[0]=0xBB;
101                 packet[5]=0x01;
102                 packet[6]=rx_tx_addr[2];
103                 memset((void *)(packet+7),0x55,7);
104                 hopping_frequency_no^=1;
105         }
106         else
107         {
108                 hopping_frequency_no++;
109                 if(hopping_frequency_no>2) hopping_frequency_no=0;
110         }
111         // change frequency
112         NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
113         // switch to TX mode and disable CRC
114         NRF24L01_SetTxRxMode(TXRX_OFF);
115         NRF24L01_SetTxRxMode(TX_EN);
116         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
117                                                                                 | (1 << NRF24L01_00_CRCO)
118                                                                                 | (1 << NRF24L01_00_PWR_UP)
119                                                                                 | (0 << NRF24L01_00_PRIM_RX));
120         // clear packet status bits and TX FIFO
121         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
122         NRF24L01_FlushTx();
123         // send packet
124         NCC_Crypt_Packet();
125         NRF24L01_WritePayload(packet,NCC_TX_PACKET_LEN);
126         NRF24L01_SetPower();
129 uint16_t NCC_callback()
131         switch(phase)
132         {
133                 case NCC_BIND_TX1:
134                         if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
135                         { // RX fifo data ready
136                                 NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN);
137                                 if(NCC_Decrypt_Packet() && packet[1]==rx_tx_addr[0] && packet[2]==rx_tx_addr[1])
139                                 {
140                                         rx_id[0]=packet[3];
141                                         rx_id[1]=packet[4];
142                                         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);                    // Clear data ready, data sent, and retransmit
143                                         phase=NCC_BIND_TX2;
144                                         return NCC_PACKET_INTERVAL;
145                                 }
146                         }
147                         NCC_Write_Packet();
148                         phase = NCC_BIND_RX1;
149                         return NCC_WRITE_WAIT;
150                 case NCC_BIND_RX1:
151                         // switch to RX mode and disable CRC
152                         NRF24L01_SetTxRxMode(TXRX_OFF);
153                         NRF24L01_SetTxRxMode(RX_EN);
154                         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
155                                                                                                 | (1 << NRF24L01_00_CRCO)
156                                                                                                 | (1 << NRF24L01_00_PWR_UP)
157                                                                                                 | (1 << NRF24L01_00_PRIM_RX));
158                         NRF24L01_FlushRx();
159                         phase = NCC_BIND_TX1;
160                         return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT;
161                 case NCC_BIND_TX2:
162                         if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
163                         { // RX fifo data ready
164                                 NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN);
165                                 if(NCC_Decrypt_Packet() && packet[1]==rx_tx_addr[0] && packet[2]==rx_tx_addr[1] && packet[3]==rx_id[0] && packet[4]==rx_id[1])
166                                 {
167                                         rx_id[2]=packet[8];
168                                         rx_id[3]=packet[9];
169                                         rx_id[4]=packet[10];
170                                         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);                    // Clear data ready, data sent, and retransmit
171                                         BIND_DONE;
172                                         phase=NCC_TX3;
173                                         return NCC_PACKET_INTERVAL;
174                                 }
175                         }
176                         NCC_Write_Packet();
177                         phase = NCC_BIND_RX2;
178                         return NCC_WRITE_WAIT;
179                 case NCC_BIND_RX2:
180                         // switch to RX mode and disable CRC
181                         NRF24L01_SetTxRxMode(TXRX_OFF);
182                         NRF24L01_SetTxRxMode(RX_EN);
183                         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
184                                                                                                 | (1 << NRF24L01_00_CRCO)
185                                                                                                 | (1 << NRF24L01_00_PWR_UP)
186                                                                                                 | (1 << NRF24L01_00_PRIM_RX));
187                         NRF24L01_FlushRx();
188                         phase = NCC_BIND_TX2;
189                         return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT;
190                 case NCC_TX3:
191                         #ifdef MULTI_SYNC
192                                 telemetry_set_input_sync(NCC_PACKET_INTERVAL);
193                         #endif
194                         if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
195                         { // RX fifo data ready
196                                 NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN);
197                                 if(NCC_Decrypt_Packet() && packet[1]==rx_tx_addr[0] && packet[2]==rx_tx_addr[1] && packet[3]==rx_id[0] && packet[4]==rx_id[1])
198                                 {
199                                         //Telemetry
200                                         //packet[5] and packet[7] roll angle
201                                         //packet[6] crash detect: 0x00 no crash, 0x02 crash
202                                         #ifdef NCC1701_HUB_TELEMETRY
203                                                 v_lipo1 = packet[6]?0xFF:0x00;  // Crash indication
204                                                 v_lipo2 = 0x00;
205                                                 RX_RSSI = 0x7F;                                 // Dummy RSSI
206                                                 TX_RSSI = 0x7F;                                 // Dummy RSSI
207                                                 telemetry_link=1;
208                                         #endif
209                                 }
210                         }
211                         NCC_Write_Packet();
212                         phase = NCC_RX3;
213                         return NCC_WRITE_WAIT;
214                 case NCC_RX3:
215                         // switch to RX mode and disable CRC
216                         NRF24L01_SetTxRxMode(TXRX_OFF);
217                         NRF24L01_SetTxRxMode(RX_EN);
218                         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
219                                                                                                 | (1 << NRF24L01_00_CRCO)
220                                                                                                 | (1 << NRF24L01_00_PWR_UP)
221                                                                                                 | (1 << NRF24L01_00_PRIM_RX));
222                         NRF24L01_FlushRx();
223                         phase = NCC_TX3;
224                         return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT;
225         }
226         return 0;
229 const uint8_t PROGMEM NCC_TX_DATA[][6]= {
230         { 0x6D, 0x97, 0x04, 0x48, 0x43, 0x26 }, 
231         { 0x35, 0x4B, 0x80, 0x44, 0x4C, 0x0B },
232         { 0x50, 0xE2, 0x32, 0x2D, 0x4B, 0x0A },
233         { 0xBF, 0x34, 0xF3, 0x45, 0x4D, 0x0D },
234         { 0xDD, 0x7D, 0x5A, 0x46, 0x28, 0x23 },
235         { 0xED, 0x19, 0x06, 0x2C, 0x4A, 0x09 },
236         { 0xE9, 0xA8, 0x91, 0x2B, 0x49, 0x07 },
237         { 0x66, 0x17, 0x7D, 0x48, 0x43, 0x26 },
238         { 0xC2, 0x93, 0x55, 0x44, 0x4C, 0x0B },
241 void NCC_init(void)
243         BIND_IN_PROGRESS;       // autobind protocol
244         
245         // Load TX data
246         uint8_t rand=rx_tx_addr[3]%9;
247         for(uint8_t i=0; i<3; i++)
248         {
249                 rx_tx_addr[i]=pgm_read_byte_near(&NCC_TX_DATA[rand][i]);
250                 hopping_frequency[i]=pgm_read_byte_near(&NCC_TX_DATA[rand][i+3]);
251         }
253         // RX data is acquired during bind
254         rx_id[0]=0x00;
255         rx_id[1]=0x00;
256         rx_id[2]=0x20;
257         rx_id[3]=0x20;
258         rx_id[4]=0x20;
260         hopping_frequency[4]=0x08;      // bind channel 1
261         hopping_frequency[5]=0x2A;      // bind channel 2
262         hopping_frequency_no=4;         // start with bind
263         NCC_RF_init();
264         phase=NCC_BIND_TX1;
267 #endif