main firmware: basic user UI, setting save / restore added
Can now use the buttons to change programs, change active LED zones, change LED brightness and enter and exit programming mode. Exiting programming mode will save settings. Holding MODE upon boot will load defaults (though not overwrite them in EEPROM). Also added basic power management. If the badge is still for 15min, LEDs will go out. When LEDs are blank due to brightness off setting or timeout, they are turned off to save power. Moving badge, entering programming mode, changing the program, or changing brightness will enable the LEDs.
This commit is contained in:
@@ -6,11 +6,17 @@
|
||||
*/
|
||||
|
||||
|
||||
static uint8_t mode = BTN_MODE_IDLE;
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hk32f030m.h"
|
||||
#include "btn.h"
|
||||
|
||||
|
||||
|
||||
// static uint8_t mode = BTN_MODE_IDLE;
|
||||
|
||||
|
||||
|
||||
Btn_t btn[BTN_COUNT] = {0};
|
||||
|
||||
|
||||
@@ -28,6 +34,7 @@ static void btn_check(uint8_t idx, uint8_t state)
|
||||
}
|
||||
} else {
|
||||
btn[idx].held = 0;
|
||||
btn[idx].hold_rt_ctr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +43,9 @@ void btn_tick()
|
||||
uint8_t i;
|
||||
|
||||
// increment hold
|
||||
btn_check(0, BTN1);
|
||||
btn_check(1, BTN2);
|
||||
btn_check(2, BTN3);
|
||||
btn_check(BTN_MODE, GPIOA->IDR & 0x4);
|
||||
btn_check(BTN_PROG, GPIOA->IDR & 0x2);
|
||||
btn_check(BTN_SET, GPIOA->IDR & 0x8);
|
||||
|
||||
// process
|
||||
for (i = 0; i < BTN_COUNT; i++) {
|
||||
@@ -47,14 +54,21 @@ void btn_tick()
|
||||
// release first
|
||||
if (btn[i].held == 0) {
|
||||
// yes, released
|
||||
btn[i].state = BTN_RELEASE;
|
||||
btn[i].state |= BTN_RELEASE;
|
||||
|
||||
// do we trigger hold?
|
||||
} else if (btn[i].hold_time && (btn[i].held >> BTN_HOLD_SHIFT) == btn[i].hold_time) {
|
||||
} else if (btn[i].hold_thresh && (btn[i].held >> BTN_HOLD_SHIFT) >= btn[i].hold_thresh) {
|
||||
// yes, held, but only set if we didn't already
|
||||
if (!(btn[i].state & BTN_HELD)) {
|
||||
btn[i].state = BTN_HELD;
|
||||
btn[i].hold_rt_ctr = btn[i].hold_retrig;
|
||||
} else if (btn[i].hold_retrig) {
|
||||
// retrigger counter
|
||||
btn[i].hold_rt_ctr++;
|
||||
if (btn[i].hold_rt_ctr == btn[i].hold_retrig) {
|
||||
// clear held callback
|
||||
btn[i].state |= BTN_HELDRT;
|
||||
btn[i].hold_rt_ctr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -77,30 +91,28 @@ void btn_callback()
|
||||
if ((s & BTN_PUSH) && !(s & BTN_PUSH_CB)) {
|
||||
btn[i].state |= BTN_PUSH_CB;
|
||||
if (btn[i].push_cb) {
|
||||
btn[i].push_cb();
|
||||
}
|
||||
}
|
||||
|
||||
if (btn[i].hold_retrig) {
|
||||
if (btn[i].hold_rt_ctr) {
|
||||
btn[i].hold_rt_ctr--;
|
||||
} else {
|
||||
btn[i].hold_rt_ctr = btn[i].hold_retrig;
|
||||
btn[i].state &= ~(BTN_HELD_CB);
|
||||
btn[i].push_cb(i);
|
||||
}
|
||||
}
|
||||
|
||||
if ((s & BTN_HELD) && !(s & BTN_HELD_CB)) {
|
||||
btn[i].state |= BTN_HELD_CB;
|
||||
if (btn[i].held_cb) {
|
||||
btn[i].held_cb();
|
||||
btn[i].held_cb(i);
|
||||
}
|
||||
}
|
||||
|
||||
if ((s & BTN_HELDRT) && !(s & BTN_HELD_CB)) {
|
||||
btn[i].state |= BTN_HELDRT_CB;
|
||||
if (btn[i].held_cb) {
|
||||
btn[i].held_cb(i);
|
||||
}
|
||||
}
|
||||
|
||||
if ((s & BTN_RELEASE) && !(s & BTN_RELEASE_CB)) {
|
||||
btn[i].state |= BTN_RELEASE_CB;
|
||||
if (btn[i].release_cb) {
|
||||
btn[i].release_cb();
|
||||
btn[i].release_cb(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,17 @@
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "btn.h"
|
||||
#include "hsv2rgb.h"
|
||||
#include "led_sk6x_spi.h"
|
||||
#include "led_user.h"
|
||||
#include "prng.h"
|
||||
#include "userconf.h"
|
||||
|
||||
|
||||
|
||||
#define LEDPROG_MAX_PROGRAMS 7
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +31,6 @@ void ledprog5_flicker_all();
|
||||
void ledprog6_ramper();
|
||||
|
||||
|
||||
static uint8_t settings[16][4];
|
||||
|
||||
const void (*led_prog_list[])() = {
|
||||
ledprog0_twinkle_white,
|
||||
@@ -35,38 +42,204 @@ const void (*led_prog_list[])() = {
|
||||
ledprog6_ramper
|
||||
};
|
||||
|
||||
void (*ledprog)();
|
||||
static uint8_t led_prog_active = 0;
|
||||
static uint32_t work[4];
|
||||
|
||||
static uint8_t r, g, b;
|
||||
|
||||
static uint8_t prog_mode = 0;
|
||||
static uint8_t prog_tmr = 0;
|
||||
static uint8_t prog_led = 0;
|
||||
static uint8_t prog_idx = 0;
|
||||
|
||||
/*
|
||||
* program pages:
|
||||
* 1-4: 4 program bytes for active led program
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void ledprog_default()
|
||||
{
|
||||
settings[3][2] = 2;
|
||||
settings[3][3] = 30;
|
||||
uconf.led[3][2] = 2;
|
||||
uconf.led[3][3] = 30;
|
||||
|
||||
settings[4][1] = 248;
|
||||
settings[4][2] = 170;
|
||||
settings[4][3] = 16;
|
||||
uconf.led[4][1] = 248;
|
||||
uconf.led[4][2] = 170;
|
||||
uconf.led[4][3] = 16;
|
||||
|
||||
settings[6][1] = 192;
|
||||
settings[6][2] = 30;
|
||||
settings[6][3] = 6;
|
||||
uconf.led[6][1] = 192;
|
||||
uconf.led[6][2] = 30;
|
||||
uconf.led[6][3] = 6;
|
||||
}
|
||||
|
||||
void ledprog_change(uint8_t idx)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
ledprog = led_prog_list[idx];
|
||||
led_prog_active = idx;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
work[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ledprog_btn_push_cb(uint8_t idx)
|
||||
{
|
||||
if (!prog_mode) return;
|
||||
|
||||
switch (idx) {
|
||||
case BTN_MODE: {
|
||||
|
||||
}
|
||||
case BTN_SET: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ledprog_btn_held_cb(uint8_t idx)
|
||||
{
|
||||
if (idx == BTN_PROG) {
|
||||
prog_mode ^= 1;
|
||||
prog_idx = prog_tmr = 0;
|
||||
|
||||
// when leaving programming mode we need to commit settings to flash
|
||||
if (!prog_mode) {
|
||||
uconf.led_prog_idx = led_prog_active;
|
||||
uconf_save();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (prog_mode) {
|
||||
switch (idx) {
|
||||
case BTN_MODE:
|
||||
case BTN_SET: {
|
||||
ledprog_btn_push_cb(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// allow retrigger
|
||||
btn[idx].state &= ~(BTN_HELDRT | BTN_HELDRT_CB);
|
||||
} else {
|
||||
// do not retrigger on these
|
||||
if (btn[idx].state & BTN_HELDRT_CB) return;
|
||||
|
||||
switch (idx) {
|
||||
case BTN_MODE: { // return to user's default program
|
||||
ledprog_change(uconf.led_prog_idx);
|
||||
led_sk6x_brightness(uconf.led_bright ? uconf.led_bright : 1);
|
||||
break;
|
||||
}
|
||||
case BTN_SET: { // change active zones
|
||||
uconf.led_zone++;
|
||||
if (uconf.led_zone > 7) uconf.led_zone = 1;
|
||||
led_sk6x_zone_ena(uconf.led_zone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ledprog_btn_release_cb(uint8_t idx)
|
||||
{
|
||||
if (btn[idx].state & BTN_HELD) {
|
||||
btn[idx].state = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (prog_mode) {
|
||||
switch (idx) {
|
||||
case BTN_PROG: { // change program variable page
|
||||
prog_idx++;
|
||||
if (prog_idx >= 4) prog_idx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (idx) {
|
||||
case BTN_MODE: { // change active program
|
||||
led_prog_active++;
|
||||
if (led_prog_active >= LEDPROG_MAX_PROGRAMS) led_prog_active = 0;
|
||||
ledprog_change(led_prog_active);
|
||||
|
||||
// increase brightness if we are dark
|
||||
if (uconf.led_bright) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
case BTN_PROG: { // change brightness
|
||||
uconf.led_bright++;
|
||||
if (uconf.led_bright > 5) uconf.led_bright = 0;
|
||||
led_sk6x_brightness(uconf.led_bright);
|
||||
break;
|
||||
}
|
||||
case BTN_SET: { // do nothing?
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear any button state as button is now idle
|
||||
btn[idx].state = 0;
|
||||
}
|
||||
|
||||
void ledprog_btn()
|
||||
{
|
||||
btn[BTN_PROG].held_cb = ledprog_btn_held_cb;
|
||||
btn[BTN_PROG].release_cb = ledprog_btn_release_cb;
|
||||
btn[BTN_PROG].hold_thresh = BTN_HOLD_1_00S;
|
||||
|
||||
btn[BTN_MODE].push_cb = ledprog_btn_push_cb;
|
||||
btn[BTN_MODE].held_cb = ledprog_btn_held_cb;
|
||||
btn[BTN_MODE].release_cb = ledprog_btn_release_cb;
|
||||
btn[BTN_MODE].hold_thresh = BTN_HOLD_1_00S;
|
||||
btn[BTN_MODE].hold_retrig = 10;
|
||||
|
||||
btn[BTN_SET].push_cb = ledprog_btn_push_cb;
|
||||
btn[BTN_SET].held_cb = ledprog_btn_held_cb;
|
||||
btn[BTN_SET].release_cb = ledprog_btn_release_cb;
|
||||
btn[BTN_SET].hold_thresh = BTN_HOLD_1_00S;
|
||||
btn[BTN_SET].hold_retrig = 10;
|
||||
}
|
||||
|
||||
void ledprog_run()
|
||||
{
|
||||
if (prog_mode) {
|
||||
// we need to see the LEDs
|
||||
if (!uconf.led_bright) {
|
||||
uconf.led_bright++;
|
||||
led_sk6x_brightness(uconf.led_bright);
|
||||
}
|
||||
|
||||
// 2 second LED flash timer
|
||||
if (!prog_tmr) prog_led = prog_idx + 1;
|
||||
|
||||
// flash LED to indicate the page we are programming
|
||||
if (prog_led) {
|
||||
switch (prog_tmr & 0x1f) {
|
||||
case 0x00: {
|
||||
userled_set(255);
|
||||
break;
|
||||
}
|
||||
case 0x0a: {
|
||||
userled_set(0);
|
||||
prog_led--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prog_tmr++;
|
||||
}
|
||||
|
||||
// always run a program
|
||||
led_prog_list[led_prog_active]();
|
||||
}
|
||||
|
||||
void ledprogi_twinkle(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
uint8_t x;
|
||||
@@ -82,7 +255,7 @@ void ledprogi_twinkle(uint8_t r, uint8_t g, uint8_t b)
|
||||
}
|
||||
|
||||
/*
|
||||
* settings:
|
||||
* uconf.led:
|
||||
* 0 dwell
|
||||
* 1 threshold
|
||||
*/
|
||||
@@ -92,7 +265,7 @@ void ledprog0_twinkle_white()
|
||||
}
|
||||
|
||||
/*
|
||||
* settings:
|
||||
* uconf.led:
|
||||
* 0 dwell
|
||||
* 1 threshold
|
||||
*/
|
||||
@@ -131,7 +304,7 @@ void ledprog1_twinkle_rgb_rand()
|
||||
|
||||
|
||||
/*
|
||||
* settings:
|
||||
* uconf.led:
|
||||
* 0 dwell
|
||||
* 1 threshold
|
||||
* 2 hue
|
||||
@@ -139,13 +312,13 @@ void ledprog1_twinkle_rgb_rand()
|
||||
*/
|
||||
void ledprog2_twinkle_rgb_set()
|
||||
{
|
||||
hsv2rgb_8b(settings[2][2] * 6, 255, settings[2][3], &r, &g, &b);
|
||||
hsv2rgb_8b(uconf.led[2][2] * 6, 255, uconf.led[2][3], &r, &g, &b);
|
||||
|
||||
ledprogi_twinkle(r, g, b);
|
||||
}
|
||||
|
||||
/*
|
||||
* settings:
|
||||
* uconf.led:
|
||||
* 0 dwell
|
||||
* 1 threshold
|
||||
* 2 speed
|
||||
@@ -159,7 +332,7 @@ void ledprog3_rainbow()
|
||||
uint8_t i;
|
||||
uint16_t w;
|
||||
|
||||
work[0] += (settings[3][2] * 6) + 1;
|
||||
work[0] += (uconf.led[3][2] * 6) + 1;
|
||||
work[0] %= 1536;
|
||||
w = work[0];
|
||||
|
||||
@@ -167,7 +340,7 @@ void ledprog3_rainbow()
|
||||
hsv2rgb_8b(w, 255, 255, &r, &g, &b);
|
||||
led_sk6x_set(i, r, g, b);
|
||||
|
||||
w += (settings[3][3] * 6) + 1;
|
||||
w += (uconf.led[3][3] * 6) + 1;
|
||||
w %= 1536;
|
||||
}
|
||||
}
|
||||
@@ -177,14 +350,14 @@ void ledprogi_flicker()
|
||||
uint16_t h;
|
||||
uint8_t x;
|
||||
|
||||
h = settings[4][2] * 6;
|
||||
h = uconf.led[4][2] * 6;
|
||||
|
||||
x = prng_get8();
|
||||
|
||||
if (x > settings[4][1]) {
|
||||
if (x > uconf.led[4][1]) {
|
||||
x = 255;
|
||||
} else {
|
||||
x = settings[4][3];
|
||||
x = uconf.led[4][3];
|
||||
}
|
||||
|
||||
x &= ~0x07;
|
||||
@@ -194,7 +367,7 @@ void ledprogi_flicker()
|
||||
}
|
||||
|
||||
/*
|
||||
* settings:
|
||||
* uconf.led:
|
||||
* 0 dwell
|
||||
* 1 threshold
|
||||
* 2 hue
|
||||
@@ -207,7 +380,7 @@ void ledprog4_flicker_same()
|
||||
}
|
||||
|
||||
/*
|
||||
* settings (uses ledprog4)
|
||||
* uconf.led (uses ledprog4)
|
||||
* 0 dwell
|
||||
* 1 threshold
|
||||
* 2 hue
|
||||
@@ -224,7 +397,7 @@ void ledprog5_flicker_all()
|
||||
}
|
||||
|
||||
/*
|
||||
* settings
|
||||
* uconf.led
|
||||
* 0 dwell
|
||||
* 1 speed
|
||||
* 2 hue
|
||||
@@ -245,11 +418,11 @@ void ledprog6_ramper()
|
||||
uint8_t fr;
|
||||
|
||||
|
||||
h = settings[6][2] * 6;
|
||||
fr = settings[6][3] & 0x3f;
|
||||
h = uconf.led[6][2] * 6;
|
||||
fr = uconf.led[6][3] & 0x3f;
|
||||
|
||||
// speed -64 to -1, +1 to +64
|
||||
spd = (settings[6][1] >> 1) - 64;
|
||||
spd = (uconf.led[6][1] >> 1) - 64;
|
||||
if (spd >= 0) spd++;
|
||||
work[0] += spd;
|
||||
work[0] &= 0xfff;
|
||||
|
||||
@@ -53,10 +53,13 @@
|
||||
|
||||
const uint8_t sk6x_map[8] = {0, 1, 2, 3, 4, 7, 6, 5};
|
||||
|
||||
uint8_t sk6x_led[SK6X_LED_MAX_COUNT][3]; // G-R-B order
|
||||
uint8_t sk6x_buf[SK6X_BUF_SIZE];
|
||||
static uint8_t sk6x_led[SK6X_LED_MAX_COUNT][3]; // G-R-B order
|
||||
static uint8_t sk6x_buf[SK6X_BUF_SIZE];
|
||||
|
||||
uint8_t sk6x_brightness = 3;
|
||||
static uint8_t sk6x_brightness = 0;
|
||||
static uint8_t sk6x_led_enabled = 0;
|
||||
|
||||
static uint8_t sk6x_zone = SK6X_ZONE_ALL;
|
||||
|
||||
|
||||
|
||||
@@ -80,14 +83,31 @@ __attribute__ ((long_call, section(".ramfunc"))) void led_sk6x_process()
|
||||
uint16_t n = 0;
|
||||
uint8_t b[8];
|
||||
|
||||
uint8_t v;
|
||||
|
||||
j = 0;
|
||||
|
||||
// do nothing if LEDs are turned off
|
||||
if (!sk6x_led_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// pack RGB values into 5-bits-per-bit format
|
||||
for (i = 0; i < SK6X_LED_MAX_COUNT; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
// pack values for next color
|
||||
uint8_t *p = b;
|
||||
SK6X_FILL(sk6x_led[sk6x_map[i]][j] >> sk6x_brightness);
|
||||
|
||||
v = sk6x_led[sk6x_map[i]][j] >> sk6x_brightness;
|
||||
if (i <= 4) {
|
||||
if (!(sk6x_zone & SK6X_ZONE_MAIN)) v = 0;
|
||||
} else if (i <= 5) {
|
||||
if (!(sk6x_zone & SK6X_ZONE_REAR)) v = 0;
|
||||
} else {
|
||||
if (!(sk6x_zone & SK6X_ZONE_SIDE)) v = 0;
|
||||
}
|
||||
|
||||
SK6X_FILL(v);
|
||||
|
||||
// pack 8 bits into 5 bytes in final buffer
|
||||
sk6x_buf[n + 0] = (b[0] << 3) | (b[1] >> 2);
|
||||
@@ -102,11 +122,36 @@ __attribute__ ((long_call, section(".ramfunc"))) void led_sk6x_process()
|
||||
|
||||
__attribute__ ((long_call, section(".ramfunc"))) void led_sk6x_update()
|
||||
{
|
||||
// configure MOSI pin and bit depth
|
||||
spi_mosi_sel(SPI_MOSI_LED);
|
||||
// turn on / off LEDs based on brightness setting
|
||||
if (sk6x_brightness >= 8) {
|
||||
// leds should be OFF
|
||||
|
||||
// begin sending data
|
||||
// if already off, we're done
|
||||
if (!sk6x_led_enabled) return;
|
||||
// otherwise, blank the LEDs
|
||||
led_sk6x_process();
|
||||
} else {
|
||||
// leds should be ON
|
||||
if (!sk6x_led_enabled) {
|
||||
// they aren't on, so turn them on
|
||||
adxl345_set_intr_polarity(ADXL345_INTR_ACTIVE_LO);
|
||||
sk6x_led_enabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// configure MOSI pin and bit depth, then send LED data
|
||||
spi_mosi_sel(SPI_MOSI_LED);
|
||||
spi_xfer(sk6x_buf, 0, sizeof(sk6x_buf), SPI_NO_CALLBACK);
|
||||
|
||||
// turn off LEDs based on brightness setting
|
||||
if (sk6x_brightness >= 8) {
|
||||
// leds should be OFF
|
||||
if (sk6x_led_enabled) {
|
||||
// LEDs should be blanked, so we can turn them off now
|
||||
adxl345_set_intr_polarity(ADXL345_INTR_ACTIVE_HI);
|
||||
sk6x_led_enabled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((long_call, section(".ramfunc"))) void led_sk6x_set(uint8_t index, uint8_t r, uint8_t g, uint8_t b)
|
||||
@@ -144,3 +189,18 @@ void led_sk6x_cb()
|
||||
{
|
||||
// there is nothing to handle after updating LEDs
|
||||
}
|
||||
|
||||
void led_sk6x_zone_ena(uint8_t zone_mask)
|
||||
{
|
||||
sk6x_zone = zone_mask & SK6X_ZONE_ALL;
|
||||
}
|
||||
|
||||
void led_sk6x_brightness(uint8_t brightness)
|
||||
{
|
||||
if (brightness >= 5) brightness = 5;
|
||||
|
||||
if (brightness == 0) brightness = 8;
|
||||
else brightness = 5 - brightness;
|
||||
|
||||
sk6x_brightness = brightness;
|
||||
}
|
||||
|
||||
@@ -6,3 +6,37 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "hk32f030m.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
#define USERLED_IPORT GPIOC // i2c port/pin
|
||||
#define USERLED_IPIN 6
|
||||
|
||||
#define USERLED_LPORT GPIOD // led port/pin
|
||||
#define USERLED_LPIN 7
|
||||
|
||||
|
||||
|
||||
void userled_init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void userled_set(uint8_t brightness)
|
||||
{
|
||||
if (!brightness) {
|
||||
USERLED_IPORT->MODER &= ~(0x3 << (USERLED_IPIN * 2));
|
||||
USERLED_IPORT->MODER |= (GPIO_Mode_IN << (USERLED_IPIN * 2));
|
||||
|
||||
USERLED_LPORT->BRR = (1 << USERLED_LPIN);
|
||||
} else {
|
||||
// set i2c port low while LED is lit
|
||||
USERLED_IPORT->MODER &= ~(0x3 << (USERLED_IPIN * 2));
|
||||
USERLED_IPORT->MODER |= (GPIO_Mode_OUT << (USERLED_IPIN * 2));
|
||||
USERLED_IPORT->BRR = (1 << USERLED_IPIN);
|
||||
|
||||
USERLED_LPORT->BSRR = (1 << USERLED_LPIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,18 +19,23 @@
|
||||
#include "prng.h"
|
||||
#include "spi.h"
|
||||
#include "timer.h"
|
||||
#include "userconf.h"
|
||||
|
||||
|
||||
|
||||
#define GPIO_RCC_AHB_GPIO_ALL RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | \
|
||||
RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD
|
||||
|
||||
#define NO_MOVE_SLEEP_TIME (15 * 60) * 32
|
||||
|
||||
|
||||
|
||||
static uint32_t uptime = 0; // uptime in seconds
|
||||
volatile uint16_t cnt = 0; // 1/1000 second tick
|
||||
static uint16_t cnt2 = 0; // low priority loop check
|
||||
|
||||
static uint32_t no_move_ticks; // keep track of how long we are still
|
||||
|
||||
|
||||
|
||||
static void gpio_init()
|
||||
@@ -150,17 +155,18 @@ int main(void)
|
||||
adxl345_init();
|
||||
adxl345_tick();
|
||||
|
||||
// load user config, unless SET button is held, in which case we restore defaults
|
||||
uconf_restore(!(GPIOA->IDR & (1 << 3)));
|
||||
|
||||
// configure prng
|
||||
tinymt32_init(&tinymt32_s, (adxl.x << 16) | (adxl.y << 8) | adxl.z);
|
||||
|
||||
// configure addressable LEDs
|
||||
led_sk6x_init();
|
||||
|
||||
ledprog_default();
|
||||
ledprog_change(6);
|
||||
|
||||
// configure user input
|
||||
btn_init();
|
||||
ledprog_btn();
|
||||
|
||||
// configure mainline timer
|
||||
#ifdef DEBUG
|
||||
@@ -183,7 +189,7 @@ int main(void)
|
||||
|
||||
// led programs (128Hz)
|
||||
if ((cnt2 & 0x7) == 0) {
|
||||
if (ledprog) ledprog();
|
||||
ledprog_run();
|
||||
|
||||
// stuff next LED bits
|
||||
led_sk6x_process();
|
||||
@@ -210,44 +216,22 @@ __attribute__ ((long_call, section(".ramfunc"))) void TIM6_IRQHandler()
|
||||
btn_tick();
|
||||
}
|
||||
|
||||
// temp: run LED program
|
||||
/*
|
||||
static uint8_t v[3];
|
||||
static uint8_t x = 0;
|
||||
if (!(cnt % 4)) {
|
||||
v[x]++;
|
||||
if (!v[x]) {
|
||||
x++;
|
||||
if (x >= 3) x = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// run next LED program
|
||||
|
||||
/*
|
||||
uint8_t w[2];
|
||||
w[0] = v[0] >> 2;
|
||||
w[1] = v[1] >> 2;
|
||||
w[2] = v[2] >> 2;
|
||||
led_sk6x_set(0, w[0], w[1], w[2]);
|
||||
led_sk6x_set(1, w[1], w[2], w[0]);
|
||||
led_sk6x_set(2, w[2], w[0], w[1]);
|
||||
led_sk6x_set(3, w[1], w[2], w[0]);
|
||||
led_sk6x_set(4, w[0], w[1], w[2]);
|
||||
led_sk6x_set(5, w[0], w[1], w[2]);
|
||||
led_sk6x_set(6, w[1], w[2], w[0]);
|
||||
led_sk6x_set(7, w[2], w[0], w[1]);
|
||||
*/
|
||||
/*
|
||||
for (int i = 1; i < 8; i++) {
|
||||
led_sk6x_set(i, v[0] + (i * 32), v[1] + (i * 32), v[2] + (i * 32));
|
||||
}
|
||||
*/
|
||||
|
||||
// accelerometer: tick
|
||||
if ((cnt & 0x3f) == 0x3f) {
|
||||
// accelerometer: tick 32Hz
|
||||
if ((cnt & 0x1f) == 0x1e) {
|
||||
adxl345_tick();
|
||||
|
||||
// should we sleep?
|
||||
// todo: make this interrupt driven, and tune required accel value
|
||||
if (adxl345_movement() < 6) {
|
||||
if (no_move_ticks >= NO_MOVE_SLEEP_TIME) {
|
||||
led_sk6x_brightness(0);
|
||||
} else no_move_ticks++;
|
||||
} else {
|
||||
if (no_move_ticks >= NO_MOVE_SLEEP_TIME) {
|
||||
led_sk6x_brightness(uconf.led_bright);
|
||||
}
|
||||
no_move_ticks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
79
badge_firmware/code/src/userconf.c
Normal file
79
badge_firmware/code/src/userconf.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* userconf.c
|
||||
*
|
||||
* Created on: Aug 3, 2023
|
||||
* Author: true
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hk32f030m.h"
|
||||
|
||||
#include "userconf.h"
|
||||
|
||||
#include "led_prog.h"
|
||||
#include "led_sk6x_spi.h"
|
||||
|
||||
|
||||
|
||||
#define EEPROM_BASE_ADDR 0x0c000000;
|
||||
|
||||
|
||||
|
||||
UserConf_t uconf = {0};
|
||||
|
||||
|
||||
|
||||
void uconf_save()
|
||||
{
|
||||
uint8_t i;
|
||||
UserConf_t usave;
|
||||
|
||||
uint8_t *eeprom = (uint8_t *)EEPROM_BASE_ADDR;
|
||||
uint8_t *u8save = (uint8_t *)&usave;
|
||||
|
||||
memcpy((void *)&usave, (void *)&uconf, sizeof(uconf));
|
||||
|
||||
// never save brightness as minimum value
|
||||
if (!usave.led_bright) usave.led_bright++;
|
||||
|
||||
// commit bytes to eeprom only if they differ
|
||||
for (i = 0; i < sizeof(uconf); i++) {
|
||||
if (*eeprom != *u8save) {
|
||||
// erase byte
|
||||
EEPROM_EraseByte((uint32_t)eeprom);
|
||||
|
||||
// write new byte
|
||||
EEPROM_ProgramByte((uint32_t)eeprom, *u8save);
|
||||
}
|
||||
|
||||
eeprom++;
|
||||
u8save++;
|
||||
}
|
||||
}
|
||||
|
||||
void uconf_restore(uint8_t force_defaults)
|
||||
{
|
||||
uint8_t *eeprom = (uint8_t *)EEPROM_BASE_ADDR;
|
||||
|
||||
if ((*eeprom != 0x1f) || force_defaults) {
|
||||
// nothing to restore. load defaults instead
|
||||
uconf.magic = UCONF_MAGIC;
|
||||
|
||||
uconf.led_prog_idx = 3; // rainbow
|
||||
uconf.led_bright = 3; // 50% brightness
|
||||
uconf.led_zone = 7; // all zones active
|
||||
|
||||
ledprog_default();
|
||||
} else {
|
||||
// copy from eeprom to uconf
|
||||
memcpy((void *)&uconf, (void *)eeprom, sizeof(uconf));
|
||||
}
|
||||
|
||||
// set settings from user config
|
||||
ledprog_change(uconf.led_prog_idx);
|
||||
led_sk6x_zone_ena(uconf.led_zone);
|
||||
led_sk6x_brightness(uconf.led_bright);
|
||||
}
|
||||
Reference in New Issue
Block a user