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/>.
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)
37 if(sub_protocol != KF606_ZCZ50)
40 memcpy(&packet[1],rx_tx_addr,3);
43 memcpy(packet,rx_tx_addr,4);
47 XN297_Hopping(hopping_frequency_no);
48 hopping_frequency_no ^= 1; // 2 RF channels
51 packet[1] = convert_channel_8b(THROTTLE); // 0..255
52 // Deadband is needed on aileron, 40 gives +-6%
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
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
65 else if(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
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?
79 if(sub_protocol == KF606_MIG320)
82 packet[4] = 0; // additional channel?
86 for(uint8_t i=0; i<len; i++)
87 debug("%02X ",packet[i]);
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
108 hopping_frequency[0]=0x20;
109 hopping_frequency[1]=0x23;
114 hopping_frequency[0]=0x2E;
115 hopping_frequency[1]=0x31;
117 #ifdef FORCE_MIG320_ORIGINAL_ID
121 hopping_frequency[0]=68;
122 hopping_frequency[1]=71;
124 if(sub_protocol == KF606_ZCZ50)
126 rx_tx_addr[1] = rx_tx_addr[0];
129 #ifdef FORCE_ZCZ50_ORIGINAL_ID
134 hopping_frequency[0]=48;
135 hopping_frequency[1]=51;
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()
150 telemetry_set_input_sync(KF606_PACKET_PERIOD);
153 if(--bind_counter==0)
156 XN297_SetTXAddr(rx_tx_addr, sub_protocol != KF606_ZCZ50 ? 3 : 4);
159 return KF606_PACKET_PERIOD;
164 BIND_IN_PROGRESS; // autobind protocol
165 KF606_initialize_txid();
167 hopping_frequency_no = 0;
168 bind_counter=KF606_BIND_COUNT;
175 // 250K C=7 S=Y A= E7 E7 E7 E7 E7 P(5)= AA BB 13 00 00
178 // 250K C=68 S=Y A= BB 13 00 P(5)= 55 00 80 10 00
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)
187 // 250K C=7 S=Y A= E7 E7 E7 E7 E7 P(4)= AA 67 64 01
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