From ea3f6ae9e0b622f0d2b54b1d43873bee5c811af7 Mon Sep 17 00:00:00 2001 From: true Date: Sun, 27 Oct 2024 04:14:37 -0700 Subject: [PATCH] implement factory reset, fix eeprom write routine --- nametag8_CH592/user/comm/i2c.h | 4 +- nametag8_CH592/user/comm/soft_i2c_master.c | 3 +- nametag8_CH592/user/hw/eeprom16.c | 2 +- nametag8_CH592/user/ui/btn.c | 15 ++++++ nametag8_CH592/user/ui/btn.h | 2 + nametag8_CH592/user/ui/menu5_options.c | 35 +++++++++++-- nametag8_CH592/user/ui/menu6_about.c | 18 +++---- nametag8_CH592/user/user_config.c | 61 +++++++++++++++++----- nametag8_CH592/user/user_config.h | 3 ++ 9 files changed, 114 insertions(+), 29 deletions(-) diff --git a/nametag8_CH592/user/comm/i2c.h b/nametag8_CH592/user/comm/i2c.h index 54269aa..507888e 100644 --- a/nametag8_CH592/user/comm/i2c.h +++ b/nametag8_CH592/user/comm/i2c.h @@ -22,9 +22,9 @@ * - there is no ack on address. code always assumes slave is responding. */ #define i2c_init() i2cm_init() -#define i2c_start() SetSysClock(SYSCLK_FREQ_USEI2C); i2cm_start() +#define i2c_start() { SetSysClock(SYSCLK_FREQ_USEI2C); i2cm_start(); } #define i2c_restart() i2cm_restart() -#define i2c_stop() SetSysClock(SYSCLK_FREQ_NORMAL); i2cm_stop() +#define i2c_stop() { i2cm_stop(); SetSysClock(SYSCLK_FREQ_NORMAL); } #define i2c_rd(ack) i2cm_rd(ack) #define i2c_wr(dat) i2cm_wr(dat) #define i2c_addr(a, w) i2c_start(); i2cm_addr(a, w) diff --git a/nametag8_CH592/user/comm/soft_i2c_master.c b/nametag8_CH592/user/comm/soft_i2c_master.c index af8e2bf..8f99c08 100644 --- a/nametag8_CH592/user/comm/soft_i2c_master.c +++ b/nametag8_CH592/user/comm/soft_i2c_master.c @@ -184,8 +184,9 @@ uint8_t i2cm_wr(uint8_t dat) SCL_OUTLO(); bit_delay_lo(); } - SDA_IN_HI(); + SDA_IN_HI(); __nop(); // slave will now try to ack SCL_IN_HI(); bit_delay_hi(); + while (!SCL_GET()); // nothing should stretch here, but... ack = SDA_GET(); diff --git a/nametag8_CH592/user/hw/eeprom16.c b/nametag8_CH592/user/hw/eeprom16.c index 402c5ac..4833eba 100644 --- a/nametag8_CH592/user/hw/eeprom16.c +++ b/nametag8_CH592/user/hw/eeprom16.c @@ -58,7 +58,7 @@ uint8_t eep16_is_ready() uint8_t ack; i2c_start(); - ack = i2c_wr(EEPROM_I2C_ADDR | 1); + ack = i2c_wr(EEPROM_I2C_ADDR | 0); i2c_stop(); if (ack) return 0; diff --git a/nametag8_CH592/user/ui/btn.c b/nametag8_CH592/user/ui/btn.c index e03bede..3f14172 100644 --- a/nametag8_CH592/user/ui/btn.c +++ b/nametag8_CH592/user/ui/btn.c @@ -85,6 +85,21 @@ void btn_commit_hold() ch32sub_write(REG_BTN1_REPEAT_HI, val, sizeof(val)); } +int8_t btn_get_idx(uint8_t map_idx) +{ + uint8_t *map; + + if (map_idx >= BTN_COUNT) return -1; + + if (sysflags & SYS_OLED_ROTATE_X) { + map = btn_map_rot; + } else { + map = btn_map_upr; + } + + return map[map_idx] & 0x7f; +} + __HIGH_CODE void btn_intr() diff --git a/nametag8_CH592/user/ui/btn.h b/nametag8_CH592/user/ui/btn.h index fc7a0f2..cdcd1a4 100644 --- a/nametag8_CH592/user/ui/btn.h +++ b/nametag8_CH592/user/ui/btn.h @@ -39,6 +39,8 @@ extern uint8_t btn_held; void btn_intr(); void btn_commit_hold(); +int8_t btn_get_idx(uint8_t map_idx); + #endif /* USER_UI_BTN_H_ */ diff --git a/nametag8_CH592/user/ui/menu5_options.c b/nametag8_CH592/user/ui/menu5_options.c index 9f0d2d7..81ab6be 100644 --- a/nametag8_CH592/user/ui/menu5_options.c +++ b/nametag8_CH592/user/ui/menu5_options.c @@ -101,20 +101,47 @@ void menu_5_disp(uint8_t idx) break; } case LI_FACTORY_RESET: { + uint32_t iter; + // todo: implement manual button checking here after getting button orientation code working // yes, this means reset speed depends on framerate lol + if (btn_pushed & (1 << 2)) { + factory_reset++; + } else factory_reset = 0; + if (factory_reset >= 32) { // do the factory reset + iter = uconf.iter; uconf_defaults(); - // todo: reboot? + + // we do store the old iteration value so long as it isn't + // too high in order to keep track of nvmem writes. + // if the value is unnaturally high, we'll reset to zero. + // if it's corrupt in any way, enjoy your false write count. + if (iter < 0xffffff) { + uconf.iter = iter; + } + + uconf_clear(); + + // while it isn't necesasry to write an initial config + // as the code will determine there is no valid config + // and load defaults if the nvmem is empty, + // we're doing it to write the iter value. + uconf_write(); + + // aaaand it's gone + SYS_ResetExecute(); + + while (1); } ssd1306fb_draw_str(font_table[0].font, "Hold Set to Factory Reset...", 0); txt[0] = 0; - ssd1306fb_draw_rect(50, 18, 86, 31); - for (w = 0; w < (factory_reset >> 1); w++) { - ssd1306fb_draw_vline(50 + w, 18, 31); + ssd1306fb_draw_rect(52, 18, 52 + 31, 31); + for (w = 0; w < factory_reset; w++) { + ssd1306fb_draw_vline(53 + w, 18, 31); } break; } diff --git a/nametag8_CH592/user/ui/menu6_about.c b/nametag8_CH592/user/ui/menu6_about.c index 6d48e22..49be0f3 100644 --- a/nametag8_CH592/user/ui/menu6_about.c +++ b/nametag8_CH592/user/ui/menu6_about.c @@ -260,16 +260,16 @@ void menu_6_disp(uint8_t idx) ssd1306fb_set_cursor(10, -1); ssd1306fb_draw_str(font_Dialog_plain_8, "Light: ", 1); oled.cursor_x = 39; - sprintf(txt, "%d lo, %02d + %d", lsens_get_dark_threshold(), lsens_get_coarse(), lsens_get_fine()); - ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); + //sprintf(txt, "%d lo, %02d + %d", lsens_get_dark_threshold(), lsens_get_coarse(), lsens_get_fine()); + //ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); + ssd1306fb_draw_str(font_Dialog_plain_8, "not yet implemented", 0); ssd1306fb_set_cursor(10, 7); - ssd1306fb_draw_str(font_Dialog_plain_8, "Temp: Batt:", 1); - + ssd1306fb_draw_str(font_Dialog_plain_8, "Temp:", 1); oled.cursor_x = 42; // todo: implement temperature sensing // sprintf(txt, "%d.%dC", temp_degc, temp_degc_decimal); - ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); + ssd1306fb_draw_str(font_Dialog_plain_8, "not yet implemented", 0); oled.cursor_x = 98; // battery reading support is not supported on this target @@ -278,14 +278,14 @@ void menu_6_disp(uint8_t idx) ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); ssd1306fb_set_cursor(10, 16); - ssd1306fb_draw_str(font_Dialog_plain_8, "Flash Conf Writes: ", 0); + ssd1306fb_draw_str(font_Dialog_plain_8, "EEPROM Conf Writes: ", 0); sprintf(txt, "%lu", uconf.iter); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); ssd1306fb_set_cursor(10, 24); - ssd1306fb_draw_str(font_Dialog_plain_8, "MCU: ", 1); - sprintf(txt, "%dK / %dK", MCU_FLASH, MCU_SRAM); - ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); + ssd1306fb_draw_str(font_Dialog_plain_8, "CH592 ", 0); + sprintf(txt, "F%dK / R%dK", MCU_FLASH, MCU_SRAM); + ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); break; } diff --git a/nametag8_CH592/user/user_config.c b/nametag8_CH592/user/user_config.c index 9b079a4..c6edc29 100644 --- a/nametag8_CH592/user/user_config.c +++ b/nametag8_CH592/user/user_config.c @@ -11,6 +11,7 @@ #include "led/rgbled.h" #include +#include @@ -36,14 +37,14 @@ void uconf_defaults() { int i; + memset(&uconf, 0x00, sizeof(uconf)); + 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.font_idx = 5; uconf.char_spacing = 2; uconf.y_offset = 0; @@ -74,6 +75,7 @@ void uconf_defaults() uconf.checksum = checksum_gen((uint8_t *)&uconf, sizeof(uconf) - 2); } +// returns 0 if valid static int8_t uconf_validate() { // blank check @@ -98,21 +100,56 @@ static int8_t uconf_validate() void uconf_load() { uint8_t i; + uint32_t iter = 0; + + uconf_flash_offset = FLASH_RSVD_PAGES; for (i = 0; i < FLASH_RSVD_PAGES; i++) { - // find last page of valid config from flash - uconf_flash_offset = (FLASH_RSVD_PAGES - 1) - i; - eep16_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES); + // search nv data for latest user config + eep16_read(i * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES); if (!uconf_validate()) { - // valid data - return; + if (uconf.iter > iter) { + // this page has the highest iter value, so is the latest we've found so far + uconf_flash_offset = i; + iter = uconf.iter; + } } } - // flash has no valid data whatsoever - // don't worry about flash setup; that is done during writing - uconf_flash_offset = 0xf0; - uconf_defaults(); + if (uconf_flash_offset >= FLASH_RSVD_PAGES) { + // flash has no valid data whatsoever + // load some defaults into RAM and ignore flash for now + uconf_defaults(); + } else { + // reload the latest save data found + eep16_read(uconf_flash_offset * FLASH_UCONF_BYTES, (uint8_t *)&uconf, FLASH_UCONF_BYTES); + } +} + +void uconf_clear() +{ + uint8_t i; + uint8_t c[128]; + + uint16_t fsize; + uint16_t faddr; + + memset(&c, 0xff, sizeof(c)); + uconf_flash_offset = FLASH_RSVD_PAGES; + + for (i = 0; i < FLASH_RSVD_PAGES; i++) { + // write config data + fsize = FLASH_UCONF_BYTES; + faddr = i * FLASH_UCONF_BYTES; + + while (fsize) { + while (!eep16_is_ready()); + eep16_write(faddr, c, (fsize > 128) ? 128 : fsize); + if (fsize <= 128) break; + fsize -= 128; + faddr += 128; + } + } } void uconf_write() diff --git a/nametag8_CH592/user/user_config.h b/nametag8_CH592/user/user_config.h index 4e06e8e..d6e8a33 100644 --- a/nametag8_CH592/user/user_config.h +++ b/nametag8_CH592/user/user_config.h @@ -106,9 +106,12 @@ extern uint8_t temp_degc_decimal; +// non-volatile functions void uconf_load(); void uconf_write(); +void uconf_clear(); +// volatile functions void uconf_defaults();