Traxxas TQ 1st gen: try 5
[DIY-Multiprotocol-TX-Module.git] / Multiprotocol / HOTT_cc2500.ino
blobd6c9be3ca96f9f9f53b149c401c0e8b11559f218
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(HOTT_CC2500_INO)
18 #include "iface_cc2500.h"
20 //#define HOTT_FORCE_ID         // Force ID of original dump
22 #define HOTT_TX_PACKET_LEN      50
23 #define HOTT_RX_PACKET_LEN      22
24 #define HOTT_PACKET_PERIOD      10000
25 #define HOTT_NUM_RF_CHANNELS 75
26 #define HOTT_COARSE     0
28 enum {
29     HOTT_START = 0x00,
30     HOTT_CAL   = 0x01,
31     HOTT_DATA1 = 0x02,
32     HOTT_DATA2 = 0x03,
33     HOTT_RX1   = 0x04,
34     HOTT_RX2   = 0x05,
37 #ifdef HOTT_FW_TELEMETRY
38         #define HOTT_SENSOR_TYPE 6
39         #define HOTT_SENSOR_SEARCH_PERIOD 2000
40         uint8_t HOTT_sensor_cur=0;
41         uint8_t HOTT_sensor_pages=0;
42         uint8_t HOTT_sensor_valid=false;
43         uint8_t HOTT_sensor_ok[HOTT_SENSOR_TYPE];
44         uint8_t HOTT_sensor_seq=0;
45 #endif
47 #define HOTT_FREQ0_VAL 0x6E
49 // Some important initialization parameters, all others are either default,
50 // or not important in the context of transmitter
51 // FIFOTHR  00
52 // SYNC1    D3
53 // SYNC0    91
54 // PKTLEN   32 - Packet length, 50 bytes
55 // PKTCTRL1 04 - APPEND_STATUS on=RSSI+LQI, all other are receive parameters - irrelevant
56 // PKTCTRL0 44 - whitening, use FIFO, use CRC, fixed packet length
57 // ADDR     00
58 // CHANNR   10
59 // FSCTRL1  09 - IF 
60 // FSCTRL0  00 - zero freq offset
61 // FREQ2    5C - synthesizer frequencyfor 26MHz crystal
62 // FREQ1    6C
63 // FREQ0    B9
64 // MDMCFG4  2D - 
65 // MDMCFG3  3B - 
66 // MDMCFG2  73 - disable DC blocking, MSK, no Manchester code, 32 bits sync word
67 // MDMCFG1  A3 - FEC enable, 4 preamble bytes, CHANSPC_E - 03
68 // MDMCFG0  AA - CHANSPC_M - AA
69 // DEVIATN  47 - 
70 // MCSM2    07 - 
71 // MCSM1    00 - always use CCA, go to IDLE when done
72 // MCSM0    08 - disable autocalibration, PO_TIMEOUT - 64, no pin radio control, no forcing XTAL to stay in SLEEP
73 // FOCCFG   1D
74 const PROGMEM uint8_t HOTT_init_values[] = {
75   /* 00 */ 0x2F, 0x2E, 0x2F, 0x00, 0xD3, 0x91, 0x32, 0x04,
76   /* 08 */ 0x44, 0x00, 0x00, 0x09, 0x00, 0x5C, 0x6C, HOTT_FREQ0_VAL + HOTT_COARSE,
77   /* 10 */ 0x2D, 0x3B, 0x73, 0xA3, 0xAA, 0x47, 0x07, 0x00,
78   /* 18 */ 0x08, 0x1D, 0x1C, 0xC7, 0x09, 0xF0, 0x87, 0x6B,
79   /* 20 */ 0xF0, 0xB6, 0x10, 0xEA, 0x0A, 0x00, 0x11
82 static void __attribute__((unused)) HOTT_rf_init()
84         CC2500_Strobe(CC2500_SIDLE);
86         for (uint8_t i = 0; i < 39; ++i)
87                 CC2500_WriteReg(i, pgm_read_byte_near(&HOTT_init_values[i]));
89         CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
90         
91         CC2500_SetTxRxMode(TX_EN);
92         CC2500_SetPower();
95 static void __attribute__((unused)) HOTT_tune_chan()
97         CC2500_Strobe(CC2500_SIDLE);
98         CC2500_WriteReg(CC2500_0A_CHANNR, (rf_ch_num+1)*3);
99         CC2500_Strobe(CC2500_SCAL);
102 static void __attribute__((unused)) HOTT_tune_chan_fast()
104         CC2500_Strobe(CC2500_SIDLE);
105         CC2500_WriteReg(CC2500_0A_CHANNR, (rf_ch_num+1)*3);
106         CC2500_WriteReg(CC2500_25_FSCAL1, calData[rf_ch_num]);
109 static void __attribute__((unused)) HOTT_tune_freq()
111         if ( prev_option != option )
112         {
113                 CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
114                 CC2500_WriteReg(CC2500_0F_FREQ0, HOTT_FREQ0_VAL + HOTT_COARSE);
115                 prev_option = option ;
116                 phase = HOTT_START;                                                             // Restart the tune process if option is changed to get good tuned values
117         }
120 const uint8_t PROGMEM HOTT_hop[][HOTT_NUM_RF_CHANNELS]=
121         {       { 48, 37, 16, 62, 9, 50, 42, 22, 68, 0, 55, 35, 21, 74, 1, 56, 31, 20, 70, 11, 45, 32, 24, 71, 8, 54, 38, 26, 61, 13, 53, 30, 15, 65, 7, 52, 34, 28, 60, 3, 47, 39, 18, 69, 2, 49, 44, 23, 72, 5, 51, 43, 19, 64, 12, 46, 33, 17, 67, 6, 58, 36, 29, 73, 14, 57, 41, 25, 63, 4, 59, 40, 27, 66, 10 },
122                 { 50, 23, 5, 34, 67, 53, 22, 12, 39, 62, 51, 21, 10, 33, 63, 59, 16, 1, 43, 66, 49, 19, 8, 30, 71, 47, 24, 2, 35, 68, 45, 25, 14, 41, 74, 55, 18, 4, 32, 61, 54, 17, 11, 31, 72, 52, 28, 6, 38, 65, 46, 15, 9, 40, 60, 48, 26, 3, 37, 70, 58, 29, 0, 36, 64, 56, 20, 7, 42, 69, 57, 27, 13, 44, 73 },
123                 { 73, 51, 39, 18, 9, 64, 56, 34, 16, 12, 66, 58, 36, 25, 11, 61, 47, 40, 15, 8, 71, 50, 43, 20, 6, 62, 54, 42, 19, 3, 63, 46, 44, 29, 14, 72, 49, 33, 22, 5, 69, 57, 30, 21, 10, 70, 45, 35, 26, 7, 65, 59, 31, 28, 1, 67, 48, 32, 24, 0, 60, 55, 41, 17, 2, 74, 52, 38, 27, 4, 68, 53, 37, 23, 13 },
124                 { 52, 60, 40, 21, 14, 50, 72, 41, 23, 13, 59, 61, 39, 16, 6, 58, 66, 33, 17, 5, 55, 64, 43, 20, 12, 54, 74, 35, 29, 3, 46, 63, 37, 22, 10, 48, 65, 31, 27, 9, 49, 73, 38, 24, 11, 56, 70, 32, 15, 1, 51, 71, 44, 18, 8, 45, 67, 36, 25, 7, 57, 62, 34, 28, 2, 53, 69, 42, 19, 4, 47, 68, 30, 26, 0 },
125                 { 50, 16, 34, 6, 71, 51, 24, 40, 7, 68, 57, 27, 33, 14, 70, 55, 26, 30, 5, 74, 47, 28, 44, 11, 67, 49, 15, 32, 9, 61, 52, 22, 37, 13, 66, 59, 18, 42, 3, 62, 46, 29, 31, 12, 60, 48, 19, 38, 1, 72, 58, 17, 36, 4, 64, 53, 21, 39, 0, 63, 56, 20, 41, 2, 65, 45, 25, 35, 10, 69, 54, 23, 43, 8, 73 },
126                 { 55, 38, 12, 62, 23, 52, 44, 3, 66, 18, 54, 36, 10, 74, 16, 56, 42, 9, 70, 17, 58, 33, 5, 69, 20, 50, 40, 1, 63, 24, 53, 37, 13, 65, 15, 48, 34, 4, 61, 22, 57, 31, 6, 64, 26, 46, 35, 11, 72, 21, 47, 30, 7, 68, 29, 45, 32, 8, 60, 19, 49, 43, 2, 67, 27, 51, 39, 0, 71, 28, 59, 41, 14, 73, 25 },
127                 { 70, 32, 18, 10, 58, 69, 38, 22, 2, 54, 67, 36, 19, 12, 57, 62, 34, 20, 14, 52, 63, 41, 15, 3, 51, 73, 42, 28, 6, 48, 60, 43, 29, 5, 45, 64, 31, 17, 4, 56, 65, 35, 26, 13, 53, 61, 37, 23, 1, 49, 68, 40, 16, 9, 47, 71, 39, 25, 7, 50, 66, 33, 24, 8, 59, 72, 44, 27, 11, 46, 74, 30, 21, 0, 55 },
128                 { 6, 45, 71, 27, 44, 10, 46, 74, 22, 32, 0, 55, 69, 21, 33, 4, 50, 66, 18, 38, 7, 57, 62, 19, 36, 1, 48, 70, 20, 40, 8, 47, 68, 15, 43, 2, 58, 61, 26, 42, 3, 56, 72, 23, 34, 14, 54, 67, 16, 37, 5, 59, 64, 24, 30, 12, 52, 65, 25, 39, 13, 49, 73, 17, 31, 9, 53, 60, 28, 35, 11, 51, 63, 29, 41 },
129                 { 31, 65, 50, 20, 13, 37, 66, 45, 23, 5, 32, 69, 54, 19, 7, 39, 74, 52, 27, 1, 42, 64, 53, 22, 4, 43, 70, 58, 16, 3, 40, 71, 57, 17, 0, 35, 63, 56, 18, 9, 44, 72, 51, 21, 6, 33, 67, 46, 25, 11, 30, 73, 55, 15, 8, 36, 62, 48, 24, 10, 41, 60, 49, 29, 14, 34, 61, 47, 26, 2, 38, 68, 59, 28, 12 },
130                 { 67, 22, 49, 36, 13, 64, 28, 57, 37, 6, 65, 29, 46, 39, 3, 70, 26, 45, 35, 1, 62, 24, 58, 34, 10, 68, 19, 53, 33, 4, 66, 21, 52, 31, 7, 74, 18, 47, 32, 5, 61, 16, 51, 38, 8, 72, 23, 55, 30, 12, 73, 17, 59, 44, 0, 60, 15, 50, 43, 14, 63, 27, 48, 42, 11, 71, 20, 54, 41, 9, 69, 25, 56, 40, 2 },
131                 { 19, 38, 14, 66, 57, 18, 44, 7, 74, 48, 23, 30, 6, 71, 58, 26, 32, 5, 61, 46, 20, 34, 0, 68, 45, 24, 36, 1, 70, 50, 27, 33, 10, 63, 52, 16, 42, 9, 65, 51, 15, 41, 11, 64, 53, 22, 37, 3, 60, 56, 28, 35, 4, 67, 49, 17, 39, 13, 69, 54, 25, 43, 2, 73, 55, 21, 31, 8, 62, 47, 29, 40, 12, 72, 59 },
132                 { 4, 52, 64, 28, 44, 14, 46, 74, 16, 32, 11, 50, 68, 27, 36, 0, 47, 70, 26, 34, 13, 57, 61, 18, 38, 6, 56, 62, 19, 40, 5, 58, 67, 17, 31, 12, 54, 63, 22, 33, 3, 53, 72, 21, 41, 10, 48, 66, 15, 35, 7, 45, 60, 20, 37, 9, 51, 69, 25, 42, 2, 59, 71, 24, 39, 1, 55, 65, 23, 30, 8, 49, 73, 29, 43 },
133                 { 44, 66, 19, 1, 56, 35, 62, 20, 4, 54, 39, 70, 24, 5, 55, 31, 74, 26, 12, 58, 32, 60, 17, 10, 45, 37, 63, 22, 3, 50, 33, 64, 16, 7, 51, 34, 61, 21, 8, 48, 38, 68, 29, 0, 46, 36, 72, 28, 14, 49, 42, 69, 25, 6, 57, 43, 65, 18, 2, 52, 30, 71, 23, 13, 47, 41, 67, 15, 9, 53, 40, 73, 27, 11, 59 },
134                 { 12, 16, 36, 46, 69, 6, 20, 44, 58, 62, 11, 19, 34, 48, 71, 1, 18, 42, 50, 74, 3, 25, 31, 47, 65, 0, 24, 33, 45, 72, 2, 23, 35, 56, 64, 10, 22, 38, 49, 63, 7, 26, 37, 51, 70, 14, 21, 30, 53, 67, 5, 15, 40, 52, 66, 9, 17, 39, 55, 60, 13, 27, 41, 54, 73, 4, 28, 32, 57, 61, 8, 29, 43, 59, 68 },
135                 { 63, 42, 18, 2, 57, 71, 34, 22, 10, 48, 67, 36, 25, 4, 46, 60, 31, 28, 6, 47, 74, 37, 15, 0, 55, 65, 32, 24, 12, 56, 66, 40, 27, 14, 52, 62, 38, 19, 3, 50, 73, 33, 29, 11, 53, 61, 35, 16, 7, 58, 72, 41, 26, 5, 59, 69, 30, 20, 9, 51, 68, 44, 23, 1, 49, 70, 39, 17, 8, 54, 64, 43, 21, 13, 45 },
136                 { 52, 1, 71, 17, 36, 47, 7, 64, 26, 32, 53, 5, 60, 20, 42, 57, 2, 66, 18, 34, 56, 4, 63, 24, 35, 46, 13, 72, 22, 30, 48, 0, 67, 21, 39, 50, 3, 74, 16, 31, 59, 14, 61, 23, 37, 45, 6, 65, 19, 44, 51, 11, 62, 27, 41, 55, 9, 68, 15, 38, 58, 8, 70, 29, 40, 54, 10, 69, 28, 33, 49, 12, 73, 25, 43 }
137                 };
138 const uint16_t PROGMEM HOTT_hop_val[] = { 0xC06B, 0xC34A, 0xDB24, 0x8E09, 0x272E, 0x217F, 0x155B, 0xEDE8, 0x1D31, 0x0986, 0x56F7, 0x6454, 0xC42D, 0x01D2, 0xC253, 0x1180 };
140 static void __attribute__((unused)) HOTT_TXID_init()
142         packet[0] = pgm_read_word_near( &HOTT_hop_val[num_ch] );
143         packet[1] = pgm_read_word_near( &HOTT_hop_val[num_ch] )>>8;
145         for(uint8_t i=0; i<HOTT_NUM_RF_CHANNELS; i++)
146                 hopping_frequency[i]=pgm_read_byte_near( &HOTT_hop[num_ch][i] );
147         #ifdef HOTT_FORCE_ID
148                 memcpy(rx_tx_addr,"\x7C\x94\x00\x0D\x50",5);    //TX1
149                 memcpy(rx_tx_addr,"\xEA\x4D\x00\x01\x50",5);    //TX2
150         #endif
151         memset(&packet[30],0xFF,9);
152         packet[39]=0x07;                                                                        // unknown and constant
153         if(IS_BIND_IN_PROGRESS)
154         {
155                 memset(&packet[40],0xFA,5);
156                 memcpy(&packet[45],rx_tx_addr,5);
157         }
158         else
159         {
160                 memcpy(&packet[40],rx_tx_addr,5);
161                 uint16_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
162                 debug("RXID: ");
163                 for(uint8_t i=0;i<5;i++)
164                 {
165                         packet[45+i]=eeprom_read_byte((EE_ADDR)(addr+i));
166                         debug(" %02X",packet[45+i]);
167                 }
168                 debugln("");
169         }
172 static void __attribute__((unused)) HOTT_prep_data_packet() {
173         static uint8_t upper = 0;                                                               // toggles between sending channels 1..8,9..12 and 1..8,13..16
174         
175         packet[2] = hopping_frequency_no;                                               // send next frequency to be used
176         packet[3] = upper;                                                                              // indicate upper or lower channels (only supporting 16 channels)                                                                               
177         
178         #ifdef FAILSAFE_ENABLE
179                 static uint8_t failsafe_count = 0;                                      // failsafe packet state machine (need to send two packets)
181                 if(IS_FAILSAFE_VALUES_on && IS_BIND_DONE) {                     // if TX wants to send failsafe data and RX is connected
182                         failsafe_count++;                                                               // prepare to send next packet
184                         if(failsafe_count >= 3) {                                               // done sending two failsafe channel data packets
185                                 FAILSAFE_VALUES_off;                                    
186                                 failsafe_count = 0;
187                         }
188                 }
189                 else
190                         failsafe_count = 0;
191         #endif
193         // Channels value are PPM*2, -100%=1100µs, +100%=1900µs, order TAER
194         //
195         // Note: failsafe packets are differnt to normal operation packets
196         // normal operation toggles between sending channels 1..8,9..12 and 1..8,13..16 using bit0 as high/low indicator in packet[3]
197         // while failsafe packets send channels 1..12, 13..24 (and probably 25..32) using bit0 in packet[3] as packet type indicator
198         // packet[3] = 0x40 -> failsafe packet with data for channels 1..12
199         // packet[3] = 0x41 -> failsafe packet with data for channels 13..24
200         //
201         uint16_t val;
202         for(uint8_t i = 0 ; i < 12*2 ; i += 2) {                                // working 12 channels (using 2 bytes per channel)
203                 uint8_t chIndex = i >> 1 ;                                                      // normal operation channel number
204                 uint8_t fschIndex = chIndex;                                            // linear channel number for failsafe
205                 
206                 if(upper && chIndex >= 8) chIndex += 4;                         // for normal operation toggle between channels 1..8,9..12 and 1..8,13..16
207                 val = Channel_data[chIndex];                                            // get normal operation channel data
208                 val = (((val << 2) + val) >> 2)+ 860*2;                         // convert channel data 0..2047 to 1720..4278 <-> -125%<->+125%
209                                                                                                                         // val = (val*5/4+860*2)
211                 #ifdef FAILSAFE_ENABLE
212                         if(failsafe_count == 1 || failsafe_count == 2) {// failsafe data needs to be sent to RX
213                                 uint16_t fs = 0x8000;                                           // default failsafe mode is hold
215                                 if(failsafe_count == 1) {                                       // send fail safe packet containing channels 1..12
216                                         packet[3] = 0x40;                                               // indicate packet has failsafe values for channels 1..12
217                                         fs = Failsafe_data[fschIndex];                  // get failsafe channel data
218                                 } else {                                                                        // send fail safe packet containing channels 13..24
219                                         packet[3] = 0x41;                                               // indicate packet has failsafe values for channels 13..24
220                                         if(fschIndex < 4)                                               // we only work 16 channels so send channels 13..16, rest default
221                                                 fs = Failsafe_data[fschIndex+12];       // get failsafe channel data 13..16
222                                   } 
224                                 if( fs == FAILSAFE_CHANNEL_HOLD ||                      // treat HOLD and NOPULSES as channel hold 
225                                         fs == FAILSAFE_CHANNEL_NOPULSES)
226                                         val = 0x8000;                                                   // set channel failsafe mode hold flag
227                                 else {
228                                         val = (((fs << 2) + fs) >> 2) +860*2;   // convert channel data 0..2047 to 1720..4278 <-> -125%<->+125%
229                                         val |= 0x4000;                                                  // set channel failsafe mode position flag                                      
230                                 }
231                         } 
232                 #endif
234                 packet[i + 4]   = val;                                                          // first channel data at packet[4] and packet[5]
235                 packet[i + 4+1] = val >> 8;
236         }
238         upper ^= 0x01;                                                                                  // toggle to upper and lower channels
240         packet[28] = 0x80;                                                                              // no sensor
241         packet[29] = 0x02;                                                                              // 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->text config menu, 0x0A->no more RX telemetry
243         #ifdef HOTT_FW_TELEMETRY
244                 if(IS_BIND_DONE)
245                 {
246                         static uint8_t prev_SerialRX_val=0;
247                         if(HoTT_SerialRX)
248                         {//Text mode
249                                 uint8_t sensor=HoTT_SerialRX_val&0xF0;
250                                 if((sensor&0x80) && sensor!=0xF0 && (HoTT_SerialRX_val&0x0F) >= 0x07)
251                                 {//Valid Text query
252                                         if(sensor==0x80) HoTT_SerialRX_val&=0x0F;       // RX only
253                                         if(prev_SerialRX_val!=HoTT_SerialRX_val)
254                                         {
255                                                 prev_SerialRX_val=HoTT_SerialRX_val;
256                                                 packet[28] = HoTT_SerialRX_val;                 // send the button being pressed only once
257                                         }
258                                         else
259                                                 packet[28] = HoTT_SerialRX_val | 0x0F;  // no button pressed
260                                 }
261                                 else
262                                         packet[28] = 0x0F;                                                      // RX, no button pressed
263                                 if(sub_protocol == HOTT_SYNC)
264                                         packet[29] = ((HOTT_sensor_seq+1)<<3) | 1;      // Telemetry packet sequence
265                                 else
266                                         packet[29] = 0x01;                                                      // 0x01->Text config menu
267                         }
268                         else
269                         {
270                                 packet[28] = 0x89+HOTT_sensor_cur;                              // 0x89/8A/8B/8C/8D/8E during normal packets
271                                 if(sub_protocol == HOTT_SYNC)
272                                         packet[29] = ((HOTT_sensor_seq+1)<<3) | 2;      // Telemetry packet sequence
273                         }
274                         //debugln("28=%02X,29=%02X",packet[28],packet[29]);
275                 }
276         #endif
278         CC2500_WriteReg(CC2500_06_PKTLEN, HOTT_TX_PACKET_LEN);
279         CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, packet, HOTT_TX_PACKET_LEN);
280         #if 0
281                 debug("RF:%02X P:",rf_ch_num);
282                 for(uint8_t i=0;i<HOTT_TX_PACKET_LEN;i++)
283                         debug(" %02X",packet[i]);
284                 debugln("");
285         #endif
286         hopping_frequency_no++;
287         hopping_frequency_no %= HOTT_NUM_RF_CHANNELS;
288         rf_ch_num=hopping_frequency[hopping_frequency_no];
291 uint16_t HOTT_callback()
293         switch(phase)
294         {
295                 case HOTT_START:
296                         rf_ch_num = 0;
297                         HOTT_tune_chan();
298                         phase = HOTT_CAL;
299                         return 2000;
300                 case HOTT_CAL:
301                         calData[rf_ch_num]=CC2500_ReadReg(CC2500_25_FSCAL1);
302                         if (++rf_ch_num < HOTT_NUM_RF_CHANNELS)
303                                 HOTT_tune_chan();
304                         else
305                         {
306                                 hopping_frequency_no = 0;
307                                 rf_ch_num=hopping_frequency[hopping_frequency_no];
308                                 counter = 0;
309                                 CC2500_SetTxRxMode(RX_EN);
310                                 phase = HOTT_DATA1;
311                         }
312                         return 2000;
314                 /* Work cycle: 10ms */
315                 case HOTT_DATA1:
316                         //Set RF freq, setup LBT and prep packet
317                         #ifdef MULTI_SYNC
318                                 telemetry_set_input_sync(HOTT_PACKET_PERIOD);
319                         #endif
320                         //Clear all
321                         CC2500_Strobe(CC2500_SIDLE);
322                         CC2500_Strobe(CC2500_SNOP);
323                         CC2500_Strobe(CC2500_SFTX);
324                         CC2500_Strobe(CC2500_SFRX);
325                         CC2500_WriteReg(CC2500_04_SYNC1, 0xD3);
326                         CC2500_WriteReg(CC2500_05_SYNC0, 0x91);
327                         //Set RF freq
328                         HOTT_tune_freq();
329                         HOTT_tune_chan_fast();
330                         //Setup LBT
331                         CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xFF);
332                         CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x0C);
333                         CC2500_Strobe(CC2500_SRX);
334                         //Prep packet
335                         HOTT_prep_data_packet();
336                         //Listen
337                         CC2500_WriteReg(CC2500_17_MCSM1, 0x10);         //??
338                         CC2500_WriteReg(CC2500_18_MCSM0, 0x18);         //??
339                         CC2500_Strobe(CC2500_SRX);                                      //??
340                         phase++;                //HOTT_DATA2
341                         return 1095;
342                 case HOTT_DATA2:
343                         //LBT
344                         if((CC2500_ReadReg(CC2500_38_PKTSTATUS | CC2500_READ_BURST)&0x10)==0)
345                         { //Channel is busy
346                                 LBT_POWER_on;                                                                           // Reduce to low power before transmitting
347                                 debugln("Busy %d",rf_ch_num);
348                         }
349                         CC2500_WriteReg(CC2500_17_MCSM1, 0x00);         //??
350                         CC2500_WriteReg(CC2500_18_MCSM0, 0x08);         //??
351                         CC2500_SetPower();
352                         //Send packet
353                         CC2500_SetTxRxMode(TX_EN);
354                         CC2500_Strobe(CC2500_STX);
355                         phase++;                //HOTT_RX1
356                         return 3880;
357                 case HOTT_RX1:
358                         //Clear all
359                         CC2500_Strobe(CC2500_SIDLE);
360                         CC2500_Strobe(CC2500_SFTX);
361                         CC2500_Strobe(CC2500_SFRX);
362                         //RX
363                         if(packet[29] & 0xF8)
364                         {// Sync telemetry
365                                 CC2500_WriteReg(CC2500_04_SYNC1, 0x2C);
366                                 CC2500_WriteReg(CC2500_05_SYNC0, 0x6E);
367                         }
368                         CC2500_SetTxRxMode(RX_EN);
369                         CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7);
370                         CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x09);
371                         CC2500_WriteReg(CC2500_06_PKTLEN, HOTT_RX_PACKET_LEN);
372                         CC2500_Strobe(CC2500_SRX);
373                         phase++;                //HOTT_RX2
374                         return 4025;
375                 case HOTT_RX2:
376                         //Telemetry
377                         len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
378                         if (len==HOTT_RX_PACKET_LEN+2)
379                         {
380                                 CC2500_ReadData(packet_in, len);
381                                 if((packet_in[HOTT_RX_PACKET_LEN+1]&0x80) && memcmp(rx_tx_addr,packet_in,5)==0)
382                                 { // CRC OK and TX ID matches
383                                         if(IS_BIND_IN_PROGRESS)
384                                         {
385                                                 //GR-16:  D4 20 F2 E6 F6 31 BD 01 00 90 00 FF 03 00 9E 1B 00 00 00 00 00 00
386                                                 //GR-12L: D4 20 F2 E6 F6 6E EE 01 00 B1 00 FF 03 00 0E 08 10 00 02 00 00 00
387                                                 //Vector: D4 20 F2 E6 F6 00 00 3A 01 A1 00 00 1A 24 35 1A 00 24 00 00 00 1A
388                                                 //        -----TXID----- -----RXID----- ---------------Unknown-------------
389                                                 debug("B:");
390                                                 for(uint8_t i=0;i<HOTT_RX_PACKET_LEN;i++)
391                                                         debug(" %02X", packet_in[i]);
392                                                 debugln("");
393                                                 uint16_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
394                                                 for(uint8_t i=0; i<5; i++)
395                                                         eeprom_write_byte((EE_ADDR)(addr+i),packet_in[5+i]);
396                                                 BIND_DONE;
397                                                 HOTT_TXID_init();
398                                         }
399                                         #ifdef HOTT_FW_TELEMETRY
400                                                 else
401                                                 {       //Telemetry
402                                                         // [0..4] = TXID
403                                                         // [5..9] = RXID
404                                                         // [10] = holds warnings issued by hott devices
405                                                         // [11] = telmetry pages. For sensors 0x00 to 0x04, for config mennu 0x00 to 0x12.
406                                                         // Normal telem page 0 = 0x55, 0x32, 0x38, 0x55, 0x64, 0x32, 0xD0, 0x07, 0x00, 0x55
407                                                         //   Page 0 [12] = [21] = [15]
408                                                         //   Page 0 [13] = RX_Voltage Cur*10 in V
409                                                         //   Page 0 [14] = Temperature-20 in °C
410                                                         //   Page 0 [15] = RX_RSSI CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
411                                                         //   Page 0 [16] = RX_LQI in %
412                                                         //   Page 0 [17] = RX_Voltage Min*10 in V
413                                                         //   Page 0 [18,19] = [19]<<8+[18]=max lost packet time in ms, max value seems 2s=0x7D0
414                                                         //   Page 0 [20] = rx events
415                                                         //
416                                                         // Config menu consists of the different telem pages put all together
417                                                         //   Page X [12] = seems like all the telem pages with the same value are going together to make the full config menu text. Seen so far 'a', 'b', 'c', 'd' 
418                                                         //   Page X [13..21] = 9 ascii chars to be displayed, char is highlighted when ascii|0x80
419                                                         //   Screen display is 21 characters large which means that once the first 21 chars are filled go to the begining of the next line
420                                                         //   Menu commands are sent through TX packets:
421                                                         //     packet[28]= 0xXF=>no key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0 or D
422                                                         //     packet[29]= 0xX1/0xX9 with X=0 or X counting 0,1,1,2,2,..,9,9
423                                                         // Reduce telemetry to 14 bytes
424                                                         packet_in[0]= packet_in[HOTT_RX_PACKET_LEN];
425                                                         packet_in[1]= TX_LQI;
426                                                         uint8_t hott_warnings = packet_in[10];                                          // save warnings from hott devices
427                                                         bool send_telem=true;
428                                                         HOTT_sensor_seq++;                                                                                      // Increment RX sequence counter
429                                                         if(packet[29] & 1)
430                                                         { //Text mode
431                                                                 HOTT_sensor_seq %= 19;                                                                  // 19 pages in Text mode
432                                                                 HOTT_sensor_pages = 0;
433                                                                 HOTT_sensor_valid = false;
434                                                                 packet_in[10] = 0x80;                                                                   // Marking telem Text mode
435                                                                 packet_in[12] = 0;
436                                                                 for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
437                                                                         packet_in[12] |= HOTT_sensor_ok[i]<<i;                          // Send detected sensors
438                                                         }
439                                                         else
440                                                         { //Binary sensor
441                                                                 HOTT_sensor_seq %= 5;                                                                   // 5 pages in binary mode per sensor
442                                                                 if(state==0 && HOTT_sensor_ok[0]==false && HOTT_sensor_ok[1]==false && HOTT_sensor_ok[2]==false && HOTT_sensor_ok[3]==false && HOTT_sensor_ok[4]==false && HOTT_sensor_ok[5]==false)
443                                                                         HOTT_sensor_seq=0;                                                                      // No sensors always ask page 0
444                                                                 if(state)
445                                                                         state--;
446                                                                 if( packet_in[11]==1 )                                                                  // Page 1
447                                                                 {
448                                                                         if( packet_in[12] == (HOTT_sensor_cur+9)<<4 )
449                                                                         { //Requested sensor is sending: 0x90/A0/B0/C0/D0/E0
450                                                                                 HOTT_sensor_pages = 0;                                                  // Sensor first page received
451                                                                                 HOTT_sensor_valid = true;                                               // Data from the expected sensor is being received
452                                                                                 HOTT_sensor_ok[(packet_in[12]>>4)-9]=true;                                      
453                                                                         }
454                                                                         else
455                                                                         {
456                                                                                 HOTT_sensor_valid = false;
457                                                                                 HOTT_sensor_pages = 0x1E;                                               // Switch to next sensor
458                                                                         }
459                                                                 }
460                                                                 if(packet_in[11])
461                                                                 { //Page != 0
462                                                                         if(HOTT_sensor_valid)                                                           // Valid
463                                                                         {
464                                                                                 packet_in[10] = HOTT_sensor_cur+9;                              // Mark telem with sensor ID
465                                                                                 HOTT_sensor_pages |= 1<<packet_in[11];                  // Page received
466                                                                         }
467                                                                         else
468                                                                                 send_telem=false;                                                               // Do not send
469                                                                 }
470                                                                 else
471                                                                         packet_in[10]=0;                                                                        // Mark telem with sensor 0=RX
472                                                         }
473                                                         debug("T%d=",send_telem);
474                                                         for(uint8_t i=10;i < HOTT_RX_PACKET_LEN; i++)
475                                                         {
476                                                                 packet_in[i-8]=packet_in[i];
477                                                                 debug(" %02X",packet_in[i]);
478                                                         }
479                                                         packet_in[14] = hott_warnings;                                                          // restore saved warnings from hott devices
480                                                         debugln("");
481                                                         if(send_telem)
482                                                                 telemetry_link=2;
483                                                         if((HOTT_sensor_pages&0x1E) == 0x1E)                                            // All 4 pages received from the sensor
484                                                         { //Next sensor
485                                                                 uint8_t loop=0;
486                                                                 do
487                                                                 {
488                                                                         HOTT_sensor_cur++;                                                                      // Switch to next sensor
489                                                                         HOTT_sensor_cur %= HOTT_SENSOR_TYPE;
490                                                                         loop++;
491                                                                 }
492                                                                 while(HOTT_sensor_ok[HOTT_sensor_cur]==false && loop<HOTT_SENSOR_TYPE+1 && state==0);
493                                                                 HOTT_sensor_valid=false;
494                                                                 HOTT_sensor_pages=0;
495                                                                 HOTT_sensor_seq=0;
496                                                                 debugln("Sensor:%02X",HOTT_sensor_cur+9);
497                                                         }                                                                               
498                                                 }
499                                                 pps_counter++;
500                                         #endif
501                                 }
502                         }
503                         #ifdef HOTT_FW_TELEMETRY
504                                 packet_count++;
505                                 if(packet_count>=100)
506                                 {
507                                         TX_LQI=pps_counter;
508                                         if(pps_counter==0)
509                                         { // lost connection with RX, power cycle? research sensors again.
510                                                 HOTT_sensor_cur=3;
511                                                 HOTT_sensor_seq=0;
512                                                 HOTT_sensor_valid=false;
513                                                 for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
514                                                         HOTT_sensor_ok[i]=false;        // no sensors detected
515                                                 state=HOTT_SENSOR_SEARCH_PERIOD;
516                                         }
517                                         pps_counter=packet_count=0;
518                                 }
519                         #endif
520                         phase=HOTT_DATA1;
521                         return 1000;
522         }
523         return 0;
526 void HOTT_init()
528         num_ch=random(0xfefefefe)%16;
529         HOTT_TXID_init();
530         HOTT_rf_init();
531         #ifdef HOTT_FW_TELEMETRY
532                 HoTT_SerialRX_val=0;
533                 HoTT_SerialRX=false;
534                 HOTT_sensor_cur=3;
535                 HOTT_sensor_pages=0;
536                 HOTT_sensor_valid=false;
537                 HOTT_sensor_seq=0;
538                 for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
539                         HOTT_sensor_ok[i]=false;        // no sensors detected
540                 packet_count=0;
541                 state=HOTT_SENSOR_SEARCH_PERIOD;
542         #endif
543         phase = HOTT_START;
546 #endif