From 6b25f79af039b8b367b4fff8c3aadac1cca0ab7d Mon Sep 17 00:00:00 2001 From: Björn Stenberg Date: Mon, 15 Jul 2002 11:02:12 +0000 Subject: Settings are now saved in RTC RAM on Recorder (Heikki Hannikainen). Introduced debug menu (Heikki Hannikainen). Cleaned up settings API. Added scroll_speed init. Moved dbg_ports() and dbg_rtc() from firmware/debug.c to apps/debug_menu.c Made panic buffer static. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1347 a1c6a512-1295-4272-9138-f99709370657 --- apps/settings.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 264 insertions(+), 38 deletions(-) (limited to 'apps/settings.c') diff --git a/apps/settings.c b/apps/settings.c index 5d33ad8f50..58633396bf 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -8,6 +8,7 @@ * $Id$ * * Copyright (C) 2002 by wavey@wavey.org + * RTC config saving code (C) 2002 by hessu@hes.iki.fi * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. @@ -26,84 +27,309 @@ #include "button.h" #include "lcd.h" #include "mpeg.h" +#include "string.h" struct user_settings global_settings; +#ifdef HAVE_RTC + +/******************************************** + +Config block as saved on the battery-packed RTC user RAM memory block +of 44 bytes, starting at offset 0x14 of the RTC memory space. + +offset abs +0x00 0x14 "Roc" header signature: 0x52 0x6f 0x63 +0x03 0x17 +0x04 0x18 +0x05 0x19 +0x06 0x1a +0x07 0x1b +0x08 0x1c +0x09 0x1d +0x0a 0x1e +0x0b 0x1f +0x0c 0x20 +0x0d 0x21 +0x0e 0x22 +0x0f 0x23 +0x10 0x24 + + + + the geeky but useless statistics part: +0x24 +0x28 + +0x2a + +Config memory is reset to 0xff and initialized with 'factory defaults' if +a valid header & checksum is not found. Config version number is only +increased when information is _relocated_ or space is _reused_ so that old +versions can read and modify configuration changed by new versions. New +versions should check for the value of '0xff' in each config memory +location used, and reset the setting in question with a factory default if +needed. Memory locations not used by a given version should not be +modified unless the header & checksum test fails. + +*************************************/ + +#include "rtc.h" +static unsigned char rtc_config_block[44]; + +/* + * Calculates the checksum for the config block and places it in the given 2-byte buffer + */ + +static void calculate_config_checksum(unsigned char *cksum) +{ + unsigned char *p; + cksum[0] = cksum[1] = 0; + + for (p = rtc_config_block; + p < rtc_config_block + sizeof(rtc_config_block) - 2; + p++) + { + cksum[0] = cksum[0] ^ *p; + p++; + cksum[1] = cksum[1] ^ *p; + } +} + +/* + * initialize the config block buffer + */ +static void init_config_buffer( void ) +{ + DEBUGF( "init_config_buffer()\n" ); + + /* reset to 0xff - all unused */ + memset(rtc_config_block, 0xff, sizeof(rtc_config_block)); + /* insert header */ + rtc_config_block[0] = 'R'; + rtc_config_block[1] = 'o'; + rtc_config_block[2] = 'c'; + rtc_config_block[3] = 0x0; /* config block version number */ +} + +/* + * save the config block buffer on the RTC RAM + */ +static int save_config_buffer( void ) +{ + unsigned char addr = 0x14; + int r; + unsigned char *p; + + DEBUGF( "save_config_buffer()\n" ); + + /* update the checksum in the end of the block before saving */ + calculate_config_checksum(rtc_config_block + sizeof(rtc_config_block) - 2); + + /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so + that it would write a number of bytes at a time since the RTC chip + supports that, but this will have to do for now 8-) */ + for (p = rtc_config_block; + p < rtc_config_block + sizeof(rtc_config_block); + p++) + { + r = rtc_write(addr, *p); + if (r) { + DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", addr, r ); + return r; + } + addr++; + } + + return 0; +} + /* - * persist all runtime user settings to disk + * load the config block buffer from the RTC RAM */ -int persist_all_settings( void ) +static int load_config_buffer( void ) { + unsigned char addr = 0x14; + unsigned char cksum[2]; + unsigned char *p; + + DEBUGF( "load_config_buffer()\n" ); + + /* FIXME: the same comment applies here as for rtc_write */ + for (p = rtc_config_block; + p < rtc_config_block + sizeof(rtc_config_block); + p++) + { + *p = rtc_read(addr); + addr++; + } + + /* calculate the checksum, check it and the header */ + calculate_config_checksum(cksum); + + if (rtc_config_block[0x0] == 'R' + && rtc_config_block[0x1] == 'o' + && rtc_config_block[0x2] == 'c' + && rtc_config_block[0x3] == 0x0 + && cksum[0] == rtc_config_block[0x2a] + && cksum[1] == rtc_config_block[0x2b]) { + DEBUGF( "load_config_buffer: header & checksum test ok" ); + return 0; /* header and checksum is valid */ + } + + /* if checksum is not valid, initialize the config buffer to all-unused */ + DEBUGF( "load_config_buffer: header & checksum test failed" ); + init_config_buffer(); return 1; } +#endif /* HAVE_RTC */ + /* - * persist all the playlist information to disk + * persist all runtime user settings to disk or RTC RAM */ -int persist_all_playlist_info( void ) +int settings_save( void ) { + DEBUGF( "settings_save()\n" ); + +#ifdef HAVE_RTC + /* update the config block buffer with current + settings and save the block in the RTC */ + rtc_config_block[0x4] = (unsigned char)global_settings.volume; + rtc_config_block[0x5] = (unsigned char)global_settings.balance; + rtc_config_block[0x6] = (unsigned char)global_settings.bass; + rtc_config_block[0x7] = (unsigned char)global_settings.treble; + rtc_config_block[0x8] = (unsigned char)global_settings.loudness; + rtc_config_block[0x9] = (unsigned char)global_settings.bass_boost; + + rtc_config_block[0xa] = (unsigned char)global_settings.contrast; + rtc_config_block[0xb] = (unsigned char)global_settings.backlight; + rtc_config_block[0xc] = (unsigned char)global_settings.poweroff; + rtc_config_block[0xd] = (unsigned char)global_settings.resume; + + rtc_config_block[0xe] = (unsigned char) + ((global_settings.playlist_shuffle & 1) | + ((global_settings.mp3filter & 1) << 1)); + + rtc_config_block[0xf] = (unsigned char) + ((global_settings.scroll_speed << 3) | + (global_settings.wps_display & 7)); + + memcpy(&rtc_config_block[0x24], &global_settings.total_uptime, 4); + memcpy(&rtc_config_block[0x28], &global_settings.total_boots, 2); + + save_config_buffer(); +#endif /* HAVE_RTC */ + return 1; } /* - * load settings from disk + * load settings from disk or RTC RAM */ -void reload_all_settings( struct user_settings *settings ) +void settings_load(void) { +#ifdef HAVE_RTC + unsigned char c; +#endif + DEBUGF( "reload_all_settings()\n" ); - /* this is a TEMP stub version */ - /* populate settings with default values */ + settings_reset(); - reset_settings( settings ); +#ifdef HAVE_RTC + /* load the buffer from the RTC (resets it to all-unused if the block + is invalid) and decode the settings which are set in the block */ + if (!load_config_buffer()) { + if (rtc_config_block[0x4] != 0xFF) + global_settings.volume = rtc_config_block[0x4]; + if (rtc_config_block[0x5] != 0xFF) + global_settings.balance = rtc_config_block[0x5]; + if (rtc_config_block[0x6] != 0xFF) + global_settings.bass = rtc_config_block[0x6]; + if (rtc_config_block[0x7] != 0xFF) + global_settings.treble = rtc_config_block[0x7]; + if (rtc_config_block[0x8] != 0xFF) + global_settings.loudness = rtc_config_block[0x8]; + if (rtc_config_block[0x9] != 0xFF) + global_settings.bass_boost = rtc_config_block[0x9]; + + if (rtc_config_block[0xa] != 0xFF) + global_settings.contrast = rtc_config_block[0xa]; + if (rtc_config_block[0xb] != 0xFF) + global_settings.backlight = rtc_config_block[0xb]; + if (rtc_config_block[0xc] != 0xFF) + global_settings.poweroff = rtc_config_block[0xc]; + if (rtc_config_block[0xd] != 0xFF) + global_settings.resume = rtc_config_block[0xd]; + if (rtc_config_block[0xe] != 0xFF) { + global_settings.playlist_shuffle = rtc_config_block[0xe] & 1; + global_settings.mp3filter = (rtc_config_block[0xe] >> 1) & 1; + } + + c = rtc_config_block[0xf] >> 3; + if (c != 31) + global_settings.scroll_speed = c; + + c = rtc_config_block[0xf] & 7; + if (c != 7) + global_settings.wps_display = c; + + if (rtc_config_block[0x24] != 0xFF) + memcpy(&global_settings.total_uptime, &rtc_config_block[0x24], 4); + if (rtc_config_block[0x28] != 0xFF) + memcpy(&global_settings.total_boots, &rtc_config_block[0x28], 2); + } + +#endif /* HAVE_RTC */ } /* * reset all settings to their default value */ -void reset_settings( struct user_settings *settings ) { +void settings_reset(void) { - DEBUGF( "reset_settings()\n" ); - - settings->volume = mpeg_sound_default(SOUND_VOLUME); - settings->balance = DEFAULT_BALANCE_SETTING; - settings->bass = mpeg_sound_default(SOUND_BASS); - settings->treble = mpeg_sound_default(SOUND_TREBLE); - settings->loudness = DEFAULT_LOUDNESS_SETTING; - settings->bass_boost = DEFAULT_BASS_BOOST_SETTING; - settings->contrast = DEFAULT_CONTRAST_SETTING; - settings->poweroff = DEFAULT_POWEROFF_SETTING; - settings->backlight = DEFAULT_BACKLIGHT_SETTING; - settings->wps_display = DEFAULT_WPS_DISPLAY; - settings->mp3filter = true; - settings->playlist_shuffle = false; + DEBUGF( "settings_reset()\n" ); + + global_settings.volume = mpeg_sound_default(SOUND_VOLUME); + global_settings.balance = DEFAULT_BALANCE_SETTING; + global_settings.bass = mpeg_sound_default(SOUND_BASS); + global_settings.treble = mpeg_sound_default(SOUND_TREBLE); + global_settings.loudness = DEFAULT_LOUDNESS_SETTING; + global_settings.bass_boost = DEFAULT_BASS_BOOST_SETTING; + global_settings.contrast = DEFAULT_CONTRAST_SETTING; + global_settings.poweroff = DEFAULT_POWEROFF_SETTING; + global_settings.backlight = DEFAULT_BACKLIGHT_SETTING; + global_settings.wps_display = DEFAULT_WPS_DISPLAY; + global_settings.mp3filter = true; + global_settings.playlist_shuffle = false; + global_settings.total_boots = 0; + global_settings.total_uptime = 0; + global_settings.scroll_speed = 8; } /* * dump the list of current settings */ -void display_current_settings( struct user_settings *settings ) +void settings_display(void) { #ifdef DEBUG - DEBUGF( "\ndisplay_current_settings()\n" ); + DEBUGF( "\nsettings_display()\n" ); DEBUGF( "\nvolume:\t\t%d\nbalance:\t%d\nbass:\t\t%d\ntreble:\t\t%d\nloudness:\t%d\nbass boost:\t%d\n", - settings->volume, - settings->balance, - settings->bass, - settings->treble, - settings->loudness, - settings->bass_boost ); + global_settings.volume, + global_settings.balance, + global_settings.bass, + global_settings.treble, + global_settings.loudness, + global_settings.bass_boost ); DEBUGF( "contrast:\t%d\npoweroff:\t%d\nbacklight:\t%d\n", - settings->contrast, - settings->poweroff, - settings->backlight ); -#else - /* Get rid of warning */ - settings = settings; + global_settings.contrast, + global_settings.poweroff, + global_settings.backlight ); #endif } -- cgit v1.2.3