migrate code to AS7, including fucked up arduino import
arduino as a library will not build with -flto. I can't figure it out. so we waste some space compared to what platformio was building. oh well. there's still over 1K of space left for programs.
This commit is contained in:
162
fw/HackSpaceCon_AS7/HSC_Wand/wand_program.cpp
Normal file
162
fw/HackSpaceCon_AS7/HSC_Wand/wand_program.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
hackspacecon wand firmware
|
||||
|
||||
initially written by true
|
||||
rgb programs and further hacking by 000000widow
|
||||
|
||||
----
|
||||
|
||||
this version was hacked to work with AS7.
|
||||
|
||||
the resulting binary at time of porting takes an additional
|
||||
531 bytes of flash and 8 bytes of SRAM. I do not know why.
|
||||
|
||||
|
||||
operation workflow:
|
||||
|
||||
- at initial reset (battery inserted), set up GPIO and peripherals. this
|
||||
includes setting up button wake interrupt. sleep MCU into standby mode.
|
||||
|
||||
- when button state changes, MCU will wake up and process the interrupt.
|
||||
if button is pushed (btn gpio is low), prepare to run next RGB program.
|
||||
|
||||
- rgb program setup involves turning on power to the LEDs and enabling
|
||||
TCB0 periodic timer to interrupt every ~61Hz. this timer interrupt
|
||||
does not handle the rgb program, but will wake the CPU which resumes
|
||||
processing in the loop() function.
|
||||
|
||||
- call the rgb program with the `init` parameter set to 1. idle the CPU.
|
||||
|
||||
- rgb prog timer will interrupt every ~61Hz. this will wake the CPU and
|
||||
send the previously rendered LED data, then call the rgb prog function.
|
||||
afterward, the CPU idles. process repeats until the rgb prog fn returns 0.
|
||||
|
||||
- every time the rgb program is run, the rgb data to send is updated.
|
||||
the data is not actually sent until next wakeup in less than 16.4ms.
|
||||
this allows the functions to have variable processing time, but the
|
||||
output to have a consistent ~61Hz (~16.4ms) timing.
|
||||
|
||||
- once rgb program has finalized, clean up state, disable LED power, and sleep
|
||||
the CPU in standby mode. MCU will wake again once the button is activated.
|
||||
|
||||
|
||||
todo:
|
||||
- test the code
|
||||
- set the RGB output data in the sample rainbow puke program
|
||||
- add more programs
|
||||
- support incrementing or randomly selecting the next program on each button push
|
||||
- run TCB0 in standby mode to save a little more power
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "rgbled.h"
|
||||
|
||||
|
||||
#define PIN_LED_PWRENA PIN_PA6
|
||||
|
||||
|
||||
|
||||
enum {
|
||||
RGB_IDLE,
|
||||
RGB_INIT,
|
||||
RGB_RUNNING
|
||||
};
|
||||
|
||||
enum {
|
||||
PROG_RUN = 0,
|
||||
PROG_INIT = 1
|
||||
};
|
||||
|
||||
uint8_t run_rgbprog = RGB_IDLE;
|
||||
uint8_t rgbprog_idx = 0;
|
||||
|
||||
|
||||
|
||||
void idle_cpu()
|
||||
{
|
||||
SLPCTRL.CTRLA = SLPCTRL_SMODE_IDLE_gc | SLPCTRL_SEN_bm;
|
||||
__asm("sleep");
|
||||
}
|
||||
|
||||
void sleep_cpu()
|
||||
{
|
||||
SLPCTRL.CTRLA = SLPCTRL_SMODE_STDBY_gc | SLPCTRL_SEN_bm;
|
||||
__asm("sleep");
|
||||
}
|
||||
|
||||
|
||||
// mcu init
|
||||
void setup() {
|
||||
// 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_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_PA1, LOW);
|
||||
pinMode(PIN_PA1, OUTPUT); // LED data
|
||||
|
||||
// set up the RGB ~61Hz periodic timer
|
||||
conf_rgb_timer();
|
||||
|
||||
// enable global interrupts (though they should already be enabled?)
|
||||
sei();
|
||||
}
|
||||
|
||||
// mcu program loop
|
||||
void loop() {
|
||||
switch (run_rgbprog) {
|
||||
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) {
|
||||
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.
|
||||
|
||||
idle_cpu(); // we can idle CPU after running the program
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RGB_RUNNING: { // continuing to run a program
|
||||
rgb.show(); // send updates to the led
|
||||
// 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;
|
||||
}
|
||||
|
||||
idle_cpu(); // we can idle CPU after running the program
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: { // no longer running a program
|
||||
disable_rgb_timer(); // disable RGB program timer,
|
||||
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
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user