diff --git a/src/m_default/_default.c b/src/m_default/_default.c index 591171e..b9cbbe7 100644 --- a/src/m_default/_default.c +++ b/src/m_default/_default.c @@ -3,6 +3,7 @@ #include #include "mode.h" +#include "storage.h" #include "thread.h" #include "usbstdio.h" #include "vnd_cfg.h" @@ -35,6 +36,8 @@ enum m_default_feature { mdef_feat_tempsense = 1<<4, }; +static bool data_dirty = false; + #ifdef DBOARD_HAS_UART static cothread_t uartthread; static uint8_t uartstack[THREAD_STACK_SIZE]; @@ -81,6 +84,17 @@ static void enter_cb(void) { serprogthread = co_derive(serprogstack, sizeof serprogstack, serprog_thread_fn); thread_enter(serprogthread); // will call cdc_serprog_init() on correct thread #endif + + if (!data_dirty) { // only read when not read yet + struct mode_info mi = storage_mode_get_info(1); + if (mi.size != 0 && mi.version == 0x0010 /* TODO: version migration? */) { + uint8_t dst[2]; + storage_mode_read(1, dst, 0, 2); + + cdc_uart_set_hwflow(dst[0]); + tempsense_set_addr(dst[1]); + } + } } static void leave_cb(void) { // TODO: CMSISDAP? @@ -144,7 +158,12 @@ static void handle_cmd_cb(uint8_t cmd) { break; case mdef_cmd_tempsense: #ifdef DBOARD_HAS_TEMPSENSOR - tempsense_bulk_cmd(); + { + uint8_t addra = tempsense_get_addr(); + tempsense_bulk_cmd(); + uint8_t addrb = tempsense_get_addr(); + data_dirty |= addra != addrb; + } #else vnd_cfg_write_str(cfg_resp_illcmd, "temperature sensor not implemented on this device"); #endif @@ -156,9 +175,10 @@ static void handle_cmd_cb(uint8_t cmd) { resp = cdc_uart_get_hwflow() ? 1 : 0; vnd_cfg_write_resp(cfg_resp_ok, 1, &resp); } else { - if (cdc_uart_set_hwflow(resp != 0)) + if (cdc_uart_set_hwflow(resp != 0)) { vnd_cfg_write_resp(cfg_resp_ok, 0, NULL); - else + data_dirty = true; + } else vnd_cfg_write_str(cfg_resp_illcmd, "UART flow control setting not supported on this device"); } #else @@ -387,6 +407,19 @@ static bool my_vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, } #endif +static uint16_t my_get_size(void) { return 2; } +static void my_get_data(void* dst, size_t offset, size_t maxsize) { + (void)offset; (void)maxsize; + + uint8_t* d = dst; + + d[0] = cdc_uart_get_hwflow() ? 1 : 0; + d[1] = tempsense_get_addr(); + + data_dirty = false; +} +static bool my_is_dirty(void) { return data_dirty; } + extern struct mode m_01_default; // clang-format off struct mode m_01_default = { @@ -402,6 +435,13 @@ struct mode m_01_default = { .task = task_cb, .handle_cmd = handle_cmd_cb, + .storage = { + .stclass = mode_storage_32b, + .get_size = my_get_size, + .get_data = my_get_data, + .is_dirty = my_is_dirty + }, + #if defined(DBOARD_HAS_CMSISDAP) && CFG_TUD_HID > 0 #if 0 .tud_hid_get_report_cb = my_hid_get_report_cb, diff --git a/src/m_sump/_sump.c b/src/m_sump/_sump.c index 4e2cb82..da3e1e2 100644 --- a/src/m_sump/_sump.c +++ b/src/m_sump/_sump.c @@ -3,6 +3,7 @@ #include #include "mode.h" +#include "storage.h" #include "thread.h" #include "usbstdio.h" #include "vnd_cfg.h" @@ -20,6 +21,8 @@ enum m_sump_feature { msump_feat_sump = 1<<0, }; +static bool data_dirty = false; + #ifdef DBOARD_HAS_SUMP static cothread_t sumpthread; static uint8_t sumpstack[THREAD_STACK_SIZE]; @@ -44,6 +47,16 @@ static void enter_cb(void) { sumpthread = co_derive(sumpstack, sizeof sumpstack, sump_thread_fn); thread_enter(sumpthread); #endif + + if (!data_dirty) { // only read when not read yet + struct mode_info mi = storage_mode_get_info(4); + if (mi.size != 0 && mi.version == 0x0010 /* TODO: version migration? */) { + uint8_t dst[1]; + storage_mode_read(4, dst, 0, 1); + + sump_hw_set_overclock(dst[0]); + } + } } static void leave_cb(void) { #ifdef DBOARD_HAS_SUMP @@ -133,7 +146,6 @@ enum { #define EPNUM_CDC_STDIO_NOTIF 0x85 // clang-format off -// TODO: replace magic 64s by actual buffer size macros static const uint8_t desc_configuration[] = { TUD_CONFIG_DESCRIPTOR(1, ITF_NUM__TOTAL, STRID_CONFIG, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), @@ -178,6 +190,17 @@ static void my_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_cod } #endif +static uint16_t my_get_size(void) { return 1; } +static void my_get_data(void* dst, size_t offset, size_t maxsize) { + (void)offset; (void)maxsize; + + uint8_t* d = dst; + d[0] = sump_hw_get_overclock(); + + data_dirty = false; +} +static bool my_is_dirty(void) { return data_dirty; } + extern struct mode m_04_sump; // clang-format off struct mode m_04_sump = { @@ -188,6 +211,13 @@ struct mode m_04_sump = { .usb_desc = desc_configuration, .string_desc = string_desc_arr, + .storage = { + .stclass = mode_storage_32b, + .get_size = my_get_size, + .get_data = my_get_data, + .is_dirty = my_is_dirty + }, + .enter = enter_cb, .leave = leave_cb, .task = task_cb, diff --git a/src/storage.c b/src/storage.c index a253d39..ff1c11d 100644 --- a/src/storage.c +++ b/src/storage.c @@ -6,14 +6,14 @@ #include "storage.h" #if !defined(PERSISTENT_STORAGE) || !defined(DBOARD_HAS_STORAGE) -/*int storage_init(void) { return -1; } +int storage_init(void) { return -1; } bool storage_flush_data(void) { return false; } -struct mode_info storage_mode_get_size(int _) { +struct mode_info storage_mode_get_info(int _) { (void)_; return (struct mode_info){ .size = 0, .version = 0 }; } void storage_mode_read(int _, void* __, size_t ___, size_t ____) { (void)_; (void)__; (void)___; (void)____; -}*/ +} #else #include "storage_internal.h" diff --git a/src/storage.h b/src/storage.h index 25c4b6a..b5bfb06 100644 --- a/src/storage.h +++ b/src/storage.h @@ -20,6 +20,7 @@ enum mode_storage_class { struct mode_storage { enum mode_storage_class stclass; uint16_t (*get_size)(void); + // if stclass < 512b, offset & maxsize can be ignored void (*get_data)(void* dst, size_t offset, size_t maxsize); bool (*is_dirty)(void); // if data was changed since last mode_read/get_data call }; diff --git a/src/storage_save.c b/src/storage_save.c index 771581b..45956bb 100644 --- a/src/storage_save.c +++ b/src/storage_save.c @@ -48,7 +48,7 @@ static size_t storage_allocate_new(void) { uint16_t dsize = mode_list[mode]->storage.get_size(); if (dsize > stclass_sz[stcls]) continue; - if (current_wrhead + dsize > current_page_end) { // welp + if (current_wrhead + dsize > current_page_end) { // FIXME: data that is >1 page size (do we want to support this?) current_page_end = current_page; current_page -= STORAGE_ERASEWRITE_ALIGN; current_wrhead = current_page;