summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2004-04-30 20:37:11 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2004-04-30 20:37:11 +0000
commit68002763a788e7b56904c658e73a78d4d7b1e6ab (patch)
treeee6d22c0572f38e78619813e20c4954e177ae002
parent7bd007a597a15cd5fcb4f9c7d20f4309e2cbe1e3 (diff)
downloadrockbox-68002763a788e7b56904c658e73a78d4d7b1e6ab.zip
rockbox-68002763a788e7b56904c658e73a78d4d7b1e6ab.tar.gz
rockbox-68002763a788e7b56904c658e73a78d4d7b1e6ab.tar.bz2
rockbox-68002763a788e7b56904c658e73a78d4d7b1e6ab.tar.xz
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
-rw-r--r--apps/plugin.c87
-rw-r--r--apps/plugin.h28
2 files changed, 113 insertions, 2 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index 3258dad..e92a9a4 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 720e4b2..2da469f 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)