Compare commits

..

2 Commits

Author SHA1 Message Date
true 010eeae72f fix bugs in circle fade program 2025-04-04 03:01:05 -07:00
true 0ac7f4e7e2 changed code to match board; fixed a couple bugs
was able to put the button on PA2 and confirm PA1 for the LED data. because we're using PA2 for the button, we have async sleep support and no longer need to do all the button checks and mitigations for the partial-async pin which was used before.

compiled code size is slightly larger after removal of mitigations and other minor fixes...
2025-04-04 02:58:24 -07:00
3 changed files with 42 additions and 53 deletions

View File

@ -8,33 +8,29 @@ extern uint8_t run_rgbprog;
// TCB0 general interrupt
ISR(TCB0_INT_vect)
{
// reset the INTFLAGS - necessary on this series
uint8_t intflags = TCB0.INTFLAGS;
TCB0.INTFLAGS = intflags;
uint8_t intflags = TCB0.INTFLAGS;
// in this program, this interrupt is only used for timing.
// we'll now return to executing loop()
// reset the INTFLAGS - necessary on this series
TCB0.INTFLAGS = intflags;
}
// button interrupt
ISR(PORTA_PORT_vect)
{
// reset the INTFLAGS - necessary on this series
uint8_t intflags = PORTA.INTFLAGS;
PORTA.INTFLAGS = intflags;
// shitty debounce; this is bad practice
delay(5);
// was our pin changed?
if (intflags & PIN3_bm) {
// is the pin low?
if (!digitalRead(PIN_PA3)) {
// start running a program if one isn't running already
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_rgbprog++;
}
// start or re-start running a program
run_rgbprog = 1; // run a new program
}
// reset the INTFLAGS - necessary on this series
PORTA.INTFLAGS = intflags;
}

View File

@ -48,12 +48,14 @@
#include "rgbled.h"
#define PIN_LED_PWRENA PIN_PA6
enum {
RGB_PROG_IDLE,
RGB_PROG_INIT,
RGB_PROG_RUNNING,
RGB_PROG_BTN_RELEASE
RGB_IDLE,
RGB_INIT,
RGB_RUNNING
};
enum {
@ -61,7 +63,7 @@ enum {
PROG_INIT = 1
};
uint8_t run_rgbprog = RGB_PROG_IDLE;
uint8_t run_rgbprog = RGB_IDLE;
uint8_t rgbprog_idx = 0;
@ -81,23 +83,22 @@ void sleep_cpu()
// mcu init
void setup() {
// configure PA3 as both edge interrupt input for button
// note: only PA2 and PA6 support async wakeup and thus we can't check for
// falling edge on PA3. we're not using PA6 for the button as a
// future program may use SPI MISO to drive the LEDs.
// because of this, we need to wake up on both edges.
PORTA.DIRCLR = PIN3_bm;
PORTA.PIN3CTRL = PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc;
// configure PA2 as falling edge interrupt for button
// note: only PA2 and PA6 support async wakeup.
// since we're using PA2, we're good to wakeup from a
// falling edge (button pushed) event only.
PORTA.DIRCLR = PIN2_bm;
PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc;
// configure other hardware pins as appropriate
pinMode(PIN_PA1, INPUT_PULLUP); // unused
pinMode(PIN_PA7, INPUT_PULLUP); // unused
pinMode(PIN_PA3, INPUT_PULLUP); // unused, spare pad on board
pinMode(PIN_PA7, INPUT_PULLUP); // unused, voltage passthru
digitalWrite(PIN_PA6, LOW);
pinMode(PIN_PA6, OUTPUT); // LED boost regulator enable
digitalWrite(PIN_PA2, LOW);
pinMode(PIN_PA2, OUTPUT); // LED data
digitalWrite(PIN_PA1, LOW);
pinMode(PIN_PA1, OUTPUT); // LED data
// set up the RGB ~61Hz periodic timer
conf_rgb_timer();
@ -109,12 +110,12 @@ void setup() {
// mcu program loop
void loop() {
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,
case RGB_INIT: { // just started running a program
digitalWrite(PIN_LED_PWRENA, HIGH); // enable LED power supply,
delay(20); // wait a moment for LEDs to stabilize,
rgbprog_idx++; // select the next program in sequence,
if (rgbprog_idx > PROG_COUNT) {
if (rgbprog_idx >= PROG_COUNT) {
rgbprog_idx = 0;
}
@ -128,11 +129,11 @@ void loop() {
break;
}
case RGB_PROG_RUNNING: { // continuing to run a program
case RGB_RUNNING: { // continuing to run a program
rgb.show(); // send updates to the led
if (!rgb_program[0](PROG_RUN)) { // then process the next program frame
run_rgbprog = RGB_PROG_IDLE; // until the program says it's done
// then process the next program frame
if (!rgb_program[rgbprog_idx](PROG_RUN)) {
run_rgbprog = RGB_IDLE; // until the program says it's done
break;
}
@ -141,18 +142,10 @@ void loop() {
break;
}
case RGB_PROG_BTN_RELEASE: { // button released wakes MCU, but we're still running a program
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
break;
}
default: { // no longer running a program
disable_rgb_timer(); // disable RGB program timer,
digitalWrite(PIN_PA6, LOW); // disable LED power supply,
run_rgbprog = RGB_PROG_IDLE; // and clear run_rgbprog.
digitalWrite(PIN_LED_PWRENA, LOW); // disable LED power supply,
run_rgbprog = RGB_IDLE; // and clear run_rgbprog.
sleep_cpu(); // finally, go to sleep in standby mode

View File

@ -110,14 +110,14 @@ uint8_t rgbp_circlefade(uint8_t init)
// set our timer when initializing. otherwise every call is identical
if (init) {
prog_timeout = CF_TIMEOUT;
circlefade_idx = 0;
circlefade_idx = 4; // top LED
}
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
// fade each LED down every frame
for (i = 0; i < (sizeof(rgbled) / sizeof(rgbled[0])); i++) {
if (rgbled[i] >= CF_FADERATE) {
rgbled[i] -= CF_FADERATE;
@ -131,7 +131,7 @@ uint8_t rgbp_circlefade(uint8_t init)
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
if (++circlefade_idx >= RGB_COUNT) { // then work on the next LED in sequence
circlefade_idx = 0;
}
}