From 68002763a788e7b56904c658e73a78d4d7b1e6ab Mon Sep 17 00:00:00 2001 From: Jörg Hohensohn Date: Fri, 30 Apr 2004 20:37:11 +0000 Subject: new plugin features for stuff I'm working on: user timer, TSR, threads, contrast, playback control git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4563 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ apps/plugin.h | 28 +++++++++++++++++-- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/apps/plugin.c b/apps/plugin.c index 3258dadad2..e92a9a4d84 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -68,6 +68,8 @@ extern void bitswap(unsigned char *data, int length); static bool plugin_loaded = false; static int plugin_size = 0; +static void (*pfn_timer)(void) = NULL; /* user timer handler */ +static void (*pfn_tsr_exit)(void) = NULL; /* TSR exit callback */ static int plugin_test(int api_version, int model, int memsize); @@ -188,6 +190,24 @@ static struct plugin_api rockbox_api = { #ifdef HAVE_LCD_BITMAP checkbox, #endif +#ifndef SIMULATOR + plugin_register_timer, + plugin_unregister_timer, +#endif + plugin_tsr, + create_thread, + remove_thread, + lcd_set_contrast, + mpeg_play, + mpeg_stop, + mpeg_pause, + mpeg_resume, + mpeg_next, + mpeg_prev, + mpeg_ff_rewind, + mpeg_next_track, + mpeg_has_changed_track, + mpeg_status, }; int plugin_load(char* plugin, void* parameter) @@ -202,6 +222,12 @@ int plugin_load(char* plugin, void* parameter) int fd; #endif + if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ + { + pfn_tsr_exit(); /* force it to exit now */ + pfn_tsr_exit = NULL; + } + #ifdef HAVE_LCD_BITMAP int xm,ym; lcd_clear_display(); @@ -335,6 +361,67 @@ void* plugin_get_mp3_buffer(int* buffer_size) #endif } +#ifndef SIMULATOR +/* Register a periodic time callback, called every "cycles" CPU clocks. + Note that this function will be called in interrupt context! */ +int plugin_register_timer(int cycles, int prio, void (*timer_callback)(void)) +{ + int phi = 0; /* bits for the prescaler */ + int prescale = 1; + + while (cycles > 0x10000) + { /* work out the smallest prescaler that makes it fit */ + phi++; + prescale *= 2; + cycles /= 2; + } + + if (prescale > 8 || cycles == 0 || prio < 1 || prio > 15) + return 0; /* error, we can't do such period, bad argument */ + + and_b(~0x10, &TSTR); /* Stop the timer 4 */ + and_b(~0x10, &TSNC); /* No synchronization */ + and_b(~0x10, &TMDR); /* Operate normally */ + + pfn_timer = timer_callback; /* install 2nd level ISR */ + + TSR4 &= ~0x01; + TIER4 = 0xF9; /* Enable GRA match interrupt */ + + GRA4 = (unsigned short)(cycles - 1); + TCR4 = 0x20 | phi; /* clear at GRA match, set prescaler */ + IPRD = (IPRD & 0xFF0F) | prio << 4; /* interrupt priority */ + or_b(0x10, &TSTR); /* start timer 4 */ + + return cycles * prescale; /* return the actual period, in CPU clocks */ +} + +/* disable the user timer */ +void plugin_unregister_timer(void) +{ + and_b(~0x10, &TSTR); /* stop the timer 4 */ + IPRD = (IPRD & 0xFF0F); /* disable interrupt */ + pfn_timer = NULL; +} + +/* interrupt handler for user timer */ +#pragma interrupt +void IMIA4(void) +{ + if (pfn_timer != NULL) + pfn_timer(); /* call the user timer function */ +} +#endif /* #ifndef SIMULATOR */ + +/* The plugin wants to stay resident after leaving its main function, e.g. + runs from timer or own thread. The callback is registered to later + instruct it to free its resources before a new plugin gets loaded. */ +void plugin_tsr(void (*exit_callback)(void)) +{ + pfn_tsr_exit = exit_callback; /* remember the callback for later */ +} + + static int plugin_test(int api_version, int model, int memsize) { if (api_version < PLUGIN_MIN_API_VERSION || diff --git a/apps/plugin.h b/apps/plugin.h index 720e4b20f3..2da469f004 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -43,9 +43,10 @@ #include "mpeg.h" #include "mp3_playback.h" #include "settings.h" +#include "thread.h" /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 11 +#define PLUGIN_API_VERSION 12 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any @@ -195,7 +196,7 @@ struct plugin_api { void* (*plugin_get_mp3_buffer)(int* buffer_size); void (*mpeg_sound_set)(int setting, int value); #ifndef SIMULATOR - void (*mp3_play_init)(void); + void (*mp3_play_init)(void); /* FIXME: remove this next time we break compatibility */ void (*mp3_play_data)(unsigned char* start, int size, void (*get_more)(unsigned char** start, int* size)); void (*mp3_play_pause)(bool play); void (*mp3_play_stop)(void); @@ -210,12 +211,35 @@ struct plugin_api { #ifdef HAVE_LCD_BITMAP void (*checkbox)(int x, int y, int width, int height, bool checked); #endif +#ifndef SIMULATOR + int (*plugin_register_timer)(int cycles, int prio, void (*timer_callback)(void)); + void (*plugin_unregister_timer)(void); +#endif + void (*plugin_tsr)(void (*exit_callback)(void)); + int (*create_thread)(void* function, void* stack, int stack_size, char *name); + void (*remove_tread)(void); + void (*lcd_set_contrast)(int x); + + /* playback control */ + void (*mpeg_play)(int offset); + void (*mpeg_stop)(void); + void (*mpeg_pause)(void); + void (*mpeg_resume)(void); + void (*mpeg_next)(void); + void (*mpeg_prev)(void); + void (*mpeg_ff_rewind)(int newtime); + struct mp3entry* (*mpeg_next_track)(void); + bool (*mpeg_has_changed_track)(void); + int (*mpeg_status)(void); }; /* defined by the plugin loader (plugin.c) */ int plugin_load(char* plugin, void* parameter); void* plugin_get_buffer(int *buffer_size); void* plugin_get_mp3_buffer(int *buffer_size); +int plugin_register_timer(int cycles, int prio, void (*timer_callback)(void)); +void plugin_unregister_timer(void); +void plugin_tsr(void (*exit_callback)(void)); /* defined by the plugin */ enum plugin_status plugin_start(struct plugin_api* rockbox, void* parameter) -- cgit v1.2.3