summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/playback.c149
-rw-r--r--apps/playlist_viewer.c2
-rw-r--r--apps/plugin.c16
-rw-r--r--apps/plugin.h33
-rw-r--r--apps/plugins/doom/rockdoom.c19
-rw-r--r--apps/plugins/midiplay.c15
-rw-r--r--apps/plugins/mp3_encoder.c14
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c14
-rw-r--r--apps/plugins/pacbox/pacbox.c22
-rw-r--r--apps/plugins/rockboy/rockboy.c16
-rw-r--r--apps/plugins/zxbox/zxbox.c17
-rw-r--r--apps/talk.c2
-rw-r--r--apps/talk.h2
-rw-r--r--firmware/export/audio.h5
-rw-r--r--firmware/export/config.h3
15 files changed, 204 insertions, 125 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 279fb15482..9bf6942e7f 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -296,8 +296,8 @@ static unsigned char sim_iram[CODEC_IRAM_SIZE]; /* IRAM codec swap buffer for si
296#define CODEC_IRAM_ORIGIN sim_iram 296#define CODEC_IRAM_ORIGIN sim_iram
297#endif 297#endif
298 298
299static unsigned char *iram_buf[2]; /* Ptr to IRAM buffers for normal/voice codecs */ 299static unsigned char *iram_buf[2] = { NULL, NULL }; /* Ptr to IRAM buffers for normal/voice codecs */
300static unsigned char *dram_buf[2]; /* Ptr to DRAM buffers for normal/voice codecs */ 300static unsigned char *dram_buf[2] = { NULL, NULL }; /* Ptr to DRAM buffers for normal/voice codecs */
301static struct mutex mutex_codecthread; /* Mutex to control which codec (normal/voice) is running */ 301static struct mutex mutex_codecthread; /* Mutex to control which codec (normal/voice) is running */
302 302
303/* Voice state */ 303/* Voice state */
@@ -307,6 +307,10 @@ static volatile bool voice_codec_loaded; /* Is voice codec loaded (V/A-) */
307static char *voicebuf; 307static char *voicebuf;
308static size_t voice_remaining; 308static size_t voice_remaining;
309 309
310#ifdef IRAM_STEAL
311static bool voice_iram_stolen = false; /* Voice IRAM has been stolen for other use */
312#endif
313
310static void (*voice_getmore)(unsigned char** start, int* size); 314static void (*voice_getmore)(unsigned char** start, int* size);
311 315
312struct voice_info { 316struct voice_info {
@@ -318,15 +322,21 @@ static void voice_thread(void);
318 322
319#endif /* PLAYBACK_VOICE */ 323#endif /* PLAYBACK_VOICE */
320 324
325/* --- Shared semi-private interfaces --- */
326
327/* imported */
328extern void talk_buffer_steal(void);
329#ifdef HAVE_RECORDING
330extern void pcm_rec_error_clear(void);
331extern unsigned long pcm_rec_status(void);
332#endif
333
334
321/* --- External interfaces --- */ 335/* --- External interfaces --- */
322 336
323void mp3_play_data(const unsigned char* start, int size, 337void mp3_play_data(const unsigned char* start, int size,
324 void (*get_more)(unsigned char** start, int* size)) 338 void (*get_more)(unsigned char** start, int* size))
325{ 339{
326 /* must reset the buffer before any playback begins if needed */
327 if (buffer_state == BUFFER_STATE_TRASHED)
328 audio_reset_buffer(pcmbuf_get_bufsize());
329
330#ifdef PLAYBACK_VOICE 340#ifdef PLAYBACK_VOICE
331 static struct voice_info voice_clip; 341 static struct voice_info voice_clip;
332 voice_clip.callback = get_more; 342 voice_clip.callback = get_more;
@@ -366,11 +376,20 @@ void mpeg_id3_options(bool _v1first)
366 376
367unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size) 377unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
368{ 378{
369 unsigned char *buf = audiobuf; 379 unsigned char *buf, *end;
370 unsigned char *end = audiobufend;
371 380
372 audio_stop(); 381 audio_stop();
373 382
383 if (buffer_size == NULL)
384 {
385 /* Special case for talk_init to use */
386 buffer_state = BUFFER_STATE_TRASHED;
387 return NULL;
388 }
389
390 buf = audiobuf;
391 end = audiobufend;
392
374 if (talk_buf || !talk_voice_required() 393 if (talk_buf || !talk_voice_required()
375 || buffer_state == BUFFER_STATE_TRASHED) 394 || buffer_state == BUFFER_STATE_TRASHED)
376 { 395 {
@@ -395,17 +414,57 @@ unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
395 return buf; 414 return buf;
396} 415}
397 416
417#ifdef IRAM_STEAL
418void audio_iram_steal(void)
419{
420 /* We need to stop audio playback in order to use codec IRAM */
421 audio_stop();
422
423#ifdef PLAYBACK_VOICE
424 if (NULL != iram_buf[CODEC_IDX_VOICE])
425 {
426 /* Wait for voice to swap back in if current codec was audio */
427 while (current_codec != CODEC_IDX_VOICE)
428 yield();
429
430 voice_stop();
431
432 /* Save voice IRAM - safe to do here since state is known */
433 memcpy(iram_buf[CODEC_IDX_VOICE], (void *)CODEC_IRAM_ORIGIN,
434 CODEC_IRAM_SIZE);
435 voice_iram_stolen = true;
436 }
437 else
438 {
439 /* Nothing much to do if no voice */
440 voice_iram_stolen = false;
441 }
442#endif
443}
444#endif /* IRAM_STEAL */
445
398#ifdef HAVE_RECORDING 446#ifdef HAVE_RECORDING
399unsigned char *audio_get_recording_buffer(size_t *buffer_size) 447unsigned char *audio_get_recording_buffer(size_t *buffer_size)
400{ 448{
401 /* don't allow overwrite of voice swap area or we'll trash the 449 /* don't allow overwrite of voice swap area or we'll trash the
402 swapped-out voice codec but can use whole thing if none */ 450 swapped-out voice codec but can use whole thing if none */
403 unsigned char *end = iram_buf[CODEC_IDX_VOICE] ? 451 unsigned char *end;
404 iram_buf[CODEC_IDX_VOICE] : audiobufend;
405 452
406 audio_stop(); 453 audio_stop();
407 talk_buffer_steal(); 454 talk_buffer_steal();
408 455
456#ifdef PLAYBACK_VOICE
457#ifdef IRAM_STEAL
458 end = dram_buf[CODEC_IDX_VOICE] ?
459 dram_buf[CODEC_IDX_VOICE] : audiobufend;
460#else
461 end = iram_buf[CODEC_IDX_VOICE] ?
462 iram_buf[CODEC_IDX_VOICE] : audiobufend;
463#endif /* IRAM_STEAL */
464#else
465 end = audiobufend;
466#endif /* PLAYBACK_VOICE */
467
409 buffer_state = BUFFER_STATE_TRASHED; 468 buffer_state = BUFFER_STATE_TRASHED;
410 469
411 *buffer_size = end - audiobuf; 470 *buffer_size = end - audiobuf;
@@ -645,7 +704,6 @@ void audio_flush_and_reload_tracks(void)
645void audio_error_clear(void) 704void audio_error_clear(void)
646{ 705{
647#ifdef AUDIO_HAVE_RECORDING 706#ifdef AUDIO_HAVE_RECORDING
648 extern void pcm_rec_error_clear(void);
649 pcm_rec_error_clear(); 707 pcm_rec_error_clear();
650#endif 708#endif
651} 709}
@@ -662,7 +720,6 @@ int audio_status(void)
662 720
663#ifdef HAVE_RECORDING 721#ifdef HAVE_RECORDING
664 /* Do this here for constitency with mpeg.c version */ 722 /* Do this here for constitency with mpeg.c version */
665 extern unsigned long pcm_rec_status(void);
666 ret |= pcm_rec_status(); 723 ret |= pcm_rec_status();
667#endif 724#endif
668 725
@@ -820,7 +877,6 @@ void voice_stop(void)
820 877
821 878
822/* --- Routines called from multiple threads --- */ 879/* --- Routines called from multiple threads --- */
823
824#ifdef PLAYBACK_VOICE 880#ifdef PLAYBACK_VOICE
825static void swap_codec(void) 881static void swap_codec(void)
826{ 882{
@@ -829,8 +885,26 @@ static void swap_codec(void)
829 logf("swapping out codec:%d", my_codec); 885 logf("swapping out codec:%d", my_codec);
830 886
831 /* Save our current IRAM and DRAM */ 887 /* Save our current IRAM and DRAM */
888#ifdef IRAM_STEAL
889 if (voice_iram_stolen)
890 {
891 logf("swap: iram restore");
892 voice_iram_stolen = false;
893 /* Don't swap trashed data into buffer - _should_ always be the case
894 if voice_iram_stolen is true since the voice has been swapped in
895 before hand */
896 if (my_codec == CODEC_IDX_VOICE)
897 goto skip_iram_swap;
898 }
899#endif
900
832 memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN, 901 memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN,
833 CODEC_IRAM_SIZE); 902 CODEC_IRAM_SIZE);
903
904#ifdef IRAM_STEAL
905skip_iram_swap:
906#endif
907
834 memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE); 908 memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE);
835 909
836 /* Release my semaphore */ 910 /* Release my semaphore */
@@ -1085,6 +1159,21 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1085 { 1159 {
1086 /* Set up new voice data */ 1160 /* Set up new voice data */
1087 struct voice_info *voice_data; 1161 struct voice_info *voice_data;
1162#ifdef IRAM_STEAL
1163 if (voice_iram_stolen)
1164 {
1165 logf("voice: iram restore");
1166 memcpy((void*)CODEC_IRAM_ORIGIN,
1167 iram_buf[CODEC_IDX_VOICE],
1168 CODEC_IRAM_SIZE);
1169 voice_iram_stolen = false;
1170 }
1171#endif
1172 /* must reset the buffer before any playback
1173 begins if needed */
1174 if (buffer_state == BUFFER_STATE_TRASHED)
1175 audio_reset_buffer(pcmbuf_get_bufsize());
1176
1088 voice_is_playing = true; 1177 voice_is_playing = true;
1089 trigger_cpu_boost(); 1178 trigger_cpu_boost();
1090 voice_data = ev.data; 1179 voice_data = ev.data;
@@ -2809,6 +2898,10 @@ static void audio_fill_file_buffer(
2809 bool had_next_track = audio_next_track() != NULL; 2898 bool had_next_track = audio_next_track() != NULL;
2810 bool continue_buffering; 2899 bool continue_buffering;
2811 2900
2901 /* must reset the buffer before use if trashed */
2902 if (buffer_state != BUFFER_STATE_NORMAL)
2903 audio_reset_buffer(pcmbuf_get_bufsize());
2904
2812 if (!audio_initialize_buffer_fill(!start_play)) 2905 if (!audio_initialize_buffer_fill(!start_play))
2813 return ; 2906 return ;
2814 2907
@@ -3156,10 +3249,6 @@ static void audio_play_start(size_t offset)
3156 /* Wait for any previously playing audio to flush - TODO: Not necessary? */ 3249 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3157 audio_stop_codec_flush(); 3250 audio_stop_codec_flush();
3158 3251
3159 /* must reset the buffer before any playback begins if needed */
3160 if (buffer_state != BUFFER_STATE_NORMAL)
3161 audio_reset_buffer(pcmbuf_get_bufsize());
3162
3163 track_changed = true; 3252 track_changed = true;
3164 playlist_end = false; 3253 playlist_end = false;
3165 3254
@@ -3272,14 +3361,34 @@ static void audio_reset_buffer(size_t pcmbufsize)
3272 if (talk_voice_required()) 3361 if (talk_voice_required())
3273 { 3362 {
3274#ifdef PLAYBACK_VOICE 3363#ifdef PLAYBACK_VOICE
3364#ifdef IRAM_STEAL
3365 filebuflen -= CODEC_IRAM_SIZE + 2*CODEC_SIZE;
3366#else
3367 filebuflen -= 2*(CODEC_IRAM_SIZE + CODEC_SIZE);
3368#endif
3275 /* Allow 2 codecs at end of audio buffer */ 3369 /* Allow 2 codecs at end of audio buffer */
3276 filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE); 3370 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3277 3371 and out of the way of buffer usage or else a call to audio_get_buffer
3372 and subsequent buffer use might trash the swap space. A plugin
3373 initializing IRAM after getting the full buffer would present similar
3374 problem. Options include: failing the request if the other buffer
3375 has been obtained already or never allowing use of the voice IRAM
3376 buffer within the audio buffer. Using buffer_alloc basically
3377 implements the second in a more convenient way. */
3278 iram_buf[CODEC_IDX_AUDIO] = filebuf + filebuflen; 3378 iram_buf[CODEC_IDX_AUDIO] = filebuf + filebuflen;
3279 dram_buf[CODEC_IDX_AUDIO] = iram_buf[CODEC_IDX_AUDIO] + CODEC_IRAM_SIZE; 3379 dram_buf[CODEC_IDX_AUDIO] = iram_buf[CODEC_IDX_AUDIO] + CODEC_IRAM_SIZE;
3380
3381#ifdef IRAM_STEAL
3382 /* Allocate voice IRAM swap buffer once */
3383 if (iram_buf[CODEC_IDX_VOICE] == NULL)
3384 iram_buf[CODEC_IDX_VOICE] = buffer_alloc(CODEC_IRAM_SIZE);
3385 dram_buf[CODEC_IDX_VOICE] = dram_buf[CODEC_IDX_AUDIO] + CODEC_SIZE;
3386#else
3280 iram_buf[CODEC_IDX_VOICE] = dram_buf[CODEC_IDX_AUDIO] + CODEC_SIZE; 3387 iram_buf[CODEC_IDX_VOICE] = dram_buf[CODEC_IDX_AUDIO] + CODEC_SIZE;
3281 dram_buf[CODEC_IDX_VOICE] = iram_buf[CODEC_IDX_VOICE] + CODEC_IRAM_SIZE; 3388 dram_buf[CODEC_IDX_VOICE] = iram_buf[CODEC_IDX_VOICE] + CODEC_IRAM_SIZE;
3282#endif 3389#endif /* IRAM_STEAL */
3390
3391#endif /* PLAYBACK_VOICE */
3283 } 3392 }
3284 else 3393 else
3285 { 3394 {
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 87bbaa4b11..8670f0ad46 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -467,7 +467,9 @@ static int onplay_menu(int index)
467 if (current_track->display_index!=viewer.num_tracks || 467 if (current_track->display_index!=viewer.num_tracks ||
468 global_settings.repeat_mode == REPEAT_ALL) 468 global_settings.repeat_mode == REPEAT_ALL)
469 { 469 {
470#if CONFIG_CODEC != SWCODEC
470 talk_buffer_steal(); /* will use the mp3 buffer */ 471 talk_buffer_steal(); /* will use the mp3 buffer */
472#endif
471 audio_play(0); 473 audio_play(0);
472 viewer.current_playing_track = -1; 474 viewer.current_playing_track = -1;
473 } 475 }
diff --git a/apps/plugin.c b/apps/plugin.c
index 90b3837cf8..a00a54e4ec 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -471,6 +471,9 @@ static const struct plugin_api rockbox_api = {
471 lcd_set_backdrop, 471 lcd_set_backdrop,
472#endif 472#endif
473 473
474#ifdef IRAM_STEAL
475 plugin_iram_init,
476#endif
474}; 477};
475 478
476int plugin_load(const char* plugin, void* parameter) 479int plugin_load(const char* plugin, void* parameter)
@@ -683,9 +686,20 @@ void* plugin_get_audio_buffer(int* buffer_size)
683 audio_stop(); 686 audio_stop();
684 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ 687 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
685 *buffer_size = audiobufend - audiobuf; 688 *buffer_size = audiobufend - audiobuf;
686#endif
687 return audiobuf; 689 return audiobuf;
690#endif
691}
692
693#ifdef IRAM_STEAL
694/* Initializes plugin IRAM */
695void plugin_iram_init(char *iramstart, char *iramcopy, size_t iram_size,
696 char *iedata, size_t iedata_size)
697{
698 audio_iram_steal();
699 memcpy(iramstart, iramcopy, iram_size);
700 memset(iedata, 0, iedata_size);
688} 701}
702#endif /* IRAM_STEAL */
689 703
690/* The plugin wants to stay resident after leaving its main function, e.g. 704/* The plugin wants to stay resident after leaving its main function, e.g.
691 runs from timer or own thread. The callback is registered to later 705 runs from timer or own thread. The callback is registered to later
diff --git a/apps/plugin.h b/apps/plugin.h
index e9a6cfdaed..608009d549 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -107,7 +107,7 @@
107#define PLUGIN_MAGIC 0x526F634B /* RocK */ 107#define PLUGIN_MAGIC 0x526F634B /* RocK */
108 108
109/* increase this every time the api struct changes */ 109/* increase this every time the api struct changes */
110#define PLUGIN_API_VERSION 35 110#define PLUGIN_API_VERSION 36
111 111
112/* update this to latest version if a change to the api struct breaks 112/* update this to latest version if a change to the api struct breaks
113 backwards compatibility (and please take the opportunity to sort in any 113 backwards compatibility (and please take the opportunity to sort in any
@@ -582,6 +582,11 @@ struct plugin_api {
582#if LCD_DEPTH > 1 582#if LCD_DEPTH > 1
583 void (*lcd_set_backdrop)(fb_data* backdrop); 583 void (*lcd_set_backdrop)(fb_data* backdrop);
584#endif 584#endif
585
586#ifdef IRAM_STEAL
587 void (*plugin_iram_init)(char *iramstart, char *iramcopy, size_t iram_size,
588 char *iedata, size_t iedata_size);
589#endif
585}; 590};
586 591
587/* plugin header */ 592/* plugin header */
@@ -593,6 +598,7 @@ struct plugin_header {
593 unsigned char *end_addr; 598 unsigned char *end_addr;
594 enum plugin_status(*entry_point)(struct plugin_api*, void*); 599 enum plugin_status(*entry_point)(struct plugin_api*, void*);
595}; 600};
601
596#ifdef PLUGIN 602#ifdef PLUGIN
597#ifndef SIMULATOR 603#ifndef SIMULATOR
598extern unsigned char plugin_start_addr[]; 604extern unsigned char plugin_start_addr[];
@@ -607,12 +613,33 @@ extern unsigned char plugin_end_addr[];
607 const struct plugin_header __header = { \ 613 const struct plugin_header __header = { \
608 PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \ 614 PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
609 NULL, NULL, plugin_start }; 615 NULL, NULL, plugin_start };
610#endif 616#endif /* SIMULATOR */
611#endif 617
618#ifdef USE_IRAM
619/* Declare IRAM variables */
620#define PLUGIN_IRAM_DECLARE \
621 extern char iramcopy[]; \
622 extern char iramstart[]; \
623 extern char iramend[]; \
624 extern char iedata[]; \
625 extern char iend[];
626/* Initialize IRAM */
627#define PLUGIN_IRAM_INIT(api) \
628 (api)->plugin_iram_init(iramstart, iramcopy, iramend-iramstart, \
629 iedata, iend-iedata);
630#else
631#define PLUGIN_IRAM_DECLARE
632#define PLUGIN_IRAM_INIT(api)
633#endif /* USE_IRAM */
634#endif /* PLUGIN */
612 635
613int plugin_load(const char* plugin, void* parameter); 636int plugin_load(const char* plugin, void* parameter);
614void* plugin_get_buffer(int *buffer_size); 637void* plugin_get_buffer(int *buffer_size);
615void* plugin_get_audio_buffer(int *buffer_size); 638void* plugin_get_audio_buffer(int *buffer_size);
639#ifdef IRAM_STEAL
640void plugin_iram_init(char *iramstart, char *iramcopy, size_t iram_size,
641 char *iedata, size_t iedata_size);
642#endif
616 643
617/* plugin_tsr, 644/* plugin_tsr,
618 callback returns true to allow the new plugin to load, 645 callback returns true to allow the new plugin to load,
diff --git a/apps/plugins/doom/rockdoom.c b/apps/plugins/doom/rockdoom.c
index 2b42322daa..8b73a5bb96 100644
--- a/apps/plugins/doom/rockdoom.c
+++ b/apps/plugins/doom/rockdoom.c
@@ -39,14 +39,7 @@
39#include "st_stuff.h" 39#include "st_stuff.h"
40 40
41PLUGIN_HEADER 41PLUGIN_HEADER
42 42PLUGIN_IRAM_DECLARE
43#ifdef USE_IRAM
44extern char iramcopy[];
45extern char iramstart[];
46extern char iramend[];
47extern char iedata[];
48extern char iend[];
49#endif
50 43
51extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough 44extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough
52 45
@@ -785,13 +778,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
785 rb->cpu_boost(true); 778 rb->cpu_boost(true);
786#endif 779#endif
787 780
788#ifdef USE_IRAM 781 PLUGIN_IRAM_INIT(rb)
789 /* We need to stop audio playback in order to use IRAM */
790 rb->audio_stop();
791
792 memcpy(iramstart, iramcopy, iramend-iramstart);
793 memset(iedata, 0, iend - iedata);
794#endif
795 782
796 rb->lcd_setfont(0); 783 rb->lcd_setfont(0);
797 784
@@ -830,7 +817,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
830 if (result < 0) 817 if (result < 0)
831 { 818 {
832#ifdef HAVE_ADJUSTABLE_CPU_FREQ 819#ifdef HAVE_ADJUSTABLE_CPU_FREQ
833 rb->cpu_boost(false); 820 rb->cpu_boost(false);
834#endif 821#endif
835 if( result == -1 ) return PLUGIN_OK; // Quit was selected 822 if( result == -1 ) return PLUGIN_OK; // Quit was selected
836 else if( result == -2 ) return PLUGIN_ERROR; // Missing base wads 823 else if( result == -2 ) return PLUGIN_ERROR; // Missing base wads
diff --git a/apps/plugins/midiplay.c b/apps/plugins/midiplay.c
index 585c7eec25..a0e7d0e3c2 100644
--- a/apps/plugins/midiplay.c
+++ b/apps/plugins/midiplay.c
@@ -19,7 +19,7 @@
19#include "../../plugin.h" 19#include "../../plugin.h"
20 20
21PLUGIN_HEADER 21PLUGIN_HEADER
22 22PLUGIN_IRAM_DECLARE
23 23
24/* variable button definitions */ 24/* variable button definitions */
25#if CONFIG_KEYPAD == RECORDER_PAD 25#if CONFIG_KEYPAD == RECORDER_PAD
@@ -102,14 +102,6 @@ short gmbuf[BUF_SIZE*NBUF] IBSS_ATTR;
102int quit=0; 102int quit=0;
103struct plugin_api * rb; 103struct plugin_api * rb;
104 104
105#ifdef USE_IRAM
106extern char iramcopy[];
107extern char iramstart[];
108extern char iramend[];
109extern char iedata[];
110extern char iend[];
111#endif
112
113enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 105enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
114{ 106{
115 int retval = 0; 107 int retval = 0;
@@ -122,10 +114,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
122 } 114 }
123 rb->lcd_setfont(0); 115 rb->lcd_setfont(0);
124 116
125#ifdef USE_IRAM 117 PLUGIN_IRAM_INIT(rb)
126 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
127 rb->memset(iedata, 0, iend - iedata);
128#endif
129 118
130#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 119#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
131 rb->cpu_boost(true); 120 rb->cpu_boost(true);
diff --git a/apps/plugins/mp3_encoder.c b/apps/plugins/mp3_encoder.c
index 6d66111d16..5bfd384349 100644
--- a/apps/plugins/mp3_encoder.c
+++ b/apps/plugins/mp3_encoder.c
@@ -14,17 +14,10 @@
14#include "plugin.h" 14#include "plugin.h"
15 15
16PLUGIN_HEADER 16PLUGIN_HEADER
17PLUGIN_IRAM_DECLARE
17 18
18static struct plugin_api* rb; 19static struct plugin_api* rb;
19 20
20#ifdef USE_IRAM
21extern char iramcopy[];
22extern char iramstart[];
23extern char iramend[];
24extern char iedata[];
25extern char iend[];
26#endif
27
28#define SAMP_PER_FRAME 1152 21#define SAMP_PER_FRAME 1152
29#define SAMPL2 576 22#define SAMPL2 576
30#define SBLIMIT 32 23#define SBLIMIT 32
@@ -2377,10 +2370,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
2377 asm volatile ("move.l #0, %macsr"); /* integer mode */ 2370 asm volatile ("move.l #0, %macsr"); /* integer mode */
2378#endif 2371#endif
2379 2372
2380#ifdef USE_IRAM 2373 PLUGIN_IRAM_INIT(rb)
2381 memcpy(iramstart, iramcopy, iramend - iramstart);
2382 memset(iedata, 0, iend - iedata);
2383#endif
2384 2374
2385 rb->lcd_setfont(FONT_SYSFIXED); 2375 rb->lcd_setfont(FONT_SYSFIXED);
2386 2376
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 980061f050..0fbd0f01e6 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -31,14 +31,7 @@
31#include "video_out.h" 31#include "video_out.h"
32 32
33PLUGIN_HEADER 33PLUGIN_HEADER
34 34PLUGIN_IRAM_DECLARE
35#ifdef USE_IRAM
36extern char iramcopy[];
37extern char iramstart[];
38extern char iramend[];
39extern char iedata[];
40extern char iend[];
41#endif
42 35
43struct plugin_api* rb; 36struct plugin_api* rb;
44 37
@@ -319,10 +312,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
319 if (buffer == NULL) 312 if (buffer == NULL)
320 return PLUGIN_ERROR; 313 return PLUGIN_ERROR;
321 314
322#ifdef USE_IRAM 315 PLUGIN_IRAM_INIT(rb)
323 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
324 rb->memset(iedata, 0, iend - iedata);
325#endif
326 316
327 rb->lcd_set_backdrop(NULL); 317 rb->lcd_set_backdrop(NULL);
328 318
diff --git a/apps/plugins/pacbox/pacbox.c b/apps/plugins/pacbox/pacbox.c
index 7c2d1e21ca..62f5bcd413 100644
--- a/apps/plugins/pacbox/pacbox.c
+++ b/apps/plugins/pacbox/pacbox.c
@@ -29,14 +29,7 @@
29#include "lib/configfile.h" 29#include "lib/configfile.h"
30 30
31PLUGIN_HEADER 31PLUGIN_HEADER
32 32PLUGIN_IRAM_DECLARE
33#ifdef USE_IRAM
34extern char iramcopy[];
35extern char iramstart[];
36extern char iramend[];
37extern char iedata[];
38extern char iend[];
39#endif
40 33
41struct plugin_api* rb; 34struct plugin_api* rb;
42 35
@@ -370,21 +363,10 @@ static int gameProc( void )
370enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 363enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
371{ 364{
372 (void)parameter; 365 (void)parameter;
373#ifdef USE_IRAM
374 void* audiobuf;
375 int audiosize;
376#endif
377 366
378 rb = api; 367 rb = api;
379 368
380#ifdef USE_IRAM 369 PLUGIN_IRAM_INIT(rb)
381 /* We need to stop audio playback in order to use IRAM, so we grab
382 the audio buffer - but we don't use it. */
383 audiobuf = rb->plugin_get_audio_buffer(&audiosize);
384
385 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
386 rb->memset(iedata, 0, iend - iedata);
387#endif
388 370
389#ifdef HAVE_ADJUSTABLE_CPU_FREQ 371#ifdef HAVE_ADJUSTABLE_CPU_FREQ
390 rb->cpu_boost(true); 372 rb->cpu_boost(true);
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c
index f82b0c283a..6a72856bbb 100644
--- a/apps/plugins/rockboy/rockboy.c
+++ b/apps/plugins/rockboy/rockboy.c
@@ -21,14 +21,7 @@
21#include "rockmacros.h" 21#include "rockmacros.h"
22 22
23PLUGIN_HEADER 23PLUGIN_HEADER
24 24PLUGIN_IRAM_DECLARE
25#ifdef USE_IRAM
26extern char iramcopy[];
27extern char iramstart[];
28extern char iramend[];
29extern char iedata[];
30extern char iend[];
31#endif
32 25
33/* here is a global api struct pointer. while not strictly necessary, 26/* here is a global api struct pointer. while not strictly necessary,
34 it's nice not to have to pass the api pointer in all function calls 27 it's nice not to have to pass the api pointer in all function calls
@@ -187,10 +180,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
187 audio_buffer_free = plugin_start_addr - (unsigned char *)audio_bufferbase; 180 audio_buffer_free = plugin_start_addr - (unsigned char *)audio_bufferbase;
188#endif 181#endif
189 setoptions(); 182 setoptions();
190#ifdef USE_IRAM 183
191 memcpy(iramstart, iramcopy, iramend-iramstart); 184 PLUGIN_IRAM_INIT(rb)
192 memset(iedata, 0, iend - iedata); 185
193#endif
194 shut=0; 186 shut=0;
195 cleanshut=0; 187 cleanshut=0;
196 188
diff --git a/apps/plugins/zxbox/zxbox.c b/apps/plugins/zxbox/zxbox.c
index 54a11d010e..753fb1ff5b 100644
--- a/apps/plugins/zxbox/zxbox.c
+++ b/apps/plugins/zxbox/zxbox.c
@@ -20,6 +20,7 @@
20#include "zxconfig.h" 20#include "zxconfig.h"
21 21
22PLUGIN_HEADER 22PLUGIN_HEADER
23PLUGIN_IRAM_DECLARE
23 24
24struct plugin_api* rb; 25struct plugin_api* rb;
25 26
@@ -37,14 +38,6 @@ int use_shm = 0;
37int small_screen,pause_on_iconify; 38int small_screen,pause_on_iconify;
38int vga_pause_bg; 39int vga_pause_bg;
39 40
40#ifdef USE_IRAM
41extern char iramcopy[];
42extern char iramstart[];
43extern char iramend[];
44extern char iedata[];
45extern char iend[];
46#endif
47
48#include "keymaps.h" 41#include "keymaps.h"
49#include "zxvid_com.h" 42#include "zxvid_com.h"
50#include "spmain.h" 43#include "spmain.h"
@@ -75,13 +68,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
75 rb->lcd_set_backdrop(NULL); 68 rb->lcd_set_backdrop(NULL);
76 rb->splash(HZ, true, "Welcome to ZXBox"); 69 rb->splash(HZ, true, "Welcome to ZXBox");
77 70
78#ifdef USE_IRAM 71 PLUGIN_IRAM_INIT(rb)
79 /* We need to stop audio playback in order to use IRAM */
80 rb->audio_stop();
81
82 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
83 rb->memset(iedata, 0, iend - iedata);
84#endif
85 72
86 sp_init(); 73 sp_init();
87 74
diff --git a/apps/talk.c b/apps/talk.c
index 018f6ed5ab..cabc93576b 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -522,7 +522,7 @@ void talk_init(void)
522 MAX_FILENAME); 522 MAX_FILENAME);
523 523
524#if CONFIG_CODEC == SWCODEC 524#if CONFIG_CODEC == SWCODEC
525 audio_stop(); 525 audio_get_buffer(false, NULL); /* Must tell audio to reinitialize */
526#endif 526#endif
527 reset_state(); /* use this for most of our inits */ 527 reset_state(); /* use this for most of our inits */
528 528
diff --git a/apps/talk.h b/apps/talk.h
index bfd08354aa..4c1ef7c625 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -62,7 +62,9 @@ extern const char* const file_thumbnail_ext; /* ".talk" for file voicing */
62void talk_init(void); 62void talk_init(void);
63bool talk_voice_required(void); /* returns true if voice codec required */ 63bool talk_voice_required(void); /* returns true if voice codec required */
64int talk_get_bufsize(void); /* get the loaded voice file size */ 64int talk_get_bufsize(void); /* get the loaded voice file size */
65#if CONFIG_CODEC != SWCODEC
65int talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ 66int talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */
67#endif
66int talk_id(long id, bool enqueue); /* play a voice ID from voicefont */ 68int talk_id(long id, bool enqueue); /* play a voice ID from voicefont */
67int talk_file(const char* filename, bool enqueue); /* play a thumbnail from file */ 69int talk_file(const char* filename, bool enqueue); /* play a thumbnail from file */
68int talk_number(long n, bool enqueue); /* say a number */ 70int talk_number(long n, bool enqueue); /* say a number */
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index 42d94a9158..573252e938 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -101,7 +101,12 @@ void audio_error_clear(void);
101int audio_get_file_pos(void); 101int audio_get_file_pos(void);
102void audio_beep(int duration); 102void audio_beep(int duration);
103void audio_init_playback(void); 103void audio_init_playback(void);
104/* Required call when audio buffer is require for some other purpose */
104unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size); 105unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size);
106#ifdef USE_IRAM
107/* Required call when codec IRAM is needed for some other purpose */
108void audio_iram_steal(void);
109#endif
105 110
106/* channel modes */ 111/* channel modes */
107enum rec_channel_modes 112enum rec_channel_modes
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 440c0faef3..74c7e924ff 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -283,6 +283,9 @@
283#define IDATA_ATTR __attribute__ ((section(".idata"))) 283#define IDATA_ATTR __attribute__ ((section(".idata")))
284#define IBSS_ATTR __attribute__ ((section(".ibss"))) 284#define IBSS_ATTR __attribute__ ((section(".ibss")))
285#define USE_IRAM 285#define USE_IRAM
286#if CONFIG_CPU != SH7034
287#define IRAM_STEAL
288#endif
286#else 289#else
287#define ICODE_ATTR 290#define ICODE_ATTR
288#define ICONST_ATTR 291#define ICONST_ATTR