Skip to content

Commit 4639789

Browse files
committed
Ares: new protocol
ARES Gamma 370, P-51D Mustang 350, RTF models with 6HPA-Tx and AZS12006-Rx (6 channel).
1 parent 0a7f74d commit 4639789

10 files changed

Lines changed: 306 additions & 6 deletions

File tree

Lua_scripts/MultiChan.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,4 @@
241241
105,0,Shenqi2,Std,1
242242
106,0,WL91x,Std,0
243243
107,0,WPL,Std,0,Light,TH_DR,ST_DR
244+
108,0,Ares,6HPA_Tx,0,CH5,CH6

Multiprotocol/Ares_cc2500.ino

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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.
6+
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.
11+
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 ARES 6HPA transmitter
16+
17+
#if defined(ARES_CC2500_INO)
18+
19+
#include "iface_cc2500.h"
20+
21+
//#define ARES_FORCE_ID
22+
23+
#define ARES_COARSE 0
24+
25+
#define ARES_PACKET_LEN 17
26+
#define ARES_NUM_FREQUENCIES 60
27+
28+
enum {
29+
ARES_START = 0x00,
30+
ARES_CALIB = 0x01,
31+
ARES_PREP = 0x02,
32+
ARES_DATA = 0x03,
33+
};
34+
35+
// CC2500 register init values captured from the ARES 6HPA transmitter
36+
const PROGMEM uint8_t ARES_init_values[] = {
37+
/* 00 */ 0x06, 0x2E, 0x2E, 0x07, 0x5A, 0x60, 0x30, 0x04,
38+
/* 08 */ 0x05, 0x00, 0x00, 0x06, 0x00, 0x5C, 0xB1, 0x3B + ARES_COARSE,
39+
/* 10 */ 0x6A, 0xF8, 0x03, 0x23, 0x7A, 0x44, 0x07, 0x30,
40+
/* 18 */ 0x18, 0x16, 0x6C, 0x43, 0x40, 0x91, 0x87, 0x6B,
41+
/* 20 */ 0xF8, 0x56, 0x10, 0xA9, 0x0A, 0x00, 0x11
42+
};
43+
44+
// Fixed hopping sequence captured from the ARES 6HPA transmitter.
45+
// This is a permutation of 60 channel values spread across the band.
46+
static const PROGMEM uint8_t ARES_hop[] = {
47+
0xB0, 0x6F, 0x1D, 0xB4, 0x74, 0x20, 0xB8, 0xD8,
48+
0x24, 0xBC, 0xDC, 0x28, 0x48, 0xE0, 0x2C, 0x4C,
49+
0xE4, 0x90, 0x50, 0xE8, 0x94, 0x54, 0xEC, 0x00,
50+
0x98, 0x58, 0x04, 0x9B, 0x5C, 0x08, 0xA0, 0xC0,
51+
0x0C, 0xA4, 0xC3, 0x10, 0x30, 0xC6, 0x14, 0x34,
52+
0xCC, 0x78, 0x38, 0xD0, 0x7C, 0x3C, 0xD4, 0x80,
53+
0x40, 0x60, 0x84, 0x44, 0x64, 0x88, 0xA8, 0x68,
54+
0x8C, 0xAC, 0x6C, 0x18
55+
};
56+
57+
static void __attribute__((unused)) ARES_CC2500_init()
58+
{
59+
CC2500_Strobe(CC2500_SRES);
60+
delayMilliseconds(1);
61+
CC2500_Strobe(CC2500_SIDLE);
62+
63+
for (uint8_t i = 0; i < 39; ++i)
64+
CC2500_WriteReg(i, pgm_read_byte_near(&ARES_init_values[i]));
65+
66+
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
67+
prev_option = option;
68+
69+
// Write PATABLE to max power (0xFF for all 8 entries) as captured
70+
for (uint8_t i = 0; i < 8; i++)
71+
CC2500_WriteReg(CC2500_3E_PATABLE, 0xFF);
72+
73+
CC2500_SetTxRxMode(TX_EN);
74+
CC2500_SetPower();
75+
}
76+
77+
// Load hopping table
78+
static void __attribute__((unused)) ARES_RF_channels()
79+
{
80+
for (uint8_t i = 0; i < ARES_NUM_FREQUENCIES; i++)
81+
hopping_frequency[i] = pgm_read_byte_near(&ARES_hop[i]);
82+
}
83+
84+
static void __attribute__((unused)) ARES_tune_chan()
85+
{
86+
CC2500_Strobe(CC2500_SIDLE);
87+
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[hopping_frequency_no]);
88+
CC2500_Strobe(CC2500_SFTX);
89+
CC2500_Strobe(CC2500_SCAL);
90+
}
91+
92+
static void __attribute__((unused)) ARES_change_chan_fast()
93+
{
94+
CC2500_Strobe(CC2500_SIDLE);
95+
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[hopping_frequency_no]);
96+
CC2500_WriteReg(CC2500_25_FSCAL1, calData[hopping_frequency_no]);
97+
}
98+
99+
// Advance the hop counter: cycles through 0-58 with step, inserting 59 when wrapping through 0
100+
static uint8_t __attribute__((unused)) ARES_next_counter(uint8_t current, uint8_t step)
101+
{
102+
if (current == 59)
103+
return 0;
104+
uint8_t next = (current + step) % 59;
105+
if (next == 0)
106+
return 59;
107+
return next;
108+
}
109+
110+
static void __attribute__((unused)) ARES_build_packet()
111+
{
112+
// Length byte: 16 data bytes follow
113+
packet[0] = 0x10;
114+
115+
// TX ID
116+
packet[1] = rx_tx_addr[1];
117+
packet[2] = rx_tx_addr[2];
118+
packet[3] = rx_tx_addr[3];
119+
120+
// 6 channels encoded as interleaved 12-bit values in bytes 4-12
121+
uint16_t ch[6];
122+
for (uint8_t i = 0; i < 6; i++)
123+
ch[i] = convert_channel_16b_nolimit(i, 1820, 3300, false);
124+
125+
packet[4] = ch[0] >> 4;
126+
packet[5] = ((ch[0] & 0x0F) << 4) | (ch[1] & 0x0F);
127+
packet[6] = ch[1] >> 4;
128+
packet[7] = ch[2] >> 4;
129+
packet[8] = ((ch[2] & 0x0F) << 4) | (ch[3] & 0x0F);
130+
packet[9] = ch[3] >> 4;
131+
packet[10] = ch[4] >> 4;
132+
packet[11] = ((ch[4] & 0x0F) << 4) | (ch[5] & 0x0F);
133+
packet[12] = ch[5] >> 4;
134+
135+
// Byte 16: counter step size (stored in crc, set to 1-58 in ARES_init)
136+
uint8_t step = crc;
137+
138+
// Bytes 13-15: running counter with rotating bit 7 frame indicator
139+
// The counter cycles 0-58 with a step, inserting 59 before wrapping to 0
140+
// Each group of 3 packets has 3 consecutive counter values
141+
// packet_count holds the current counter value
142+
uint8_t c0 = packet_count;
143+
uint8_t c1 = ARES_next_counter(c0, step);
144+
uint8_t c2 = ARES_next_counter(c1, step);
145+
146+
// Frame indicator: each data frame is sent 3 times
147+
// bind_phase tracks position 0/1/2 within the group of 3
148+
packet[13] = c0;
149+
packet[14] = c1;
150+
packet[15] = c2;
151+
packet[16] = step;
152+
153+
// Set the rotating frame bit (bit 7) on one of bytes 13-15
154+
switch (bind_phase)
155+
{
156+
case 0:
157+
packet[13] |= 0x80;
158+
break;
159+
case 1:
160+
packet[14] |= 0x80;
161+
break;
162+
case 2:
163+
packet[15] |= 0x80;
164+
break;
165+
}
166+
}
167+
168+
static void __attribute__((unused)) ARES_send_packet()
169+
{
170+
ARES_change_chan_fast();
171+
CC2500_SetPower();
172+
CC2500_WriteData(packet, ARES_PACKET_LEN);
173+
}
174+
175+
#define ARES_PACKET_PERIOD 6670 // 6.67ms between packets
176+
#define ARES_PREP_TIMING 2000
177+
178+
uint16_t ARES_callback()
179+
{
180+
switch(phase)
181+
{
182+
case ARES_START:
183+
ARES_CC2500_init();
184+
hopping_frequency_no = 0;
185+
bind_phase = 0;
186+
ARES_tune_chan();
187+
phase = ARES_CALIB;
188+
return ARES_PREP_TIMING;
189+
case ARES_CALIB:
190+
calData[hopping_frequency_no] = CC2500_ReadReg(CC2500_25_FSCAL1);
191+
hopping_frequency_no++;
192+
if (hopping_frequency_no < ARES_NUM_FREQUENCIES)
193+
ARES_tune_chan();
194+
else
195+
{
196+
hopping_frequency_no = 0;
197+
phase = ARES_PREP;
198+
}
199+
return ARES_PREP_TIMING;
200+
case ARES_PREP:
201+
if (prev_option != option)
202+
{
203+
phase = ARES_START;
204+
return ARES_PREP_TIMING;
205+
}
206+
#ifdef MULTI_SYNC
207+
telemetry_set_input_sync(ARES_PACKET_PERIOD);
208+
#endif
209+
ARES_build_packet();
210+
phase = ARES_DATA;
211+
// Fall through
212+
case ARES_DATA:
213+
ARES_send_packet();
214+
hopping_frequency_no++;
215+
if (hopping_frequency_no >= ARES_NUM_FREQUENCIES)
216+
hopping_frequency_no = 0;
217+
bind_phase++;
218+
if (bind_phase >= 3)
219+
{
220+
bind_phase = 0;
221+
// Advance counter to start of next group
222+
uint8_t step = crc;
223+
packet_count = ARES_next_counter(packet_count, step);
224+
packet_count = ARES_next_counter(packet_count, step);
225+
packet_count = ARES_next_counter(packet_count, step);
226+
}
227+
phase = ARES_PREP;
228+
return ARES_PACKET_PERIOD;
229+
}
230+
return 0;
231+
}
232+
233+
void ARES_init()
234+
{
235+
BIND_DONE; // Autobind protocol - no TX-initiated bind phase
236+
ARES_RF_channels();
237+
238+
// rx_tx_addr[1] and [2] are already set from MProtocol_id by the framework
239+
// RX_num (0-63) in byte 3 provides model match
240+
rx_tx_addr[3] = RX_num;
241+
242+
// Counter step and start from capture
243+
crc = 23;
244+
packet_count = 35;
245+
246+
#ifdef ARES_FORCE_ID
247+
rx_tx_addr[1] = 0xDC;
248+
rx_tx_addr[2] = 0xCC;
249+
rx_tx_addr[3] = 0x00;
250+
#endif
251+
phase = ARES_START;
252+
}
253+
254+
#endif

