From: sjlongland Date: Sun, 27 Sep 2015 04:23:30 +0000 (+0000) Subject: sm1000_main: Store two copies of the settings. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=8dcc4193f7bf990bc32f25c28ae0465faebf9ecb;p=freetel-svn-tracking.git sm1000_main: Store two copies of the settings. We keep a rolling serial number (64-bit, so probably flash will wear out before rollover happens) that is incremented on each write, and we write to the oldest image in flash. On load, we pick the newest one that's valid. git-svn-id: https://svn.code.sf.net/p/freetel/code@2405 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/stm32/src/sm1000_main.c b/codec2-dev/stm32/src/sm1000_main.c index 076a9b45..0ed856a8 100644 --- a/codec2-dev/stm32/src/sm1000_main.c +++ b/codec2-dev/stm32/src/sm1000_main.c @@ -69,6 +69,8 @@ unsigned int menuExit = 0; * User preferences */ static struct prefs_t { + /*! Serial number */ + uint64_t serial; /*! Menu frequency */ uint16_t menu_freq; /*! Menu speed */ @@ -79,9 +81,21 @@ static struct prefs_t { uint8_t op_mode; } prefs; -/* Preferences changed flag */ +/*! Preferences changed flag */ int prefs_changed = 0; +/*! Number of preference images kept */ +#define PREFS_IMG_NUM (2) +/*! Base ROM ID for preferences */ +#define PREFS_IMG_BASE (0) +/*! Minimum serial number */ +#define PREFS_SERIAL_MIN 8 +/*! Maximum serial number */ +#define PREFS_SERIAL_MAX UINT64_MAX + +/*! Preference serial numbers, by slot */ +static uint64_t prefs_serial[PREFS_IMG_NUM]; + struct tone_gen_t tone_gen; struct sfx_player_t sfx_player; struct morse_player_t morse_player; @@ -109,6 +123,65 @@ int16_t software_mix(int16_t a, int16_t b) { return s; } +/*! Compare current serial with oldest and newest */ +void compare_prefs(int* const oldest, int* const newest, int idx) +{ + if (newest && prefs_serial[idx]) { + if ((*newest < 0) + || (prefs_serial[idx] > prefs_serial[*newest]) + || ((prefs_serial[idx] == PREFS_SERIAL_MIN) + && (prefs_serial[*newest] == PREFS_SERIAL_MAX))) + *newest = idx; + } + + if (oldest) { + if ((*oldest < 0) + || (!prefs_serial[idx]) + || (prefs_serial[idx] < prefs_serial[*oldest]) + || ((prefs_serial[idx] == PREFS_SERIAL_MAX) + && (prefs_serial[*oldest] == PREFS_SERIAL_MIN))) + *oldest = idx; + } +} + +/*! Find oldest and newest images */ +void find_prefs(int* const oldest, int* const newest) +{ + int i; + if (newest) *newest = -1; + if (oldest) *oldest = -1; + for (i = 0; i < PREFS_IMG_NUM; i++) + compare_prefs(oldest, newest, i); +} + +/*! Load preferences from flash */ +int load_prefs() +{ + struct prefs_t image[PREFS_IMG_NUM]; + int newest = -1; + int i; + + /* Load all copies into RAM */ + for (i = 0; i < PREFS_IMG_NUM; i++) { + int res = vrom_read(PREFS_IMG_BASE + i, 0, + sizeof(image[i]), &image[i]); + if (res == sizeof(image[i])) { + prefs_serial[i] = image[i].serial; + compare_prefs(NULL, &newest, i); + } else { + prefs_serial[i] = 0; + } + } + + if (newest < 0) + /* No newest image was found */ + return -ENOENT; + + /* Load from the latest image */ + memcpy(&prefs, &image[newest], sizeof(prefs)); + return 0; +} + int main(void) { struct freedv *f; int nin, nout, i; @@ -176,13 +249,14 @@ int main(void) { } /* Button released, do an EEPROM erase */ - vrom_erase(0); + for (i = 0; i < PREFS_IMG_NUM; i++) + vrom_erase(i + PREFS_IMG_BASE); } led_rt(LED_OFF); tone_reset(&tone_gen, 0, 0); /* Try to load preferences from flash */ - if (vrom_read(0, 0, sizeof(prefs), &prefs) != sizeof(prefs)) { + if (load_prefs() < 0) { /* Fail! Load defaults. */ memset(&prefs, 0, sizeof(prefs)); prefs.op_mode = ANALOG; @@ -262,10 +336,23 @@ int main(void) { morse_play(&morse_player, NULL); menuExit = 1; if (save_settings) { + int oldest = -1; + int res; /* Copy the settings in */ prefs.menu_freq = morse_player.freq; prefs.menu_speed = morse_player.dit_time; - vrom_write(0, 0, sizeof(prefs), &prefs); + /* Increment serial number */ + prefs.serial++; + /* Find the oldest image */ + find_prefs(&oldest, NULL); + if (oldest < 0) + oldest = 0; /* No current image */ + + /* Write new settings over it */ + res = vrom_write(oldest + PREFS_IMG_BASE, 0, + sizeof(prefs), &prefs); + if (res >= 0) + prefs_serial[oldest] = prefs.serial; } } }