implement idle mode, re-implement missing accelerometer movement code

This commit is contained in:
true 2024-10-26 18:35:26 -07:00
parent e309c01d47
commit 279c7d3c68
6 changed files with 147 additions and 74 deletions

View File

@ -167,7 +167,18 @@ void oled_update_done()
}
// power saving
// todo: don't hardcode the movement values
if (accel_get_movement() > 3) {
idle_go_sleep = 0;
idle_time_still = 0;
idle_time_menu = 0;
}
// start going to sleep if the option is enabled and if we've been still for enough time
if (uconf.sleep_timeout && (idle_time_still > uconf.sleep_timeout)) {
idle_go_sleep = 1;
}
#ifdef MENU_TIMEOUT_TO_NAMETAG
@ -210,68 +221,104 @@ void lowprio_task() {
// can corrupt transactions
SYS_DisableAllIrq(&interrupt_flags);
// temporary: re-send sub interrupts, sub button holds, enable rgb_hwen
if (flags_lo & FLAG_CH32V_RESEND_CONF) {
flags_lo &= ~FLAG_CH32V_RESEND_CONF;
ch32sub_intr_defaults();
btn_commit_hold();
ch32sub_rgb_hwen(1);
}
// process sub MCU interrupt, if pending
ch32sub_process();
if (flags_lo & FLAG_RGBLED_SEND) {
flags_lo &= ~FLAG_RGBLED_SEND;
rgbled_send();
}
if (flags_lo & FLAG_ACCEL_POLL) {
flags_lo &= ~FLAG_ACCEL_POLL;
accel_poll();
}
// send the last oled frame data
if (flags_lo & FLAG_OLED_UPDATE) {
flags_lo &= ~FLAG_OLED_UPDATE;
/*** oled ***/
if (oled.callback && !(oled.state & SSD1306_STATE_BUSY)) {
if (ssd1306_cb_get()) {
oled.callback();
}
// todo: implement proper sleep mode that saves power
// and wakes up on interrupt, instead of this
if (!idle_go_sleep) {
// temporary: re-send sub interrupts, sub button holds, enable rgb_hwen
if (flags_lo & FLAG_CH32V_RESEND_CONF) {
flags_lo &= ~FLAG_CH32V_RESEND_CONF;
ch32sub_intr_defaults();
btn_commit_hold();
ch32sub_rgb_hwen(1);
}
// update
// only update this frame if we're not in the middle of starting up
if (uptime) {
// process other tasks
if (oled.state & SSD1306_STATE_INITIALIZED) {
oled.callback = oled_update_done;
}
ssd1306_update();
// process sub MCU interrupt, if pending
ch32sub_process();
if (flags_lo & FLAG_RGBLED_SEND) {
flags_lo &= ~FLAG_RGBLED_SEND;
rgbled_send();
}
cpu_use = SysTick->CNT;
// send the last oled frame data
if (flags_lo & FLAG_OLED_UPDATE) {
flags_lo &= ~FLAG_OLED_UPDATE;
if (oled.callback && !(oled.state & SSD1306_STATE_BUSY)) {
if (ssd1306_cb_get()) {
oled.callback();
}
}
// update
// only update this frame if we're not in the middle of starting up
if (uptime) {
// process other tasks
if (oled.state & SSD1306_STATE_INITIALIZED) {
oled.callback = oled_update_done;
}
ssd1306_update();
}
cpu_use = SysTick->CNT;
}
// re-enable IRQs
SYS_RecoverIrq(interrupt_flags);
// render new rgbled frame
// this is not included in cpu calcs :/
if (flags_lo & FLAG_RGBLED_RUN) {
flags_lo &= ~FLAG_RGBLED_RUN;
// make sure a valid program is selected
if (uconf.ledprog_rgb_idx > (sizeof(rgb_pgm) / sizeof(rgb_pgm[0]))) {
uconf.ledprog_rgb_idx = 0;
}
// now run a program
rgbled_runprog(st_tick >> 2);
}
} else {
switch (idle_go_sleep) {
case 1: {
idle_go_sleep++;
// just entered the mode? then turn things off
ssd1306_set_display(0);
uconf.flags |= UCONF_FLAGS_LEDS_DISABLE;
rgbled_send();
break;
}
default: {
// check to see if we should wake
if (accel_get_movement() > 3) {
idle_go_sleep = 0;
idle_time_still = 0;
idle_time_menu = 0;
// wake up things
ssd1306_set_display(1);
uconf.flags &= ~UCONF_FLAGS_LEDS_DISABLE;
rgbled_send();
}
break;
}
}
}
// re-enable IRQs
SYS_RecoverIrq(interrupt_flags);
// render new rgbled frame
// this is not included in cpu calcs :/
if (flags_lo & FLAG_RGBLED_RUN) {
flags_lo &= ~FLAG_RGBLED_RUN;
// make sure a valid program is selected
if (uconf.ledprog_rgb_idx > (sizeof(rgb_pgm) / sizeof(rgb_pgm[0]))) {
uconf.ledprog_rgb_idx = 0;
}
// now run a program
rgbled_runprog(st_tick >> 2);
}
// drop into lower clock rate
SetSysClock(SYSCLK_FREQ_IDLE);
}
@ -342,6 +389,7 @@ void RTC_IRQHandler(void)
}
idle_time_still++;
idle_time_menu++;
}
oled_tick++;

View File

@ -13,6 +13,7 @@
#include "misc/i8atan2.h"
#include <stdio.h>
#include <stdlib.h>
@ -20,8 +21,11 @@
AccelData accel;
uint8_t accel_found = 0;
int16_t movement;
uint16_t movement_worst;
uint8_t movement_idx; // index into "read" register
int16_t movement_read[4]; // last read movement value
int16_t movement; // last calculated movement value
uint16_t movement_worst; // worst seen movement value
// hardware
@ -29,7 +33,6 @@ static stmdev_ctx_t dev_ctx;
int32_t accel_i2c_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)
{
(void)(handle);
@ -96,6 +99,7 @@ void accel_init()
}
}
__HIGH_CODE
void accel_poll()
{
uint8_t reg = 1;
@ -111,13 +115,30 @@ void accel_poll()
// read acceleration data
memset(xyz, 0x00, 3 * sizeof(int16_t));
lis2dw12_acceleration_raw_get(&dev_ctx, xyz);
accel.x = xyz[0] >>= 8;
accel.y = xyz[1] >>= 8;
accel.z = xyz[2] >>= 8;
// compute our shitty "movement" thing
// awful way to detect being still
reg = sizeof(movement_read) / sizeof(movement_read[0]);
movement_idx++;
if (movement_idx == reg) {
movement_idx = 0;
movement = abs(movement_read[3] - movement_read[0]);
if (movement > movement_worst) {
movement_worst = movement;
}
}
movement_read[movement_idx] = abs(accel.x) + abs(accel.y);
}
}
}
__HIGH_CODE
int8_t accel_get_rotation(struct AccelData *a)
{
int8_t nx, ny, ret;

View File

@ -27,8 +27,8 @@ typedef struct AccelData {
extern AccelData accel;
extern uint8_t accel_found;
extern uint16_t movement_worst;

View File

@ -217,7 +217,7 @@ void menu_6_disp(uint8_t idx)
sprintf(txt, "m%i", abs(accel_get_movement()));
ssd1306fb_set_cursor(104, 10);
ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0);
sprintf(txt, "w%d", 0); // todo: fix this: movement_worst);
sprintf(txt, "w%d", movement_worst);
ssd1306fb_set_cursor(106, 17);
ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0);

