From 46c68f5d29c2cc8871486ee2a2e46d204c6f8047 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sat, 26 Oct 2019 19:09:02 +0200 Subject: add preliminary ws2812b uart app --- src/app/ws2812b_uart/main.cc | 202 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 src/app/ws2812b_uart/main.cc (limited to 'src/app/ws2812b_uart/main.cc') diff --git a/src/app/ws2812b_uart/main.cc b/src/app/ws2812b_uart/main.cc new file mode 100644 index 0000000..0becbf9 --- /dev/null +++ b/src/app/ws2812b_uart/main.cc @@ -0,0 +1,202 @@ +#include "arch.h" +#include "driver/neopixel.h" +#include "driver/stdin.h" +#include "driver/stdout.h" +#include +#include +#include +#include + +#define NUM_PIXELS 66 + +Adafruit_NeoPixel np(NUM_PIXELS, GPIO::pb0, NEO_GRB+NEO_KHZ800); + +class Blinkencat { + public: + enum Mode : uint8_t { + OFF = 0, + RGBWHEEL_FAST, + RGBWHEEL_SLOW, + RGBFADE_FAST, + RGBFADE_SLOW, + BRIGHTRGBWHEEL_FAST, + BRIGHTRGBWHEEL_SLOW, + BRIGHTRGBFADE_FAST, + BRIGHTRGBFADE_SLOW, + COLD_WHITE, + STROBE, + COLOR_STROBE, + MODE_ENUM_MAX + }; + + Mode mode; + + void setup(void); + void next_mode(void); + void idle(void); + void loop(void); + + Blinkencat() : mode(RGBWHEEL_SLOW) {} +}; + +void Blinkencat::setup(void) +{ + np.setup(); + gpio.input(GPIO::pb1, 0); + gpio.input(GPIO::pd3, 1); + gpio.enable_int(GPIO::pd3); + + // One ADC conversion per four seconds + TCCR1A = 0; + TCCR1B = _BV(CS12) | _BV(CS10); + + // Measure internal 1.1V bandgap using VCC as reference on each Timer 1 overflow + ADMUX = _BV(REFS0) | 0x0e; + ADCSRB = _BV(ADTS2) | _BV(ADTS1); + ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADPS2) | _BV(ADPS1); +} + +void Blinkencat::idle(void) +{ + SMCR = _BV(SE); + asm("sleep"); + SMCR = 0; +} + +void Blinkencat::next_mode(void) +{ + mode = (Mode)((mode + 1) % MODE_ENUM_MAX); +} + +void Blinkencat::loop(void) +{ + static uint16_t rgbwheel_offset = 0; + static uint16_t rgbfade_hsv = 0; + static uint8_t strobe_on = 0; + + /* + // not working due to bad logic levels + if (gpio.read(GPIO::pb1)) { + // Arduino and WS2812 strip are connected in parallel with the battery, + // which will significantly confuse the charging circuit when the + // strip is active while charging. So we make sure that it isn't. + mode = OFF; + } + */ + + switch (mode) { + case OFF: + // the mode may have been set by an ISR, which may in turn have + // been handled immediately after an np.show() call. So we must + // observe the 300us idle time mandated by WS2812. + _delay_ms(1); + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + np.setPixelColor(i, np.Color(0, 0, 0)); + } + np.show(); + idle(); + break; + case RGBWHEEL_FAST: + case RGBWHEEL_SLOW: + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t hsv = (i * 252 + rgbwheel_offset) % 6553; + np.setPixelColor((NUM_PIXELS-1) - i, np.gamma32(np.ColorHSV(hsv * 10, 255, 127))); + } + rgbwheel_offset = (rgbwheel_offset + 10) % 6553; + np.show(); + _delay_ms(1); + if (mode == RGBWHEEL_SLOW) { + _delay_ms(9); + } + break; + case RGBFADE_FAST: + case RGBFADE_SLOW: + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + np.setPixelColor(i, np.ColorHSV(rgbfade_hsv * 10, 255, 63)); + } + rgbfade_hsv = (rgbfade_hsv + 10) % 6553; + np.show(); + _delay_ms(1); + if (mode == RGBFADE_SLOW) { + _delay_ms(99); + } + break; + case BRIGHTRGBWHEEL_FAST: + case BRIGHTRGBWHEEL_SLOW: + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t hsv = (i * 252 + rgbwheel_offset) % 6553; + np.setPixelColor((NUM_PIXELS-1) - i, np.gamma32(np.ColorHSV(hsv * 10))); + } + rgbwheel_offset = (rgbwheel_offset + 10) % 6553; + np.show(); + _delay_ms(1); + if (mode == BRIGHTRGBWHEEL_SLOW) { + _delay_ms(9); + } + break; + case BRIGHTRGBFADE_FAST: + case BRIGHTRGBFADE_SLOW: + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + np.setPixelColor(i, np.ColorHSV(rgbfade_hsv * 10)); + } + rgbfade_hsv = (rgbfade_hsv + 10) % 6553; + np.show(); + _delay_ms(1); + if (mode == BRIGHTRGBFADE_SLOW) { + _delay_ms(99); + } + break; + case COLD_WHITE: + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + np.setPixelColor(i, np.Color(127, 127, 127)); + } + np.show(); + idle(); + break; + case STROBE: + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + np.setPixelColor(i, np.Color(strobe_on, strobe_on, strobe_on)); + } + np.show(); + strobe_on = 127 - strobe_on; + _delay_ms(40); + break; + case COLOR_STROBE: + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + if (strobe_on) { + np.setPixelColor(i, np.ColorHSV(rgbfade_hsv * 10)); + } else { + np.setPixelColor(i, np.Color(0, 0, 0)); + } + } + rgbfade_hsv = (rgbfade_hsv + 50) % 6553; + np.show(); + strobe_on = 127 - strobe_on; + _delay_ms(40); + break; + } +} + +Blinkencat blinkencat; + +int main(void) +{ + arch.setup(); + gpio.setup(); + kout.setup(); + kin.setup(); + + blinkencat.setup(); + + while (1) { + blinkencat.loop(); + while (kin.hasKey()) { + char key = kin.getKey(); + if ((key >= '0') && (key < '0' + blinkencat.MODE_ENUM_MAX)) { + blinkencat.mode = (Blinkencat::Mode)(key - '0'); + } + } + } + + return 0; +} -- cgit v1.2.3