implement atmolight protocol

This commit is contained in:
King Kévin 2015-07-17 10:01:43 +02:00
parent c2678063c8
commit 6b6589e93c
1 changed files with 44 additions and 75 deletions

View File

@ -31,14 +31,12 @@
#include "ws2812b.h" // to control WS2812B LEDs
/* 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)
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[16]; // input from USART, enough space for one fnordlight command or sync sequence
volatile uint8_t uart_in[19]; // input from USART, enough space for one atmolight message
volatile uint8_t uart_in_i = 0; // UART input index
/* flags, set in the interrupts and handled in the main program */
volatile bool uart_flag = false; // data on UART has been received
volatile char uart_char = 0; // UART data
volatile bool command_flag = false; // a command has been received
/* switch off LED */
void led_off(void)
@ -70,39 +68,10 @@ void wdt_init(void)
/* receive UART input */
ISR(USART_RX_vect) { /* UART receive interrupt */
uart_char = getchar(); // save current character
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
if (uart_in_i<sizeof(uart_in)) {
uart_in[uart_in_i] = getchar(); // save current character
uart_in_i++; // got to next one
uart_flag = true; // warm main programm
}
}
@ -129,53 +98,53 @@ void io_init(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
/* 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();
printf(PSTR("welcome on the VLC+fnordlicht+WS2812B AtmoLight\n"));
printf(PSTR("welcome on the VLC+AtmoLight+WS2812B CuVoodoo AtmoLight\n"));
led_off();
while (true) { // endless loop for micro-controller
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;
}
while (command_flag) { // UART input command is ready
led_on();
command_action(); // process command
command_flag = false; // clear flag
led_off();
if (((uart_in_i==1) && !(uart_in[0]==0xff)) ||
((uart_in_i==2) && !(uart_in[1]==0x00)) ||
((uart_in_i==3) && !(uart_in[2]==0x00)) ||
((uart_in_i==4) && !(uart_in[3]==0x0f))) { // wait for start sequence
led_on(); // indicate something is wrong
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;