Index: apps/plugins/timer.c =================================================================== --- apps/plugins/timer.c (revision 0) +++ apps/plugins/timer.c (revision 0) @@ -0,0 +1,245 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: timer.c $ + * + * Most of the code is copied from battery_bench.c and test_sampr.c + * + * 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. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef SIMULATOR /* not for the simulator */ + +#include "plugin.h" +PLUGIN_HEADER + +#define EV_EXIT 1337 +#define TIME_OFFSET 2 /* prevent player from shutdown */ + +/* seems to work with 1300, but who knows... */ +#define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200 + +/****************************** Plugin Entry Point ****************************/ +static struct plugin_api* rb; +MEM_FUNCTION_WRAPPERS(rb); +int main(void); +bool exit_tsr(bool); +void thread(void); + +/* one frame of bitswapped mp3 data */ +static uint16_t sinus[]={ + 0, 2057, 4106, 6139, 8148, + 10125, 12062, 13951, 15785, 17557, + 19259, 20886, 22430, 23886, 25247, + 26509, 27666, 28713, 29648, 30465, + 31163, 31737, 32186, 32508, 32702, + 32767, 32702, 32508, 32186, 31737, + 31163, 30465, 29648, 28713, 27666, + 26509, 25247, 23886, 22430, 20886, + 19259, 17557, 15785, 13951, 12062, + 10125, 8148, 6139, 4106, 2057, + 0, -2057, -4106, -6139, -8148, + -10125, -12062, -13951, -15785, -17557, + -19259, -20886, -22430, -23886, -25247, + -26509, -27666, -28713, -29648, -30465, + -31163, -31737, -32186, -32508, -32702, + -32767, -32702, -32508, -32186, -31737, + -31163, -30465, -29648, -28713, -27666, + -26509, -25247, -23886, -22430, -20886, + -19259, -17557, -15785, -13951, -12062, + -10125, -8148, -6139, -4106, -2057, +}; +/* 10 cycles of wavform */ +static int32_t audio[1000]; + +void init_audio(void) +{ + int i; + /* Initialize one cycle of the waveform */ + for (i = 0; i < 100; i++) + { + uint16_t val = sinus[i]; + audio[i] = (val << 16) | val; + } + + /* Duplicate it 9 more times */ + for (i = 1; i < 10; i++) + { + rb->memcpy(audio + i*100, audio, 100*sizeof(int32_t)); + } +} + +/* callback to request more mp3 data */ +void callback(unsigned char** start, size_t* size) +{ + *start = (unsigned char *) audio; /* give it the same frame again */ + *size = sizeof(audio); +} +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + (void)parameter; + rb = api; + return main(); +} + +struct thread_entry *thread_id; +struct event_queue thread_q; + +bool exit_tsr(bool reenter) +{ + if(rb->get_sleep_timer()<=0) /* thread has finished */ + return true; + + (void)reenter; + int i; + struct screen *disp; + FOR_NB_SCREENS(i){ + disp = rb->screens[i]; + disp->clear_display(); + disp->puts_scroll(0, 0, "Timer is currently running."); + disp->puts_scroll(0, 1, "Press OFF to cancel"); +#ifdef HAVE_LCD_BITMAP + disp->puts_scroll(0, 2, "Anything else will resume"); +#endif + disp->update(); + } + + if (rb->get_action(CONTEXT_STD,TIMEOUT_BLOCK) == ACTION_STD_CANCEL) + { + /* cancel timer */ + rb->set_sleep_timer(0); /* stop sleep_timer */ + rb->queue_post(&thread_q, EV_EXIT, 0); + rb->thread_wait(thread_id); + /* remove the thread's queue from the broadcast list */ + rb->queue_delete(&thread_q); + return true; + } + return false; +} + +/* use long for aligning */ +unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)]; + +void thread(void) +{ + struct queue_event ev; + int remain, counter=0; + long sleeptime = 5 * HZ; + int interval = HZ>>1; + do + { + rb->queue_wait_w_tmo(&thread_q, &ev, sleeptime); + switch (ev.id) + { + case SYS_USB_CONNECTED: + rb->usb_acknowledge(SYS_USB_CONNECTED_ACK); + case SYS_POWEROFF: + case EV_EXIT: + return; + } + remain = rb->get_sleep_timer() - TIME_OFFSET; + if(remain<=0){ /* start alarm */ + rb->set_sleep_timer(0); /* stop sleep_timer */ + rb->audio_stop(); +#ifndef SIMULATOR + while(rb->button_get_w_tmo(interval) == BUTTON_NONE){ + /* alternating between highest and 2nd highest freq */ + rb->pcm_set_frequency( + rb->hw_freq_sampr[(counter++&1)==1]); + rb->pcm_apply_settings(); + rb->pcm_play_data(callback, NULL, 0); + } + rb->pcm_play_stop(); + while (rb->pcm_is_playing()) rb->yield(); + /* restore default - user of apis is responsible for restoring + default state - normally playback at 44100Hz */ + rb->pcm_set_frequency(HW_FREQ_DEFAULT); +#endif + if (!rb->audio_status() && rb->global_status->resume_index != -1) + { + if (rb->playlist_resume() != -1) + { + rb->playlist_start(rb->global_status->resume_index, + rb->global_status->resume_offset); + } + } + return; + } + } while(1); +} + +int main(void) +{ + init_audio(); + int i; + FOR_NB_SCREENS(i){ + rb->screens[i]->puts(0,0,"Timer"); + rb->screens[i]->update(); + } + #define BUFFER_SIZE 10 + unsigned char buf[BUFFER_SIZE]; + int button=ACTION_WPS_PLAY; + int min=0; + bool done=false; + do{ + if(button!=ACTION_NONE){ + rb->snprintf(buf,BUFFER_SIZE,"%d min",min); + FOR_NB_SCREENS(i){ + rb->screens[i]->puts(0,1,buf); + rb->screens[i]->update(); + } + } + button = rb->get_action(CONTEXT_WPS,HZ); + switch(button){ + case ACTION_WPS_STOP: + min=0; + case ACTION_WPS_BROWSE: + case ACTION_WPS_PLAY: + done=true; + break; + case ACTION_WPS_VOLUP: + min++; + break; + case ACTION_WPS_VOLDOWN: + if(min>0) min--; + break; + case ACTION_WPS_SEEKFWD: + case ACTION_WPS_SKIPNEXT: + min+=10; + break; + case ACTION_WPS_SEEKBACK: + case ACTION_WPS_SKIPPREV: + if(min>=10) min-=10; + break; + } + if(rb->default_event_handler(button)==SYS_USB_CONNECTED) + return PLUGIN_USB_CONNECTED; + }while(!done); + + if(min>0){ + rb->splash(HZ,"Starting Timer ..."); + rb->set_sleep_timer(min * 60 + TIME_OFFSET); + while(rb->get_sleep_timer()==0) /* wait until timer is started */ + rb->yield(); + rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */ + if((thread_id = rb->create_thread(thread, thread_stack, + sizeof(thread_stack), 0, "Timer" + IF_PRIO(, PRIORITY_BACKGROUND) + IF_COP(, CPU))) == NULL) + { + rb->splash(HZ, "Cannot create thread!"); + return PLUGIN_ERROR; + } + rb->plugin_tsr(exit_tsr); + } + return PLUGIN_OK; +} +#endif Index: apps/plugins/SOURCES =================================================================== --- apps/plugins/SOURCES (revision 17158) +++ apps/plugins/SOURCES (working copy) @@ -19,6 +19,7 @@ stopwatch.c vbrfix.c viewer.c +timer.c #ifdef OLYMPUS_MROBE_500 /* remove these once the plugins before it are compileable */ Index: apps/plugins/CATEGORIES =================================================================== --- apps/plugins/CATEGORIES (revision 17158) +++ apps/plugins/CATEGORIES (working copy) @@ -97,3 +97,4 @@ wormlet,games xobox,games zxbox,viewers +timer,apps Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 17158) +++ apps/plugin.h (working copy) @@ -719,7 +719,8 @@ bool (*search_albumart_files)(const struct mp3entry *id3, const char *size_string, char *buf, int buflen); #endif - + void (*set_sleep_timer)(int seconds); + int (*get_sleep_timer)(void); /* new stuff at the end, sort into place next time the API gets incompatible */ Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 17158) +++ apps/plugin.c (working copy) @@ -573,7 +573,8 @@ find_albumart, search_albumart_files, #endif - + set_sleep_timer, + get_sleep_timer, /* new stuff at the end, sort into place next time the API gets incompatible */