Skip to content

Commit db017c7

Browse files
committed
HS6200 emulation using CYRF for E01X protocol
1 parent 24aaa0d commit db017c7

File tree

10 files changed

+188
-158
lines changed

10 files changed

+188
-158
lines changed

Multiprotocol/E01X_nrf24l01.ino renamed to Multiprotocol/E01X_cyrf6936.ino

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
*/
1515
// compatible with E012 and E015
1616

17-
#if defined(E01X_NRF24L01_INO)
17+
#if defined(E01X_CYRF6936_INO)
1818

19-
#include "iface_nrf24l01.h"
19+
#include "iface_HS6200.h"
2020

2121
//Protocols constants
2222
#define E01X_BIND_COUNT 500
@@ -28,7 +28,8 @@
2828
#define E012_NUM_RF_CHANNELS 4
2929
#define E012_PACKET_SIZE 15
3030

31-
#define E015_PACKET_PERIOD 4500 // stock Tx=9000, but let's send more packets ...
31+
//#define E015_FORCE_ID
32+
#define E015_PACKET_PERIOD 9000
3233
#define E015_RF_CHANNEL 0x2d // 2445 MHz
3334
#define E015_PACKET_SIZE 10
3435
#define E015_BIND_PACKET_SIZE 9
@@ -87,13 +88,15 @@ static void __attribute__((unused)) E01X_send_packet()
8788
packet[0] = rx_tx_addr[1];
8889
if(IS_BIND_IN_PROGRESS)
8990
{
91+
rf_ch_num = E012_RF_BIND_CHANNEL;
9092
packet[1] = 0xaa;
9193
memcpy(&packet[2], hopping_frequency, E012_NUM_RF_CHANNELS);
9294
memcpy(&packet[6], rx_tx_addr, E01X_ADDRESS_LENGTH);
93-
rf_ch_num=E012_RF_BIND_CHANNEL;
9495
}
9596
else
9697
{
98+
rf_ch_num = hopping_frequency[hopping_frequency_no++];
99+
hopping_frequency_no %= E012_NUM_RF_CHANNELS;
97100
packet[1] = 0x01
98101
| GET_FLAG(E01X_RTH_SW, E012_FLAG_RTH)
99102
| GET_FLAG(E01X_HEADLESS_SW, E012_FLAG_HEADLESS)
@@ -107,8 +110,6 @@ static void __attribute__((unused)) E01X_send_packet()
107110
packet[8] = 0x00;
108111
packet[9] = 0x00;
109112
packet[10]= 0x00;
110-
rf_ch_num=hopping_frequency[hopping_frequency_no++];
111-
hopping_frequency_no %= E012_NUM_RF_CHANNELS;
112113
}
113114
packet[11] = 0x00;
114115
packet[12] = 0x00;
@@ -117,17 +118,19 @@ static void __attribute__((unused)) E01X_send_packet()
117118
}
118119
else
119120
{ // E015
121+
rf_ch_num = E015_RF_CHANNEL;
120122
if(IS_BIND_IN_PROGRESS)
121123
{
122124
packet[0] = 0x18;
123125
packet[1] = 0x04;
124126
packet[2] = 0x06;
125127
// data phase address
126128
memcpy(&packet[3], rx_tx_addr, E01X_ADDRESS_LENGTH);
129+
packet[8] = 0x63; // unknown calculation
127130
// checksum
128-
packet[8] = packet[3];
129-
for(uint8_t i=4; i<8; i++)
130-
packet[8] += packet[i];
131+
//packet[8] = packet[3];
132+
//for(uint8_t i=4; i<8; i++)
133+
// packet[8] += packet[i];
131134
packet_length=E015_BIND_PACKET_SIZE;
132135
}
133136
else
@@ -154,24 +157,15 @@ static void __attribute__((unused)) E01X_send_packet()
154157
}
155158
}
156159

157-
HS6200_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
158-
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
159-
160-
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
161-
NRF24L01_FlushTx();
162-
163-
HS6200_WritePayload(packet, packet_length);
164-
165-
// Check and adjust transmission power. We do this after
166-
// transmission to not bother with timeout after power
167-
// settings change - we have plenty of time until next
168-
// packet.
169-
NRF24L01_SetPower();
160+
HS6200_RFChannel(rf_ch_num);
161+
HS6200_SetPower();
162+
delayMicroseconds(270); // Wait for RF channel to settle
163+
HS6200_SendPayload(packet, packet_length);
170164
}
171165

