Traxxas TQ 1st gen: try 5
[DIY-Multiprotocol-TX-Module.git] / Multiprotocol / Corona_cc2500.ino
blobff6fc9d0cecec4f3241b538c6eb795aab0e00603
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(CORONA_CC2500_INO)
18 #include "iface_cc2500.h"
20 //#define CORONA_FORCE_ID
22 #define CORONA_RF_NUM_CHANNELS  3
23 #define CORONA_ADDRESS_LENGTH   4
24 #define CORONA_BIND_CHANNEL_V1  0xD1    // also Flydream V3
25 #define CORONA_BIND_CHANNEL_V2  0xB8
26 #define CORONA_COARSE                   0x00
27 #define FDV3_BIND_PERIOD                5000
28 #define FDV3_CHANNEL_PERIOD             4000
30 const PROGMEM uint8_t CORONA_init_values[] = {
31   /* 00 */ 0x29, 0x2E, 0x06, 0x07, 0xD3, 0x91, 0xFF, 0x04,
32   /* 08 */ 0x05, 0x00, CORONA_BIND_CHANNEL_V1, 0x06, 0x00, 0x5C, 0x4E, 0xC4 + CORONA_COARSE,
33   /* 10 */ 0x5B, 0xF8, 0x03, 0x23, 0xF8, 0x47, 0x07, 0x30,
34   /* 18 */ 0x18, 0x16, 0x6C, 0x43, 0x40, 0x91, 0x87, 0x6B,
35   /* 20 */ 0xF8, 0x56, 0x10, 0xA9, 0x0A, 0x00, 0x11, 0x41,
36   /* 28 */ 0x00, 0x59, 0x7F, 0x3F, 0x81, 0x35, 0x0B
39 uint8_t fdv3_id_send;
41 static void __attribute__((unused)) CORONA_rf_init()
43         CC2500_Strobe(CC2500_SIDLE);
45         for (uint8_t i = 0; i <= 0x2E; ++i)
46                 CC2500_WriteReg(i, pgm_read_byte_near(&CORONA_init_values[i]));
47         if(sub_protocol==COR_V2)
48         {
49                 CC2500_WriteReg(CC2500_0A_CHANNR, CORONA_BIND_CHANNEL_V2);
50                 CC2500_WriteReg(CC2500_0E_FREQ1, 0x80);
51                 CC2500_WriteReg(CC2500_0F_FREQ0, 0x00 + CORONA_COARSE);
52                 CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
53                 CC2500_WriteReg(CC2500_17_MCSM1, 0x00);
54             CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0x67);
55                 CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0xFB);
56                 CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xDC);
57         }
58         else if(sub_protocol==FD_V3)
59         {
60                 // Flydream receiver captures have deviation 50, tx captures show 47
61                 CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
62         }
63         
64         CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
66         //not sure what they are doing to the PATABLE since basically only the first byte is used and it's only 8 bytes long. So I think they end up filling the PATABLE fully with 0xFF
67         CC2500_WriteRegisterMulti(CC2500_3E_PATABLE,(const uint8_t *)"\x08\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 13);
69         CC2500_SetTxRxMode(TX_EN);
70         CC2500_SetPower();
73 // Generate id and hopping freq
74 static void __attribute__((unused)) CORONA_TXID_init()
76         #ifdef CORONA_FORCE_ID
77                 // Example of ID and channels taken from dumps
78                 switch(sub_protocol)
79                 {
80                         case COR_V1:
81                                 memcpy((void *)rx_tx_addr,(void *)"\x1F\xFE\x6C\x35",CORONA_ADDRESS_LENGTH);
82                                 memcpy((void *)hopping_frequency,(void *)"\x17\x0D\x03\x49",CORONA_RF_NUM_CHANNELS+1);
83                                 break;
84                         case COR_V2:
85                                 memcpy((void *)rx_tx_addr,(void *)"\xFE\xFE\x02\xFB",CORONA_ADDRESS_LENGTH);
86                                 memcpy((void *)hopping_frequency,(void *)"\x14\x3D\x35",CORONA_RF_NUM_CHANNELS);
87                         case FD_V3:
88                                 memcpy((void *)rx_tx_addr,(void *)"\x02\xFA\x38\x38",CORONA_ADDRESS_LENGTH);
89                                 memcpy((void *)hopping_frequency,(void *)"\x71\xB9\x30",CORONA_RF_NUM_CHANNELS);
90                                 break;
91         }
92         #else
93                 // From dumps channels are anything between 0x00 and 0xC5 on V1.
94                 // But 0x00 and 0xB8 should be avoided on V2 since they are used for bind.
95                 // Below code make sure channels are between 0x02 and 0xA0, spaced with
96                 // a minimum of 2 and not ordered (RX only use the 1st channel unless there is an issue).
97                 // Extra hopping frequency used for Flydream V3 id packets.
98                 uint8_t order=rx_tx_addr[3]&0x03;
99                 for(uint8_t i=0; i<CORONA_RF_NUM_CHANNELS+1; i++)
100                         hopping_frequency[i^order]=2+rx_tx_addr[3-i]%39+(i<<5)+(i<<3);
102                 if(sub_protocol!=FD_V3)
103                 {
104                         // ID looks random but on the 15 V1 dumps they all show the same odd/even rule
105                         if(rx_tx_addr[3]&0x01)
106                         {       // If [3] is odd then [0] is odd and [2] is even 
107                                 rx_tx_addr[0]|=0x01;
108                                 rx_tx_addr[2]&=0xFE;
109                         }
110                         else
111                         {       // If [3] is even then [0] is even and [2] is odd 
112                                 rx_tx_addr[0]&=0xFE;
113                                 rx_tx_addr[2]|=0x01;
114                         }
115                         rx_tx_addr[1]=0xFE;                     // Always FE in the dumps of V1 and V2
116                 }
117                 else
118                 {
119                         rx_tx_addr[1]=0xFA;                     // Always FA for Flydream V3
120                         rx_tx_addr[3]=hopping_frequency[CORONA_RF_NUM_CHANNELS];        // channel used for id/freq packets
121                 }
122         #endif
125 static uint16_t __attribute__((unused)) CORONA_build_bind_pkt()
127         if(sub_protocol==COR_V1)
128         {       // V1
129                 if(bind_counter&1)
130                 { // Send TX ID
131                         packet[0]=0x04;         // 5 bytes to follow
132                         for(uint8_t i=0; i<CORONA_ADDRESS_LENGTH; i++)
133                                 packet[i+1]=rx_tx_addr[i];
134                         packet[5]=0xCD;         // Unknown but seems to be always the same value for V1
135                         return 3689;
136                 }
137                 else
138                 { // Send hopping freq
139                         packet[0]=0x03;         // 4 bytes to follow
140                         for(uint8_t i=0; i<CORONA_RF_NUM_CHANNELS+1; i++)
141                                 packet[i+1]=hopping_frequency[i];
142                         // Only the first 3 channels of hopping_frequency used for data
143                         return 3438;
144                 }
145         }
146         else
147         {       // V2 and FDV3
148                 packet[0]=0x04;         // 5 bytes to follow
149                 for(uint8_t i=0; i<CORONA_ADDRESS_LENGTH; i++)
150                         packet[i+1]=rx_tx_addr[i];
151                 packet[5]=0x00;         // Unknown but seems to be always the same value for V2 and FDV3
152                 if(sub_protocol==FD_V3)
153                         return FDV3_BIND_PERIOD;
154                 else
155                         return 26791;
156         }
159 // 8 Channels with direct values from PPM
160 static uint16_t __attribute__((unused)) CORONA_build_packet()
162         CC2500_SetPower();
163         if(state && sub_protocol==COR_V2)
164         {       // Send identifier packet for 2.65sec. This is how the RX learns the hopping table after a bind. Why it's not part of the bind like V1 is a mistery...
165                 // Set channel
166                 CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
167                 state--;
168                 packet[0]=0x07;         // 8 bytes to follow
169                 // Send hopping freq
170                 for(uint8_t i=0; i<CORONA_RF_NUM_CHANNELS; i++)
171                         packet[i+1]=hopping_frequency[i];
172                 // Send TX ID
173                 for(uint8_t i=0; i<CORONA_ADDRESS_LENGTH; i++)
174                         packet[i+4]=rx_tx_addr[i];
175                 packet[8]=0;
176                 return 6647;
177         }
179         // Flydream every fourth packet is identifier packet and is on channel number
180         // that is last byte of rx_tx_addr
181         if (fdv3_id_send)
182         {
183                 fdv3_id_send = 0;
184                 CC2500_WriteReg(CC2500_0A_CHANNR, rx_tx_addr[CORONA_ADDRESS_LENGTH-1]);
185                 packet[0] = 0x07;   // 8 bytes to follow
186                 // Send TX ID
187                 for(uint8_t i = 0; i < CORONA_ADDRESS_LENGTH; i++)
188                         packet[i+1] = rx_tx_addr[i];
189                 // Send hopping freq
190                 for(uint8_t i = 0; i < CORONA_RF_NUM_CHANNELS; i++)
191                         packet[i+1+CORONA_ADDRESS_LENGTH] = hopping_frequency[i];
192                 packet[8] = 0;
193                 return 2*FDV3_CHANNEL_PERIOD;  // extra delay after id packet according to captures
194         }
196         // Set RF channel
197         CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[hopping_frequency_no]);
199         // Build packet
200         packet[0] = 0x10;   // 17 bytes to follow
202         // Channels
203         memset(packet+9, 0x00, 4);
204         for (uint8_t i=0; i<8; i++)
205         { // Channel values are packed
206                 uint16_t val=convert_channel_ppm(i);
207                 packet[i+1] = val;
208                 packet[9 + (i>>1)] |= (i&0x01)?(val>>4)&0xF0:(val>>8)&0x0F;
209         }
211         // TX ID
212         for (uint8_t i=0; i < CORONA_ADDRESS_LENGTH; i++)
213                 packet[i+13] = rx_tx_addr[i];
215         packet[17] = 0x00;
217         if (sub_protocol!=FD_V3)
218         {
219                 // Packet period is based on hopping
220                 switch (hopping_frequency_no)
221                 {
222                         case 0:
223                                 packet_period = sub_protocol == COR_V1
224                                 ? 4991
225                                 : 4248;
226                                 break;
227                         case 1: 
228                                 packet_period = sub_protocol == COR_V1
229                                 ? 4991
230                                 : 4345;
231                                 break;
232                         case 2: 
233                                 packet_period = sub_protocol == COR_V1
234                                 ? 12520
235                                 : 13468;
236                                 if (sub_protocol == COR_V2)
237                                         packet[17] = 0x03;
238                                 break;
239                 }
240         }
241         hopping_frequency_no++;
243         if (sub_protocol == FD_V3)
244         {
245                 if (hopping_frequency_no == CORONA_RF_NUM_CHANNELS)
246                 {
247                         fdv3_id_send = 1;
248                         packet_period = 6000; // extra delay before id packet according to captures
249                 }
250                 else
251                         packet_period = FDV3_CHANNEL_PERIOD;
252         }
254         hopping_frequency_no %= CORONA_RF_NUM_CHANNELS;
255         return packet_period;
258 uint16_t CORONA_callback()
260         #ifdef MULTI_SYNC
261                 telemetry_set_input_sync(22000);
262         #endif
263         // Tune frequency if it has been changed
264         CC2500_SetFreqOffset();
266         if(IS_BIND_IN_PROGRESS)
267         {
268                 if (bind_counter-- == 0) BIND_DONE;
269                 packet_period=CORONA_build_bind_pkt();
270         }
271         else
272                 packet_period=CORONA_build_packet();
274         // Send packet
275         CC2500_WriteData(packet, packet[0]+2);
276         return packet_period;
279 void CORONA_init()
281         switch(sub_protocol)
282         {
283                 case COR_V1:
284                         bind_counter=1400;              // Stay in bind mode for 5s
285                         break;
286                 case COR_V2:
287                         bind_counter=187;               // Stay in bind mode for 5s
288                         break;
289                 case FD_V3:
290                         bind_counter = 2000;    // Stay in bind mode for 10s
291                         break;
292         }
293         state=400;                                      // Used by V2 to send RF channels + ID for 2.65s at startup
294         hopping_frequency_no=0;
295         fdv3_id_send = 0;
296         CORONA_TXID_init();
297         CORONA_rf_init();
300 #endif