-
Notifications
You must be signed in to change notification settings - Fork 0
/
PROTOCOL
603 lines (462 loc) · 26.5 KB
/
PROTOCOL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
SERIAL PROTOCOL FOR FNORDLICHT-NG FIRMWARE
==========================================
Physical bus description
------------------------
The serial bus consists of up to 254 devices, each device having the uart rx
pin connected to the uart tx pin of the predecessor, the uart tx pin connected
to the tx successor. The uart is used with a baud rate of 19200. A device
will retransmit each received byte immediately and unaltered, the only
exception is the address byte in the sync sequence (which is incremented by one
before retransmission). An interrupt line is connected to each device.
Diagram:
+----------------+ +----------------+
| device N | | device N+1 |
UART: ... --> >-|RX TX|-> --> >-|RX TX|-> ...
| INT | | INT |
+-------+--------+ +-------+--------+
| |
INT: -------------------+--------------------------+----------> ...
Bootloader startup procedure
----------------------------
For updating the firmware installed on the devices of a bus, each device should
be equipped with a bootloader program. At power-on, the bootloader should be
started, sleep for 100ms and check afterwards, if the INT line is pulled down
(by a bus-master). If INT is not pulled down, the bootloader is allowed to
start the main firmware. Otherwise it should not attempt to start the main
firmware, but wait for commands received over the bus. This procedure allows a
recovery from a broken firmware which does not process commands received over
the bus (such as the BOOTLOADER command). To enter the bootloader via the
BOOTLOADER command, first pull down the INT line, then issue the command.
Initial sync sequence
---------------------
For the purpose of (automatic) address discovery and resetting the bus, a
sync sequence consisting of 15x ESC (0x1b) followed by an address byte is used.
The controller sends 15x ESC, followed by a null byte. Please note that the
length of the sync sequence (16 byte) is different from the length of a
command packet, which is 15 byte!
A device MUST be able to detect this sequence asynchronously, i.e. even if it is
in the middle of receiving a command packet. The device does not need to
withhold the execution of the received command packet until it is clear if a
sequence of ESC bytes constitutes a sync sequence.
Example:
A device received 4 bytes, say A B C D, of a packet, then a sync sequence.
It may (or may not) execute the packet
A B C D ESC ESC ... ESC
but the sync sequence must be detected, too.
Asynchronous detection of the sync sequence can be done by just counting the
number of consecutive ESC bytes, as 15 consecutive ESC bytes can only occur
in a sync sequence, never in a command packet (ESC cannot occur as a command in
the second byte of a command packet).
Flow:
* controller sends 15x ESC, followed by the address of the first device
(usually a null)
* first device on the bus receives and retransmits 15x ESC, receives address
byte, stores own address in ram, increments address byte and transmits new
address to next device on the bus
Result: Each device on the bus knows it's own address (=position).
Commands
--------
Commands are sent in packets, 15 bytes in length, and are passed from device
to device unmodified. The first byte is the destination address (0-254, 255
is broadcast), the second byte contains the command. The meaning of the
following 13 bytes depends on the value of the second byte (command). A
device ignores non-broadcast packets for which the address byte does not
match it's own address. Bytes which are declared as "don't care" bytes SHOULD
be set to zero, this makes future extensions easier.
List of commands:
-----------------
command | function | description
--------------------------------------------------------
0x01 | FADE_RGB | set color/fade to color (RGB)
0x02 | FADE_HSV | set color/fade to color (HSV)
0x03 | SAVE_RGB | save color to EEPROM (RGB)
0x04 | SAVE_HSV | save color to EEPROM (HSV)
0x05 | SAVE_CURRENT | save current color to EEPROM
0x06 | CONFIG_OFFSETS | set global offset values
0x07 | START_PROGRAM | start program
0x08 | STOP | stop color changing
0x09 | MODIFY_CURRENT | modify current color
0x0A | PULL_INT | pull down INT line
0x0B | CONFIG_STARTUP | configure startup
0x0C | POWERDOWN | power down the device
0x1B | | RESERVED (sync-sequence)
0x80 | BOOTLOADER | start bootloader
0x81 | BOOT_CONFIG | configure bootloader
0x82 | BOOT_INIT | initialize bootloader data buffer
0x83 | BOOT_DATA | store data in bootloader data buffer
0x84 | BOOT_CRC_CHECK | compare check-sum
0x85 | BOOT_CRC_FLASH | compare check-sum with flash
0x86 | BOOT_FLASH | write provided data to flash
0x87 | BOOT_ENTER_APP | start application
Command: FADE_RGB - set color/fade to color (RGB) (0x01)
--------------------------------------------------------
Instruct the device to fade to the specified absolute color, given as a
RGB value, with a specific speed. Step and delay might be modified by
application of the global offsets (see CONFIG_OFFSETS), color values
(red, green, blue) are used unmodified.
All values are unsigned 8 bit integers. If step is set to 255, the target
color is set without fading. If delay is 0, the target color is set
directly after receiving the command packet.
byte offset | name | description
---------------------------------
2 | step | increment step for fading
3 | delay | delay between steps when fading (in 10ms)
4 | red | red value
5 | green | green value
6 | blue | blue value
7-14 | - | don't care
Command: FADE_HSV - set color/fade to color (HSV) (0x02)
--------------------------------------------------------
Instruct the device to fade to the specified absolute color, given as a
HSV value, with a specific speed. Step, delay and hue might be modified
by application of the global offsets, saturation and value might be scaled
by global scales (see CONFIG_OFFSETS).
All values are unsigned 8 bit integers, except hue, which is a 16 bit
little endian integer. If step is set to 255, the target color is set
without fading. If delay is 0, the target color is set directly after
receiving the command packet.
byte offset | name | description
------------------------------------
2 | step | increment step for fading
3 | delay | delay between steps when fading (in 10ms)
4-5 | hue | hue, 0-360, little endian
6 | saturation | saturation
7 | value | value (brightness)
8-14 | - | don't care
Command: SAVE_RGB - save color to EEPROM (RGB) (0x03)
-----------------------------------------------------
Save a color in RGB format, a fade speed (step and delay) and a pause
length to the EEPROM. The EEPROM can store 60 color and speed/delay
values (see section "EEPROM color storage" below). While writing the
data to the EEPROM, the INT line is pulled down.
All values are unsigned 8 bit integers, except pause, which is a little
endian 16 bit integer.
byte offset | name | description
------------------------------
2 | slot | slot in the EEPROM (0-59)
3 | step | increment step for fading
4 | delay | delay between steps when fading (in 10ms)
5-6 | pause | time to wait before fading to next color (in 100ms)
7 | red | red value
8 | green | green value
9 | blue | blue value
10-14 | - | don't care
Command: SAVE_HSV - save color to EEPROM (HSV) (0x04)
-----------------------------------------------------
Save a color in HSV format, a fade speed (step and delay) and a pause
length to the EEPROM. The EEPROM can store 60 color and speed/delay
values (see section "EEPROM color storage" below). While writing the
data to the EEPROM, the INT line is pulled down.
All values are unsigned 8 bit integers, except pause and hue, which are
little endian 16 bit integers.
byte offset | name | description
-----------------------------------
2 | slot | slot in the EEPROM (0-59)
3 | step | increment step for fading
4 | delay | delay between steps when fading (in 10ms)
5-6 | pause | time to wait before fading to next color
| | (in 100ms)
7-8 | hue | hue, 0-360, little endian
9 | saturation | saturation
10 | value | value (brightness)
11-14 | - | don't care
Command: SAVE_CURRENT - save current color to EEPROM (0x05)
-----------------------------------------------------------
Save the current color to EEPROM (RGB), together with a fade speed and a
pause length. While writing the data to the EEPROM, the INT line is
pulled down.
All values are unsigned 8 bit integers, except pause, which is a little
endian 16 bit integers.
byte offset | name | description
----------------------------------------
2 | slot | slot in the EEPROM (0-59)
3 | step | increment step for fading
4 | delay | delay between steps when fading (in 10ms)
5-6 | pause | time to wait before fading to next color
| | (in 100ms)
7-14 | - | don't care
Command: CONFIG_OFFSETS - set global offset values (0x06)
---------------------------------------------------------
Set global values which influence how fast and what colors are when using
FADE_RGB or FADE_HSV or the static programs documented below. All bytes are
signed 8 bit integers, except hue, which is a little endian signed 16 bit
integer. Saturation and value are scales. This means, the final saturation
and value will be scaled with saturation/255 and value/255, respectively.
byte offset | name | description
-------------------------------------------
2 | step | increment step for fading (offset)
3 | delay | delay between steps when fading
| | (in 10ms, offset)
4-5 | hue | hue offset, signed, little endian
6 | saturation | saturation scale, unsigned, 0-255
7 | value | value scale, unsigned, 0-255
8-14 | - | don't care
Command: START_PROGRAM - start program (0x07)
---------------------------------------------
Start a program (a function compiled into the firmware) with given
parameters. This command stops all other programs (and EEPROM fade
sequences). For a list of programs and parameters see section
"Static Programs".
byte offset | name | description
---------------------------------
2 | program | program id, 0-255
3-11 | params | 10 byte parameters passed to program
12-13 | - | don't care
Command: STOP - stop color changing (0x08)
------------------------------------------
Stop all processes modifying the current color. Optionally, also stop
the current fading process.
byte offset | name | description
---------------------------------
2 | fade | stop fading if set (1)
3-14 | - | don't care
Command: MODIFY_CURRENT - modify current color (0x09)
-----------------------------------------------------
Instruct the device to fade to a new target color, which is determined
relatively to the one currently visible. This works only if no
program (or EEPROM fade sequence) is running. The current color is
faded to the target color with the given step and delay values. The
RGB offsets are applied before the HSV offsets. Setting either one to
zero will not modify the color in that color space.
Step and delay are unsigned 8 bit integers, all other values are signed 8
(or 16) bit integers.
byte offset | name | description
-------------------------------------
2 | step | increment step for fading
3 | delay | delay between steps when fading (in 10ms)
4 | red | red offset
5 | green | green offset
6 | blue | blue offset
4-5 | hue | hue offset
6 | saturation | saturation offset
7 | value | value offset
8-14 | - | don't care
Command: PULL_INT - pull down INT line (0x0A)
---------------------------------------------
Instruct the adressed device to immediately pull down the INT line
(connected to all devices in parallel) for a given amount of time. This
can be efficiently used to determine the number of devices listening to
the bus (eg. by binary search).
byte offset | name | description
---------------------------------
2 | delay | time to wait before releasing the INT line
| (in 50ms, maximum 2550ms, jitter +-10ms)
3-14 | - | don't care
Command: CONFIG_STARTUP - configure startup (0x0B)
--------------------------------------------------
Configure what a device should perform after power-up. Mode is an
unsigned 8 bit integer, selecting the desired startup mode.
Two different modes can be configured:
* NOTHING (mode == 0):
Do nothing after startup (ie do not show any color, stay black)
* PROGRAM (mode == 1):
Start a static program compiled into the firmware, using the
following 10 bytes as parameters for the program (for details
see section "Static Programs").
If startup mode is PROGRAM, the CONFIGURE_STARTUP packet is constructed in
this way (for the program indexes and meaning of the parameters see
section "Static Programs"):
byte offset | name | description
------------------------------------
2 | mode | desired startup mode (1 in this case)
3 | program | static program index
4-14 | parameters | parameters to configured program
Command: POWERDOWN - power down device (0x0C)
---------------------------------------------
Power down the device. After receiving this command, the device should
power down all light outputs and suspend itself to reduce the power
consumption to a minimum. A device must resume operation after a falling
edge on the INT pin. It is allowed to activate a pull-up resistor on
that pin, to pull the pin to a defined level.
byte offset | name | description
------------------------------------
2-14 | don't care |
Command: BOOTLOADER - start bootloader (0x80)
---------------------------------------------
If a bootloader is installed, jump to the bootloader, otherwise just
restart the device. A magic byte sequence of 0xfc27566b (little endian)
must follow the command byte. Pull down the INT line BEFORE sending this
command, otherwise the bootloader might not be able to detect wether to
start the main firmware or remain within the bootloader code.
byte offset | name | description
---------------------------------
2 | byte1 | magic byte 1 (0x6b)
3 | byte2 | magic byte 2 (0x56)
4 | byte3 | magic byte 3 (0x27)
5 | byte4 | magic byte 4 (0xfc)
6-14 | - | don't care
Command: BOOT_CONFIG - configure bootloader (0x81)
--------------------------------------------------
Set configuration options of the bootloader. Currently the only
options is the start address.
Start address is an unsigned 16-bit integer automatically incremented
by the configured packet size upon each flash command.
byte offset | name | description
---------------------------------
2-3 | start | address to flash to
4-14 | - | don't care
Command: BOOT_INIT - initialize bootloader data buffer (0x82)
-------------------------------------------------------------
This resets and clears the internal bootloader data buffer.
byte offset | name | description
---------------------------------
2-14 | data | payload
Command: BOOT_DATA - store data in the bootloader data buffer (0x83)
--------------------------------------------------------------------
Store data (up to 13 data bytes) at the end of the bootloader data
buffer. If the buffer is full, additional bytes will be ignored.
byte offset | name | description
---------------------------------
2-14 | data | payload
Command: BOOT_CRC_CHECK - compare check-sum (0x84)
--------------------------------------------------
Compare provided CRC-16 checksum against calculated checksum over the
first len bytes of previously received data in the data buffer. If both
checksums do not match, the boot loader MUST immediately pull down the
INT line. The INT line must be held down for the time specified in delay
and be released afterwards. chksum is a little endian unsigned 16 bit
integer.
The CRC calculation uses the polynomial x^16 + x^15 + x^2 + 1 (0xa001)
and 0xffff as initial value.
byte offset | name | description
---------------------------------
2-3 | len | checksum over the first len buffer bytes in the buffer
4-5 | chksum | CRC-16 checksum over the data chunk
6 | delay | time to wait before releasing the INT line
| (in 50ms, maximum 2550ms, jitter +-10ms)
7-14 | - | don't care
Command: BOOT_CRC_FLASH - compare check-sum with flash (0x85)
-------------------------------------------------------------
Compare provided CRC-16 checksum against calculated checksum over
len bytes from flash starting at addr. If both checksums do not match,
the boot loader MUST immediately pull down the INT line. The INT line
must be held down for the time specified in delay and be released
afterwards. Chksum, start and len are unsigned 16 bit little endian
integers.
The CRC calculation uses the polynomial x^16 + x^15 + x^2 + 1 (0xa001)
and 0xffff as initial value.
byte offset | name | description
---------------------------------
2-3 | addr | checksum len bytes starting at this address
4-6 | len | checksum over the first len buffer bytes in the buffer
6-8 | chksum | CRC-16 checksum over the data chunk
9 | delay | time to wait before releasing the INT line
| (in 50ms, maximum 2550ms, jitter +-10ms)
10-14 | - | don't care
Command: BOOT_FLASH - write provided data to flash (0x86)
---------------------------------------------------------
Write the data provided earlier to the flash memory of the device.
The device pulls the interrupt line down upon reception of the command
and releases it on successful completion of the command. This way the
master node is capable of detecting when the successing initial data
packet may be provided by continuously sensing the interrupt line.
After completion of this command the address where to flash to is
incremented by the configured chunk data size.
byte offset | name | description
---------------------------------
2-14 | - | don't care
Command: BOOT_ENTER_APP - start application (0x87)
--------------------------------------------------
Leave bootloader and launch application code.
byte offset | name | description
------------------------------------
2-14 | - | don't care
Static Programs
---------------
This section describes the programs which are (in the default version)
compiled into the firmware.
program "colorwheel", program index 0
-------------------------------------
This program fades throught the HSV color space, with fixed saturation and
value, starting at hue_start. In each step, hue_step is added to the
current hue value, afterwards the device fades to the resulting color (using
fade_step and fade_delay) and waits for the time specified by fade_sleep.
If add_addr is nonzero (attention: signed integer!), the fade ist not
started at hue_start but (hue_start + addr_add * device_address * hue_step).
This program honors the globally defined offsets set with the CONFIG_OFFSETS
command in each step. If a global offset is reconfigured, the new value
will be applied in the next color calculation of this program.
byte offset | name | description
---------------------------------------------------------
0 | fade_step | used for fading to new color
| | (unsigned 8 bit integer)
1 | fade_delay | used for fading to now color
| | (unsigned 8 bit integer)
2 | fade_sleep | sleep between steps (in seconds)
| | (unsigned 8 bit integer)
3-4 | hue_start | start at this hue value
| | (unsigned 16 bit integer
5-6 | hue_step | add this to the hue in each step
| | (signed 16 bit integer)
7 | add_addr | add hue_step address-times before start
| | (signed 8 bit integer)
8 | saturation | saturation
| | (unsigned 8 bit integer)
9 | value | value
| | (unsigned 8 bit integer)
program "random", program index 1
---------------------------------
When this program is started, the pseudo-random generator is initialized
with the seed value. If the use_address-bit within the flags byte is set,
the address of a device is XORed with the seed before initializing the
pseudo-random generator, so the random values also depend on the address of
the device.
In each step, this program generates a new random hue value which is at
least min_distance away from the current hue value. Afterwards the device
fades to the new color (using the generated hue and the configured
saturation and value from the parameters). The parameters fade_step and
fade_delay are used in each fade. If the wait_for_fade-bit within the
flags byte is set, the device waits until the target color is reached.
Afterwards the device sleeps for a configurable amount of time (fade_sleep).
This program honors the globally defined offsets set with the CONFIG_OFFSETS
command in each step. If a global offset is reconfigured, the new value
will be applied in the next color calculation of this program.
flags (1 byte)
--------------
Bits:
MSB LSB
7 6 5 4 3 2 1 0
| | | |
| | | \- use_address -- XOR device address and seed before
| | | initializing the pseudo random generator
| | \--- wait_for_fade -- wait until the (newly generated)
| | target color is reached before sleeping
\---------+----- reserved
byte offset | name | description
----------------------------------------------------------------------
0-1 | seed | used for initializing the random generator
| | (unsigned 16 bit integer)
2 | flags | flags
| | (unsigned 8 bit integer)
3 | fade_step | used for fading to new color
| | (unsigned 8 bit integer)
4 | fade_delay | used for fading to now color
| | (unsigned 8 bit integer)
5-6 | fade_sleep | sleep between steps (in 100ms)
| | (unsigned 16 bit integer)
7 | saturation | saturation
| | (unsigned 8 bit integer)
8 | value | value
| | (unsigned 8 bit integer)
9 | min_distance | minimal distance for new hue value
| | (unsigned 8 bit integer)
program "replay", program index 2
---------------------------------
The commands SAVE_RGB, SAVE_HSV and SAVE_CURRENT stores a color,
fade_step, fade_delay and fade_sleep to the EEPROM. This program replays
the stored colors, from start to end. If repeat is 0, the sequence stops
when end is reached, if repeat is 1, the sequence is restarted from the
beginning and if repeat is 2, the color sequence is played in reverse
order, from end to beginning.
This program honors the globally defined offsets set with the CONFIG_OFFSETS
command for hsv colors in each step. If a global offset is reconfigured,
the new value will be applied in the next color calculation of this program.
byte offset | name | description
----------------------------------------------------------------------
0 | start | index of the first color
| | (unsigned 8 bit integer)
1 | end | index of the last color (included)
| | (unsigned 8 bit integer)
3 | repeat | configure repetition
| | (unsigned 8 bit integer)
4-9 | don't care |