diff options
Diffstat (limited to 'apps/plugin.c')
-rw-r--r-- | apps/plugin.c | 87 |
1 files changed, 87 insertions, 0 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); | |||
68 | 68 | ||
69 | static bool plugin_loaded = false; | 69 | static bool plugin_loaded = false; |
70 | static int plugin_size = 0; | 70 | static int plugin_size = 0; |
71 | static void (*pfn_timer)(void) = NULL; /* user timer handler */ | ||
72 | static void (*pfn_tsr_exit)(void) = NULL; /* TSR exit callback */ | ||
71 | 73 | ||
72 | static int plugin_test(int api_version, int model, int memsize); | 74 | static int plugin_test(int api_version, int model, int memsize); |
73 | 75 | ||
@@ -188,6 +190,24 @@ static struct plugin_api rockbox_api = { | |||
188 | #ifdef HAVE_LCD_BITMAP | 190 | #ifdef HAVE_LCD_BITMAP |
189 | checkbox, | 191 | checkbox, |
190 | #endif | 192 | #endif |
193 | #ifndef SIMULATOR | ||
194 | plugin_register_timer, | ||
195 | plugin_unregister_timer, | ||
196 | #endif | ||
197 | plugin_tsr, | ||
198 | create_thread, | ||
199 | remove_thread, | ||
200 | lcd_set_contrast, | ||
201 | mpeg_play, | ||
202 | mpeg_stop, | ||
203 | mpeg_pause, | ||
204 | mpeg_resume, | ||
205 | mpeg_next, | ||
206 | mpeg_prev, | ||
207 | mpeg_ff_rewind, | ||
208 | mpeg_next_track, | ||
209 | mpeg_has_changed_track, | ||
210 | mpeg_status, | ||
191 | }; | 211 | }; |
192 | 212 | ||
193 | int plugin_load(char* plugin, void* parameter) | 213 | int plugin_load(char* plugin, void* parameter) |
@@ -202,6 +222,12 @@ int plugin_load(char* plugin, void* parameter) | |||
202 | int fd; | 222 | int fd; |
203 | #endif | 223 | #endif |
204 | 224 | ||
225 | if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ | ||
226 | { | ||
227 | pfn_tsr_exit(); /* force it to exit now */ | ||
228 | pfn_tsr_exit = NULL; | ||
229 | } | ||
230 | |||
205 | #ifdef HAVE_LCD_BITMAP | 231 | #ifdef HAVE_LCD_BITMAP |
206 | int xm,ym; | 232 | int xm,ym; |
207 | lcd_clear_display(); | 233 | lcd_clear_display(); |
@@ -335,6 +361,67 @@ void* plugin_get_mp3_buffer(int* buffer_size) | |||
335 | #endif | 361 | #endif |
336 | } | 362 | } |
337 | 363 | ||
364 | #ifndef SIMULATOR | ||
365 | /* Register a periodic time callback, called every "cycles" CPU clocks. | ||
366 | Note that this function will be called in interrupt context! */ | ||
367 | int plugin_register_timer(int cycles, int prio, void (*timer_callback)(void)) | ||
368 | { | ||
369 | int phi = 0; /* bits for the prescaler */ | ||
370 | int prescale = 1; | ||
371 | |||
372 | while (cycles > 0x10000) | ||
373 | { /* work out the smallest prescaler that makes it fit */ | ||
374 | phi++; | ||
375 | prescale *= 2; | ||
376 | cycles /= 2; | ||
377 | } | ||
378 | |||
379 | if (prescale > 8 || cycles == 0 || prio < 1 || prio > 15) | ||
380 | return 0; /* error, we can't do such period, bad argument */ | ||
381 | |||
382 | and_b(~0x10, &TSTR); /* Stop the timer 4 */ | ||
383 | and_b(~0x10, &TSNC); /* No synchronization */ | ||
384 | and_b(~0x10, &TMDR); /* Operate normally */ | ||
385 | |||
386 | pfn_timer = timer_callback; /* install 2nd level ISR */ | ||
387 | |||
388 | TSR4 &= ~0x01; | ||
389 | TIER4 = 0xF9; /* Enable GRA match interrupt */ | ||
390 | |||
391 | GRA4 = (unsigned short)(cycles - 1); | ||
392 | TCR4 = 0x20 | phi; /* clear at GRA match, set prescaler */ | ||
393 | IPRD = (IPRD & 0xFF0F) | prio << 4; /* interrupt priority */ | ||
394 | or_b(0x10, &TSTR); /* start timer 4 */ | ||
395 | |||
396 | return cycles * prescale; /* return the actual period, in CPU clocks */ | ||
397 | } | ||
398 | |||
399 | /* disable the user timer */ | ||
400 | void plugin_unregister_timer(void) | ||
401 | { | ||
402 | and_b(~0x10, &TSTR); /* stop the timer 4 */ | ||
403 | IPRD = (IPRD & 0xFF0F); /* disable interrupt */ | ||
404 | pfn_timer = NULL; | ||
405 | } | ||
406 | |||
407 | /* interrupt handler for user timer */ | ||
408 | #pragma interrupt | ||
409 | void IMIA4(void) | ||
410 | { | ||
411 | if (pfn_timer != NULL) | ||
412 | pfn_timer(); /* call the user timer function */ | ||
413 | } | ||
414 | #endif /* #ifndef SIMULATOR */ | ||
415 | |||
416 | /* The plugin wants to stay resident after leaving its main function, e.g. | ||
417 | runs from timer or own thread. The callback is registered to later | ||
418 | instruct it to free its resources before a new plugin gets loaded. */ | ||
419 | void plugin_tsr(void (*exit_callback)(void)) | ||
420 | { | ||
421 | pfn_tsr_exit = exit_callback; /* remember the callback for later */ | ||
422 | } | ||
423 | |||
424 | |||
338 | static int plugin_test(int api_version, int model, int memsize) | 425 | static int plugin_test(int api_version, int model, int memsize) |
339 | { | 426 | { |
340 | if (api_version < PLUGIN_MIN_API_VERSION || | 427 | if (api_version < PLUGIN_MIN_API_VERSION || |