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/>.
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
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)
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);
58 else if(sub_protocol==FD_V3)
60 // Flydream receiver captures have deviation 50, tx captures show 47
61 CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
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);
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
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);
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);
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);
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)
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
111 { // If [3] is even then [0] is even and [2] is odd
115 rx_tx_addr[1]=0xFE; // Always FE in the dumps of V1 and V2
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
125 static uint16_t __attribute__((unused)) CORONA_build_bind_pkt()
127 if(sub_protocol==COR_V1)
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
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
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;
159 // 8 Channels with direct values from PPM
160 static uint16_t __attribute__((unused)) CORONA_build_packet()
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...
166 CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
168 packet[0]=0x07; // 8 bytes to follow
170 for(uint8_t i=0; i<CORONA_RF_NUM_CHANNELS; i++)
171 packet[i+1]=hopping_frequency[i];
173 for(uint8_t i=0; i<CORONA_ADDRESS_LENGTH; i++)
174 packet[i+4]=rx_tx_addr[i];
179 // Flydream every fourth packet is identifier packet and is on channel number
180 // that is last byte of rx_tx_addr
184 CC2500_WriteReg(CC2500_0A_CHANNR, rx_tx_addr[CORONA_ADDRESS_LENGTH-1]);
185 packet[0] = 0x07; // 8 bytes to follow
187 for(uint8_t i = 0; i < CORONA_ADDRESS_LENGTH; i++)
188 packet[i+1] = rx_tx_addr[i];
190 for(uint8_t i = 0; i < CORONA_RF_NUM_CHANNELS; i++)
191 packet[i+1+CORONA_ADDRESS_LENGTH] = hopping_frequency[i];
193 return 2*FDV3_CHANNEL_PERIOD; // extra delay after id packet according to captures
197 CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[hopping_frequency_no]);
200 packet[0] = 0x10; // 17 bytes to follow
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);
208 packet[9 + (i>>1)] |= (i&0x01)?(val>>4)&0xF0:(val>>8)&0x0F;
212 for (uint8_t i=0; i < CORONA_ADDRESS_LENGTH; i++)
213 packet[i+13] = rx_tx_addr[i];
217 if (sub_protocol!=FD_V3)
219 // Packet period is based on hopping
220 switch (hopping_frequency_no)
223 packet_period = sub_protocol == COR_V1
228 packet_period = sub_protocol == COR_V1
233 packet_period = sub_protocol == COR_V1
236 if (sub_protocol == COR_V2)
241 hopping_frequency_no++;
243 if (sub_protocol == FD_V3)
245 if (hopping_frequency_no == CORONA_RF_NUM_CHANNELS)
248 packet_period = 6000; // extra delay before id packet according to captures
251 packet_period = FDV3_CHANNEL_PERIOD;
254 hopping_frequency_no %= CORONA_RF_NUM_CHANNELS;
255 return packet_period;
258 uint16_t CORONA_callback()
261 telemetry_set_input_sync(22000);
263 // Tune frequency if it has been changed
264 CC2500_SetFreqOffset();
266 if(IS_BIND_IN_PROGRESS)
268 if (bind_counter-- == 0) BIND_DONE;
269 packet_period=CORONA_build_bind_pkt();
272 packet_period=CORONA_build_packet();
275 CC2500_WriteData(packet, packet[0]+2);
276 return packet_period;
284 bind_counter=1400; // Stay in bind mode for 5s
287 bind_counter=187; // Stay in bind mode for 5s
290 bind_counter = 2000; // Stay in bind mode for 10s
293 state=400; // Used by V2 to send RF channels + ID for 2.65s at startup
294 hopping_frequency_no=0;