172166
static void __attribute__((unused)) E01X_RF_init()
173167
{
174-
NRF24L01_Initialize();
168+
HS6200_Init(true); // CRC enabled
175169

176170
if(sub_protocol==E012)
177171
HS6200_SetTXAddr((uint8_t *)"\x55\x42\x9C\x8F\xC9", E01X_ADDRESS_LENGTH);
@@ -218,8 +212,21 @@ void E01X_init()
218212
}
219213
else //E015
220214
{
215+
#ifdef E015_FORCE_ID
216+
rx_tx_addr[0] = 0x06;
217+
rx_tx_addr[1] = 0xC6;
218+
rx_tx_addr[2] = 0xB7;
219+
rx_tx_addr[3] = 0x56;
220+
rx_tx_addr[4] = 0x8A;
221+
#endif
222+
223+
//force the sum to give 0x63 since the id calculation is unknown
224+
uint8_t sum=0x63;
225+
for(uint8_t i=0; i < 4; i++)
226+
sum -= rx_tx_addr[i];
227+
rx_tx_addr[4] = sum;
228+
221229
packet_period=E015_PACKET_PERIOD;
222-
rf_ch_num=E015_RF_CHANNEL;
223230
armed = 0;
224231
arm_flags = 0;
225232
arm_channel_previous = E01X_ARM_SW;

Multiprotocol/HS6200_EMU.ino

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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+
#ifdef CYRF6936_INSTALLED
16+
#include "iface_HS6200.h"
17+
18+
static bool HS6200_crc;
19+
static uint16_t HS6200_crc_init;
20+
static uint8_t HS6200_address_length, HS6200_tx_addr[5];
21+
22+
static void __attribute__((unused)) HS6200_Init(bool crc_en)
23+
{
24+
CYRF_GFSK1M_Init(32, 1); //Dummy number of bytes for now
25+
HS6200_crc = crc_en;
26+
}
27+
28+
static void __attribute__((unused)) HS6200_SetTXAddr(const uint8_t* addr, uint8_t addr_len)
29+
{
30+
// precompute address crc
31+
crc = 0xffff;
32+
for(uint8_t i=0; i<addr_len; i++)
33+
crc16_update(addr[addr_len-1-i], 8);
34+
HS6200_crc_init=crc;
35+
memcpy(HS6200_tx_addr, addr, addr_len);
36+
HS6200_address_length = addr_len;
37+
}
38+
39+
static uint16_t __attribute__((unused)) HS6200_calc_crc(uint8_t* msg, uint8_t len)
40+
{
41+
uint8_t pos;
42+
43+
crc = HS6200_crc_init;
44+
// pcf + payload
45+
for(pos=0; pos < len-1; pos++)
46+
crc16_update(msg[pos], 8);
47+
// last byte (1 bit only)
48+
if(len > 0)
49+
crc16_update(msg[pos+1], 1);
50+
return crc;
51+
}
52+
53+
static void __attribute__((unused)) HS6200_SendPayload(uint8_t* msg, uint8_t len)
54+
{
55+
static const uint8_t HS6200_scramble[] = { 0x80,0xf5,0x3b,0x0d,0x6d,0x2a,0xf9,0xbc,0x51,0x8e,0x4c,0xfd,0xc1,0x65,0xd0 }; // todo: find all 32 bytes ...
56+
uint8_t payload[32];
57+
const uint8_t no_ack = 1; // never ask for an ack
58+
static uint8_t pid;
59+
uint8_t pos = 0;
60+
61+
if(len > sizeof(HS6200_scramble))
62+
len = sizeof(HS6200_scramble);
63+
64+
// address
65+
for(int8_t i=HS6200_address_length-1; i>=0; i--)
66+
payload[pos++] = HS6200_tx_addr[i];
67+
68+
// guard bytes
69+
payload[pos++] = HS6200_tx_addr[0];
70+
payload[pos++] = HS6200_tx_addr[0];
71+
72+
// packet control field
73+
payload[pos++] = ((len & 0x3f) << 2) | (pid & 0x03);
74+
payload[pos] = (no_ack & 0x01) << 7;
75+
pid++;
76+
77+
// scrambled payload
78+
if(len > 0)
79+
{
80+
payload[pos++] |= (msg[0] ^ HS6200_scramble[0]) >> 1;
81+
for(uint8_t i=1; i<len; i++)
82+
payload[pos++] = ((msg[i-1] ^ HS6200_scramble[i-1]) << 7) | ((msg[i] ^ HS6200_scramble[i]) >> 1);
83+
payload[pos] = (msg[len-1] ^ HS6200_scramble[len-1]) << 7;
84+
}
85+
86+
// crc
87+
if(HS6200_crc)
88+
{
89+
uint16_t crc = HS6200_calc_crc(&payload[HS6200_address_length+2], len+2);
90+
uint8_t hcrc = crc >> 8;
91+
uint8_t lcrc = crc & 0xff;
92+
payload[pos++] |= (hcrc >> 1);
93+
payload[pos++] = (hcrc << 7) | (lcrc >> 1);
94+
payload[pos++] = lcrc << 7;
95+
}
96+
97+
#if 0
98+
debug("E:");
99+
for(uint8_t i=0; i<pos; i++)
100+
debug(" %02X",payload[i]);
101+
debugln("");
102+
#endif
103+
104+
//CYRF wants LSB first
105+
for(uint8_t i=0; i<pos; i++)
106+
payload[i]=bit_reverse(payload[i]);
107+
//Send
108+
CYRF_WriteRegister(CYRF_01_TX_LENGTH, pos);
109+
CYRF_GFSK1M_SendPayload(payload, pos);
110+
}
111+
112+
#endif

Multiprotocol/MT99xx_ccnrf.ino

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
285285
XN297_SetFreqOffset();
286286
XN297_SetTxRxMode(TX_EN);
287287
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
288+
289+
#if 0
290+
for(uint8_t i=0; i<MT99XX_PACKET_SIZE; i++)
291+
debug(" %02X",packet[i]);
292+
debugln();
293+
#endif
288294
}
289295