Multiprotocol/Multi.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,4 @@
103103
105,Shenqi2
104104
106,WL91x
105105
107,WPL
106+
108,0,Ares

Multiprotocol/Multi_Protos.ino

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ const char STR_JIABAILE[] ="JIABAILE";
119119
const char STR_KAMTOM[] ="KAMTOM";
120120
const char STR_WL91X[] ="WL91x";
121121
const char STR_WPL[] ="WPL";
122+
const char STR_ARES[] ="ARES";
122123

123124
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
124125
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
@@ -231,6 +232,9 @@ const mm_protocol_definition multi_protocols[] = {
231232
#if defined(MULTI_CONFIG_INO)
232233
{PROTO_CONFIG, STR_CONFIG, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, 0, CONFIG_init, CONFIG_callback },
233234
#endif
235+
#if defined(ARES_CC2500_INO)
236+
{PROTO_ARES, STR_ARES, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, ARES_init, ARES_callback },
237+
#endif
234238
#if defined(ASSAN_NRF24L01_INO)
235239
{PROTO_ASSAN, STR_ASSAN, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, ASSAN_init, ASSAN_callback },
236240
#endif

Multiprotocol/Multiprotocol.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#define VERSION_MAJOR 1
2020
#define VERSION_MINOR 3
2121
#define VERSION_REVISION 4
22-
#define VERSION_PATCH_LEVEL 62
22+
#define VERSION_PATCH_LEVEL 63
2323

2424
#define MODE_SERIAL 0
2525

@@ -135,6 +135,7 @@ enum PROTOCOLS
135135
PROTO_SHENQI2 = 105, // =>NRF24L01
136136
PROTO_WL91X = 106, // =>CC2500 & NRF24L01
137137
PROTO_WPL = 107, // =>NRF24L01
138+
PROTO_ARES = 108, // =>CC2500
138139

139140
PROTO_NANORF = 126, // =>NRF24L01
140141
PROTO_TEST = 127, // =>CC2500

Multiprotocol/Multiprotocol.ino

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ uint16_t packet_period;
104104
uint8_t packet_count;
105105
uint8_t packet_sent;
106106
uint8_t packet_length;
107-
#if defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO) || defined(MLINK_CYRF6936_INO)
107+
#if defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO) || defined(MLINK_CYRF6936_INO) || defined(ARES_CC2500_INO)
108108
uint8_t hopping_frequency[78];
109109
#else
110110
uint8_t hopping_frequency[50];
@@ -130,7 +130,7 @@ uint16_t pps_counter;
130130
#ifdef CC2500_INSTALLED
131131
#ifdef SCANNER_CC2500_INO
132132
uint8_t calData[255];
133-
#elif defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO)
133+
#elif defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO) || defined(ARES_CC2500_INO)
134134
uint8_t calData[75];
135135
#else
136136
uint8_t calData[50];
@@ -635,7 +635,11 @@ void setup()
635635
option = FORCE_HOTT_TUNING; // Use config-defined tuning value for HOTT
636636
else
637637
#endif
638-
option = (uint8_t)PPM_prot_line->option; // Use radio-defined option value
638+
#if defined(FORCE_ARES_TUNING) && defined(ARES_CC2500_INO)
639+
if (protocol==PROTO_ARES)
640+
option = FORCE_ARES_TUNING; // Use config-defined tuning value for ARES
641+
else
642+
#endif option = (uint8_t)PPM_prot_line->option; // Use radio-defined option value
639643

640644
if(PPM_prot_line->power) POWER_FLAG_on;
641645
if(PPM_prot_line->autobind)
@@ -1376,6 +1380,11 @@ void update_serial_data()
13761380
if (protocol==PROTO_HOTT)
13771381
option=FORCE_HOTT_TUNING; // Use config-defined tuning value for HOTT
13781382
else
1383+
#endif
1384+
#if defined(FORCE_ARES_TUNING) && defined(ARES_CC2500_INO)
1385+
if (protocol==PROTO_ARES)
1386+
option=FORCE_ARES_TUNING; // Use config-defined tuning value for ARES
1387+
else
13791388
#endif
13801389
option=rx_ok_buff[3]; // Use radio-defined option value
13811390

Multiprotocol/Validate.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@
6969

7070
// Check forced tuning values are valid
7171
//CC2500
72+
#ifdef FORCE_ARES_TUNING
73+
#if ( FORCE_ARES_TUNING < -127 ) || ( FORCE_ARES_TUNING > 127 )
74+
#error "The ARES forced frequency tuning value is outside of the range -127..127."
75+
#endif
76+
#endif
7277
#ifdef FORCE_CORONA_TUNING
7378
#if ( FORCE_CORONA_TUNING < -127 ) || ( FORCE_CORONA_TUNING > 127 )
7479
#error "The CORONA forced frequency tuning value is outside of the range -127..127."
@@ -276,6 +281,7 @@
276281
#endif
277282

278283
#if not defined(CC2500_INSTALLED) || defined MULTI_EU
284+
#undef ARES_CC2500_INO
279285
#undef CORONA_CC2500_INO
280286
#undef E016HV2_CC2500_INO
281287
#undef ESKY150V2_CC2500_INO
@@ -410,6 +416,7 @@
410416
#endif
411417

412418
#ifdef MULTI_SURFACE
419+
#undef ARES_CC2500_INO
413420
#undef BUGS_A7105_INO
414421
#undef HEIGHT_A7105_INO
415422
#undef HUBSAN_A7105_INO

0 commit comments

Comments
 (0)