Skip to content

Commit d0a6fae

Browse files
committed
Parse RF code into a struct code, and report structured data on the serial port
1 parent e2f1fe9 commit d0a6fae

File tree

1 file changed

+119
-20
lines changed

1 file changed

+119
-20
lines changed

nexa_decoder/nexa_decoder.ino

+119-20
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929

3030
#include <limits.h>
3131

32+
#define DEBUG 0
33+
3234
// Adjust the following to match where the RF receiver is connected.
3335
#define RF_SETUP() bitClear(DDRB, 0)
3436
#define RF_READ() bitRead(PINB, 0)
3537

36-
const unsigned int BUF_SIZE = 1536;
38+
const size_t BUF_SIZE = 1280;
3739
char buf[BUF_SIZE];
3840
size_t i = 0;
3941

@@ -45,6 +47,13 @@ enum {
4547

4648
byte cur_bit = 0;
4749

50+
struct code {
51+
byte device[3]; // 24-bit (A) or 8-bit (B) device identifier
52+
byte channel; // 4-bit intra-device channel identifier (= 0 for B)
53+
bool group; // true iff the group bit is set (false for B)
54+
bool state; // ON - true, OFF - false
55+
};
56+
4857
void setup()
4958
{
5059
/*
@@ -97,7 +106,7 @@ int next_pulse()
97106
*
98107
* This is equivalent to floor(log2(v)) + 1.
99108
*/
100-
unsigned int numbits(unsigned int v)
109+
unsigned int num_bits(unsigned int v)
101110
{
102111
unsigned int ret = 0;
103112
while (v) {
@@ -125,7 +134,7 @@ int quantize_pulse(int p)
125134
int sign = (p > 0) ? 1 : -1;
126135
p *= sign; // abs value
127136
p >>= 9; // divide by 512
128-
switch (numbits(p)) {
137+
switch (num_bits(p)) {
129138
case 0: // 0µs <= p < 512µs
130139
return sign * 1;
131140
case 1: // 512µs <= p < 1024µs
@@ -142,6 +151,102 @@ int quantize_pulse(int p)
142151
}
143152
}
144153

154+
const char *three_bytes_in_hex(byte s[3])
155+
{
156+
static char buf[7]; // 6 hex digits + NUL
157+
const char hex[] = "0123456789ABCDEF";
158+
buf[0] = hex[(s[2] >> 4) & B1111];
159+
buf[1] = hex[(s[2] >> 0) & B1111];
160+
buf[2] = hex[(s[1] >> 4) & B1111];
161+
buf[3] = hex[(s[1] >> 0) & B1111];
162+
buf[4] = hex[(s[0] >> 4) & B1111];
163+
buf[5] = hex[(s[0] >> 0) & B1111];
164+
buf[6] = '\0';
165+
return buf;
166+
}
167+
168+
/*
169+
* Transmit the given code on the serial port.
170+
*/
171+
void transmit_code(struct code *c)
172+
{
173+
Serial.print(three_bytes_in_hex(c->device));
174+
Serial.print(':');
175+
Serial.print(c->group ? '1' : '0');
176+
Serial.print(':');
177+
Serial.print(c->channel, HEX);
178+
Serial.print(':');
179+
Serial.println(c->state ? '1' : '0');
180+
Serial.flush();
181+
}
182+
183+
/*
184+
* Parse the given format/code into a struct code and transmit it.
185+
*/
186+
void parse_code(char format, uint32_t code)
187+
{
188+
struct code c;
189+
static const unsigned char bit_swapper[] = {
190+
0, 8, 4, 12, 2, 10, 6, 14,
191+
1, 9, 5, 13, 3, 11, 7, 15 };
192+
193+
if (format == 'A') { // 32 bits: DDDDDDDDDDDDDDDDDDDDDDDD10GSCCCC
194+
c.device[0] = code >> 8;
195+
c.device[1] = code >> 16;
196+
c.device[2] = code >> 24;
197+
c.channel = code & B1111;
198+
c.group = code & B100000;
199+
c.state = code & B10000;
200+
}
201+
else if (format == 'B') { // 12 bits: DDDDDDDD011S
202+
c.device[0] = 0;
203+
c.device[1] = 0;
204+
c.device[2] = 0;
205+
c.channel = 0;
206+
c.group = 0;
207+
c.state = code & 1;
208+
byte d = code >> 4;
209+
c.device[0] |= bit_swapper[((d >> 4) & B1111)] << 4;
210+
c.device[0] |= bit_swapper[(d & B1111)];
211+
}
212+
transmit_code(&c);
213+
};
214+
215+
/*
216+
* Decode commands from buf[0..i], and transmit them over the serial port.
217+
*/
218+
void decode_buf()
219+
{
220+
int state = -1; // Initial state - before SYNC
221+
char format = 0; // 'A' or 'B'
222+
uint32_t code = 0; // Must be large enough to hold largest code
223+
for (size_t j = 0; j < i; j++) {
224+
char b = buf[j];
225+
if (state > 0) { // Expecting another data bit
226+
if (b == '0' || b == '1')
227+
code |= ((uint32_t)(b == '1' ? 1 : 0) << --state);
228+
else
229+
state = -1; // Revert to initial state
230+
}
231+
232+
if (state == 0) { // Finished reading data bits
233+
parse_code(format, code);
234+
code = 0;
235+
state = -1; // Look for next SYNC
236+
}
237+
else if (state == -1) { // Looking for SYNC
238+
if (b == 'A') { // SYNC for format A
239+
format = 'A';
240+
state = 32; // Expect 32 data bits
241+
}
242+
else if (b == 'B') {// SYNC for format B
243+
format = 'B';
244+
state = 12; // Expect 12 data bits
245+
}
246+
}
247+
}
248+
}
249+
145250
void loop()
146251
{
147252
new_state = UNKNOWN;
@@ -163,7 +268,6 @@ void loop()
163268
new_state = DA3;
164269
else if (cur_state == SX2 || cur_state == DB1) {
165270
if (cur_state == SX2) { // cmd format B
166-
buf[i++] = '\n';
167271
buf[i++] = 'B';
168272
}
169273
new_state = DB2;
@@ -199,7 +303,6 @@ void loop()
199303
new_state = SX2;
200304
break;
201305
case SX3:
202-
buf[i++] = '\n';
203306
buf[i++] = 'A';
204307
new_state = DA0;
205308
break;
@@ -221,23 +324,19 @@ void loop()
221324
}
222325
break;
223326
}
224-
if (i >= BUF_SIZE - 5) { // Prevent overflowing buf
225-
buf[i++] = 'X';
327+
if (i >= BUF_SIZE) // Prevent overflowing buf
226328
new_state = UNKNOWN;
227-
}
329+
228330
if (cur_state != UNKNOWN && new_state == UNKNOWN) { // => UNKNOWN
229-
// Invalid data: Print buffer.
230-
// ...but only if it has > 8 valid bits
231-
if (i > 8 + 2) {
232-
buf[i++] = '\0';
233-
Serial.print(buf);
234-
Serial.print('>');
235-
Serial.print(cur_state);
236-
Serial.print('|');
237-
Serial.print(p);
238-
Serial.print('<');
239-
Serial.flush();
240-
}
331+
#if DEBUG
332+
buf[i] = '\0';
333+
Serial.println(buf);
334+
Serial.flush();
335+
#endif DEBUG
336+
// Reached end of valid data: Decode and transmit buffer.
337+
// ...but only if it longer than the shortest command
338+
if (i > 1 + 12) // Format B: SYNC + 12 data bits
339+
decode_buf();
241340
i = 0; // Restart buffer
242341
}
243342
cur_state = new_state;

0 commit comments

Comments
 (0)