Traxxas TQ 1st gen: try 5
[DIY-Multiprotocol-TX-Module.git] / Multiprotocol / KF606_ccnrf.ino
blob516451a58880de7ea08fd39ca9cce1bf8979a2fe
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 KF606 plane.
17 #if defined(KF606_CCNRF_INO)
19 #include "iface_xn297.h"
21 //#define FORCE_KF606_ORIGINAL_ID
22 //#define FORCE_MIG320_ORIGINAL_ID
23 //#define FORCE_ZCZ50_ORIGINAL_ID
25 #define KF606_INITIAL_WAIT    500
26 #define KF606_PACKET_PERIOD   3000
27 #define KF606_RF_BIND_CHANNEL 7
28 #define KF606_PAYLOAD_SIZE    4
29 #define KF606_BIND_COUNT          857   //3sec
30 #define KF606_RF_NUM_CHANNELS 2
32 static void __attribute__((unused)) KF606_send_packet()
34         uint8_t len = KF606_PAYLOAD_SIZE;
35         if(IS_BIND_IN_PROGRESS)
36         {
37                 if(sub_protocol != KF606_ZCZ50)
38                 {
39                         packet[0] = 0xAA;
40                         memcpy(&packet[1],rx_tx_addr,3);
41                 }
42                 else
43                         memcpy(packet,rx_tx_addr,4);
44         }
45         else
46         {
47                 XN297_Hopping(hopping_frequency_no);
48                 hopping_frequency_no ^= 1;                      // 2 RF channels
50                 packet[0] = 0x55;
51                 packet[1] = convert_channel_8b(THROTTLE);                                       // 0..255
52                 // Deadband is needed on aileron, 40 gives +-6%
53                 switch(sub_protocol)
54                 {
55                         case KF606_KF606:
56                                 packet[2] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40);       // Aileron: Max values:20..80..E0, Low rates:50..80..AF, High rates:3E..80..C1
57                                 packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF);                                           // Aileron trim must be on a separated channel C1..D0..DF
58                                 break;
59                         case KF606_MIG320:
60                                 packet[2] = convert_channel_8b_limit_deadband(AILERON,0x00,0x80,0xFF,40);       // Aileron: High rate:2B..80..DA
61                                 packet[3] = convert_channel_16b_limit(CH5,0x01,0x1F);                                           // Aileron trim must be on a separated channel 01..10..1F
62                                 packet[3] += (packet[2]-0x80)>>3;                                                                                       // Drive trims for more aileron authority
63                                 if(packet[3] > 0x80)
64                                         packet[3] = 0x01;
65                                 else if(packet[3] > 0x1F)
66                                         packet[3] = 0x1F;
67                                 packet[3] |= GET_FLAG(CH6_SW, 0xC0);                                                                            // 0xC0 and 0xE0 are both turning the LED off, not sure if there is another hidden feature
68                                 break;
69                         case KF606_ZCZ50:
70                                 len--;                                                                                                                                          // uses only 3 bytes of payload
71                                 packet[0] = packet[1];                                                                                                          // Throttle: 0x00..0xFF
72                                 packet[1] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40);       // Aileron: Max values:20..80..E0, low rate 0x52..0x80..0xB1, high rate: 0x41..0x80..0xC3.
73                                 packet[2] = convert_channel_16b_limit(CH5,0x01,0x1F);                                           // Trim: 0x01..0x10..0x1F
74                                 packet[2] |= GET_FLAG(CH6_SW, 0xC0);                                                                            // Unknown: 0x00 or 0xC0. Left top switch on original TX changes nothing on my plane. Maybe ON/OFF for main motor?
75                                 break;
76                 }
77         }
79         if(sub_protocol == KF606_MIG320)
80         {
81                 len++;
82                 packet[4] = 0;  // additional channel?
83         }
85         #if 0
86                 for(uint8_t i=0; i<len; i++)
87                         debug("%02X ",packet[i]);
88                 debugln("");
89         #endif
91         // Send
92         XN297_SetPower();
93         XN297_SetFreqOffset();
94         XN297_SetTxRxMode(TX_EN);
95         XN297_WritePayload(packet, len);
98 static void __attribute__((unused)) KF606_initialize_txid()
100         rx_tx_addr[0]=rx_tx_addr[3];    // Use RX_num;
101         hopping_frequency[0]=(rx_tx_addr[0]&0x3F)+9;
102         hopping_frequency[1]=hopping_frequency[0]+3;
103         #ifdef FORCE_KF606_ORIGINAL_ID
104                 //TX1
105                 rx_tx_addr[0]=0x57;
106                 rx_tx_addr[1]=0x02;
107                 rx_tx_addr[2]=0x00;
108                 hopping_frequency[0]=0x20;
109                 hopping_frequency[1]=0x23;
110                 //TX2
111                 rx_tx_addr[0]=0x25;
112                 rx_tx_addr[1]=0x04;
113                 rx_tx_addr[2]=0x00;
114                 hopping_frequency[0]=0x2E;
115                 hopping_frequency[1]=0x31;
116         #endif
117         #ifdef FORCE_MIG320_ORIGINAL_ID
118                 rx_tx_addr[0]=0xBB;
119                 rx_tx_addr[1]=0x13;
120                 rx_tx_addr[2]=0x00;
121                 hopping_frequency[0]=68;
122                 hopping_frequency[1]=71;
123         #endif
124         if(sub_protocol == KF606_ZCZ50)
125         {
126                 rx_tx_addr[1] = rx_tx_addr[0];
127                 rx_tx_addr[0]=0xAA;
128         }
129         #ifdef FORCE_ZCZ50_ORIGINAL_ID
130                 rx_tx_addr[0]=0xAA;
131                 rx_tx_addr[1]=0x67;
132                 rx_tx_addr[2]=0x64;
133                 rx_tx_addr[3]=0x01;
134                 hopping_frequency[0]=48;
135                 hopping_frequency[1]=51;
136         #endif
139 static void __attribute__((unused)) KF606_RF_init()
141         XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
142         XN297_SetTXAddr((uint8_t*)"\xe7\xe7\xe7\xe7\xe7", 5);
143         XN297_HoppingCalib(KF606_RF_NUM_CHANNELS);                                      // Calibrate all channels
144         XN297_RFChannel(KF606_RF_BIND_CHANNEL);                                         // Set bind channel
147 uint16_t KF606_callback()
149         #ifdef MULTI_SYNC
150                 telemetry_set_input_sync(KF606_PACKET_PERIOD);
151         #endif
152         if(bind_counter)
153                 if(--bind_counter==0)
154                 {
155                         BIND_DONE;
156                         XN297_SetTXAddr(rx_tx_addr, sub_protocol != KF606_ZCZ50 ? 3 : 4);
157                 }
158         KF606_send_packet();
159         return KF606_PACKET_PERIOD;
162 void KF606_init()
164         BIND_IN_PROGRESS;       // autobind protocol
165         KF606_initialize_txid();
166         KF606_RF_init();
167         hopping_frequency_no = 0;
168         bind_counter=KF606_BIND_COUNT;
171 #endif
173 // MIG320 protocol
174 // Bind
175 // 250K C=7 S=Y A= E7 E7 E7 E7 E7 P(5)= AA BB 13 00 00
176 // 3ms on ch7
177 // Normal
178 // 250K C=68 S=Y A= BB 13 00 P(5)= 55 00 80 10 00
179 // P[1] = THR 00..FF
180 // P[2] = AIL 2B..80..DA
181 // P[3] = TRIM 01..10..1F
182 // channels 68=BB&3F+9 and 71
185 // ZCZ50v2 protocol (with fake front propeller)
186 // Bind
187 // 250K C=7 S=Y A= E7 E7 E7 E7 E7 P(4)= AA 67 64 01
188 // 3ms on ch7
189 // Normal
190 // 250K C=48 S=Y A= AA 67 64 01 P(3)= 00 80 10
191 // P[0] = THR 0x00..0xFF
192 // P[1] = AIL low rate 0x52..0x80..0xB1, high rate: 0x41..0x80..0xC3
193 // P[2] = TRIM 0x01..0x10..0x1F + UNKNOWN 0x00 or 0xC0