implement atmolight protocol
This commit is contained in:
parent
c2678063c8
commit
6b6589e93c
119
firmware/main.c
119
firmware/main.c
|
@ -31,14 +31,12 @@
|
||||||
#include "ws2812b.h" // to control WS2812B LEDs
|
#include "ws2812b.h" // to control WS2812B LEDs
|
||||||
|
|
||||||
/* global variables */
|
/* global variables */
|
||||||
const uint8_t leds_per_channel[WS2812B_NB_CHANNELS] = {11,5,9,11,5,9}; // the led strips (top 1, top 2, left, bottom 1, bottom 2, right)
|
volatile uint8_t uart_in[19]; // input from USART, enough space for one atmolight message
|
||||||
uint8_t nb_leds = 0; // the total number of LEDs (will be calculated on the number of LEDs per channel)
|
volatile uint8_t uart_in_i = 0; // UART input index
|
||||||
volatile uint8_t uart_in[16]; // input from USART, enough space for one fnordlight command or sync sequence
|
|
||||||
|
|
||||||
/* flags, set in the interrupts and handled in the main program */
|
/* flags, set in the interrupts and handled in the main program */
|
||||||
volatile bool uart_flag = false; // data on UART has been received
|
volatile bool uart_flag = false; // data on UART has been received
|
||||||
volatile char uart_char = 0; // UART data
|
volatile char uart_char = 0; // UART data
|
||||||
volatile bool command_flag = false; // a command has been received
|
|
||||||
|
|
||||||
/* switch off LED */
|
/* switch off LED */
|
||||||
void led_off(void)
|
void led_off(void)
|
||||||
|
@ -70,39 +68,10 @@ void wdt_init(void)
|
||||||
|
|
||||||
/* receive UART input */
|
/* receive UART input */
|
||||||
ISR(USART_RX_vect) { /* UART receive interrupt */
|
ISR(USART_RX_vect) { /* UART receive interrupt */
|
||||||
uart_char = getchar(); // save current character
|
if (uart_in_i<sizeof(uart_in)) {
|
||||||
uart_flag = true; // warm main programm
|
uart_in[uart_in_i] = getchar(); // save current character
|
||||||
}
|
uart_in_i++; // got to next one
|
||||||
|
uart_flag = true; // warm main programm
|
||||||
/* process command */
|
|
||||||
void command_action(void)
|
|
||||||
{
|
|
||||||
/* parse command */
|
|
||||||
switch (uart_in[1]) {
|
|
||||||
case 0x01: // set LED colors
|
|
||||||
if (uart_in[0]<nb_leds) { // set LED color
|
|
||||||
for (uint8_t channel = 0; channel<sizeof(leds_per_channel); channel++) { // find right channel
|
|
||||||
if (uart_in[0]<leds_per_channel[channel]) { // find right LED
|
|
||||||
ws2812b_set_led_color(channel,uart_in[0],uart_in[4],uart_in[5],uart_in[6]);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
uart_in[0] -= leds_per_channel[channel]; // go to next channel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // use additional LED setting as signal to show the LEDs
|
|
||||||
ws2812b_show();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x08: // stop color changing
|
|
||||||
ws2812b_show(); // use this as flush command
|
|
||||||
break;
|
|
||||||
case 0x80: // start bootloader
|
|
||||||
case 0x87: // start application
|
|
||||||
ws2812b_off();
|
|
||||||
ws2812b_show();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break; // all other commands are not relevant
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,53 +98,53 @@ void io_init(void)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
uint8_t uart_in_i = 0; // UART input index
|
|
||||||
uint8_t escape_count = 0; // number of escape bytes received
|
|
||||||
|
|
||||||
io_init(); // initialize IOs
|
io_init(); // initialize IOs
|
||||||
|
|
||||||
/* count the total number of LEDs */
|
|
||||||
for (uint8_t i=0; i<sizeof(leds_per_channel); i++) {
|
|
||||||
nb_leds += leds_per_channel[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
led_on();
|
led_on();
|
||||||
printf(PSTR("welcome on the VLC+fnordlicht+WS2812B AtmoLight\n"));
|
printf(PSTR("welcome on the VLC+AtmoLight+WS2812B CuVoodoo AtmoLight\n"));
|
||||||
led_off();
|
led_off();
|
||||||
|
|
||||||
while (true) { // endless loop for micro-controller
|
while (true) { // endless loop for micro-controller
|
||||||
while (uart_flag) {
|
while (uart_flag) {
|
||||||
/* go to next character but next got pass the last
|
|
||||||
* only sync sequences can be longer than 15, but should only be 16
|
|
||||||
* but sometimes (bug) they are longer
|
|
||||||
* then ignore the escape byte until the sequence ends
|
|
||||||
*/
|
|
||||||
uart_in[uart_in_i] = uart_char;
|
|
||||||
if (uart_in_i<sizeof(uart_in)-1) {
|
|
||||||
uart_in_i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uart_char==0x1b) { // escape byte received
|
|
||||||
if (escape_count<15) { // there should be maximum 15 escape bytes. ignore all additional
|
|
||||||
escape_count++; // count number of escape bytes
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (escape_count>=15) { // end of sync sequence
|
|
||||||
uart_in_i = 0; // reset input but don't handle sync sequence
|
|
||||||
}
|
|
||||||
escape_count = 0; // restart count
|
|
||||||
}
|
|
||||||
if (uart_in_i>=15 && escape_count<15) { // end of command
|
|
||||||
command_flag = true; // notify a command is ready
|
|
||||||
uart_in_i = 0; // reset input
|
|
||||||
}
|
|
||||||
uart_flag = false;
|
uart_flag = false;
|
||||||
}
|
if (((uart_in_i==1) && !(uart_in[0]==0xff)) ||
|
||||||
while (command_flag) { // UART input command is ready
|
((uart_in_i==2) && !(uart_in[1]==0x00)) ||
|
||||||
led_on();
|
((uart_in_i==3) && !(uart_in[2]==0x00)) ||
|
||||||
command_action(); // process command
|
((uart_in_i==4) && !(uart_in[3]==0x0f))) { // wait for start sequence
|
||||||
command_flag = false; // clear flag
|
led_on(); // indicate something is wrong
|
||||||
led_off();
|
uart_in_i = 0; // reset if start sequence is not detected
|
||||||
|
} else {
|
||||||
|
led_off();
|
||||||
|
/* process colors on channels */
|
||||||
|
if (uart_in_i==10) { // left atmolight channel received (WS2812B channel 2)
|
||||||
|
for (uint8_t led=0; led<11; led++) {
|
||||||
|
ws2812b_set_led_color(2,led,uart_in[7],uart_in[8],uart_in[9]);
|
||||||
|
}
|
||||||
|
} else if (uart_in_i==13) { // right atmolight channel received (WS2812B channel 5)
|
||||||
|
for (uint8_t led=0; led<11; led++) {
|
||||||
|
ws2812b_set_led_color(5,led,uart_in[10],uart_in[11],uart_in[12]);
|
||||||
|
}
|
||||||
|
} else if (uart_in_i==16) { // top atmolight channel received (WS2812B channel 0+1)
|
||||||
|
for (uint8_t led=0; led<11; led++) {
|
||||||
|
ws2812b_set_led_color(0,led,uart_in[13],uart_in[14],uart_in[15]);
|
||||||
|
}
|
||||||
|
for (uint8_t led=0; led<8; led++) {
|
||||||
|
ws2812b_set_led_color(1,led,uart_in[13],uart_in[14],uart_in[15]);
|
||||||
|
}
|
||||||
|
} else if (uart_in_i==19) { // bottom atmolight channel received (WS2812B channel 3+4)
|
||||||
|
for (uint8_t led=0; led<11; led++) {
|
||||||
|
ws2812b_set_led_color(3,led,uart_in[16],uart_in[17],uart_in[18]);
|
||||||
|
}
|
||||||
|
for (uint8_t led=0; led<8; led++) {
|
||||||
|
ws2812b_set_led_color(4,led,uart_in[16],uart_in[17],uart_in[18]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uart_in_i>=sizeof(uart_in)) { // end of message
|
||||||
|
uart_in_i = 0; // start with next message
|
||||||
|
ws2812b_show(); // show the new colors
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue