@@ -20,6 +20,7 @@ Multiprotocol is distributed in the hope that it will be useful,
20
20
21
21
// #define FORCE_KF606_ORIGINAL_ID
22
22
// #define FORCE_MIG320_ORIGINAL_ID
23
+ // #define FORCE_ZCZ50_ORIGINAL_ID
23
24
24
25
#define KF606_INITIAL_WAIT 500
25
26
#define KF606_PACKET_PERIOD 3000
@@ -30,10 +31,16 @@ Multiprotocol is distributed in the hope that it will be useful,
30
31
31
32
static void __attribute__ ((unused)) KF606_send_packet()
32
33
{
34
+ uint8_t len = KF606_PAYLOAD_SIZE;
33
35
if (IS_BIND_IN_PROGRESS)
34
36
{
35
- packet[0 ] = 0xAA ;
36
- memcpy (&packet[1 ],rx_tx_addr,3 );
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 );
37
44
}
38
45
else
39
46
{
@@ -43,25 +50,32 @@ static void __attribute__((unused)) KF606_send_packet()
43
50
packet[0 ] = 0x55 ;
44
51
packet[1 ] = convert_channel_8b (THROTTLE); // 0..255
45
52
// Deadband is needed on aileron, 40 gives +-6%
46
- if (sub_protocol == KF606_KF606 )
53
+ switch (sub_protocol)
47
54
{
48
- 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
49
- packet[3 ] = convert_channel_16b_limit (CH5,0xC1 ,0xDF ); // Aileron trim must be on a separated channel C1..D0..DF
50
- }
51
- else
52
- {
53
- packet[2 ] = convert_channel_8b_limit_deadband (AILERON,0x00 ,0x80 ,0xFF ,40 ); // Aileron: High rate:2B..80..DA
54
- packet[3 ] = convert_channel_16b_limit (CH5,0x01 ,0x1F ); // Aileron trim must be on a separated channel 01..10..1F
55
- packet[3 ] += (packet[2 ]-0x80 )>>3 ; // Drive trims for more aileron authority
56
- if (packet[3 ] > 0x80 )
57
- packet[3 ] = 0x01 ;
58
- else if (packet[3 ] > 0x1F )
59
- packet[3 ] = 0x1F ;
60
- packet[3 ] |= GET_FLAG (CH6_SW, 0xC0 ); // 0xC0 and 0xE0 are both turning the LED off, not sure if there is another hidden feature
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 ;
61
76
}
62
77
}
63
78
64
- uint8_t len = KF606_PAYLOAD_SIZE;
65
79
if (sub_protocol == KF606_MIG320)
66
80
{
67
81
len++;
@@ -107,6 +121,19 @@ static void __attribute__((unused)) KF606_initialize_txid()
107
121
hopping_frequency[0 ]=68 ;
108
122
hopping_frequency[1 ]=71 ;
109
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
110
137
}
111
138
112
139
static void __attribute__ ((unused)) KF606_RF_init()
@@ -126,7 +153,7 @@ uint16_t KF606_callback()
126
153
if (--bind_counter==0 )
127
154
{
128
155
BIND_DONE;
129
- XN297_SetTXAddr (rx_tx_addr, 3 );
156
+ XN297_SetTXAddr (rx_tx_addr, sub_protocol != KF606_ZCZ50 ? 3 : 4 );
130
157
}
131
158
KF606_send_packet ();
132
159
return KF606_PACKET_PERIOD;
@@ -153,3 +180,14 @@ void KF606_init()
153
180
// P[2] = AIL 2B..80..DA
154
181
// P[3] = TRIM 01..10..1F
155
182
// channels 68=BB&3F+9 and 71
183
+
184
+
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
0 commit comments