First commit.
This commit is contained in:
201
src/main.cpp
Normal file
201
src/main.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
#include <FastLED.h>
|
||||
#include "main.h"
|
||||
|
||||
#define WS2812B_PIN 14
|
||||
#define LED_DATA_PIN 13 // D7 // Hardware-MOSI
|
||||
#define LED_CLOCK_PIN 14 // D5 // Hardware-CLK
|
||||
#define STATUS_LED_PIN 1
|
||||
#define FIRMWARE_VERSION_MAJOR 1
|
||||
#define FIRMWARE_VERSION_MINOR 3
|
||||
#define MAX_LED_COUNT 10000
|
||||
|
||||
CRGB* leds;
|
||||
uint16_t led_count;
|
||||
uint8_t blink_mode = 0;
|
||||
unsigned long blink_timer_ts;
|
||||
unsigned long blink_mode_timeout_timer_ts;
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
led_count = 256;
|
||||
leds = new CRGB[256];
|
||||
//FastLED.addLeds<WS2812B, WS2812B_PIN, GRB>(leds, 256);
|
||||
FastLED.addLeds<APA102, LED_DATA_PIN, LED_CLOCK_PIN>(leds, 256);
|
||||
FastLED[0].setLeds(leds, 256);
|
||||
pinMode(STATUS_LED_PIN, OUTPUT);
|
||||
set_blink(0);
|
||||
blink_timer_ts = blink_mode_timeout_timer_ts = millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
byte recv = Serial.read();
|
||||
switch(recv) {
|
||||
case 'L': cmd_length(); break;
|
||||
case 'F': cmd_fill(); break;
|
||||
case 'R': cmd_receive(); break;
|
||||
case 'O': cmd_output(); break;
|
||||
case 'C': cmd_clear(); break;
|
||||
case 'V': cmd_version(); break;
|
||||
case 'M': cmd_get_max(); break;
|
||||
default: send_nack(); break;
|
||||
}
|
||||
set_blink(1);
|
||||
}
|
||||
blink();
|
||||
}
|
||||
|
||||
void set_blink(uint8_t mode) {
|
||||
blink_mode = mode;
|
||||
blink_mode_timeout_timer_ts = millis();
|
||||
}
|
||||
|
||||
void blink() {
|
||||
unsigned long now = millis();
|
||||
unsigned long blink_timer = now - blink_timer_ts;
|
||||
unsigned long blink_mode_timeout_timer = now - blink_mode_timeout_timer_ts;
|
||||
|
||||
switch(blink_mode) {
|
||||
case 0: // active until first command is received
|
||||
if(blink_timer < 1500) {
|
||||
status_led_on();
|
||||
} else if(blink_timer < 1600) {
|
||||
status_led_off();
|
||||
} else {
|
||||
blink_timer_ts = now;
|
||||
status_led_on();
|
||||
}
|
||||
break;
|
||||
case 1: // active after receiving a command - ends after 500ms
|
||||
if(blink_timer > 30) {
|
||||
blink_timer_ts = now;
|
||||
status_led_toggle();
|
||||
}
|
||||
if(blink_mode_timeout_timer > 500) {
|
||||
set_blink(2);
|
||||
}
|
||||
break;
|
||||
case 2: // waiting for commands
|
||||
if (blink_timer < 1500) {
|
||||
status_led_off();
|
||||
} else if (blink_timer < 1600) {
|
||||
status_led_on();
|
||||
} else if (blink_timer < 1700) {
|
||||
status_led_off();
|
||||
} else if (blink_timer < 1800) {
|
||||
status_led_on();
|
||||
} else {
|
||||
blink_timer_ts = now;
|
||||
status_led_off();
|
||||
}
|
||||
break;
|
||||
default: // should newer be reached
|
||||
if (blink_timer > 1000) {
|
||||
status_led_toggle();
|
||||
blink_timer_ts = now;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_output() {
|
||||
FastLED.show();
|
||||
send_ack();
|
||||
}
|
||||
|
||||
void cmd_fill() {
|
||||
uint16_t first_led = receive_word();
|
||||
uint16_t cmd_leds = receive_word();
|
||||
CRGB color = receive_color();
|
||||
|
||||
if (first_led <= led_count && cmd_leds>0 && first_led + cmd_leds + 1 <= led_count) {
|
||||
uint16_t end_led = first_led + cmd_leds;
|
||||
for(uint16_t i=first_led; i<end_led; i++) {
|
||||
leds[i] = color;
|
||||
}
|
||||
send_ack();
|
||||
} else {
|
||||
send_nack();
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_receive() {
|
||||
uint16_t first_led = receive_word();
|
||||
uint16_t cmd_leds = receive_word();
|
||||
if (first_led <= led_count && cmd_leds>0 && first_led + cmd_leds + 1 <= led_count) {
|
||||
uint16_t end_led = first_led + cmd_leds;
|
||||
for(uint16_t i=first_led; i<end_led; i++) {
|
||||
leds[i] = receive_color();
|
||||
}
|
||||
send_ack();
|
||||
} else {
|
||||
send_nack();
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_length() {
|
||||
uint16_t new_len = receive_word();
|
||||
|
||||
if (new_len>0 && new_len<=MAX_LED_COUNT) {
|
||||
delete leds;
|
||||
leds = new CRGB[new_len];
|
||||
led_count = new_len;
|
||||
FastLED[0].setLeds(leds, led_count);
|
||||
send_ack();
|
||||
} else {
|
||||
send_nack();
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_clear() {
|
||||
for(uint16_t i=0; i<led_count; i++) {
|
||||
leds[i] = CRGB::Black;
|
||||
}
|
||||
send_ack();
|
||||
}
|
||||
|
||||
void cmd_version() {
|
||||
Serial.write(FIRMWARE_VERSION_MAJOR);
|
||||
Serial.write(FIRMWARE_VERSION_MINOR);
|
||||
send_ack();
|
||||
}
|
||||
|
||||
void cmd_get_max() {
|
||||
Serial.write(MAX_LED_COUNT >> 8);
|
||||
Serial.write(MAX_LED_COUNT & 0xFF);
|
||||
send_ack();
|
||||
}
|
||||
|
||||
void send_ack() {
|
||||
Serial.write('A');
|
||||
}
|
||||
|
||||
void send_nack() {
|
||||
Serial.write('N');
|
||||
}
|
||||
|
||||
uint8_t receive_byte() {
|
||||
while (!Serial.available()) {}
|
||||
return Serial.read();
|
||||
}
|
||||
|
||||
uint16_t receive_word() {
|
||||
return (receive_byte() << 8) | receive_byte();
|
||||
}
|
||||
|
||||
CRGB receive_color() {
|
||||
return CRGB(receive_byte(), receive_byte(), receive_byte());
|
||||
}
|
||||
|
||||
void status_led_on() {
|
||||
digitalWrite(STATUS_LED_PIN, LOW);
|
||||
}
|
||||
|
||||
void status_led_off() {
|
||||
digitalWrite(STATUS_LED_PIN, HIGH);
|
||||
}
|
||||
|
||||
void status_led_toggle() {
|
||||
digitalWrite(STATUS_LED_PIN, !digitalRead(STATUS_LED_PIN));
|
||||
}
|
Reference in New Issue
Block a user