summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-07-26 20:01:11 +0000
committerJens Arnold <amiconn@rockbox.org>2005-07-26 20:01:11 +0000
commite44372ef18cbf30f0e174ed76be4ee4e6206f2cc (patch)
tree8860863bbfb7a6151173e7428900d9de2bdbba73
parentc20a00ef3e35b15acf422a2e7f6716abde840c24 (diff)
downloadrockbox-e44372ef18cbf30f0e174ed76be4ee4e6206f2cc.tar.gz
rockbox-e44372ef18cbf30f0e174ed76be4ee4e6206f2cc.zip
Moved implementation of user timer to the firmware layer, implemented it for iriver, and made it shareable based on priorities. On iriver, the user timer is shared between the backlight fading and other use, so if a plugin registers the timer, the backlight will resort to simple on/off switching until the plugin releases the timer again. Sorted and bumped the plugin api.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7242 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.c108
-rw-r--r--apps/plugin.h71
-rw-r--r--apps/plugins/alpine_cdc.c8
-rw-r--r--apps/plugins/lib/gray_core.c4
-rw-r--r--apps/plugins/metronome.c4
-rw-r--r--apps/plugins/oscilloscope.c4
-rw-r--r--apps/plugins/video.c16
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/backlight.c101
-rw-r--r--firmware/export/backlight.h3
-rw-r--r--firmware/export/timer.h34
-rw-r--r--firmware/timer.c181
12 files changed, 335 insertions, 200 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index 7bfa0e2a0f..6c018067ea 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -45,6 +45,7 @@
45#include "mp3data.h" 45#include "mp3data.h"
46#include "powermgmt.h" 46#include "powermgmt.h"
47#include "system.h" 47#include "system.h"
48#include "timer.h"
48#include "sound.h" 49#include "sound.h"
49#include "database.h" 50#include "database.h"
50#if (CONFIG_HWCODEC == MASNONE) 51#if (CONFIG_HWCODEC == MASNONE)
@@ -74,9 +75,6 @@ extern unsigned char pluginbuf[];
74/* for actual plugins only, not for codecs */ 75/* for actual plugins only, not for codecs */
75static bool plugin_loaded = false; 76static bool plugin_loaded = false;
76static int plugin_size = 0; 77static int plugin_size = 0;
77#ifndef SIMULATOR
78static void (*pfn_timer)(void) = NULL; /* user timer handler */
79#endif
80static void (*pfn_tsr_exit)(void) = NULL; /* TSR exit callback */ 78static void (*pfn_tsr_exit)(void) = NULL; /* TSR exit callback */
81 79
82static int plugin_test(int api_version, int model, int memsize); 80static int plugin_test(int api_version, int model, int memsize);
@@ -116,6 +114,14 @@ static const struct plugin_api rockbox_api = {
116 lcd_fillrect, 114 lcd_fillrect,
117 lcd_mono_bitmap_part, 115 lcd_mono_bitmap_part,
118 lcd_mono_bitmap, 116 lcd_mono_bitmap,
117#if LCD_DEPTH > 1
118 lcd_set_foreground,
119 lcd_get_foreground,
120 lcd_set_background,
121 lcd_get_background,
122 lcd_bitmap_part,
123 lcd_bitmap,
124#endif
119 lcd_putsxy, 125 lcd_putsxy,
120 lcd_puts_style, 126 lcd_puts_style,
121 lcd_puts_scroll_style, 127 lcd_puts_scroll_style,
@@ -126,6 +132,7 @@ static const struct plugin_api rockbox_api = {
126 scrollbar, 132 scrollbar,
127 checkbox, 133 checkbox,
128 font_get, 134 font_get,
135 font_getstringsize,
129#endif 136#endif
130 backlight_on, 137 backlight_on,
131 backlight_off, 138 backlight_off,
@@ -211,6 +218,9 @@ static const struct plugin_api rockbox_api = {
211#ifdef HAVE_ADJUSTABLE_CPU_FREQ 218#ifdef HAVE_ADJUSTABLE_CPU_FREQ
212 cpu_boost, 219 cpu_boost,
213#endif 220#endif
221 timer_register,
222 timer_unregister,
223 timer_set_period,
214#endif 224#endif
215 225
216 /* strings and memory */ 226 /* strings and memory */
@@ -220,6 +230,7 @@ static const struct plugin_api rockbox_api = {
220 strlen, 230 strlen,
221 strrchr, 231 strrchr,
222 strcmp, 232 strcmp,
233 strncmp,
223 strcasecmp, 234 strcasecmp,
224 strncasecmp, 235 strncasecmp,
225 memset, 236 memset,
@@ -289,6 +300,10 @@ static const struct plugin_api rockbox_api = {
289 &tagdb_fd, 300 &tagdb_fd,
290 &tagdb_initialized, 301 &tagdb_initialized,
291 tagdb_init, 302 tagdb_init,
303 /* runtime database */
304 &rundbheader,
305 &rundb_fd,
306 &rundb_initialized,
292 307
293 /* misc */ 308 /* misc */
294 srand, 309 srand,
@@ -299,14 +314,13 @@ static const struct plugin_api rockbox_api = {
299 set_time, 314 set_time,
300 plugin_get_buffer, 315 plugin_get_buffer,
301 plugin_get_audio_buffer, 316 plugin_get_audio_buffer,
302#ifndef SIMULATOR
303 plugin_register_timer,
304 plugin_unregister_timer,
305#endif
306 plugin_tsr, 317 plugin_tsr,
307#if defined(DEBUG) || defined(SIMULATOR) 318#if defined(DEBUG) || defined(SIMULATOR)
308 debugf, 319 debugf,
309#endif 320#endif
321#ifdef ROCKBOX_HAS_LOGF
322 logf,
323#endif
310 &global_settings, 324 &global_settings,
311 mp3info, 325 mp3info,
312 count_mp3_frames, 326 count_mp3_frames,
@@ -326,24 +340,6 @@ static const struct plugin_api rockbox_api = {
326 /* new stuff at the end, sort into place next time 340 /* new stuff at the end, sort into place next time
327 the API gets incompatible */ 341 the API gets incompatible */
328 342
329#ifdef ROCKBOX_HAS_LOGF
330 logf,
331#endif
332 &rundbheader,
333 &rundb_fd,
334 &rundb_initialized,
335 strncmp,
336#if LCD_DEPTH > 1
337 lcd_set_foreground,
338 lcd_get_foreground,
339 lcd_set_background,
340 lcd_get_background,
341 lcd_bitmap_part,
342 lcd_bitmap,
343#endif
344#ifdef HAVE_LCD_BITMAP
345 font_getstringsize,
346#endif
347}; 343};
348 344
349int plugin_load(const char* plugin, void* parameter) 345int plugin_load(const char* plugin, void* parameter)
@@ -486,68 +482,6 @@ void* plugin_get_audio_buffer(int* buffer_size)
486 return audiobuf; 482 return audiobuf;
487} 483}
488 484
489#ifndef SIMULATOR
490/* Register a periodic time callback, called every "cycles" CPU clocks.
491 Note that this function will be called in interrupt context! */
492int plugin_register_timer(int cycles, int prio, void (*timer_callback)(void))
493{
494 int phi = 0; /* bits for the prescaler */
495 int prescale = 1;
496
497 while (cycles > 0x10000)
498 { /* work out the smallest prescaler that makes it fit */
499 phi++;
500 prescale *= 2;
501 cycles /= 2;
502 }
503
504 if (prescale > 8 || cycles == 0 || prio < 1 || prio > 15)
505 return 0; /* error, we can't do such period, bad argument */
506
507 backlight_allow_timer(false); /* stop backlight from messing with the timer */
508#if CONFIG_CPU == SH7034
509 and_b(~0x10, &TSTR); /* Stop the timer 4 */
510 and_b(~0x10, &TSNC); /* No synchronization */
511 and_b(~0x10, &TMDR); /* Operate normally */
512
513 pfn_timer = timer_callback; /* install 2nd level ISR */
514
515 and_b(~0x01, &TSR4);
516 TIER4 = 0xF9; /* Enable GRA match interrupt */
517
518 GRA4 = (unsigned short)(cycles - 1);
519 TCR4 = 0x20 | phi; /* clear at GRA match, set prescaler */
520 IPRD = (IPRD & 0xFF0F) | prio << 4; /* interrupt priority */
521 or_b(0x10, &TSTR); /* start timer 4 */
522#else
523 pfn_timer = timer_callback;
524#endif
525 return cycles * prescale; /* return the actual period, in CPU clocks */
526}
527
528/* disable the user timer */
529void plugin_unregister_timer(void)
530{
531#if CONFIG_CPU == SH7034
532 and_b(~0x10, &TSTR); /* stop the timer 4 */
533 IPRD = (IPRD & 0xFF0F); /* disable interrupt */
534 pfn_timer = NULL;
535#endif
536 backlight_allow_timer(true);
537}
538
539#if CONFIG_CPU == SH7034
540/* interrupt handler for user timer */
541#pragma interrupt
542void IMIA4(void)
543{
544 if (pfn_timer != NULL)
545 pfn_timer(); /* call the user timer function */
546 and_b(~0x01, &TSR4); /* clear the interrupt */
547}
548#endif /* CONFIG_CPU == SH7034 */
549#endif /* #ifndef SIMULATOR */
550
551/* The plugin wants to stay resident after leaving its main function, e.g. 485/* The plugin wants to stay resident after leaving its main function, e.g.
552 runs from timer or own thread. The callback is registered to later 486 runs from timer or own thread. The callback is registered to later
553 instruct it to free its resources before a new plugin gets loaded. */ 487 instruct it to free its resources before a new plugin gets loaded. */
diff --git a/apps/plugin.h b/apps/plugin.h
index f504bacf22..7cda354808 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -48,6 +48,7 @@
48#include "pcm_playback.h" 48#include "pcm_playback.h"
49#endif 49#endif
50#include "settings.h" 50#include "settings.h"
51#include "timer.h"
51#include "thread.h" 52#include "thread.h"
52#include "playlist.h" 53#include "playlist.h"
53#ifdef HAVE_LCD_BITMAP 54#ifdef HAVE_LCD_BITMAP
@@ -87,12 +88,12 @@
87#endif 88#endif
88 89
89/* increase this every time the api struct changes */ 90/* increase this every time the api struct changes */
90#define PLUGIN_API_VERSION 46 91#define PLUGIN_API_VERSION 47
91 92
92/* update this to latest version if a change to the api struct breaks 93/* update this to latest version if a change to the api struct breaks
93 backwards compatibility (and please take the opportunity to sort in any 94 backwards compatibility (and please take the opportunity to sort in any
94 new function which are "waiting" at the end of the function table) */ 95 new function which are "waiting" at the end of the function table) */
95#define PLUGIN_MIN_API_VERSION 42 96#define PLUGIN_MIN_API_VERSION 47
96 97
97/* plugin return codes */ 98/* plugin return codes */
98enum plugin_status { 99enum plugin_status {
@@ -168,6 +169,23 @@ struct plugin_api {
168 int stride, int x, int y, int width, int height); 169 int stride, int x, int y, int width, int height);
169 void (*lcd_mono_bitmap)(const unsigned char *src, int x, int y, 170 void (*lcd_mono_bitmap)(const unsigned char *src, int x, int y,
170 int width, int height); 171 int width, int height);
172#if LCD_DEPTH > 1
173#ifdef HAVE_LCD_COLOR
174 void (*lcd_set_foreground)(struct rgb color);
175 struct rgb (*lcd_get_foreground)(void);
176 void (*lcd_set_background)(struct rgb color);
177 struct rgb (*lcd_get_background)(void);
178#else
179 void (*lcd_set_foreground)(int brightness);
180 int (*lcd_get_foreground)(void);
181 void (*lcd_set_background)(int brightness);
182 int (*lcd_get_background)(void);
183#endif
184 void (*lcd_bitmap_part)(const unsigned char *src, int src_x, int src_y,
185 int stride, int x, int y, int width, int height);
186 void (*lcd_bitmap)(const unsigned char *src, int x, int y, int width,
187 int height);
188#endif
171 void (*lcd_putsxy)(int x, int y, const unsigned char *string); 189 void (*lcd_putsxy)(int x, int y, const unsigned char *string);
172 void (*lcd_puts_style)(int x, int y, const unsigned char *str, int style); 190 void (*lcd_puts_style)(int x, int y, const unsigned char *str, int style);
173 void (*lcd_puts_scroll_style)(int x, int y, const unsigned char* string, 191 void (*lcd_puts_scroll_style)(int x, int y, const unsigned char* string,
@@ -181,6 +199,8 @@ struct plugin_api {
181 int min_shown, int max_shown, int orientation); 199 int min_shown, int max_shown, int orientation);
182 void (*checkbox)(int x, int y, int width, int height, bool checked); 200 void (*checkbox)(int x, int y, int width, int height, bool checked);
183 struct font* (*font_get)(int font); 201 struct font* (*font_get)(int font);
202 int (*font_getstringsize)(const unsigned char *str, int *w, int *h,
203 int fontnumber);
184#endif 204#endif
185 void (*backlight_on)(void); 205 void (*backlight_on)(void);
186 void (*backlight_off)(void); 206 void (*backlight_off)(void);
@@ -272,6 +292,11 @@ struct plugin_api {
272#ifdef HAVE_ADJUSTABLE_CPU_FREQ 292#ifdef HAVE_ADJUSTABLE_CPU_FREQ
273 void (*cpu_boost)(bool on_off); 293 void (*cpu_boost)(bool on_off);
274#endif 294#endif
295 bool (*timer_register)(int reg_prio, void (*unregister_callback)(void),
296 long cycles, int int_prio,
297 void (*timer_callback)(void));
298 void (*timer_unregister)(void);
299 bool (*timer_set_period)(long count);
275#endif 300#endif
276 301
277 /* strings and memory */ 302 /* strings and memory */
@@ -281,6 +306,7 @@ struct plugin_api {
281 size_t (*strlen)(const char *str); 306 size_t (*strlen)(const char *str);
282 char * (*strrchr)(const char *s, int c); 307 char * (*strrchr)(const char *s, int c);
283 int (*strcmp)(const char *, const char *); 308 int (*strcmp)(const char *, const char *);
309 int (*strncmp)(const char *, const char *, size_t);
284 int (*strcasecmp)(const char *, const char *); 310 int (*strcasecmp)(const char *, const char *);
285 int (*strncasecmp)(const char *s1, const char *s2, size_t n); 311 int (*strncasecmp)(const char *s1, const char *s2, size_t n);
286 void* (*memset)(void *dst, int c, size_t length); 312 void* (*memset)(void *dst, int c, size_t length);
@@ -350,6 +376,10 @@ struct plugin_api {
350 int *tagdb_fd; 376 int *tagdb_fd;
351 int *tagdb_initialized; 377 int *tagdb_initialized;
352 int (*tagdb_init) (void); 378 int (*tagdb_init) (void);
379 /* runtime database */
380 struct rundb_header *rundbheader;
381 int *rundb_fd;
382 int *rundb_initialized;
353 383
354 /* misc */ 384 /* misc */
355 void (*srand)(unsigned int seed); 385 void (*srand)(unsigned int seed);
@@ -361,14 +391,13 @@ struct plugin_api {
361 int (*set_time)(const struct tm *tm); 391 int (*set_time)(const struct tm *tm);
362 void* (*plugin_get_buffer)(int* buffer_size); 392 void* (*plugin_get_buffer)(int* buffer_size);
363 void* (*plugin_get_audio_buffer)(int* buffer_size); 393 void* (*plugin_get_audio_buffer)(int* buffer_size);
364#ifndef SIMULATOR
365 int (*plugin_register_timer)(int cycles, int prio, void (*timer_callback)(void));
366 void (*plugin_unregister_timer)(void);
367#endif
368 void (*plugin_tsr)(void (*exit_callback)(void)); 394 void (*plugin_tsr)(void (*exit_callback)(void));
369#if defined(DEBUG) || defined(SIMULATOR) 395#if defined(DEBUG) || defined(SIMULATOR)
370 void (*debugf)(const char *fmt, ...); 396 void (*debugf)(const char *fmt, ...);
371#endif 397#endif
398#ifdef ROCKBOX_HAS_LOGF
399 void (*logf)(const char *fmt, ...);
400#endif
372 struct user_settings* global_settings; 401 struct user_settings* global_settings;
373 bool (*mp3info)(struct mp3entry *entry, const char *filename, bool v1first); 402 bool (*mp3info)(struct mp3entry *entry, const char *filename, bool v1first);
374 int (*count_mp3_frames)(int fd, int startpos, int filesize, 403 int (*count_mp3_frames)(int fd, int startpos, int filesize,
@@ -395,41 +424,11 @@ struct plugin_api {
395 /* new stuff at the end, sort into place next time 424 /* new stuff at the end, sort into place next time
396 the API gets incompatible */ 425 the API gets incompatible */
397 426
398#ifdef ROCKBOX_HAS_LOGF
399 void (*logf)(const char *fmt, ...);
400#endif
401 struct rundb_header *rundbheader;
402 int *rundb_fd;
403 int *rundb_initialized;
404 int (*strncmp)(const char *, const char *, size_t);
405#if LCD_DEPTH > 1
406#ifdef HAVE_LCD_COLOR
407 void (*lcd_set_foreground)(struct rgb color);
408 struct rgb (*lcd_get_foreground)(void);
409 void (*lcd_set_background)(struct rgb color);
410 struct rgb (*lcd_get_background)(void);
411#else
412 void (*lcd_set_foreground)(int brightness);
413 int (*lcd_get_foreground)(void);
414 void (*lcd_set_background)(int brightness);
415 int (*lcd_get_background)(void);
416#endif
417 void (*lcd_bitmap_part)(const unsigned char *src, int src_x, int src_y,
418 int stride, int x, int y, int width, int height);
419 void (*lcd_bitmap)(const unsigned char *src, int x, int y, int width,
420 int height);
421#endif
422#ifdef HAVE_LCD_BITMAP
423 int (*font_getstringsize)(const unsigned char *str, int *w, int *h,
424 int fontnumber);
425#endif
426}; 427};
427 428
428int plugin_load(const char* plugin, void* parameter); 429int plugin_load(const char* plugin, void* parameter);
429void* plugin_get_buffer(int *buffer_size); 430void* plugin_get_buffer(int *buffer_size);
430void* plugin_get_audio_buffer(int *buffer_size); 431void* plugin_get_audio_buffer(int *buffer_size);
431int plugin_register_timer(int cycles, int prio, void (*timer_callback)(void));
432void plugin_unregister_timer(void);
433void plugin_tsr(void (*exit_callback)(void)); 432void plugin_tsr(void (*exit_callback)(void));
434 433
435/* defined by the plugin */ 434/* defined by the plugin */
diff --git a/apps/plugins/alpine_cdc.c b/apps/plugins/alpine_cdc.c
index 7c014a2e0c..5dd8b4a952 100644
--- a/apps/plugins/alpine_cdc.c
+++ b/apps/plugins/alpine_cdc.c
@@ -230,15 +230,15 @@ void timer_set_mode(int mode)
230 230
231 if (mode == TM_RX_TIMEOUT) 231 if (mode == TM_RX_TIMEOUT)
232 { 232 {
233 rb->plugin_register_timer(gTimer.timeout, 11, timer4_isr); 233 rb->timer_register(1, NULL, gTimer.timeout, 11, timer4_isr);
234 } 234 }
235 else if (mode == TM_TRANSMIT) 235 else if (mode == TM_TRANSMIT)
236 { 236 {
237 rb->plugin_register_timer(gTimer.transmit, 14, timer4_isr); 237 rb->timer_register(1, NULL, gTimer.transmit, 14, timer4_isr);
238 } 238 }
239 else 239 else
240 { 240 {
241 rb->plugin_unregister_timer(); 241 rb->timer_unregister();
242 } 242 }
243} 243}
244 244
@@ -252,7 +252,7 @@ void timer4_isr(void) /* IMIA4 */
252 break; 252 break;
253 case TM_RX_TIMEOUT: 253 case TM_RX_TIMEOUT:
254 receive_timeout_isr(); 254 receive_timeout_isr();
255 rb->plugin_unregister_timer(); /* single shot */ 255 rb->timer_unregister(); /* single shot */
256 break; 256 break;
257 default: 257 default:
258 timer_set_mode(TM_OFF); /* spurious interrupt */ 258 timer_set_mode(TM_OFF); /* spurious interrupt */
diff --git a/apps/plugins/lib/gray_core.c b/apps/plugins/lib/gray_core.c
index 18b9c3c821..361b392458 100644
--- a/apps/plugins/lib/gray_core.c
+++ b/apps/plugins/lib/gray_core.c
@@ -257,11 +257,11 @@ void gray_show(bool enable)
257 if (enable) 257 if (enable)
258 { 258 {
259 _gray_info.flags |= _GRAY_RUNNING; 259 _gray_info.flags |= _GRAY_RUNNING;
260 _gray_rb->plugin_register_timer(FREQ / 67, 1, _timer_isr); 260 _gray_rb->timer_register(1, NULL, FREQ / 67, 1, _timer_isr);
261 } 261 }
262 else 262 else
263 { 263 {
264 _gray_rb->plugin_unregister_timer(); 264 _gray_rb->timer_unregister();
265 _gray_info.flags &= ~_GRAY_RUNNING; 265 _gray_info.flags &= ~_GRAY_RUNNING;
266 _gray_rb->lcd_update(); /* restore whatever there was before */ 266 _gray_rb->lcd_update(); /* restore whatever there was before */
267 } 267 }
diff --git a/apps/plugins/metronome.c b/apps/plugins/metronome.c
index 3793fd9690..fa5520b635 100644
--- a/apps/plugins/metronome.c
+++ b/apps/plugins/metronome.c
@@ -235,7 +235,7 @@ void cleanup(void *parameter)
235{ 235{
236 (void)parameter; 236 (void)parameter;
237 237
238 rb->plugin_unregister_timer(); 238 rb->timer_unregister();
239 rb->mp3_play_stop(); /* stop audio ISR */ 239 rb->mp3_play_stop(); /* stop audio ISR */
240 led(0); 240 led(0);
241} 241}
@@ -278,7 +278,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter){
278 rb->mp3_play_stop(); // stop audio ISR 278 rb->mp3_play_stop(); // stop audio ISR
279 279
280 calc_period(); 280 calc_period();
281 rb->plugin_register_timer(((*rb->cpu_frequency)/1024), 1, timer_callback); 281 rb->timer_register(1, NULL, (*rb->cpu_frequency)/1024, 1, timer_callback);
282 282
283 draw_display(); 283 draw_display();
284 284
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index ae77f33369..f5e5189e2e 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -192,7 +192,7 @@ void cleanup(void *parameter)
192{ 192{
193 (void)parameter; 193 (void)parameter;
194 194
195 rb->plugin_unregister_timer(); 195 rb->timer_unregister();
196} 196}
197 197
198enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 198enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
@@ -205,7 +205,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
205 (void)parameter; 205 (void)parameter;
206 rb = api; 206 rb = api;
207 207
208 rb->plugin_register_timer(FREQ / 67, 1, timer_isr); 208 rb->timer_register(1, NULL, FREQ / 67, 1, timer_isr);
209 209
210 while (!exit) 210 while (!exit)
211 { 211 {
diff --git a/apps/plugins/video.c b/apps/plugins/video.c
index b4b27e0cb8..1a288eec84 100644
--- a/apps/plugins/video.c
+++ b/apps/plugins/video.c
@@ -388,7 +388,7 @@ void timer4_isr(void)
388 else 388 else
389 { 389 {
390 gPlay.bVideoUnderrun = true; 390 gPlay.bVideoUnderrun = true;
391 rb->plugin_unregister_timer(); // disable ourselves 391 rb->timer_unregister(); // disable ourselves
392 return; // no data available 392 return; // no data available
393 } 393 }
394 } 394 }
@@ -490,7 +490,7 @@ int SeekTo(int fd, int nPos)
490 if (gPlay.bHasAudio) 490 if (gPlay.bHasAudio)
491 rb->mp3_play_stop(); // stop audio ISR 491 rb->mp3_play_stop(); // stop audio ISR
492 if (gPlay.bHasVideo) 492 if (gPlay.bHasVideo)
493 rb->plugin_unregister_timer(); // stop the timer 493 rb->timer_unregister(); // stop the timer
494 494
495 rb->lseek(fd, nPos, SEEK_SET); 495 rb->lseek(fd, nPos, SEEK_SET);
496 496
@@ -538,9 +538,9 @@ int SeekTo(int fd, int nPos)
538 gPlay.bVideoUnderrun = false; 538 gPlay.bVideoUnderrun = false;
539 // start display interrupt 539 // start display interrupt
540#if FREQ == 12000000 /* Ondio speed kludge */ 540#if FREQ == 12000000 /* Ondio speed kludge */
541 rb->plugin_register_timer(gPlay.nFrameTimeAdjusted, 1, timer4_isr); 541 rb->timer_register(1, NULL, gPlay.nFrameTimeAdjusted, 1, timer4_isr);
542#else 542#else
543 rb->plugin_register_timer(gFileHdr.video_frametime, 1, timer4_isr); 543 rb->timer_register(1, NULL, gFileHdr.video_frametime, 1, timer4_isr);
544#endif 544#endif
545 } 545 }
546 546
@@ -553,7 +553,7 @@ void Cleanup(void *fd)
553 rb->close(*(int*)fd); // close the file 553 rb->close(*(int*)fd); // close the file
554 554
555 if (gPlay.bHasVideo) 555 if (gPlay.bHasVideo)
556 rb->plugin_unregister_timer(); // stop video ISR, now I can use the display again 556 rb->timer_unregister(); // stop video ISR, now I can use the display again
557 557
558 if (gPlay.bHasAudio) 558 if (gPlay.bHasAudio)
559 rb->mp3_play_stop(); // stop audio ISR 559 rb->mp3_play_stop(); // stop audio ISR
@@ -705,7 +705,7 @@ int PlayTick(int fd)
705 if (gPlay.bHasAudio) 705 if (gPlay.bHasAudio)
706 rb->mp3_play_pause(false); // pause audio 706 rb->mp3_play_pause(false); // pause audio
707 if (gPlay.bHasVideo) 707 if (gPlay.bHasVideo)
708 rb->plugin_unregister_timer(); // stop the timer 708 rb->timer_unregister(); // stop the timer
709 } 709 }
710 else if (gPlay.state == paused) 710 else if (gPlay.state == paused)
711 { 711 {
@@ -719,10 +719,10 @@ int PlayTick(int fd)
719 if (gPlay.bHasVideo) 719 if (gPlay.bHasVideo)
720 { // start the video 720 { // start the video
721#if FREQ == 12000000 /* Ondio speed kludge */ 721#if FREQ == 12000000 /* Ondio speed kludge */
722 rb->plugin_register_timer( 722 rb->timer_register(1, NULL,
723 gPlay.nFrameTimeAdjusted, 1, timer4_isr); 723 gPlay.nFrameTimeAdjusted, 1, timer4_isr);
724#else 724#else
725 rb->plugin_register_timer( 725 rb->timer_register(1, NULL,
726 gFileHdr.video_frametime, 1, timer4_isr); 726 gFileHdr.video_frametime, 1, timer4_isr);
727#endif 727#endif
728 } 728 }
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 5fbe6be20e..06b4ce0765 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -101,6 +101,7 @@ hwcompat.c
101kernel.c 101kernel.c
102rolo.c 102rolo.c
103thread.c 103thread.c
104timer.c
104crt0.S 105crt0.S
105#endif 106#endif
106mp3_playback.c 107mp3_playback.c
diff --git a/firmware/backlight.c b/firmware/backlight.c
index e997ccaa2a..25cc045e62 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -27,6 +27,7 @@
27#include "usb.h" 27#include "usb.h"
28#include "power.h" 28#include "power.h"
29#include "system.h" 29#include "system.h"
30#include "timer.h"
30 31
31#ifdef HAVE_REMOTE_LCD 32#ifdef HAVE_REMOTE_LCD
32#include "lcd-remote.h" 33#include "lcd-remote.h"
@@ -66,7 +67,6 @@ static unsigned int remote_backlight_timeout = 5;
66static const char backlight_fade_value[8] = { 0, 1, 2, 4, 6, 8, 10, 20 }; 67static const char backlight_fade_value[8] = { 0, 1, 2, 4, 6, 8, 10, 20 };
67static int fade_in_count = 1; 68static int fade_in_count = 1;
68static int fade_out_count = 4; 69static int fade_out_count = 4;
69static bool timer_allowed = true;
70 70
71static bool bl_timer_active = false; 71static bool bl_timer_active = false;
72static int bl_dim_current = BL_PWM_COUNT; 72static int bl_dim_current = BL_PWM_COUNT;
@@ -75,44 +75,20 @@ static int bl_pwm_counter = 0;
75static volatile int bl_cycle_counter = 0; 75static volatile int bl_cycle_counter = 0;
76static enum {DIM_STATE_START, DIM_STATE_MAIN} bl_dim_state = DIM_STATE_START; 76static enum {DIM_STATE_START, DIM_STATE_MAIN} bl_dim_state = DIM_STATE_START;
77 77
78void backlight_start_timer(void) 78static void backlight_isr(void)
79{
80 unsigned int count;
81
82 if (bl_timer_active)
83 return ;
84
85 /* Prevent cpu frequency changes while dimming. */
86 cpu_boost(true);
87 count = 1;
88 bl_timer_active = true;
89
90 /* We are using timer 1 */
91 TRR1 = count; /* The reference count */
92 TCN1 = 0; /* reset the timer */
93 TMR1 = 0x011d; /* prescaler=2, restart, CLK/16, enabled */
94
95 TER1 = 0xff; /* Clear all events */
96
97 /* ICR2 (Timer2) */
98 ICR0 = (ICR0 & 0xffff00ff) | 0x00009000; /* Interrupt on level 4.0 */
99 IMR &= ~(1<<10);
100}
101
102void TIMER1(void) __attribute__ ((interrupt_handler));
103void TIMER1(void)
104{ 79{
105 int timer_period; 80 int timer_period;
106 bool idle = false; 81 bool idle = false;
107 82
108 timer_period = FREQ / 2000 * BL_PWM_INTERVAL / 1000 / 32; 83 timer_period = FREQ / 1000 * BL_PWM_INTERVAL / 1000;
109 switch (bl_dim_state) { 84 switch (bl_dim_state)
85 {
110 /* New cycle */ 86 /* New cycle */
111 case DIM_STATE_START: 87 case DIM_STATE_START:
112 bl_pwm_counter = 0; 88 bl_pwm_counter = 0;
113 bl_cycle_counter++; 89 bl_cycle_counter++;
114 90
115 if (bl_dim_current > 0 && bl_dim_current < BL_PWM_COUNT) 91 if (bl_dim_current > 0 && bl_dim_current < BL_PWM_COUNT)
116 { 92 {
117 and_l(~0x00020000, &GPIO1_OUT); 93 and_l(~0x00020000, &GPIO1_OUT);
118 bl_pwm_counter = bl_dim_current; 94 bl_pwm_counter = bl_dim_current;
@@ -125,6 +101,7 @@ void TIMER1(void)
125 and_l(~0x00020000, &GPIO1_OUT); 101 and_l(~0x00020000, &GPIO1_OUT);
126 else 102 else
127 or_l(0x00020000, &GPIO1_OUT); 103 or_l(0x00020000, &GPIO1_OUT);
104
128 if (bl_dim_current == bl_dim_target) 105 if (bl_dim_current == bl_dim_target)
129 idle = true; 106 idle = true;
130 } 107 }
@@ -137,9 +114,8 @@ void TIMER1(void)
137 bl_dim_state = DIM_STATE_START; 114 bl_dim_state = DIM_STATE_START;
138 timer_period = timer_period * (BL_PWM_COUNT - bl_pwm_counter) / BL_PWM_COUNT; 115 timer_period = timer_period * (BL_PWM_COUNT - bl_pwm_counter) / BL_PWM_COUNT;
139 break ; 116 break ;
140
141 } 117 }
142 118
143 if ((bl_dim_target > bl_dim_current) && (bl_cycle_counter >= fade_in_count)) 119 if ((bl_dim_target > bl_dim_current) && (bl_cycle_counter >= fade_in_count))
144 { 120 {
145 bl_dim_current++; 121 bl_dim_current++;
@@ -155,37 +131,50 @@ void TIMER1(void)
155 if (idle) 131 if (idle)
156 { 132 {
157 cpu_boost(false); 133 cpu_boost(false);
134 timer_unregister();
158 bl_timer_active = false; 135 bl_timer_active = false;
159 TMR1 = 0;
160 } 136 }
137 else
138 timer_set_period(timer_period);
139}
161 140
162 TRR1 = timer_period; 141static void backlight_switch(void)
163 TCN1 = 0; 142{
164 TER1 = 0xff; /* Clear all events */ 143 if (bl_dim_target > (BL_PWM_COUNT/2))
144 {
145 and_l(~0x00020000, &GPIO1_OUT);
146 bl_dim_current = BL_PWM_COUNT;
147 }
148 else
149 {
150 or_l(0x00020000, &GPIO1_OUT);
151 bl_dim_current = 0;
152 }
165} 153}
166 154
167static void __backlight_dim(int value) 155static void backlight_release_timer(void)
168{ 156{
169 bl_dim_target = value; 157 cpu_boost(false);
170 backlight_start_timer(); 158 timer_unregister();
159 bl_timer_active = false;
160 backlight_switch();
171} 161}
172 162
173void backlight_allow_timer(bool on) 163static void backlight_dim(int value)
174{ 164{
175 timer_allowed = on; 165 bl_dim_target = value;
176 166
177 if (!timer_allowed && bl_timer_active) 167 if (bl_timer_active)
178 { 168 return ;
179 cpu_boost(false);
180 bl_dim_current = bl_dim_target;
181 bl_timer_active = false;
182 TMR1 = 0;
183 169
184 if (bl_dim_current) 170 if (timer_register(0, backlight_release_timer, 1, 0, backlight_isr))
185 and_l(~0x00020000, &GPIO1_OUT); 171 {
186 else 172 /* Prevent cpu frequency changes while dimming. */
187 or_l(0x00020000, &GPIO1_OUT); 173 cpu_boost(true);
174 bl_timer_active = true;
188 } 175 }
176 else
177 backlight_switch();
189} 178}
190 179
191void backlight_set_fade_in(int index) 180void backlight_set_fade_in(int index)
@@ -202,8 +191,8 @@ void backlight_set_fade_out(int index)
202static void __backlight_off(void) 191static void __backlight_off(void)
203{ 192{
204#if CONFIG_BACKLIGHT == BL_IRIVER 193#if CONFIG_BACKLIGHT == BL_IRIVER
205 if (timer_allowed && (fade_out_count > 0)) 194 if (fade_out_count > 0)
206 __backlight_dim(0); 195 backlight_dim(0);
207 else 196 else
208 { 197 {
209 bl_dim_target = bl_dim_current = 0; 198 bl_dim_target = bl_dim_current = 0;
@@ -224,8 +213,8 @@ static void __backlight_off(void)
224static void __backlight_on(void) 213static void __backlight_on(void)
225{ 214{
226#if CONFIG_BACKLIGHT == BL_IRIVER 215#if CONFIG_BACKLIGHT == BL_IRIVER
227 if (timer_allowed && (fade_in_count > 0)) 216 if (fade_in_count > 0)
228 __backlight_dim(BL_PWM_COUNT); 217 backlight_dim(BL_PWM_COUNT);
229 else 218 else
230 { 219 {
231 bl_dim_target = bl_dim_current = BL_PWM_COUNT; 220 bl_dim_target = bl_dim_current = BL_PWM_COUNT;
diff --git a/firmware/export/backlight.h b/firmware/export/backlight.h
index 8d1b56c695..b2a2448328 100644
--- a/firmware/export/backlight.h
+++ b/firmware/export/backlight.h
@@ -30,9 +30,6 @@ void backlight_set_timeout(int index);
30#if CONFIG_BACKLIGHT == BL_IRIVER 30#if CONFIG_BACKLIGHT == BL_IRIVER
31void backlight_set_fade_in(int index); 31void backlight_set_fade_in(int index);
32void backlight_set_fade_out(int index); 32void backlight_set_fade_out(int index);
33void backlight_allow_timer(bool on);
34#else
35#define backlight_allow_timer(on)
36#endif 33#endif
37bool backlight_get_on_when_charging(void); 34bool backlight_get_on_when_charging(void);
38void backlight_set_on_when_charging(bool yesno); 35void backlight_set_on_when_charging(bool yesno);
diff --git a/firmware/export/timer.h b/firmware/export/timer.h
new file mode 100644
index 0000000000..73936ca28c
--- /dev/null
+++ b/firmware/export/timer.h
@@ -0,0 +1,34 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2005 Jens Arnold
11*
12* All files in this archive are subject to the GNU General Public License.
13* See the file COPYING in the source tree root for full license agreement.
14*
15* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16* KIND, either express or implied.
17*
18****************************************************************************/
19
20#ifndef __TIMER_H__
21#define __TIMER_H__
22
23#include <stdbool.h>
24#include "config.h"
25
26#ifndef SIMULATOR
27
28bool timer_register(int reg_prio, void (*unregister_callback)(void),
29 long cycles, int int_prio, void (*timer_callback)(void));
30bool timer_set_period(long cycles);
31void timer_unregister(void);
32
33#endif /* !SIMULATOR */
34#endif /* __TIMER_H__ */
diff --git a/firmware/timer.c b/firmware/timer.c
new file mode 100644
index 0000000000..3e524ace35
--- /dev/null
+++ b/firmware/timer.c
@@ -0,0 +1,181 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2005 Jens Arnold
11*
12* All files in this archive are subject to the GNU General Public License.
13* See the file COPYING in the source tree root for full license agreement.
14*
15* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16* KIND, either express or implied.
17*
18****************************************************************************/
19
20#include <stdbool.h>
21#include "config.h"
22#include "cpu.h"
23#include "system.h"
24#include "timer.h"
25
26#ifndef SIMULATOR
27
28static int timer_prio = -1;
29static void (*pfn_timer)(void) = NULL; /* timer callback */
30static void (*pfn_unregister)(void) = NULL; /* unregister callback */
31
32
33/* interrupt handler */
34#if CONFIG_CPU == SH7034
35void IMIA4(void) __attribute__((interrupt_handler));
36void IMIA4(void)
37{
38 if (pfn_timer != NULL)
39 pfn_timer();
40 and_b(~0x01, &TSR4); /* clear the interrupt */
41}
42#elif defined CPU_COLDFIRE
43void TIMER1(void) __attribute__ ((interrupt_handler));
44void TIMER1(void)
45{
46 if (pfn_timer != NULL)
47 pfn_timer();
48 TER1 = 0xff; /* clear all events */
49}
50#endif /* CONFIG_CPU */
51
52static bool timer_set(long cycles, bool start)
53{
54 int phi = 0; /* bits for the prescaler */
55 int prescale = 1;
56
57#ifdef CPU_COLDFIRE
58 cycles >>= 1; /* the coldfire timer works on busclk == cpuclk/2 */
59#endif
60
61 while (cycles > 0x10000)
62 { /* work out the smallest prescaler that makes it fit */
63#if CONFIG_CPU == SH7034
64 phi++;
65#endif
66 prescale *= 2;
67 cycles >>= 1;
68 }
69
70#if CONFIG_CPU == SH7034
71 if (prescale > 8)
72 return false;
73
74 if (start)
75 {
76 if (pfn_unregister != NULL)
77 {
78 pfn_unregister();
79 pfn_unregister = NULL;
80 }
81
82 and_b(~0x10, &TSTR); /* Stop the timer 4 */
83 and_b(~0x10, &TSNC); /* No synchronization */
84 and_b(~0x10, &TMDR); /* Operate normally */
85
86 TIER4 = 0xF9; /* Enable GRA match interrupt */
87 }
88
89 TCR4 = 0x20 | phi; /* clear at GRA match, set prescaler */
90 GRA4 = (unsigned short)(cycles - 1);
91 if (start || (TCNT4 >= GRA4))
92 TCNT4 = 0;
93 and_b(~0x01, &TSR4); /* clear an eventual interrupt */
94
95#elif defined CPU_COLDFIRE
96 if (prescale > 4096)
97 return false;
98
99 if (prescale > 256)
100 {
101 phi = 0x05; /* prescale sysclk/16, timer enabled */
102 prescale >>= 4;
103 }
104 else
105 phi = 0x03; /* prescale sysclk, timer enabled */
106
107 if (start)
108 {
109 if (pfn_unregister != NULL)
110 {
111 pfn_unregister();
112 pfn_unregister = NULL;
113 }
114 phi &= ~1; /* timer disabled at start */
115 }
116
117 /* We are using timer 1 */
118 TMR1 = 0x0018 | (unsigned short)phi | ((unsigned short)(prescale - 1) << 8);
119 TRR1 = (unsigned short)(cycles - 1);
120 if (start || (TCN1 >= TRR1))
121 TCN1 = 0; /* reset the timer */
122 TER1 = 0xff; /* clear all events */
123
124#endif /* CONFIG_CPU */
125 return true;
126}
127
128/* Register a user timer, called every <count> CPU cycles */
129bool timer_register(int reg_prio, void (*unregister_callback)(void),
130 long cycles, int int_prio, void (*timer_callback)(void))
131{
132 if (reg_prio <= timer_prio || cycles == 0)
133 return false;
134
135#if CONFIG_CPU == SH7034
136 if (int_prio < 1 || int_prio > 15)
137 return false;
138#elif defined CPU_COLDFIRE
139 (void)int_prio;
140#endif
141
142 if (!timer_set(cycles, true))
143 return false;
144
145 pfn_timer = timer_callback;
146 pfn_unregister = unregister_callback;
147 timer_prio = reg_prio;
148
149#if CONFIG_CPU == SH7034
150 IPRD = (IPRD & 0xFF0F) | int_prio << 4; /* interrupt priority */
151 or_b(0x10, &TSTR); /* start timer 4 */
152#elif defined CPU_COLDFIRE
153 /* ICR2 (Timer1) */
154 ICR0 = (ICR0 & 0xffff00ff) | 0x00009000; /* interrupt on level 4.0 */
155 and_l(~(1<<10), &IMR);
156 TMR1 |= 1; /* start timer */
157#endif
158
159 return true;
160}
161
162bool timer_set_period(long cycles)
163{
164 return timer_set(cycles, false);
165}
166
167void timer_unregister(void)
168{
169#if CONFIG_CPU == SH7034
170 and_b(~0x10, &TSTR); /* stop the timer 4 */
171 IPRD = (IPRD & 0xFF0F); /* disable interrupt */
172#elif defined CPU_COLDFIRE
173 TMR1 = 0; /* disable timer 1 */
174 or_l((1<<10), &IMR); /* disable interrupt */
175#endif
176 pfn_timer = NULL;
177 pfn_unregister = NULL;
178 timer_prio = -1;
179}
180
181#endif /* !SIMULATOR */