290296
static void __attribute__((unused)) MT99XX_RF_init()

Multiprotocol/Multi_Protos.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,8 @@ const mm_protocol_definition multi_protocols[] = {
247247
#if defined(E016HV2_CC2500_INO)
248248
{PROTO_E016HV2, STR_E016HV2, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, E016HV2_init, E016HV2_callback },
249249
#endif
250-
#if defined(E01X_NRF24L01_INO)
251-
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 2, OPTION_OPTION, 0, 0, SW_NRF, E01X_init, E01X_callback },
250+
#if defined(E01X_CYRF6936_INO)
251+
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 2, OPTION_NONE, 0, 0, SW_CYRF, E01X_init, E01X_callback },
252252
#endif
253253
#if defined(E129_CYRF6936_INO)
254254
{PROTO_E129, STR_E129, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E129_init, E129_callback },

Multiprotocol/Multiprotocol.h

Lines changed: 2 additions & 2 deletions
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 3
22-
#define VERSION_PATCH_LEVEL 4
22+
#define VERSION_PATCH_LEVEL 6
2323

2424
#define MODE_SERIAL 0
2525

@@ -73,7 +73,7 @@ enum PROTOCOLS
7373
PROTO_BUGSMINI = 42, // =>NRF24L01
7474
PROTO_TRAXXAS = 43, // =>CYRF6936
7575
PROTO_NCC1701 = 44, // =>NRF24L01
76-
PROTO_E01X = 45, // =>NRF24L01
76+
PROTO_E01X = 45, // =>CYRF6936
7777
PROTO_V911S = 46, // =>NRF24L01
7878
PROTO_GD00X = 47, // =>NRF24L01
7979
PROTO_V761 = 48, // =>NRF24L01

Multiprotocol/NRF24l01_SPI.ino

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -244,112 +244,6 @@ uint8_t NRF24L01_packet_ack()
244244
return PKT_PENDING;
245245
}
246246

