LEDs now operating on button push

Fixed several bugs:
- TCB wasn't running. The datasheet steps were not complete.
- TCA was waking the MCU and causing the main program to run. Added checks
  to ensure program only runs on button or TCB wakeup.
- Fixed some peculiarities with specific RGBLED programs
This commit is contained in:
Brooke 2025-04-28 21:07:46 -04:00
parent 9827a8f6be
commit 4d58a3df74
5 changed files with 36 additions and 14 deletions

View File

@ -19,6 +19,7 @@ ISR(TCB0_INT_vect)
// in this program, this interrupt is only used for timing. // in this program, this interrupt is only used for timing.
// we'll now return to executing loop() // we'll now return to executing loop()
rgb_run_next = 1;
// reset the INTFLAGS - necessary on this series // reset the INTFLAGS - necessary on this series
TCB0.INTFLAGS = intflags; TCB0.INTFLAGS = intflags;
@ -30,12 +31,15 @@ ISR(PORTA_PORT_vect)
uint8_t intflags = PORTA.INTFLAGS; uint8_t intflags = PORTA.INTFLAGS;
// shitty debounce; this is bad practice // shitty debounce; this is bad practice
delay(5); delay(8);
// was our pin changed? // was our pin changed?
if (intflags & PIN2_bm) { if (intflags & PIN2_bm) {
// start or re-start running a program // start or re-start running a program
if (!digitalRead(PIN_PA2)) {
run_rgbprog = 1; // run a new program run_rgbprog = 1; // run a new program
rgb_run_next = 1;
}
} }
// reset the INTFLAGS - necessary on this series // reset the INTFLAGS - necessary on this series

View File

@ -30,17 +30,20 @@ uint8_t (*rgb_program[PROG_COUNT])(uint8_t) = {
uint8_t rgbled[3 * RGB_COUNT]; uint8_t rgbled[3 * RGB_COUNT];
volatile uint8_t rgb_run_next = 0; // set to 1 to run next frame
// configures and enables the 50Hz timer interrupt that is used for RGB program updates // configures and enables the 50Hz timer interrupt that is used for RGB program updates
void conf_rgb_timer() void conf_rgb_timer()
{ {
// this timer will run at half speed. // this timer will run at half speed.
// so 8MHz / 2 (timer prescale) / 2 (CLK_PER) = 2MHz // so 16MHz / 2 (timer prescale) / 2 (CLK_PER) = 4MHz
// this will allow a cycle time with 33333 counts to be 60Hz. // this will allow a cycle time with full counts to be ~61Hz.
disable_rgb_timer(); disable_rgb_timer();
TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc; // prescale timer to run at half speed TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc; // prescale timer to run at half speed
TCB0.CCMP = 33333 - 1; // count to full TCB0.CCMP = 0xffff; // count to full
TCB0.CNT = 0; TCB0.CNT = 0;
} }
@ -56,7 +59,7 @@ uint8_t r, g, b;
#define RAINBOW_OFFSET (1536/5) // offset between each LED #define RAINBOW_OFFSET (1536/5) // offset between each LED
#define RAINBOW_TIMEOUT 240 // how long to show this program #define RAINBOW_TIMEOUT 240 // how long to show this program
#define RAINBOW_SAT 0xff // saturation #define RAINBOW_SAT 0xff // saturation
#define RAINBOW_VAL 0x40 // value (brightness); keep low enough to keep average current down #define RAINBOW_VAL 0x20 // value (brightness); keep low enough to keep average current down
uint16_t rainbow_hue = 0; uint16_t rainbow_hue = 0;
@ -101,23 +104,25 @@ uint8_t rgbp_rainbow(uint8_t init)
// rgb program 2: circle loops with fading // 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_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_BRIGHTNESS 48 // 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 #define CF_FADERATE 6 // how much to fade all LEDs each frame
uint8_t circlefade_idx = 0; uint8_t circlefade_idx = 0;
uint8_t circlefade_delay = 0;
uint8_t rgbp_circlefade(uint8_t init) uint8_t rgbp_circlefade(uint8_t init)
{ {
uint8_t i; uint8_t i;
uint8_t t; uint8_t t;
// set our timer when initializing. otherwise every call is identical // set our timer when initializing. otherwise every call is identical
if (init) { if (init) {
prog_timeout = CF_TIMEOUT; prog_timeout = CF_TIMEOUT;
circlefade_idx = 4; // top LED circlefade_idx = 4; // top LED
} }
if (--prog_timeout) { if (prog_timeout) {
t = (uint8_t)(CF_TIMEOUT - prog_timeout); // get time elapsed t = (uint8_t)(CF_TIMEOUT - prog_timeout); // get time elapsed
t &= 0x3; // light a new LED every 4th loop t &= 0x3; // light a new LED every 4th loop
@ -133,7 +138,7 @@ uint8_t rgbp_circlefade(uint8_t init)
// set the next LED in sequence on to full brightness every 4 cycles // set the next LED in sequence on to full brightness every 4 cycles
if (prog_timeout >= 10) { // as long as >10 loops remain, if (prog_timeout >= 10) { // as long as >10 loops remain,
if (!t) { // then on a loop boundary, light the next LED if (!t) { // then on a loop boundary, light the next LED
rgb.setPixelColor(circlefade_idx, CF_BRIGHTNESS, CF_BRIGHTNESS, CF_BRIGHTNESS); rgb.setPixelColor(circlefade_idx, 56, 16, 44);
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; circlefade_idx = 0;
@ -141,6 +146,8 @@ uint8_t rgbp_circlefade(uint8_t init)
} }
} }
prog_timeout--;
return 1; return 1;
} }

View File

@ -19,8 +19,9 @@
#define enable_rgb_timer() {TCB0.CNT = 0; TCB0.CTRLA |= 1;}; #define enable_rgb_timer() {TCB0.CNT = 0; TCB0.INTFLAGS = 0xff; \
#define disable_rgb_timer() {TCB0.CTRLA &= ~1;}; TCB0.INTCTRL = TCB_CAPT_bm; TCB0.CTRLA |= TCB_ENABLE_bm;};
#define disable_rgb_timer() {TCB0.INTCTRL = 0; TCB0.CTRLA &= ~TCB_ENABLE_bm;};
@ -31,6 +32,10 @@ extern uint8_t (*rgb_program[PROG_COUNT])(uint8_t);
extern volatile uint8_t rgb_run_next;
void conf_rgb_timer(); void conf_rgb_timer();

View File

@ -120,6 +120,12 @@ void setup() {
// mcu program loop // mcu program loop
void loop() { void loop() {
while (!rgb_run_next) {
// __asm("sleep");
}
rgb_run_next = 0;
switch (run_rgbprog) { switch (run_rgbprog) {
case RGB_INIT: { // just started running a program case RGB_INIT: { // just started running a program
digitalWrite(PIN_LED_PWRENA, HIGH); // enable LED power supply, digitalWrite(PIN_LED_PWRENA, HIGH); // enable LED power supply,