Traxxas TQ 1st gen: try 5
[DIY-Multiprotocol-TX-Module.git] / Multiprotocol / H8_3D_nrf24l01.ino
blobeb7a3b0b09df7aa5a6c052bfb1ac2d139df5959f
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  */
15 // compatible with EAchine 3D X4, CG023/CG031, Attop YD-822/YD-829/YD-829C and H8_3D/JJRC H20/H22
16 // Merged CG023 and H8_3D protocols
17 // Last sync with hexfet new_protocols/cg023_nrf24l01.c dated 2015-10-03
18 // Last sync with hexfet new_protocols/h8_3d_nrf24l01.c dated 2015-11-18
20 #if defined(H8_3D_NRF24L01_INO)
22 #include "iface_xn297.h"
24 #define H8_3D_PACKET_PERIOD             1800
25 #define H20H_PACKET_PERIOD              9340
26 #define H20MINI_PACKET_PERIOD   3100
27 #define H8_3D_INITIAL_WAIT              500
28 #define H8_3D_PACKET_SIZE               20
29 #define H8_3D_RF_NUM_CHANNELS   4
30 #define H20H_BIND_RF                    0x49
31 #define H8_3D_BIND_COUNT                1000
33 enum H8_3D_FLAGS {
34     // flags going to packet[17]
35     H8_3D_FLAG_FLIP      = 0x01,
36     H8_3D_FLAG_RATE_MID  = 0x02,
37     H8_3D_FLAG_RATE_HIGH = 0x04,
38     H8_3D_FLAG_LIGTH     = 0x08, // Light on H22
39     H8_3D_FLAG_HEADLESS  = 0x10, // RTH + headless on H8, headless on JJRC H20, RTH on H22
40     H8_3D_FLAG_RTH               = 0x20, // 360 flip mode on H8 3D and H22, RTH on JJRC H20
43 enum H8_3D_FLAGS_2 {
44     // flags going to packet[18]
45     H8_3D_FLAG_VIDEO      = 0x80,
46     H8_3D_FLAG_PICTURE    = 0x40,
47     H8_3D_FLAG_CALIBRATE1 = 0x20,  // H8 3D acc calibration, H20,H20H headless calib
48     H8_3D_FLAG_CALIBRATE2 = 0x10,  // H11D, H20, H20H acc calibration
49     H8_3D_FLAG_CAM_DN     = 0x08,
50     H8_3D_FLAG_CAM_UP     = 0x04,
53 static void __attribute__((unused)) H8_3D_send_packet()
55         if(sub_protocol==H20H)
56                 packet[0] = 0x14;
57         else // H8_3D, H20MINI, H30MINI
58                 packet[0] = 0x13;
60         packet[1] = rx_tx_addr[0]; 
61         packet[2] = rx_tx_addr[1];
62         packet[3] = rx_tx_addr[2];
63         packet[4] = rx_tx_addr[3];
64         packet[8] = rx_tx_addr[0]+rx_tx_addr[1]+rx_tx_addr[2]+rx_tx_addr[3]; // txid checksum
65         memset(&packet[9], 0, 10);
66         if (IS_BIND_IN_PROGRESS)
67         {    
68                 packet[5] = 0x00;
69                 packet[6] = 0x00;
70                 packet[7] = 0x01;
71         }
72         else
73         {
74                 packet[5] = hopping_frequency_no;
75                 packet[7] = 0x03;
77                 rudder = convert_channel_16b_limit(RUDDER,0x44,0xBC);                   // yaw right : 0x80 (neutral) - 0xBC (right)
78                 if(sub_protocol!=H20H)
79                 { // H8_3D, H20MINI, H30MINI
80                         packet[6] = 0x08;
81                         packet[9] = convert_channel_8b(THROTTLE);                                       // throttle  : 0x00 - 0xFF
82                         packet[15] = 0x20;      // trims
83                         packet[16] = 0x20;      // trims
84                         if (rudder<=0x80)
85                                 rudder=0x80-rudder;                                                                             // yaw left  : 0x00 (neutral) - 0x3C (left)
86                         if(rudder==0x01 || rudder==0x81)
87                                 rudder=0x00;    // Small deadband
88                 }
89                 else
90                 { //H20H
91                         packet[6] = hopping_frequency_no == 0 ? 8 - packet_count : 16 - packet_count;
92                         packet[9] = convert_channel_16b_limit(THROTTLE, 0x43, 0xBB);    // throttle : 0x43 - 0x7F - 0xBB
93                         packet[15]= 0x40;       // trims
94                         packet[16]= 0x40;       // trims
95                         rudder--;                                                                                                       // rudder : 0x43 - 0x7F - 0xBB
96                         if (rudder>=0x7F-1 && rudder<=0x7F+1)
97                                 rudder=0x7F;    // Small deadband
98                 }
99                 packet[10] = rudder;
100                 packet[11] = convert_channel_16b_limit(ELEVATOR, 0x43, 0xBB);   // elevator : 0x43 - 0x7F - 0xBB
101                 packet[12] = convert_channel_16b_limit(AILERON,  0x43, 0xBB);   // aileron  : 0x43 - 0x7F - 0xBB
102                 // neutral trims
103                 packet[13] = 0x20;
104                 packet[14] = 0x20;
105                 // flags
106                 packet[17] =                                      H8_3D_FLAG_RATE_HIGH
107                                         | GET_FLAG(CH5_SW,H8_3D_FLAG_FLIP)
108                                         | GET_FLAG(CH6_SW,H8_3D_FLAG_LIGTH) //H22 light
109                                         | GET_FLAG(CH9_SW,H8_3D_FLAG_HEADLESS)
110                                         | GET_FLAG(CH10_SW,H8_3D_FLAG_RTH); // 180/360 flip mode on H8 3D
111                 packet[18] =  GET_FLAG(CH7_SW,H8_3D_FLAG_PICTURE)
112                                         | GET_FLAG(CH8_SW,H8_3D_FLAG_VIDEO)
113                                         | GET_FLAG(CH11_SW,H8_3D_FLAG_CALIBRATE1)
114                                         | GET_FLAG(CH12_SW,H8_3D_FLAG_CALIBRATE2);
115                 if(Channel_data[CH13]<CHANNEL_MIN_COMMAND)
116                         packet[18] |= H8_3D_FLAG_CAM_DN;
117                 if(CH13_SW)
118                         packet[18] |= H8_3D_FLAG_CAM_UP;
119         }
120         uint8_t  sum = packet[9];
121         for (uint8_t i=10; i < H8_3D_PACKET_SIZE-1; i++)
122                 sum += packet[i];
123         packet[19] = sum; // data checksum
124         
125         // RF channel
126         if(sub_protocol!=H20H)
127         { // H8_3D, H20MINI, H30MINI
128                 XN297_RFChannel(IS_BIND_IN_PROGRESS ? hopping_frequency[0] : hopping_frequency[hopping_frequency_no++]);
129                 hopping_frequency_no %= H8_3D_RF_NUM_CHANNELS;
130         }
131         else
132         { // H20H
133                 XN297_RFChannel(IS_BIND_IN_PROGRESS ? H20H_BIND_RF : hopping_frequency[packet_count>>3]);  
134                 if(IS_BIND_DONE)
135                 {
136                         packet_count++;
137                         if(packet_count>15)
138                         {
139                                 packet_count = 0;
140                                 hopping_frequency_no = 0;
141                         }
142                         else
143                                 if(packet_count > 7)
144                                         hopping_frequency_no = 1;
145                 }
146         }
147         
148         // Send
149         XN297_SetPower();
150         XN297_SetTxRxMode(TX_EN);
151         XN297_WritePayload(packet, H8_3D_PACKET_SIZE);
154 static void __attribute__((unused)) H8_3D_RF_init()
156         XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
158         if(sub_protocol==H20H)
159                 XN297_SetTXAddr((uint8_t *)"\xEE\xDD\xCC\xBB\x11", 5);
160         else // H8_3D, H20MINI, H30MINI
161                 XN297_SetTXAddr((uint8_t *)"\xC4\x57\x09\x65\x21", 5);
164 uint16_t H8_3D_callback()
166         if(bind_counter)
167         {
168                 bind_counter--;
169                 if (bind_counter == 0)
170                 {
171                         BIND_DONE;
172                         packet_count=0;
173                 }
174         }
175         #ifdef MULTI_SYNC
176         else
177                 telemetry_set_input_sync(packet_period);
178         #endif
180         H8_3D_send_packet();
181         return  packet_period;
184 // captured from H20H stock transmitters
185 const uint8_t PROGMEM h20h_tx_rf_map[3][6] = {{/*ID*/0x83, 0x3c, 0x60, 0x00, /*RF*/0x47, 0x3e},
186                                                                                           {/*ID*/0x5c, 0x2b, 0x60, 0x00, /*RF*/0x4a, 0x3c},
187                                                                                           {/*ID*/0x57, 0x07, 0x00, 0x00, /*RF*/0x41, 0x48} };
188 // captured from H20 Mini / H30 Mini stock transmitters
189 const uint8_t PROGMEM h20mini_tx_rf_map[4][8] =  {{/*ID*/0xb4, 0xbb, 0x09, 0x00, /*RF*/0x3e, 0x45, 0x47, 0x4a},
190                                                                                                   {/*ID*/0x94, 0x9d, 0x0b, 0x00, /*RF*/0x3e, 0x43, 0x49, 0x4a},
191                                                                                                   {/*ID*/0xd1, 0xd0, 0x00, 0x00, /*RF*/0x3f, 0x42, 0x46, 0x4a},
192                                                                                                   {/*ID*/0xcb, 0xcd, 0x04, 0x00, /*RF*/0x41, 0x43, 0x46, 0x4a}};
193 static void __attribute__((unused)) H8_3D_initialize_txid()
195         uint8_t id_num=rx_tx_addr[4];
196         switch(sub_protocol)
197         {
198                 case H8_3D:
199             for(uint8_t i=0; i<4; i++)
200                 hopping_frequency[i] = 6 + (0x0f*i) + (((rx_tx_addr[i] >> 4) + (rx_tx_addr[i] & 0x0f)) % 0x0f);
201                         break;
202                 case H20H:
203             id_num%=3; // 3 different IDs
204                         for(uint8_t i=0; i<4; i++)
205                         {
206                                 rx_tx_addr[i] = pgm_read_byte_near(&h20h_tx_rf_map[id_num][i]);
207                                 if(i<2)
208                                         hopping_frequency[i] = pgm_read_byte_near(&h20h_tx_rf_map[id_num][i+4]);
209                         }
210                         break;
211                 case H20MINI:
212                 case H30MINI:
213             id_num%=4; // 4 different IDs
214                         for(uint8_t i=0; i<4; i++)
215                         {
216                                 rx_tx_addr[i] = pgm_read_byte_near(&h20mini_tx_rf_map[id_num][i]);
217                                 hopping_frequency[i] = pgm_read_byte_near(&h20mini_tx_rf_map[id_num][i+4]);
218                         }
219                         break;
220         }
223 void H8_3D_init(void)
225         BIND_IN_PROGRESS;       // autobind protocol
226     bind_counter = H8_3D_BIND_COUNT;
227         H8_3D_initialize_txid();
228         H8_3D_RF_init();
229         switch(sub_protocol)
230         {
231         case H8_3D:
232                         packet_period=H8_3D_PACKET_PERIOD;
233                         break;
234                 case H20H:
235                         packet_period=H20H_PACKET_PERIOD;
236                         break;
237                 case H20MINI:
238                 case H30MINI:
239                         packet_period=H20MINI_PACKET_PERIOD;
240                         break;
241         }
244 #endif