diff --git a/badge_firmware/code/inc/btn.h b/badge_firmware/code/inc/btn.h index d593bbb..5870596 100644 --- a/badge_firmware/code/inc/btn.h +++ b/badge_firmware/code/inc/btn.h @@ -17,15 +17,26 @@ #define BTN_PUSH (1 << 0) #define BTN_HELD (1 << 1) -#define BTN_RELEASE (1 << 2) +#define BTN_HELDRT (1 << 2) +#define BTN_RELEASE (1 << 3) #define BTN_PUSH_CB (1 << 4) #define BTN_HELD_CB (1 << 5) -#define BTN_RELEASE_CB (1 << 6) +#define BTN_HELDRT_CB (1 << 6) +#define BTN_RELEASE_CB (1 << 7) #define BTN_DEBOUNCE 11 // how many button ticks to wait before registering press #define BTN_MAX_HOLD (512*30) // longest reported / processed hold time (30s) -#define BTN_HOLD_SHIFT 6 // rshift value to get 1/16th sec hold time +#define BTN_HOLD_SHIFT 5 // rshift value to get 1/16th sec hold time + +#define BTN_HOLD_0_25S 4 +#define BTN_HOLD_0_50S 8 +#define BTN_HOLD_1_00S 16 +#define BTN_HOLD_1_50S 24 +#define BTN_HOLD_2_00S (16 * 2) +#define BTN_HOLD_3_00S (16 * 3) +#define BTN_HOLD_4_00S (16 * 4) +#define BTN_HOLD_5_00S (16 * 5) @@ -36,9 +47,9 @@ typedef struct Btn_t { uint16_t hold_retrig; // hold time retrigger threshold in button ticks, 0 disables uint16_t hold_rt_ctr; // hold retrigger counter - void (*push_cb)(); - void (*held_cb)(); - void (*release_cb)(); + void (*push_cb)(uint8_t); + void (*held_cb)(uint8_t); + void (*release_cb)(uint8_t); } Btn_t; /* diff --git a/badge_firmware/code/inc/led_prog.h b/badge_firmware/code/inc/led_prog.h index a9e385a..bbab581 100644 --- a/badge_firmware/code/inc/led_prog.h +++ b/badge_firmware/code/inc/led_prog.h @@ -10,12 +10,12 @@ -extern void (*ledprog)(); +void ledprog_default(); // set ledprog settings to defaults +void ledprog_change(); // change active ledprog idx +void ledprog_run(); - -void ledprog_default(); -void ledprog_change(); +void ledprog_btn(); // assign buttons to ledprog diff --git a/badge_firmware/code/inc/led_sk6x_spi.h b/badge_firmware/code/inc/led_sk6x_spi.h index 14b0365..7417a75 100644 --- a/badge_firmware/code/inc/led_sk6x_spi.h +++ b/badge_firmware/code/inc/led_sk6x_spi.h @@ -21,6 +21,11 @@ //#define SK6X_HI 0xc0 // 0b11000000, or 0.25/0.75uS on/off //#define SK6X_LO 0xfc // 0b11111100, or 0.75/0.25uS on/off +#define SK6X_ZONE_MAIN 0x01 +#define SK6X_ZONE_SIDE 0x02 +#define SK6X_ZONE_REAR 0x04 +#define SK6X_ZONE_ALL (SK6X_ZONE_MAIN | SK6X_ZONE_SIDE | SK6X_ZONE_REAR) + void led_sk6x_init(); @@ -31,6 +36,9 @@ void led_sk6x_set_all(uint8_t r, uint8_t g, uint8_t b); void led_sk6x_process(); void led_sk6x_update(); +void led_sk6x_zone_ena(uint8_t zone_mask); +void led_sk6x_brightness(uint8_t brightness); + #endif /* CODE_INC_LED_SK6X_SPI_H_ */ diff --git a/badge_firmware/code/inc/led_user.h b/badge_firmware/code/inc/led_user.h index f038ffc..e7d9f2d 100644 --- a/badge_firmware/code/inc/led_user.h +++ b/badge_firmware/code/inc/led_user.h @@ -10,4 +10,9 @@ +void userled_init(); +void userled_set(uint8_t brightness); + + + #endif /* CODE_INC_LED_USER_H_ */ diff --git a/badge_firmware/code/inc/userconf.h b/badge_firmware/code/inc/userconf.h new file mode 100644 index 0000000..64ad99f --- /dev/null +++ b/badge_firmware/code/inc/userconf.h @@ -0,0 +1,36 @@ +/* + * userconf.h + * + * Created on: Aug 3, 2023 + * Author: true + */ + +#ifndef CODE_INC_USERCONF_H_ +#define CODE_INC_USERCONF_H_ + + + +#define UCONF_MAGIC 0x1f + + + +typedef struct UserConf_t { + uint8_t magic; + uint8_t led_prog_idx; + uint8_t led_zone; + uint8_t led_bright; + uint8_t led[15][4]; +} UserConf_t; + + + +extern UserConf_t uconf; + + + +void uconf_save(); +void uconf_restore(uint8_t force_defaults); + + + +#endif /* CODE_INC_USERCONF_H_ */ diff --git a/badge_firmware/code/src/btn.c b/badge_firmware/code/src/btn.c index da2d082..17453ef 100644 --- a/badge_firmware/code/src/btn.c +++ b/badge_firmware/code/src/btn.c @@ -6,11 +6,17 @@ */ -static uint8_t mode = BTN_MODE_IDLE; - +#include +#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); } } } diff --git a/badge_firmware/code/src/led_prog.c b/badge_firmware/code/src/led_prog.c index 5edace5..19b835b 100644 --- a/badge_firmware/code/src/led_prog.c +++ b/badge_firmware/code/src/led_prog.c @@ -8,9 +8,17 @@ #include + +#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; diff --git a/badge_firmware/code/src/led_sk6x_spi.c b/badge_firmware/code/src/led_sk6x_spi.c index bf89137..b0ef52c 100644 --- a/badge_firmware/code/src/led_sk6x_spi.c +++ b/badge_firmware/code/src/led_sk6x_spi.c @@ -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; +} diff --git a/badge_firmware/code/src/led_user.c b/badge_firmware/code/src/led_user.c index beb701a..7a60055 100644 --- a/badge_firmware/code/src/led_user.c +++ b/badge_firmware/code/src/led_user.c @@ -6,3 +6,37 @@ */ +#include "hk32f030m.h" +#include + + + +#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); + } +} diff --git a/badge_firmware/code/src/main.c b/badge_firmware/code/src/main.c index c459435..3588ba7 100644 --- a/badge_firmware/code/src/main.c +++ b/badge_firmware/code/src/main.c @@ -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; + } } diff --git a/badge_firmware/code/src/userconf.c b/badge_firmware/code/src/userconf.c new file mode 100644 index 0000000..0012955 --- /dev/null +++ b/badge_firmware/code/src/userconf.c @@ -0,0 +1,79 @@ +/* + * userconf.c + * + * Created on: Aug 3, 2023 + * Author: true + */ + + +#include +#include + +#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); +}