247-
//
248-
// HS6200 emulation layer
249-
///////////////////////////
250-
static uint8_t hs6200_crc;
251-
static uint16_t hs6200_crc_init;
252-
static uint8_t hs6200_tx_addr[5];
253-
static uint8_t hs6200_address_length;
254-
255-
static const uint8_t hs6200_scramble[] = {
256-
0x80,0xf5,0x3b,0x0d,0x6d,0x2a,0xf9,0xbc,
257-
0x51,0x8e,0x4c,0xfd,0xc1,0x65,0xd0 }; // todo: find all 32 bytes ...
258-
259-
void HS6200_SetTXAddr(const uint8_t* addr, uint8_t len)
260-
{
261-
if(len < 4)
262-
len = 4;
263-
else if(len > 5)
264-
len = 5;
265-
266-
// use nrf24 address field as a longer preamble
267-
if(addr[len-1] & 0x80)
268-
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\x55\x55\x55\x55\x55", 5);
269-
else
270-
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xaa\xaa\xaa\xaa\xaa", 5);
271-
272-
// precompute address crc
273-
crc = 0xffff;
274-
for(int i=0; i<len; i++)
275-
crc16_update(addr[len-1-i], 8);
276-
hs6200_crc_init=crc;
277-
memcpy(hs6200_tx_addr, addr, len);
278-
hs6200_address_length = len;
279-
}
280-
281-
static uint16_t hs6200_calc_crc(uint8_t* msg, uint8_t len)
282-
{
283-
uint8_t pos;
284-
285-
crc = hs6200_crc_init;
286-
// pcf + payload
287-
for(pos=0; pos < len-1; pos++)
288-
crc16_update(msg[pos], 8);
289-
// last byte (1 bit only)
290-
if(len > 0)
291-
crc16_update(msg[pos+1], 1);
292-
return crc;
293-
}
294-
295-
void HS6200_Configure(uint8_t flags)
296-
{
297-
hs6200_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
298-
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
299-
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xff);
300-
}
301-
302-
void HS6200_WritePayload(uint8_t* msg, uint8_t len)
303-
{
304-
uint8_t payload[32];
305-
const uint8_t no_ack = 1; // never ask for an ack
306-
static uint8_t pid;
307-
uint8_t pos = 0;
308-
309-
if(len > sizeof(hs6200_scramble))
310-
len = sizeof(hs6200_scramble);
311-
312-
// address
313-
for(int i=hs6200_address_length-1; i>=0; i--)
314-
payload[pos++] = hs6200_tx_addr[i];
315-
316-
// guard bytes
317-
payload[pos++] = hs6200_tx_addr[0];
318-
payload[pos++] = hs6200_tx_addr[0];
319-
320-
// packet control field
321-
payload[pos++] = ((len & 0x3f) << 2) | (pid & 0x03);
322-
payload[pos] = (no_ack & 0x01) << 7;
323-
pid++;
324-
325-
// scrambled payload
326-
if(len > 0)
327-
{
328-
payload[pos++] |= (msg[0] ^ hs6200_scramble[0]) >> 1;
329-
for(uint8_t i=1; i<len; i++)
330-
payload[pos++] = ((msg[i-1] ^ hs6200_scramble[i-1]) << 7) | ((msg[i] ^ hs6200_scramble[i]) >> 1);
331-
payload[pos] = (msg[len-1] ^ hs6200_scramble[len-1]) << 7;
332-
}
333-
334-
// crc
335-
if(hs6200_crc)
336-
{
337-
uint16_t crc = hs6200_calc_crc(&payload[hs6200_address_length+2], len+2);
338-
uint8_t hcrc = crc >> 8;
339-
uint8_t lcrc = crc & 0xff;
340-
payload[pos++] |= (hcrc >> 1);
341-
payload[pos++] = (hcrc << 7) | (lcrc >> 1);
342-
payload[pos++] = lcrc << 7;
343-
}
344-
345-
NRF24L01_WritePayload(payload, pos);
346-
delayMicroseconds(option+20);
347-
NRF24L01_WritePayload(payload, pos);
348-
}
349-
//
350-
// End of HS6200 emulation
351-
////////////////////////////
352-
353247
///////////////
354248
// LT8900 emulation layer
355249
uint8_t LT8900_buffer[64];

0 commit comments

Comments
 (0)