1
0
Fork 0
forked from len0rd/rockbox

Added resume. Works in dirs and playlists, shuffled or not. Resumes mid-song, but press pause on players before you shutdown so they get a chance to store the position on disk. Recorders use RTC ram. Todo: Time display is wrong after mid-track resume and ffd/rew is not handled.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1787 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Björn Stenberg 2002-08-16 14:41:47 +00:00
parent 085e774675
commit 6224cdb166
12 changed files with 379 additions and 144 deletions

View file

@ -37,10 +37,9 @@
struct user_settings global_settings;
static unsigned short last_checksum = 0;
#define CONFIG_BLOCK_VERSION 1
#define CONFIG_BLOCK_SIZE 44
#define CONFIG_BLOCK_SIZE 512
#define RTC_BLOCK_SIZE 44
/********************************************
@ -64,6 +63,8 @@ offset abs
0x0f 0x23 <scroll speed & WPS display byte>
0x10 0x24 <playlist options byte>
0x11 0x25 <AVC byte>
0x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume>
0x16 0x2b <(int) Byte offset into resume file>
<all unused space filled with 0xff>
@ -81,24 +82,30 @@ 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.
Rest of config block, only saved to disk:
0xF8 (int) Playlist shuffle seed
0xFC (char[260]) Resume playlist (path/to/dir or path/to/playlist.m3u)
*************************************/
#include "rtc.h"
static unsigned char rtc_config_block[CONFIG_BLOCK_SIZE];
static unsigned char config_block[CONFIG_BLOCK_SIZE];
/*
* Calculates the checksum for the config block and places it in the given 2-byte buffer
* Calculates the checksum for the config block and returns it
*/
static unsigned short calculate_config_checksum(void)
static unsigned short calculate_config_checksum(unsigned char* buf)
{
unsigned int i;
unsigned char cksum[2];
cksum[0] = cksum[1] = 0;
for (i=0; i < CONFIG_BLOCK_SIZE - 2; i+=2 ) {
cksum[0] ^= rtc_config_block[i];
cksum[1] ^= rtc_config_block[i+1];
for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) {
cksum[0] ^= buf[i];
cksum[1] ^= buf[i+1];
}
return (cksum[0] << 8) | cksum[1];
@ -112,12 +119,12 @@ static void init_config_buffer( void )
DEBUGF( "init_config_buffer()\n" );
/* reset to 0xff - all unused */
memset(rtc_config_block, 0xff, CONFIG_BLOCK_SIZE);
memset(config_block, 0xff, CONFIG_BLOCK_SIZE);
/* insert header */
rtc_config_block[0] = 'R';
rtc_config_block[1] = 'o';
rtc_config_block[2] = 'c';
rtc_config_block[3] = CONFIG_BLOCK_VERSION;
config_block[0] = 'R';
config_block[1] = 'o';
config_block[2] = 'c';
config_block[3] = CONFIG_BLOCK_VERSION;
}
/*
@ -126,7 +133,6 @@ static void init_config_buffer( void )
static int save_config_buffer( void )
{
unsigned short chksum;
#ifdef HAVE_RTC
unsigned int i;
#endif
@ -134,36 +140,29 @@ static int save_config_buffer( void )
DEBUGF( "save_config_buffer()\n" );
/* update the checksum in the end of the block before saving */
chksum = calculate_config_checksum();
rtc_config_block[ CONFIG_BLOCK_SIZE - 2 ] = chksum >> 8;
rtc_config_block[ CONFIG_BLOCK_SIZE - 1 ] = chksum & 0xff;
/* don't save if no changes were made */
if ( chksum == last_checksum )
return 0;
last_checksum = chksum;
chksum = calculate_config_checksum(config_block);
config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8;
config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff;
#ifdef HAVE_RTC
/* 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 (i=0; i < CONFIG_BLOCK_SIZE; i++ ) {
int r = rtc_write(0x14+i, rtc_config_block[i]);
for (i=0; i < RTC_BLOCK_SIZE; i++ ) {
int r = rtc_write(0x14+i, config_block[i]);
if (r) {
DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", 14+i, r );
return r;
}
}
#else
#endif
if(battery_level_safe() && (fat_startsector()!=0))
ata_delayed_write( 61, rtc_config_block);
if (fat_startsector() != 0)
ata_delayed_write( 61, config_block);
else
return -1;
#endif
return 0;
}
@ -173,40 +172,61 @@ static int save_config_buffer( void )
static int load_config_buffer( void )
{
unsigned short chksum;
bool correct = false;
#ifdef HAVE_RTC
unsigned int i;
unsigned char rtc_block[RTC_BLOCK_SIZE];
#endif
DEBUGF( "load_config_buffer()\n" );
if (fat_startsector() != 0) {
ata_read_sectors( 61, 1, config_block);
/* calculate the checksum, check it and the header */
chksum = calculate_config_checksum(config_block);
if (config_block[0] == 'R' &&
config_block[1] == 'o' &&
config_block[2] == 'c' &&
config_block[3] == CONFIG_BLOCK_VERSION &&
(chksum >> 8) == config_block[RTC_BLOCK_SIZE - 2] &&
(chksum & 0xff) == config_block[RTC_BLOCK_SIZE - 1])
{
DEBUGF( "load_config_buffer: header & checksum test ok\n" );
correct = true;
}
}
#ifdef HAVE_RTC
/* FIXME: the same comment applies here as for rtc_write */
for (i=0; i < CONFIG_BLOCK_SIZE; i++ )
rtc_config_block[i] = rtc_read(0x14+i);
#else
ata_read_sectors( 61, 1, rtc_config_block);
/* read rtc block */
for (i=0; i < RTC_BLOCK_SIZE; i++ )
rtc_block[i] = rtc_read(0x14+i);
chksum = calculate_config_checksum(rtc_block);
/* if rtc block is ok, use that */
if (rtc_block[0] == 'R' &&
rtc_block[1] == 'o' &&
rtc_block[2] == 'c' &&
rtc_block[3] == CONFIG_BLOCK_VERSION &&
(chksum >> 8) == rtc_block[RTC_BLOCK_SIZE - 2] &&
(chksum & 0xff) == rtc_block[RTC_BLOCK_SIZE - 1])
{
memcpy(config_block, rtc_block, RTC_BLOCK_SIZE);
correct = true;
}
#endif
/* calculate the checksum, check it and the header */
chksum = calculate_config_checksum();
if (rtc_config_block[0] == 'R' &&
rtc_config_block[1] == 'o' &&
rtc_config_block[2] == 'c' &&
rtc_config_block[3] == CONFIG_BLOCK_VERSION &&
(chksum >> 8) == rtc_config_block[CONFIG_BLOCK_SIZE - 2] &&
(chksum & 0xff) == rtc_config_block[CONFIG_BLOCK_SIZE - 1])
{
DEBUGF( "load_config_buffer: header & checksum test ok\n" );
last_checksum = chksum;
return 0; /* header and checksum is valid */
if ( !correct ) {
/* if checksum is not valid, clear the config buffer */
DEBUGF( "load_config_buffer: header & checksum test failed\n" );
init_config_buffer();
return -1;
}
/* if checksum is not valid, initialize the config buffer to all-unused */
DEBUGF( "load_config_buffer: header & checksum test failed\n" );
init_config_buffer();
return 1;
return 0;
}
/*
@ -218,33 +238,47 @@ int settings_save( void )
/* 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;
config_block[0x4] = (unsigned char)global_settings.volume;
config_block[0x5] = (unsigned char)global_settings.balance;
config_block[0x6] = (unsigned char)global_settings.bass;
config_block[0x7] = (unsigned char)global_settings.treble;
config_block[0x8] = (unsigned char)global_settings.loudness;
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;
config_block[0xa] = (unsigned char)global_settings.contrast;
config_block[0xb] = (unsigned char)global_settings.backlight;
config_block[0xc] = (unsigned char)global_settings.poweroff;
config_block[0xd] = (unsigned char)global_settings.resume;
rtc_config_block[0xe] = (unsigned char)
config_block[0xe] = (unsigned char)
((global_settings.playlist_shuffle & 1) |
((global_settings.mp3filter & 1) << 1) |
((global_settings.sort_case & 1) << 2) |
((global_settings.discharge & 1) << 3) |
((global_settings.statusbar & 1) << 4));
rtc_config_block[0xf] = (unsigned char)
config_block[0xf] = (unsigned char)
((global_settings.scroll_speed << 3) |
(global_settings.wps_display & 7));
rtc_config_block[0x11] = (unsigned char)global_settings.avc;
config_block[0x10] = (unsigned char)global_settings.ff_rewind;
config_block[0x11] = (unsigned char)global_settings.avc;
memcpy(&rtc_config_block[0x24], &global_settings.total_uptime, 4);
memcpy(&config_block[0x12], &global_settings.resume_index, 4);
memcpy(&config_block[0x16], &global_settings.resume_offset, 4);
memcpy(&config_block[0xF8], &global_settings.resume_seed, 4);
memcpy(&config_block[0x24], &global_settings.total_uptime, 4);
strncpy(&config_block[0xFC], global_settings.resume_file, MAX_PATH);
DEBUGF("+Resume file %s\n",global_settings.resume_file);
DEBUGF("+Resume index %X offset %X\n",
global_settings.resume_index,
global_settings.resume_offset);
DEBUGF("+Resume shuffle %s seed %X\n",
global_settings.playlist_shuffle?"on":"off",
global_settings.resume_seed);
if(save_config_buffer())
{
lcd_clear_display();
@ -277,51 +311,65 @@ void settings_load(void)
/* 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 (config_block[0x4] != 0xFF)
global_settings.volume = config_block[0x4];
if (config_block[0x5] != 0xFF)
global_settings.balance = config_block[0x5];
if (config_block[0x6] != 0xFF)
global_settings.bass = config_block[0x6];
if (config_block[0x7] != 0xFF)
global_settings.treble = config_block[0x7];
if (config_block[0x8] != 0xFF)
global_settings.loudness = config_block[0x8];
if (config_block[0x9] != 0xFF)
global_settings.bass_boost = config_block[0x9];
if (rtc_config_block[0xa] != 0xFF) {
global_settings.contrast = rtc_config_block[0xa];
if (config_block[0xa] != 0xFF) {
global_settings.contrast = config_block[0xa];
if ( global_settings.contrast < MIN_CONTRAST_SETTING )
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
}
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;
global_settings.sort_case = (rtc_config_block[0xe] >> 2) & 1;
global_settings.discharge = (rtc_config_block[0xe] >> 3) & 1;
global_settings.statusbar = (rtc_config_block[0xe] >> 4) & 1;
if (config_block[0xb] != 0xFF)
global_settings.backlight = config_block[0xb];
if (config_block[0xc] != 0xFF)
global_settings.poweroff = config_block[0xc];
if (config_block[0xd] != 0xFF)
global_settings.resume = config_block[0xd];
if (config_block[0xe] != 0xFF) {
global_settings.playlist_shuffle = config_block[0xe] & 1;
global_settings.mp3filter = (config_block[0xe] >> 1) & 1;
global_settings.sort_case = (config_block[0xe] >> 2) & 1;
global_settings.discharge = (config_block[0xe] >> 3) & 1;
global_settings.statusbar = (config_block[0xe] >> 4) & 1;
}
c = rtc_config_block[0xf] >> 3;
c = config_block[0xf] >> 3;
if (c != 31)
global_settings.scroll_speed = c;
c = rtc_config_block[0xf] & 7;
c = config_block[0xf] & 7;
if (c != 7)
global_settings.wps_display = c;
if (rtc_config_block[0x11] != 0xFF)
global_settings.avc = rtc_config_block[0x11];
if (config_block[0x10] != 0xFF)
global_settings.ff_rewind = config_block[0x10];
if (rtc_config_block[0x24] != 0xFF)
memcpy(&global_settings.total_uptime, &rtc_config_block[0x24], 4);
if (config_block[0x11] != 0xFF)
global_settings.avc = config_block[0x11];
if (config_block[0x12] != 0xFF)
memcpy(&global_settings.resume_index, &config_block[0x12], 4);
if (config_block[0x16] != 0xFF)
memcpy(&global_settings.resume_offset, &config_block[0x16], 4);
memcpy(&global_settings.resume_seed, &config_block[0xF8], 4);
if (config_block[0x24] != 0xFF)
memcpy(&global_settings.total_uptime, &config_block[0x24], 4);
strncpy(global_settings.resume_file, &config_block[0xFC], MAX_PATH);
global_settings.resume_file[MAX_PATH]=0;
}
lcd_set_contrast(global_settings.contrast);
lcd_scroll_speed(global_settings.scroll_speed);
@ -345,6 +393,7 @@ void settings_reset(void) {
global_settings.loudness = mpeg_sound_default(SOUND_LOUDNESS);
global_settings.bass_boost = mpeg_sound_default(SOUND_SUPERBASS);
global_settings.avc = mpeg_sound_default(SOUND_AVC);
global_settings.resume = true;
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
global_settings.poweroff = DEFAULT_POWEROFF_SETTING;
global_settings.backlight = DEFAULT_BACKLIGHT_SETTING;
@ -358,6 +407,8 @@ void settings_reset(void) {
global_settings.total_uptime = 0;
global_settings.scroll_speed = 8;
global_settings.ff_rewind = DEFAULT_FF_REWIND_SETTING;
global_settings.resume_index = -1;
global_settings.resume_offset = -1;
}