View File

@ -32,34 +32,34 @@ static const uint8_t uconf_edge_defaults[8][8] = {
static void uconf_defaults()
void uconf_defaults()
{
int i;
uconf.ver = UCONF_VER;
uconf.flags = UCONF_FLAGS_LEDS_ENABLE;
uconf.framemod = UCONF_FRAMERATE_FULL;
uconf.nameconf = UCONF_NAME_DISP_DEMOWAVE1 | UCONF_NAME_MODE_AUTOROTATE | UCONF_NAME_MODE_COLOR_INVERT;
uconf.ver = UCONF_VER;
uconf.flags = UCONF_FLAGS_LEDS_ENABLE;
uconf.framemod = UCONF_FRAMERATE_FULL;
uconf.nameconf = UCONF_NAME_DISP_DEMOWAVE1 | UCONF_NAME_MODE_AUTOROTATE | UCONF_NAME_MODE_COLOR_INVERT;
// UCONF_NAME_DISP_DEMOWAVES1 | UCONF_NAME_MODE_AUTOROTATE | UCONF_NAME_MODE_COLOR_INVERT;
if (uconf_flash_offset == 0xf0) {
uconf.iter = 0;
uconf.iter = 0;
}
uconf.font_idx = 4;
uconf.char_spacing = 2;
uconf.y_offset = 0;
uconf.font_idx = 4;
uconf.char_spacing = 2;
uconf.y_offset = 0;
// todo: add LUT
strcpy(uconf.name, "Supercon");
uconf.favcolor_hue = 170;
uconf.favcolor_sat = 240;
uconf.favcolor_val = 32;
uconf.favcolor_hue = 170;
uconf.favcolor_sat = 240;
uconf.favcolor_val = 32;
uconf.altcolor_hue = 0;
uconf.altcolor_sat = 240;
uconf.altcolor_val = 32;
uconf.altcolor_hue = 0;
uconf.altcolor_sat = 240;
uconf.altcolor_val = 32;
uconf.ledprog_rgb_idx = 4;
uconf.ledprog_rgb_idx = 4;
for (i = 0; i < 8; i++) {
uconf.ledprog_rgb[i] = 0;
@ -67,10 +67,11 @@ static void uconf_defaults()
memcpy(uconf.ledprog_rgb_data, uconf_edge_defaults, sizeof(uconf_edge_defaults));
uconf.lsens_dark_thresh = 0x6a0; // todo: figure out what this should be by testing
uconf.sleep_timeout = 20 * 60;
uconf.lsens_dark_thresh = 0x6a0; // todo: figure out what this should be by testing
uconf.menu_timeout = 5 * 60;
uconf.sleep_timeout = 20 * 60;
uconf.checksum = checksum_gen((uint8_t *)&uconf, sizeof(uconf) - 2);
uconf.checksum = checksum_gen((uint8_t *)&uconf, sizeof(uconf) - 2);
}
static int8_t uconf_validate()

View File

@ -83,8 +83,9 @@ typedef struct UserConf {
uint8_t padding0; // 52
uint8_t ledprog_rgb[16]; // 68
uint8_t ledprog_rgb_data[16][8]; // 196
uint8_t padding1[52]; // 248
uint16_t lsens_dark_thresh; // 250
uint8_t padding1[50]; // 246
uint16_t lsens_dark_thresh; // 248
uint16_t menu_timeout; // 250
uint16_t sleep_timeout; // 252
uint16_t tempcx10_offset; // 253-254
uint16_t checksum; // 255-256
@ -106,6 +107,8 @@ extern uint8_t temp_degc_decimal;
void uconf_load();
void uconf_write();
void uconf_defaults();
#endif /* USER_CONFIG_H_ */