diff --git a/fw/HackSpaceCon/src/isr.cpp b/fw/HackSpaceCon/src/isr.cpp index 896eeba..b5a1f99 100644 --- a/fw/HackSpaceCon/src/isr.cpp +++ b/fw/HackSpaceCon/src/isr.cpp @@ -1,7 +1,8 @@ #include +#include "rgbled.h" -extern uint8_t run_rgb_program; +extern uint8_t run_rgbprog; // TCB0 general interrupt @@ -27,11 +28,13 @@ ISR(PORTA_PORT_vect) // is the pin low? if (!digitalRead(PIN_PA3)) { // start running a program if one isn't running already - if (!run_rgb_program) run_rgb_program = 1; - } else if (run_rgb_program == 2) { + if (!run_rgbprog) { + run_rgbprog = 1; // run a program + } + } else if (run_rgbprog == 2) { // if we're running a program when the button is released (likely), // then skip this interrupt - run_rgb_program++; + run_rgbprog++; } } } \ No newline at end of file diff --git a/fw/HackSpaceCon/src/main.cpp b/fw/HackSpaceCon/src/main.cpp index 8c61625..b5e766a 100644 --- a/fw/HackSpaceCon/src/main.cpp +++ b/fw/HackSpaceCon/src/main.cpp @@ -61,7 +61,8 @@ enum { PROG_INIT = 1 }; -uint8_t run_rgb_program = 0; +uint8_t run_rgbprog = RGB_PROG_IDLE; +uint8_t rgbprog_idx = 0; @@ -107,13 +108,18 @@ void setup() { // mcu program loop void loop() { - switch (run_rgb_program) { + switch (run_rgbprog) { case RGB_PROG_INIT: { // just started running a program digitalWrite(PIN_PA6, HIGH); // enable LED power supply, delay(10); // wait a moment for LEDs to stabilize, - rgb_program[0](PROG_INIT); // initialize the program, - run_rgb_program++; // and set to running mode. + rgbprog_idx++; // select the next program in sequence, + if (rgbprog_idx > PROG_COUNT) { + rgbprog_idx = 0; + } + + rgb_program[rgbprog_idx](PROG_INIT);// initialize the program, + run_rgbprog++; // and set to running mode. enable_rgb_timer(); // then start the RGB program timebase. @@ -126,7 +132,7 @@ void loop() { rgb.show(); // send updates to the led if (!rgb_program[0](PROG_RUN)) { // then process the next program frame - run_rgb_program = RGB_PROG_IDLE;// until the program says it's done + run_rgbprog = RGB_PROG_IDLE; // until the program says it's done break; } @@ -136,7 +142,7 @@ void loop() { } case RGB_PROG_BTN_RELEASE: { // button released wakes MCU, but we're still running a program - run_rgb_program = RGB_PROG_RUNNING; // so skip processing this cycle and go back to stage 2 + run_rgbprog = RGB_PROG_RUNNING; // so skip processing this cycle and go back to stage 2 idle_cpu(); // we can idle the CPU after doing nothing @@ -146,7 +152,7 @@ void loop() { default: { // no longer running a program disable_rgb_timer(); // disable RGB program timer, digitalWrite(PIN_PA6, LOW); // disable LED power supply, - run_rgb_program = RGB_PROG_IDLE; // and clear run_rgb_program. + run_rgbprog = RGB_PROG_IDLE; // and clear run_rgbprog. sleep_cpu(); // finally, go to sleep in standby mode diff --git a/fw/HackSpaceCon/src/rgbled.cpp b/fw/HackSpaceCon/src/rgbled.cpp index 9920eef..f245ee6 100644 --- a/fw/HackSpaceCon/src/rgbled.cpp +++ b/fw/HackSpaceCon/src/rgbled.cpp @@ -9,15 +9,18 @@ tinyNeoPixel rgb = tinyNeoPixel(RGB_COUNT, PIN_PA1, NEO_GRB, rgbled); +// rgb program prototypes uint8_t rgbp_rainbow(uint8_t init); +uint8_t rgbp_circlefade(uint8_t init); -uint8_t (*rgb_program[1])(uint8_t) = { - rgbp_rainbow +// rgb program function pointer array +uint8_t (*rgb_program[PROG_COUNT])(uint8_t) = { + rgbp_rainbow, + rgbp_circlefade }; -#define RGB_COUNT 5 uint8_t rgbled[3 * RGB_COUNT]; @@ -40,6 +43,8 @@ void conf_rgb_timer() // globals for all rgb programs uint16_t prog_timeout; +uint16_t hue; +uint8_t r, g, b; // rgb program 0: rainbow puke @@ -53,9 +58,7 @@ uint16_t rainbow_hue = 0; uint8_t rgbp_rainbow(uint8_t init) { - uint8_t i; - uint8_t r, g, b; - uint16_t hue; + uint8_t i; // set our timer when initializing. otherwise every call is identical if (init) { @@ -89,4 +92,49 @@ uint8_t rgbp_rainbow(uint8_t init) // done with program return 0; -} \ No newline at end of file +} + + +// rgb program 2: circle loops with fading +#define CF_TIMEOUT 90 // how long to show this program (max 255, ideally (20*loopcount)+10) +#define CF_BRIGHTNESS 64 // how bright to make the LED. don't make too bright or badge will brown out +#define CF_FADERATE 12 // how much to fade all LEDs each frame + +uint8_t circlefade_idx = 0; + +uint8_t rgbp_circlefade(uint8_t init) +{ + uint8_t i; + uint8_t t; + + // set our timer when initializing. otherwise every call is identical + if (init) { + prog_timeout = CF_TIMEOUT; + circlefade_idx = 0; + } + + if (--prog_timeout) { + t = (uint8_t)(CF_TIMEOUT - prog_timeout); // get time elapsed + t &= 0x3; // light a new LED every 4th loop + + // fade each LED down every cycle + for (i = 0; i < (sizeof(rgbled) / sizeof(rgbled[0])); i++) { + if (rgbled[i] >= CF_FADERATE) { + rgbled[i] -= CF_FADERATE; + } else { + rgbled[i] = 0; + } + } + + // set the next LED in sequence on to full brightness every 4 cycles + if (prog_timeout >= 10) { // as long as >10 loops remain, + if (!t) { // then on a loop boundary, light the next LED + rgb.setPixelColor(circlefade_idx, CF_BRIGHTNESS, CF_BRIGHTNESS, CF_BRIGHTNESS); + + if (++circlefade_idx > RGB_COUNT) { // then work on the next LED in sequence + circlefade_idx = 0; + } + } + } + } +} diff --git a/fw/HackSpaceCon/src/rgbled.h b/fw/HackSpaceCon/src/rgbled.h index 1957e32..c1f4f43 100644 --- a/fw/HackSpaceCon/src/rgbled.h +++ b/fw/HackSpaceCon/src/rgbled.h @@ -4,6 +4,7 @@ #define RGB_COUNT 5 +#define PROG_COUNT 2 @@ -15,7 +16,7 @@ extern tinyNeoPixel rgb; extern uint8_t rgbled[3 * RGB_COUNT]; -extern uint8_t (*rgb_program[1])(uint8_t); +extern uint8_t (*rgb_program[PROG_COUNT])(uint8_t);