mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-07-10 13:29:52 -04:00
Compare commits
6 commits
a1b7e7b134
...
ea570c5728
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea570c5728 | ||
|
|
be1e074800 | ||
|
|
84fa538979 | ||
|
|
5c1ae51193 | ||
|
|
b782f15eaa | ||
|
|
c9417e24c1 |
25 changed files with 681 additions and 219 deletions
|
|
@ -12507,20 +12507,6 @@
|
||||||
*: "Средна побитова скорост"
|
*: "Средна побитова скорост"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
|
||||||
id: LANG_PLAYTIME_ERROR
|
|
||||||
desc: playing time screen
|
|
||||||
user: core
|
|
||||||
<source>
|
|
||||||
*: "Error while gathering info"
|
|
||||||
</source>
|
|
||||||
<dest>
|
|
||||||
*: "Грешка при събирането на информация"
|
|
||||||
</dest>
|
|
||||||
<voice>
|
|
||||||
*: "Грешка при събирането на информация"
|
|
||||||
</voice>
|
|
||||||
</phrase>
|
|
||||||
<phrase>
|
<phrase>
|
||||||
id: LANG_PLAYING_TIME
|
id: LANG_PLAYING_TIME
|
||||||
desc: onplay menu
|
desc: onplay menu
|
||||||
|
|
@ -14686,7 +14672,7 @@
|
||||||
user: core
|
user: core
|
||||||
<source>
|
<source>
|
||||||
*: "Press LEFT to cancel."
|
*: "Press LEFT to cancel."
|
||||||
android,hifietma*,zenvision: "Press BACK to cancel."
|
android,hifietma*: "Press BACK to cancel."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel."
|
||||||
ihifi760,ihifi960: "Double tap RETURN to cancel."
|
ihifi760,ihifi960: "Double tap RETURN to cancel."
|
||||||
ihifi770,ihifi770c,ihifi800: "Press HOME to cancel."
|
ihifi770,ihifi770c,ihifi800: "Press HOME to cancel."
|
||||||
|
|
@ -14701,7 +14687,7 @@
|
||||||
</source>
|
</source>
|
||||||
<dest>
|
<dest>
|
||||||
*: "Натиснете LEFT за отказ."
|
*: "Натиснете LEFT за отказ."
|
||||||
android,hifietma*,zenvision: "Натиснете BACK за отказ."
|
android,hifietma*: "Натиснете BACK за отказ."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Натиснете POWER за отказ."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Натиснете POWER за отказ."
|
||||||
ihifi760,ihifi960: "Натиснете двукратно RETURN за отказ."
|
ihifi760,ihifi960: "Натиснете двукратно RETURN за отказ."
|
||||||
ihifi770,ihifi770c,ihifi800: "Натиснете HOME за отказ."
|
ihifi770,ihifi770c,ihifi800: "Натиснете HOME за отказ."
|
||||||
|
|
@ -14716,7 +14702,7 @@
|
||||||
</dest>
|
</dest>
|
||||||
<voice>
|
<voice>
|
||||||
*: "Натиснете LEFT за отказ."
|
*: "Натиснете LEFT за отказ."
|
||||||
android,hifietma*,zenvision: "Натиснете BACK за отказ."
|
android,hifietma*: "Натиснете BACK за отказ."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Натиснете POWER за отказ."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Натиснете POWER за отказ."
|
||||||
ihifi760,ihifi960: "Натиснете двукратно RETURN за отказ."
|
ihifi760,ihifi960: "Натиснете двукратно RETURN за отказ."
|
||||||
ihifi770,ihifi770c,ihifi800: "Натиснете HOME за отказ."
|
ihifi770,ihifi770c,ihifi800: "Натиснете HOME за отказ."
|
||||||
|
|
@ -15211,13 +15197,13 @@
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
<phrase>
|
||||||
id: LANG_VOICED_DATE_FORMAT
|
id: LANG_VOICED_DATE_FORMAT
|
||||||
desc: format string for how dates will be read back. Y == 4-digit year, A == month name, m == numeric month, d == numeric day. For example, "AdY" will read "January 21 2021"
|
desc: format string for how dates will be read back. Y == 4-digit year (grouped), y == 4-digit year (numeric), A == month name, m == numeric month, d == numeric day. For example, for 2021-01-05, "AdY" will be voiced as "January 5 twenty twenty-one" and "dmy" will be voiced as "5 1 two thousand twenty one
|
||||||
user: core
|
user: core
|
||||||
<source>
|
<source>
|
||||||
*: "dAY"
|
*: "dAY"
|
||||||
</source>
|
</source>
|
||||||
<dest>
|
<dest>
|
||||||
*: "~dAY"
|
*: "dAy"
|
||||||
</dest>
|
</dest>
|
||||||
<voice>
|
<voice>
|
||||||
*: ""
|
*: ""
|
||||||
|
|
@ -15832,20 +15818,6 @@
|
||||||
*: "Браузър по подразбиране"
|
*: "Браузър по подразбиране"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
|
||||||
id: LANG_AMAZE_MENU
|
|
||||||
desc: Amaze game
|
|
||||||
user: core
|
|
||||||
<source>
|
|
||||||
*: "Amaze Main Menu"
|
|
||||||
</source>
|
|
||||||
<dest>
|
|
||||||
*: "Главно меню на Amaze"
|
|
||||||
</dest>
|
|
||||||
<voice>
|
|
||||||
*: "Главно меню на Amaze"
|
|
||||||
</voice>
|
|
||||||
</phrase>
|
|
||||||
<phrase>
|
<phrase>
|
||||||
id: LANG_SET_MAZE_SIZE
|
id: LANG_SET_MAZE_SIZE
|
||||||
desc: Maze size in Amaze game
|
desc: Maze size in Amaze game
|
||||||
|
|
@ -16098,34 +16070,6 @@
|
||||||
*: "Настройки на Mik mod"
|
*: "Настройки на Mik mod"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
|
||||||
id: LANG_MIKMOD_MENU
|
|
||||||
desc: mikmod plugin
|
|
||||||
user: core
|
|
||||||
<source>
|
|
||||||
*: "Mikmod Menu"
|
|
||||||
</source>
|
|
||||||
<dest>
|
|
||||||
*: "Меню на Mikmod"
|
|
||||||
</dest>
|
|
||||||
<voice>
|
|
||||||
*: "Меню на Mik mod"
|
|
||||||
</voice>
|
|
||||||
</phrase>
|
|
||||||
<phrase>
|
|
||||||
id: LANG_CHESSBOX_MENU
|
|
||||||
desc: chessbox plugin
|
|
||||||
user: core
|
|
||||||
<source>
|
|
||||||
*: "Chessbox Menu"
|
|
||||||
</source>
|
|
||||||
<dest>
|
|
||||||
*: "Меню на Chessbox"
|
|
||||||
</dest>
|
|
||||||
<voice>
|
|
||||||
*: "Меню на Chess box"
|
|
||||||
</voice>
|
|
||||||
</phrase>
|
|
||||||
<phrase>
|
<phrase>
|
||||||
id: VOICE_INVALID_VOICE_FILE
|
id: VOICE_INVALID_VOICE_FILE
|
||||||
desc: played if the voice file fails to load
|
desc: played if the voice file fails to load
|
||||||
|
|
@ -16987,3 +16931,48 @@
|
||||||
usbdac: "USB ЦАП е активен"
|
usbdac: "USB ЦАП е активен"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_ANNOUNCE_STATUS
|
||||||
|
desc: announnnce_status plugin
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Announce Status"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Съобщаване на състоянието"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Съобщаване на състоянието"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_USE_LED_INDICATORS
|
||||||
|
desc: LED indicators setting
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: none
|
||||||
|
general_purpose_led: "Use LED indicators"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: none
|
||||||
|
general_purpose_led: "Използване на светодиодни индикатори"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: none
|
||||||
|
general_purpose_led: "Използване на светодиодни индикатори"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_KEEP_DIRECTORY
|
||||||
|
desc: file browser setting
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Always remember last folder"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Винаги помни последната папка"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Винаги помни последната папка"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
||||||
|
|
@ -14690,7 +14690,7 @@
|
||||||
user: core
|
user: core
|
||||||
<source>
|
<source>
|
||||||
*: "Press LEFT to cancel."
|
*: "Press LEFT to cancel."
|
||||||
android,hifietma*,zenvision: "Press BACK to cancel."
|
android,hifietma*: "Press BACK to cancel."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel."
|
||||||
ihifi760,ihifi960: "Double tap RETURN to cancel."
|
ihifi760,ihifi960: "Double tap RETURN to cancel."
|
||||||
ihifi770,ihifi770c,ihifi800: "Press HOME to cancel."
|
ihifi770,ihifi770c,ihifi800: "Press HOME to cancel."
|
||||||
|
|
@ -14705,7 +14705,7 @@
|
||||||
</source>
|
</source>
|
||||||
<dest>
|
<dest>
|
||||||
*: "Zum Abbrechen LINKS drücken."
|
*: "Zum Abbrechen LINKS drücken."
|
||||||
android,hifietma*,vibe500,zenvision: "Zum Abbrechen ZURÜCK drücken."
|
android,hifietma*,vibe500: "Zum Abbrechen ZURÜCK drücken."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Zum Abbrechen POWER drücken."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Zum Abbrechen POWER drücken."
|
||||||
ihifi760,ihifi960: "Zum Abbrechen ZURÜCK doppeldrücken."
|
ihifi760,ihifi960: "Zum Abbrechen ZURÜCK doppeldrücken."
|
||||||
ihifi770,ihifi770c,ihifi800: "Zum Abbrechen STARTMENÜ drücken."
|
ihifi770,ihifi770c,ihifi800: "Zum Abbrechen STARTMENÜ drücken."
|
||||||
|
|
@ -14719,7 +14719,7 @@
|
||||||
</dest>
|
</dest>
|
||||||
<voice>
|
<voice>
|
||||||
*: "Zum Abbrechen LINKS drücken."
|
*: "Zum Abbrechen LINKS drücken."
|
||||||
android,hifietma*,vibe500,zenvision: "Zum Abbrechen ZURÜCK drücken."
|
android,hifietma*,vibe500: "Zum Abbrechen ZURÜCK drücken."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Zum Abbrechen POWER drücken."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Zum Abbrechen POWER drücken."
|
||||||
ihifi760,ihifi960: "Zum Abbrechen ZURÜCK doppeldrücken."
|
ihifi760,ihifi960: "Zum Abbrechen ZURÜCK doppeldrücken."
|
||||||
ihifi770,ihifi770c,ihifi800: "Zum Abbrechen STARTMENÜ drücken."
|
ihifi770,ihifi770c,ihifi800: "Zum Abbrechen STARTMENÜ drücken."
|
||||||
|
|
@ -15213,7 +15213,7 @@
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
<phrase>
|
||||||
id: LANG_VOICED_DATE_FORMAT
|
id: LANG_VOICED_DATE_FORMAT
|
||||||
desc: format string for how dates will be read back. Y == 4-digit year, A == month name, m == numeric month, d == numeric day. For example, "AdY" will read "January 21 2021"
|
desc: format string for how dates will be read back. Y == 4-digit year (grouped), y == 4-digit year (numeric), A == month name, m == numeric month, d == numeric day. For example, for 2021-01-05, "AdY" will be voiced as "January 5 twenty twenty-one" and "dmy" will be voiced as "5 1 two thousand twenty one
|
||||||
user: core
|
user: core
|
||||||
<source>
|
<source>
|
||||||
*: "dAY"
|
*: "dAY"
|
||||||
|
|
@ -16978,3 +16978,17 @@
|
||||||
*: "Status mitteilen"
|
*: "Status mitteilen"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_KEEP_DIRECTORY
|
||||||
|
desc: file browser setting
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Always remember last folder"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Zuletzt verwendeten Ordner immer merken"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Zuletzt verwendeten Ordner immer merken"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
||||||
|
|
@ -644,7 +644,6 @@ static const struct plugin_api rockbox_api = {
|
||||||
#endif
|
#endif
|
||||||
&audio_master_sampr_list[0],
|
&audio_master_sampr_list[0],
|
||||||
&hw_freq_sampr[0],
|
&hw_freq_sampr[0],
|
||||||
pcm_apply_settings,
|
|
||||||
pcm_play_lock,
|
pcm_play_lock,
|
||||||
pcm_play_unlock,
|
pcm_play_unlock,
|
||||||
pcm_current_sink_caps,
|
pcm_current_sink_caps,
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ int plugin_open(const char *plugin, const char *parameter);
|
||||||
* when this happens please take the opportunity to sort in
|
* when this happens please take the opportunity to sort in
|
||||||
* any new functions "waiting" at the end of the list.
|
* any new functions "waiting" at the end of the list.
|
||||||
*/
|
*/
|
||||||
#define PLUGIN_API_VERSION 279
|
#define PLUGIN_API_VERSION 280
|
||||||
|
|
||||||
/* 239 Marks the removal of ARCHOS HWCODEC and CHARCELL */
|
/* 239 Marks the removal of ARCHOS HWCODEC and CHARCELL */
|
||||||
|
|
||||||
|
|
@ -743,7 +743,6 @@ struct plugin_api {
|
||||||
#endif
|
#endif
|
||||||
const unsigned long *audio_master_sampr_list;
|
const unsigned long *audio_master_sampr_list;
|
||||||
const unsigned long *hw_freq_sampr;
|
const unsigned long *hw_freq_sampr;
|
||||||
void (*pcm_apply_settings)(void);
|
|
||||||
void (*pcm_play_lock)(void);
|
void (*pcm_play_lock)(void);
|
||||||
void (*pcm_play_unlock)(void);
|
void (*pcm_play_unlock)(void);
|
||||||
const struct pcm_sink_caps* (*pcm_current_sink_caps)(void);
|
const struct pcm_sink_caps* (*pcm_current_sink_caps)(void);
|
||||||
|
|
|
||||||
|
|
@ -462,7 +462,7 @@ void get_more(const void** start, size_t* size)
|
||||||
I_UpdateSound(); // Force sound update
|
I_UpdateSound(); // Force sound update
|
||||||
|
|
||||||
*start = mixbuffer;
|
*start = mixbuffer;
|
||||||
*size = SAMPLECOUNT*2*sizeof(short);
|
*size = MIXBUFFERSIZE*sizeof(short);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,5 @@
|
||||||
-- [[ conversion to old style pcm_ functions ]]
|
-- [[ conversion to old style pcm_ functions ]]
|
||||||
if not rb.pcm then rb.splash(rb.HZ, "No Support!") return nil end
|
if not rb.pcm then rb.splash(rb.HZ, "No Support!") return nil end
|
||||||
|
|
||||||
rb.pcm_apply_settings = function() rb.pcm("apply_settings") end
|
|
||||||
rb.pcm_play_lock = function() rb.pcm("play_lock") end
|
rb.pcm_play_lock = function() rb.pcm("play_lock") end
|
||||||
rb.pcm_play_unlock = function() rb.pcm("play_unlock") end
|
rb.pcm_play_unlock = function() rb.pcm("play_unlock") end
|
||||||
|
|
|
||||||
|
|
@ -549,10 +549,10 @@ RB_WRAP(sound)
|
||||||
|
|
||||||
RB_WRAP(pcm)
|
RB_WRAP(pcm)
|
||||||
{
|
{
|
||||||
enum e_pcm {PCM_APPLYSETTINGS = 0, PCM_PLAYLOCK, PCM_PLAYUNLOCK,
|
enum e_pcm {PCM_PLAYLOCK = 0, PCM_PLAYUNLOCK,
|
||||||
PCM_ECOUNT};
|
PCM_ECOUNT};
|
||||||
|
|
||||||
const char *pcm_option[] = {"apply_settings", "play_lock", "play_unlock",
|
const char *pcm_option[] = {"play_lock", "play_unlock",
|
||||||
NULL};
|
NULL};
|
||||||
|
|
||||||
lua_pushnil(L); /*push nil so options w/o return have something to return */
|
lua_pushnil(L); /*push nil so options w/o return have something to return */
|
||||||
|
|
@ -560,9 +560,6 @@ RB_WRAP(pcm)
|
||||||
int option = luaL_checkoption (L, 1, NULL, pcm_option);
|
int option = luaL_checkoption (L, 1, NULL, pcm_option);
|
||||||
switch(option)
|
switch(option)
|
||||||
{
|
{
|
||||||
case PCM_APPLYSETTINGS:
|
|
||||||
rb->pcm_apply_settings();
|
|
||||||
break;
|
|
||||||
case PCM_PLAYLOCK:
|
case PCM_PLAYLOCK:
|
||||||
rb->pcm_play_lock();
|
rb->pcm_play_lock();
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ void rockbox_open_audio(int rate)
|
||||||
|
|
||||||
/* Set sample rate of the audio buffer. */
|
/* Set sample rate of the audio buffer. */
|
||||||
rb->mixer_set_frequency(rate);
|
rb->mixer_set_frequency(rate);
|
||||||
rb->pcm_apply_settings();
|
|
||||||
|
|
||||||
/* Initialize output buffer. */
|
/* Initialize output buffer. */
|
||||||
for(i = 0; i < OUTBUFSIZE; i++)
|
for(i = 0; i < OUTBUFSIZE; i++)
|
||||||
|
|
@ -86,7 +85,6 @@ void rockbox_close_audio(void)
|
||||||
|
|
||||||
/* Restore default sampling rate. */
|
/* Restore default sampling rate. */
|
||||||
rb->mixer_set_frequency(HW_SAMPR_DEFAULT);
|
rb->mixer_set_frequency(HW_SAMPR_DEFAULT);
|
||||||
rb->pcm_apply_settings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rockbox audio callback. */
|
/* Rockbox audio callback. */
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,6 @@ static void set_frequency(int index)
|
||||||
update_gen_step();
|
update_gen_step();
|
||||||
|
|
||||||
rb->mixer_set_frequency(hw_sampr);
|
rb->mixer_set_frequency(hw_sampr);
|
||||||
rb->pcm_apply_settings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_VOLUME_IN_LIST
|
#ifndef HAVE_VOLUME_IN_LIST
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,6 @@ bool syssnd_init(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rb->mixer_set_frequency(HW_FREQ_44);
|
rb->mixer_set_frequency(HW_FREQ_44);
|
||||||
rb->pcm_apply_settings();
|
|
||||||
|
|
||||||
rb->memset(channels, 0, sizeof(channels));
|
rb->memset(channels, 0, sizeof(channels));
|
||||||
rb->memset(mixBuffers, 0, sizeof(mixBuffers));
|
rb->memset(mixBuffers, 0, sizeof(mixBuffers));
|
||||||
|
|
@ -286,7 +285,6 @@ void syssnd_shutdown(void)
|
||||||
|
|
||||||
/* Restore default sampling rate. */
|
/* Restore default sampling rate. */
|
||||||
rb->mixer_set_frequency(HW_SAMPR_DEFAULT);
|
rb->mixer_set_frequency(HW_SAMPR_DEFAULT);
|
||||||
rb->pcm_apply_settings();
|
|
||||||
|
|
||||||
rb->talk_disable(false);
|
rb->talk_disable(false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -616,6 +616,10 @@ static void init_state(void)
|
||||||
record_status = RECORD_STOPPED;
|
record_status = RECORD_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* To avoid having to pull in all of pcm-internal.h */
|
||||||
|
void pcm_set_frequency(unsigned int samplerate);
|
||||||
|
void pcm_apply_settings(void);
|
||||||
|
|
||||||
/* Set hardware samplerate and save it */
|
/* Set hardware samplerate and save it */
|
||||||
static void update_samplerate_config(unsigned long sampr)
|
static void update_samplerate_config(unsigned long sampr)
|
||||||
{
|
{
|
||||||
|
|
@ -876,7 +880,7 @@ copy_buffer_mono_lr(void *dst, const void *src, size_t src_size)
|
||||||
int16_t *d = (int16_t*) dst;
|
int16_t *d = (int16_t*) dst;
|
||||||
int16_t const *s = (int16_t const*) src;
|
int16_t const *s = (int16_t const*) src;
|
||||||
ssize_t copy_size = src_size;
|
ssize_t copy_size = src_size;
|
||||||
|
|
||||||
/* mono = (L + R) / 2 */
|
/* mono = (L + R) / 2 */
|
||||||
while(copy_size > 0) {
|
while(copy_size > 0) {
|
||||||
*d++ = ((int32_t)s[0] + (int32_t)s[1] + 1) >> 1;
|
*d++ = ((int32_t)s[0] + (int32_t)s[1] + 1) >> 1;
|
||||||
|
|
|
||||||
|
|
@ -1754,10 +1754,6 @@ void pcmbuf_set_low_latency(bool state)
|
||||||
\param state
|
\param state
|
||||||
\description
|
\description
|
||||||
|
|
||||||
void pcm_apply_settings(void)
|
|
||||||
\group sound
|
|
||||||
\description
|
|
||||||
|
|
||||||
void pcm_calculate_rec_peaks(int *left, int *right)
|
void pcm_calculate_rec_peaks(int *left, int *right)
|
||||||
\group sound
|
\group sound
|
||||||
\conditions (defined(HAVE_RECORDING))
|
\conditions (defined(HAVE_RECORDING))
|
||||||
|
|
|
||||||
|
|
@ -1942,7 +1942,6 @@ target/arm/stm32/debug-stm32h7.c
|
||||||
#endif
|
#endif
|
||||||
target/arm/stm32/gpio-stm32h7.c
|
target/arm/stm32/gpio-stm32h7.c
|
||||||
target/arm/stm32/i2c-stm32h7.c
|
target/arm/stm32/i2c-stm32h7.c
|
||||||
target/arm/stm32/pcm-stm32h7.c
|
|
||||||
target/arm/stm32/sdmmc-stm32h7.c
|
target/arm/stm32/sdmmc-stm32h7.c
|
||||||
target/arm/stm32/spi-stm32h7.c
|
target/arm/stm32/spi-stm32h7.c
|
||||||
target/arm/stm32/system-stm32h7.c
|
target/arm/stm32/system-stm32h7.c
|
||||||
|
|
@ -1959,6 +1958,9 @@ target/arm/stm32/echoplayer/button-echoplayer.c
|
||||||
target/arm/stm32/echoplayer/clock-echoplayer.c
|
target/arm/stm32/echoplayer/clock-echoplayer.c
|
||||||
target/arm/stm32/echoplayer/i2c-echoplayer.c
|
target/arm/stm32/echoplayer/i2c-echoplayer.c
|
||||||
target/arm/stm32/echoplayer/lcd-echoplayer.c
|
target/arm/stm32/echoplayer/lcd-echoplayer.c
|
||||||
|
#ifndef BOOTLOADER
|
||||||
|
target/arm/stm32/echoplayer/pcm-echoplayer.c
|
||||||
|
#endif
|
||||||
target/arm/stm32/echoplayer/power-echoplayer.c
|
target/arm/stm32/echoplayer/power-echoplayer.c
|
||||||
target/arm/stm32/echoplayer/sdmmc-echoplayer.c
|
target/arm/stm32/echoplayer/sdmmc-echoplayer.c
|
||||||
target/arm/stm32/echoplayer/system-echoplayer.c
|
target/arm/stm32/echoplayer/system-echoplayer.c
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,14 @@
|
||||||
/* Codec / audio hardware defines */
|
/* Codec / audio hardware defines */
|
||||||
#define HW_SAMPR_CAPS SAMPR_CAP_ALL_96 // FIXME: check this section
|
#define HW_SAMPR_CAPS SAMPR_CAP_ALL_96 // FIXME: check this section
|
||||||
#define HAVE_ECHOPLAYER_CODEC
|
#define HAVE_ECHOPLAYER_CODEC
|
||||||
|
#define HAVE_AIC310X
|
||||||
#define HAVE_SW_TONE_CONTROLS
|
#define HAVE_SW_TONE_CONTROLS
|
||||||
#define HAVE_SW_VOLUME_CONTROL
|
#define HAVE_SW_VOLUME_CONTROL
|
||||||
|
|
||||||
|
#ifndef SIMULATOR
|
||||||
|
#define PCM_NATIVE_BITDEPTH 32
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Button defines */
|
/* Button defines */
|
||||||
#define CONFIG_KEYPAD ECHO_R1_PAD
|
#define CONFIG_KEYPAD ECHO_R1_PAD
|
||||||
#define HAVE_HEADPHONE_DETECTION
|
#define HAVE_HEADPHONE_DETECTION
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,13 @@
|
||||||
#ifndef __ECHOPLAYER_CODEC_H__
|
#ifndef __ECHOPLAYER_CODEC_H__
|
||||||
#define __ECHOPLAYER_CODEC_H__
|
#define __ECHOPLAYER_CODEC_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* -79 to 0 dB in 0.5 dB steps; software volume control
|
/* -79 to 0 dB in 0.5 dB steps; software volume control
|
||||||
* is used because the hardware volume controls "click"
|
* is used because the hardware volume controls "click"
|
||||||
* when changing the volume */
|
* when changing the volume */
|
||||||
AUDIOHW_SETTING(VOLUME, "dB", 1, 5, -790, 0, -200);
|
AUDIOHW_SETTING(VOLUME, "dB", 1, 5, -790, 0, -200);
|
||||||
|
|
||||||
|
void audiohw_mute(bool mute);
|
||||||
|
|
||||||
#endif /* __ECHOPLAYER_CODEC_H__ */
|
#endif /* __ECHOPLAYER_CODEC_H__ */
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,20 @@ void pcm_sync_pcm_factors(void);
|
||||||
({ (start) = (void *)(((uintptr_t)(start) + 3) & ~3); \
|
({ (start) = (void *)(((uintptr_t)(start) + 3) & ~3); \
|
||||||
(size) &= ~3; })
|
(size) &= ~3; })
|
||||||
|
|
||||||
|
/* Internal PCM API calls for playback */
|
||||||
|
void pcm_play_data(pcm_play_callback_type get_more,
|
||||||
|
pcm_status_callback_type status_cb,
|
||||||
|
const void *start, size_t size);
|
||||||
|
|
||||||
|
void pcm_play_stop(void);
|
||||||
|
void pcm_play_stop_int(void); /* requires PCM lock held */
|
||||||
|
bool pcm_is_playing(void);
|
||||||
|
|
||||||
|
void pcm_set_frequency(unsigned int samplerate);
|
||||||
|
unsigned int pcm_get_frequency(void);
|
||||||
|
/* apply settings to hardware immediately */
|
||||||
|
void pcm_apply_settings(void);
|
||||||
|
|
||||||
void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
||||||
const void *addr, int count);
|
const void *addr, int count);
|
||||||
|
|
||||||
|
|
@ -125,7 +139,6 @@ pcm_play_dma_status_callback(enum pcm_dma_status status)
|
||||||
#if defined(HAVE_SW_VOLUME_CONTROL) && !defined(PCM_SW_VOLUME_UNBUFFERED)
|
#if defined(HAVE_SW_VOLUME_CONTROL) && !defined(PCM_SW_VOLUME_UNBUFFERED)
|
||||||
void pcm_play_dma_start_int(const void *addr, size_t size);
|
void pcm_play_dma_start_int(const void *addr, size_t size);
|
||||||
void pcm_play_dma_stop_int(void);
|
void pcm_play_dma_stop_int(void);
|
||||||
void pcm_play_stop_int(void);
|
|
||||||
#endif /* HAVE_SW_VOLUME_CONTROL && !PCM_SW_VOLUME_UNBUFFERED */
|
#endif /* HAVE_SW_VOLUME_CONTROL && !PCM_SW_VOLUME_UNBUFFERED */
|
||||||
|
|
||||||
/* Called by the bottom layer ISR when more data is needed. Returns true
|
/* Called by the bottom layer ISR when more data is needed. Returns true
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ typedef void (*pcm_play_callback_type)(const void **start, size_t *size);
|
||||||
/* Typedef for registered status callback */
|
/* Typedef for registered status callback */
|
||||||
typedef enum pcm_dma_status (*pcm_status_callback_type)(enum pcm_dma_status status);
|
typedef enum pcm_dma_status (*pcm_status_callback_type)(enum pcm_dma_status status);
|
||||||
|
|
||||||
/* set the pcm frequency - use values in hw_sampr_list
|
/* set the pcm frequency - use values in hw_sampr_list
|
||||||
* when CONFIG_SAMPR_TYPES is #defined, or-in SAMPR_TYPE_* fields with
|
* when CONFIG_SAMPR_TYPES is #defined, or-in SAMPR_TYPE_* fields with
|
||||||
* frequency value. SAMPR_TYPE_PLAY is 0 and the default if none is
|
* frequency value. SAMPR_TYPE_PLAY is 0 and the default if none is
|
||||||
* specified. */
|
* specified. */
|
||||||
|
|
@ -54,15 +54,6 @@ unsigned int pcm_sampr_type_rec_to_play(unsigned int samplerate);
|
||||||
#endif
|
#endif
|
||||||
#endif /* CONFIG_SAMPR_TYPES */
|
#endif /* CONFIG_SAMPR_TYPES */
|
||||||
|
|
||||||
/* set next frequency to be used */
|
|
||||||
void pcm_set_frequency(unsigned int samplerate);
|
|
||||||
/* return last-set frequency */
|
|
||||||
unsigned int pcm_get_frequency(void);
|
|
||||||
/* apply settings to hardware immediately */
|
|
||||||
void pcm_apply_settings(void);
|
|
||||||
|
|
||||||
/** RAW PCM playback routines **/
|
|
||||||
|
|
||||||
/* Reenterable locks for locking and unlocking the playback interrupt */
|
/* Reenterable locks for locking and unlocking the playback interrupt */
|
||||||
void pcm_play_lock(void);
|
void pcm_play_lock(void);
|
||||||
void pcm_play_unlock(void);
|
void pcm_play_unlock(void);
|
||||||
|
|
@ -77,11 +68,6 @@ const struct pcm_sink_caps* pcm_sink_caps(enum pcm_sink_ids sink);
|
||||||
/* shortcut for plugins */
|
/* shortcut for plugins */
|
||||||
const struct pcm_sink_caps* pcm_current_sink_caps(void);
|
const struct pcm_sink_caps* pcm_current_sink_caps(void);
|
||||||
|
|
||||||
/* This is for playing "raw" PCM data */
|
|
||||||
void pcm_play_data(pcm_play_callback_type get_more,
|
|
||||||
pcm_status_callback_type status_cb,
|
|
||||||
const void *start, size_t size);
|
|
||||||
|
|
||||||
/* Kept internally for global PCM and used by mixer's verion of peak
|
/* Kept internally for global PCM and used by mixer's verion of peak
|
||||||
calculation */
|
calculation */
|
||||||
struct pcm_peaks
|
struct pcm_peaks
|
||||||
|
|
@ -92,9 +78,6 @@ struct pcm_peaks
|
||||||
long tick; /* Last tick called */
|
long tick; /* Last tick called */
|
||||||
};
|
};
|
||||||
|
|
||||||
void pcm_play_stop(void);
|
|
||||||
bool pcm_is_playing(void);
|
|
||||||
|
|
||||||
#ifdef HAVE_RECORDING
|
#ifdef HAVE_RECORDING
|
||||||
|
|
||||||
/** RAW PCM recording routines **/
|
/** RAW PCM recording routines **/
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,6 @@ volatile pcm_status_callback_type
|
||||||
/* PCM playback state */
|
/* PCM playback state */
|
||||||
volatile bool pcm_playing SHAREDBSS_ATTR = false;
|
volatile bool pcm_playing SHAREDBSS_ATTR = false;
|
||||||
|
|
||||||
void pcm_play_stop_int(void);
|
|
||||||
|
|
||||||
struct pcm_sink* pcm_get_current_sink(void)
|
struct pcm_sink* pcm_get_current_sink(void)
|
||||||
{
|
{
|
||||||
return sinks[cur_sink];
|
return sinks[cur_sink];
|
||||||
|
|
|
||||||
|
|
@ -475,6 +475,9 @@ void mixer_set_frequency(unsigned int samplerate)
|
||||||
mix_frame_size = 1;
|
mix_frame_size = 1;
|
||||||
|
|
||||||
mix_frame_size *= MIX_FRAME_SAMPLES * 4;
|
mix_frame_size *= MIX_FRAME_SAMPLES * 4;
|
||||||
|
|
||||||
|
if (pcm_is_initialized())
|
||||||
|
pcm_apply_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get output samplerate */
|
/* Get output samplerate */
|
||||||
|
|
|
||||||
|
|
@ -86,11 +86,68 @@ static bool swd_menu(void)
|
||||||
return simplelist_show_list(&info);
|
return simplelist_show_list(&info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ECHO_R1)
|
||||||
|
extern volatile int pcm_sai_xrun_count;
|
||||||
|
extern volatile int pcm_dma_teif_count;
|
||||||
|
extern volatile int pcm_dma_dmeif_count;
|
||||||
|
extern volatile int pcm_dma_feif_count;
|
||||||
|
|
||||||
|
struct pcmdebug_counter
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
volatile int *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pcmdebug_counter pcmdebug_counters[] =
|
||||||
|
{
|
||||||
|
{"SAI xrun count", &pcm_sai_xrun_count},
|
||||||
|
{"DMA TEIF count", &pcm_dma_teif_count},
|
||||||
|
{"DMA DMEIF count", &pcm_dma_dmeif_count},
|
||||||
|
{"DMA FEIF count", &pcm_dma_feif_count},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pcmdebug_menu_action_cb(int action, struct gui_synclist *lists)
|
||||||
|
{
|
||||||
|
if (action == ACTION_STD_OK)
|
||||||
|
{
|
||||||
|
int item = gui_synclist_get_sel_pos(lists);
|
||||||
|
const struct pcmdebug_counter *counter = &pcmdebug_counters[item];
|
||||||
|
|
||||||
|
*counter->value = 0;
|
||||||
|
action = ACTION_REDRAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == ACTION_NONE)
|
||||||
|
action = ACTION_REDRAW;
|
||||||
|
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *pcmdebug_menu_get_name(int item, void *data, char *buf, size_t bufsz)
|
||||||
|
{
|
||||||
|
const struct pcmdebug_counter *counter = &pcmdebug_counters[item];
|
||||||
|
(void)data;
|
||||||
|
|
||||||
|
snprintf(buf, bufsz, "%s: %d", counter->name, *counter->value);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pcm_debug_menu(void)
|
||||||
|
{
|
||||||
|
struct simplelist_info info;
|
||||||
|
simplelist_info_init(&info, "PCM debug", ARRAYLEN(pcmdebug_counters), NULL);
|
||||||
|
info.action_callback = pcmdebug_menu_action_cb;
|
||||||
|
info.get_name = pcmdebug_menu_get_name;
|
||||||
|
return simplelist_show_list(&info);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Menu definition */
|
/* Menu definition */
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
bool (*function) (void);
|
bool (*function) (void);
|
||||||
} menuitems[] = {
|
} menuitems[] = {
|
||||||
|
{"PCM debug", pcm_debug_menu},
|
||||||
{"SWD/JTAG", swd_menu},
|
{"SWD/JTAG", swd_menu},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,151 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "audiohw.h"
|
#include "audiohw.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "panic.h"
|
||||||
|
#include "aic310x.h"
|
||||||
|
#include "pcm_sw_volume.h"
|
||||||
|
#include "power-echoplayer.h"
|
||||||
|
#include "gpio-stm32h7.h"
|
||||||
|
#include "i2c-echoplayer.h"
|
||||||
|
|
||||||
|
static int tlv_read_multiple(uint8_t reg, uint8_t *data, size_t count)
|
||||||
|
{
|
||||||
|
return stm32_i2c_read_mem(&i2c1_ctl, AIC310X_I2C_ADDR, reg, data, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tlv_write_multiple(uint8_t reg, const uint8_t *data, size_t count)
|
||||||
|
{
|
||||||
|
return stm32_i2c_write_mem(&i2c1_ctl, AIC310X_I2C_ADDR, reg, data, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct aic310x tlv_codec = {
|
||||||
|
.read_multiple = tlv_read_multiple,
|
||||||
|
.write_multiple = tlv_write_multiple,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct codec_reg_data
|
||||||
|
{
|
||||||
|
uint8_t reg;
|
||||||
|
uint8_t val;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct codec_reg_data codec_init_seq[] = {
|
||||||
|
/* Set output driver configuration to stereo psuedo-differential */
|
||||||
|
{ .reg = AIC310X_HEADSET_DETECT_B, .val = 0x08 },
|
||||||
|
|
||||||
|
/* Clock input is CODEC_CLKIN (bypass codec PLL) */
|
||||||
|
{ .reg = AIC310X_CLOCK, .val = 0x01 },
|
||||||
|
|
||||||
|
/* Route left ch. -> left DAC, right ch -> right DAC */
|
||||||
|
{ .reg = AIC310X_DATA_PATH, .val = 0x0A },
|
||||||
|
|
||||||
|
/* Power on DACs, set HPLCOM = VCM, set HPRCOM = VCM,
|
||||||
|
* enable short circuit protection */
|
||||||
|
{ .reg = AIC310X_HPOUT_DRIVER_CTRL, .val = 0x0C },
|
||||||
|
{ .reg = AIC310X_DAC_POWER_CTRL, .val = 0xD0 },
|
||||||
|
|
||||||
|
/* Unmute the DACs */
|
||||||
|
{ .reg = AIC310X_LEFT_DAC_DIGITAL_VOLUME, .val = 0x00 },
|
||||||
|
{ .reg = AIC310X_RIGHT_DAC_DIGITAL_VOLUME, .val = 0x00 },
|
||||||
|
|
||||||
|
/* Route DACs to output drivers */
|
||||||
|
{ .reg = AIC310X_DAC_L1_TO_HPLOUT_VOLUME, .val = 0x80 },
|
||||||
|
{ .reg = AIC310X_DAC_R1_TO_HPROUT_VOLUME, .val = 0x80 },
|
||||||
|
|
||||||
|
/* Route DACs to line out port */
|
||||||
|
{ .reg = AIC310X_DAC_L1_TO_LEFT_LO_VOLUME, .val = 0x80 },
|
||||||
|
{ .reg = AIC310X_DAC_R1_TO_RIGHT_LO_VOLUME, .val = 0x80 },
|
||||||
|
|
||||||
|
/* Power on headphone output drivers */
|
||||||
|
{ .reg = AIC310X_HPLCOM_LEVEL_CONTROL, .val = 0x01 },
|
||||||
|
{ .reg = AIC310X_HPRCOM_LEVEL_CONTROL, .val = 0x01 },
|
||||||
|
{ .reg = AIC310X_HPLOUT_LEVEL_CONTROL, .val = 0x01 },
|
||||||
|
{ .reg = AIC310X_HPROUT_LEVEL_CONTROL, .val = 0x01 },
|
||||||
|
|
||||||
|
/* Power up line out drivers */
|
||||||
|
{ .reg = AIC310X_RIGHT_LO_LEVEL_CONTROL, .val = 0x01 },
|
||||||
|
{ .reg = AIC310X_LEFT_LO_LEVEL_CONTROL, .val = 0x01 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void write_aic310x_seq(const struct codec_reg_data *seq, size_t count)
|
||||||
|
{
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
if (aic310x_write(&tlv_codec, seq->reg, seq->val))
|
||||||
|
panicf("aic310x wr fail: %02x", (unsigned int)seq->reg);
|
||||||
|
|
||||||
|
seq++;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wait_aic310x_active(void)
|
||||||
|
{
|
||||||
|
long end_tick = current_tick + HZ;
|
||||||
|
while (TIME_BEFORE(current_tick, end_tick))
|
||||||
|
{
|
||||||
|
uint8_t tmp;
|
||||||
|
int err = tlv_read_multiple(AIC310X_PAGE_SELECT, &tmp, 1);
|
||||||
|
if (err == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
panicf("aic310x init timeout");
|
||||||
|
}
|
||||||
|
|
||||||
void audiohw_init(void)
|
void audiohw_init(void)
|
||||||
{
|
{
|
||||||
|
/* initialize driver */
|
||||||
|
aic310x_init(&tlv_codec);
|
||||||
|
|
||||||
|
/* bring 1.8v regulator up */
|
||||||
|
echoplayer_enable_1v8_regulator(true);
|
||||||
|
|
||||||
|
/* apply AVDD/DRVDD and DVDD */
|
||||||
|
gpio_set_level(GPIO_CODEC_AVDD_EN, 0);
|
||||||
|
gpio_set_level(GPIO_CODEC_DVDD_EN, 0);
|
||||||
|
|
||||||
|
/* delay for power stabilization */
|
||||||
|
sleep(HZ/100);
|
||||||
|
|
||||||
|
/* bring codec out of reset */
|
||||||
|
gpio_set_level(GPIO_CODEC_RESET, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audiohw_postinit(void)
|
void audiohw_postinit(void)
|
||||||
{
|
{
|
||||||
|
wait_aic310x_active();
|
||||||
|
write_aic310x_seq(codec_init_seq, ARRAYLEN(codec_init_seq));
|
||||||
}
|
}
|
||||||
|
|
||||||
void audiohw_close(void)
|
void audiohw_close(void)
|
||||||
{
|
{
|
||||||
|
/* apply reset */
|
||||||
|
gpio_set_level(GPIO_CODEC_RESET, 0);
|
||||||
|
|
||||||
|
/* remove power */
|
||||||
|
gpio_set_level(GPIO_CODEC_AVDD_EN, 1);
|
||||||
|
gpio_set_level(GPIO_CODEC_DVDD_EN, 1);
|
||||||
|
|
||||||
|
/* disable regulator */
|
||||||
|
echoplayer_enable_1v8_regulator(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void audiohw_mute(bool mute)
|
||||||
|
{
|
||||||
|
uint8_t wr_val = (mute ? 0x01 : 0x09);
|
||||||
|
|
||||||
|
/* Mute and unmute at the output drivers */
|
||||||
|
aic310x_write(&tlv_codec, AIC310X_HPLOUT_LEVEL_CONTROL, wr_val);
|
||||||
|
aic310x_write(&tlv_codec, AIC310X_HPROUT_LEVEL_CONTROL, wr_val);
|
||||||
|
aic310x_write(&tlv_codec, AIC310X_LEFT_LO_LEVEL_CONTROL, wr_val);
|
||||||
|
aic310x_write(&tlv_codec, AIC310X_RIGHT_LO_LEVEL_CONTROL, wr_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audiohw_set_volume(int vol_l, int vol_r)
|
void audiohw_set_volume(int vol_l, int vol_r)
|
||||||
{
|
{
|
||||||
(void)vol_l;
|
pcm_set_master_volume(vol_l, vol_r);
|
||||||
(void)vol_r;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ INIT_ATTR static void init_pll(void)
|
||||||
/*
|
/*
|
||||||
* Use HSE/4 input for PLL1
|
* Use HSE/4 input for PLL1
|
||||||
* Use HSE/16 input for PLL3
|
* Use HSE/16 input for PLL3
|
||||||
|
* PLL2 reserved for audio; configured in target PCM code
|
||||||
*/
|
*/
|
||||||
reg_writef(RCC_PLLCKSELR,
|
reg_writef(RCC_PLLCKSELR,
|
||||||
PLLSRC_V(HSE),
|
PLLSRC_V(HSE),
|
||||||
|
|
@ -164,7 +165,7 @@ INIT_ATTR static void init_lse(void)
|
||||||
INIT_ATTR static void init_periph_clock(void)
|
INIT_ATTR static void init_periph_clock(void)
|
||||||
{
|
{
|
||||||
reg_writef(RCC_D1CCIPR, SDMMCSEL_V(PLL1Q));
|
reg_writef(RCC_D1CCIPR, SDMMCSEL_V(PLL1Q));
|
||||||
reg_writef(RCC_D2CCIP1R, SPI45SEL_V(HSE));
|
reg_writef(RCC_D2CCIP1R, SAI1SEL_V(PLL2P), SPI45SEL_V(HSE));
|
||||||
reg_writef(RCC_D2CCIP2R, I2C123SEL_V(HSI));
|
reg_writef(RCC_D2CCIP2R, I2C123SEL_V(HSI));
|
||||||
|
|
||||||
/* Enable AXI SRAM in sleep mode to allow DMA'ing out of it */
|
/* Enable AXI SRAM in sleep mode to allow DMA'ing out of it */
|
||||||
|
|
|
||||||
381
firmware/target/arm/stm32/echoplayer/pcm-echoplayer.c
Normal file
381
firmware/target/arm/stm32/echoplayer/pcm-echoplayer.c
Normal file
|
|
@ -0,0 +1,381 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 Aidan MacDonald
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#include "pcm.h"
|
||||||
|
#include "pcm_sampr.h"
|
||||||
|
#include "pcm-internal.h"
|
||||||
|
#include "audiohw.h"
|
||||||
|
#include "panic.h"
|
||||||
|
#include "nvic-arm.h"
|
||||||
|
#include "dmamux-stm32h743.h"
|
||||||
|
#include "regs/stm32h743/rcc.h"
|
||||||
|
#include "regs/stm32h743/sai.h"
|
||||||
|
#include "regs/stm32h743/dma.h"
|
||||||
|
#include "regs/stm32h743/dmamux.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
/* Configurable bit depth */
|
||||||
|
#if PCM_NATIVE_BITDEPTH == 32
|
||||||
|
# define PCM_NATIVE_SAMPLE_SIZE 4
|
||||||
|
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_32BIT
|
||||||
|
# define SAI_DSIZE_VAL BV_SAI_SUBBLOCK_CR1_DS_32BIT
|
||||||
|
# define SAI_FIFO_THRESH BV_SAI_SUBBLOCK_CR2_FTH_QUARTER
|
||||||
|
# define SAI_FRL_VAL 64
|
||||||
|
#elif PCM_NATIVE_BITDEPTH == 24
|
||||||
|
# define PCM_NATIVE_SAMPLE_SIZE 4
|
||||||
|
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_32BIT
|
||||||
|
# define SAI_DSIZE_VAL BV_SAI_SUBBLOCK_CR1_DS_24BIT
|
||||||
|
# define SAI_FIFO_THRESH BV_SAI_SUBBLOCK_CR2_FTH_QUARTER
|
||||||
|
# define SAI_FRL_VAL 64
|
||||||
|
#elif PCM_NATIVE_BITDEPTH == 16
|
||||||
|
# define PCM_NATIVE_SAMPLE_SIZE 2
|
||||||
|
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_16BIT
|
||||||
|
# define SAI_DSIZE_VAL BV_SAI_SUBBLOCK_CR1_DS_16BIT
|
||||||
|
# define SAI_FIFO_THRESH BV_SAI_SUBBLOCK_CR2_FTH_HALF
|
||||||
|
# define SAI_FRL_VAL 32
|
||||||
|
#else
|
||||||
|
# error "Unsupported PCM bit depth"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const uintptr_t sai1 = ITA_SAI1;
|
||||||
|
static const uintptr_t sai1a = sai1 + ITO_SAI_A;
|
||||||
|
static const uintptr_t dmamux1 = ITA_DMAMUX1;
|
||||||
|
static const uintptr_t dma1 = ITA_DMA1;
|
||||||
|
static const uintptr_t dma1_ch0 = dma1 + ITO_DMA_CHN(0);
|
||||||
|
|
||||||
|
static atomic_size_t play_lock;
|
||||||
|
static volatile int play_active;
|
||||||
|
|
||||||
|
static int pcm_last_freq = -1;
|
||||||
|
|
||||||
|
volatile int pcm_sai_xrun_count;
|
||||||
|
volatile int pcm_dma_teif_count;
|
||||||
|
volatile int pcm_dma_dmeif_count;
|
||||||
|
volatile int pcm_dma_feif_count;
|
||||||
|
|
||||||
|
static void play_dma_start(const void *addr, size_t size)
|
||||||
|
{
|
||||||
|
commit_dcache_range(addr, size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of transfers is defined by PSIZE, which may
|
||||||
|
* be 16-bit or 32-bit depending on PCM native sample size.
|
||||||
|
* Each FIFO write transfers 1 sample, so we want to set
|
||||||
|
* NDT = size / PCM_NATIVE_SAMPLE_SIZE.
|
||||||
|
*
|
||||||
|
* When MSIZE == 32-bit and PSIZE == 16-bit, the DMA will
|
||||||
|
* take each 32-bit word from memory and write the lower/upper
|
||||||
|
* halfwords separately to the FIFO. The number of reads from
|
||||||
|
* memory in this case is NDT/2, so we're still transferring
|
||||||
|
* the correct amount of data.
|
||||||
|
*/
|
||||||
|
reg_varl(dma1_ch0, DMA_CHN_NDTR) = size / PCM_NATIVE_SAMPLE_SIZE;
|
||||||
|
reg_varl(dma1_ch0, DMA_CHN_M0AR) = (uintptr_t)addr;
|
||||||
|
reg_writelf(dma1_ch0, DMA_CHN_CR, EN(1));
|
||||||
|
|
||||||
|
pcm_play_dma_status_callback(PCM_DMAST_STARTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sai_init(void)
|
||||||
|
{
|
||||||
|
/* Enable SAI1 and DMA1 */
|
||||||
|
reg_writef(RCC_APB2ENR, SAI1EN(1));
|
||||||
|
reg_writef(RCC_AHB1ENR, DMA1EN(1));
|
||||||
|
|
||||||
|
/* Link DMA1_CH0 to SAI1A */
|
||||||
|
reg_writelf(dmamux1, DMAMUX_CR(0), DMAREQ_ID(DMAMUX1_REQ_SAI1A_DMA));
|
||||||
|
|
||||||
|
/* Configure DMA1 channel 0 */
|
||||||
|
reg_writelf(dma1_ch0, DMA_CHN_CR,
|
||||||
|
MBURST_V(INCR4), /* 32-bit x 4 burst = 16 bytes */
|
||||||
|
PBURST_V(INCR4), /* (16|32)-bit x 4 burst = 8-16 bytes */
|
||||||
|
TRBUFF(0), /* bufferable mode not used for SAI */
|
||||||
|
DBM(0), /* double buffer mode off */
|
||||||
|
PL_V(VERYHIGH), /* highest priority */
|
||||||
|
MSIZE_V(32BIT), /* read 32-bit words from memory */
|
||||||
|
PSIZE(DMA_PSIZE_VAL), /* set according to PCM bit depth */
|
||||||
|
MINC(1), /* increment memory address */
|
||||||
|
PINC(0), /* don't increment peripheral address */
|
||||||
|
CIRC(0), /* circular mode off */
|
||||||
|
DIR_V(MEM_TO_PERIPH), /* read from memory, write to SAI */
|
||||||
|
PFCTRL_V(DMA), /* DMA is flow controller */
|
||||||
|
TCIE(1), /* transfer complete interrupt */
|
||||||
|
TEIE(1), /* transfer error interrupt */
|
||||||
|
DMEIE(1)); /* direct mode error interrupt */
|
||||||
|
reg_writelf(dma1_ch0, DMA_CHN_FCR,
|
||||||
|
FEIE(1), /* fifo error interrupt */
|
||||||
|
DMDIS(1), /* enable fifo mode */
|
||||||
|
FTH_V(FULL)); /* fifo threshold = 4 words */
|
||||||
|
|
||||||
|
/* Set peripheral address here since it's constant */
|
||||||
|
reg_varl(dma1_ch0, DMA_CHN_PAR) =
|
||||||
|
(uintptr_t)reg_ptrl(sai1a, SAI_SUBBLOCK_DR);
|
||||||
|
|
||||||
|
/* Configure SAI for playback */
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_CR1,
|
||||||
|
OSR_V(256FS), /* MCLK is 256 x Fs */
|
||||||
|
NOMCK(0), /* MCLK enabled */
|
||||||
|
DMAEN(0), /* DMA request disabled */
|
||||||
|
SAIEN(0), /* SAI disabled */
|
||||||
|
OUTDRIV(0), /* drive outputs when SAIEN=1 */
|
||||||
|
MONO(0), /* stereo mode */
|
||||||
|
SYNCEN_V(ASYNC), /* no sync with other SAIs */
|
||||||
|
CKSTR_V(TX_FALLING_RX_RISING), /* clock edge for sampling */
|
||||||
|
LSBFIRST(0), /* transmit samples MSB first */
|
||||||
|
DS(SAI_DSIZE_VAL), /* sample size according to bit depth */
|
||||||
|
PRTCFG_V(FREE), /* free protocol */
|
||||||
|
MODE_V(MASTER_TX)); /* operate as bus master */
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_CR2,
|
||||||
|
MUTEVAL_V(ZERO_SAMPLE), /* send zero sample on mute */
|
||||||
|
MUTE(1), /* mute output initially */
|
||||||
|
TRIS(0), /* don't tri-state outputs */
|
||||||
|
FTH(SAI_FIFO_THRESH)); /* fifo threshold (2 or 4 samples) */
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_FRCR,
|
||||||
|
FSOFF(1), FSPOL(0), FSDEF(1), /* I2S format */
|
||||||
|
FSALL(SAI_FRL_VAL/2 - 1), /* FS active for half the frame */
|
||||||
|
FRL(SAI_FRL_VAL - 1)); /* set frame length */
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_SLOTR,
|
||||||
|
SLOTEN(3), NBSLOT(2 - 1), /* enable first two slots */
|
||||||
|
SLOTSZ_V(DATASZ), /* slot size = data size */
|
||||||
|
FBOFF(0)); /* no bit offset in slot */
|
||||||
|
|
||||||
|
/* Enable xrun error interrupt */
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_IM, OVRUDR(1));
|
||||||
|
|
||||||
|
/* Enable interrupts in NVIC */
|
||||||
|
nvic_enable_irq(NVIC_IRQN_DMA1_STR0);
|
||||||
|
nvic_enable_irq(NVIC_IRQN_SAI1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct div_settings
|
||||||
|
{
|
||||||
|
uint8_t pllm;
|
||||||
|
uint8_t plln;
|
||||||
|
uint8_t pllp;
|
||||||
|
uint8_t mckdiv;
|
||||||
|
};
|
||||||
|
|
||||||
|
_Static_assert(STM32_HSE_FREQ == 24000000,
|
||||||
|
"Audio clock settings only valid for 24MHz HSE");
|
||||||
|
|
||||||
|
static const struct div_settings div_settings[] = {
|
||||||
|
[HW_FREQ_96] = { .pllm = 5, .plln = 128 - 1, .pllp = 25 - 1, .mckdiv = 0 }, /* exact */
|
||||||
|
[HW_FREQ_48] = { .pllm = 5, .plln = 128 - 1, .pllp = 25 - 1, .mckdiv = 2 }, /* exact */
|
||||||
|
[HW_FREQ_24] = { .pllm = 5, .plln = 128 - 1, .pllp = 25 - 1, .mckdiv = 4 }, /* exact */
|
||||||
|
[HW_FREQ_12] = { .pllm = 5, .plln = 128 - 1, .pllp = 25 - 1, .mckdiv = 8 }, /* exact */
|
||||||
|
|
||||||
|
[HW_FREQ_88] = { .pllm = 4, .plln = 143 - 1, .pllp = 38 - 1, .mckdiv = 0 }, /* -11ppm error */
|
||||||
|
[HW_FREQ_44] = { .pllm = 4, .plln = 143 - 1, .pllp = 38 - 1, .mckdiv = 2 }, /* -11ppm error */
|
||||||
|
[HW_FREQ_22] = { .pllm = 5, .plln = 147 - 1, .pllp = 125 - 1, .mckdiv = 0 }, /* exact */
|
||||||
|
[HW_FREQ_11] = { .pllm = 5, .plln = 147 - 1, .pllp = 125 - 1, .mckdiv = 2 }, /* exact */
|
||||||
|
|
||||||
|
[HW_FREQ_64] = { .pllm = 15, .plln = 256 - 1, .pllp = 25 - 1, .mckdiv = 0 }, /* exact */
|
||||||
|
[HW_FREQ_32] = { .pllm = 15, .plln = 256 - 1, .pllp = 25 - 1, .mckdiv = 2 }, /* exact */
|
||||||
|
[HW_FREQ_16] = { .pllm = 15, .plln = 256 - 1, .pllp = 25 - 1, .mckdiv = 4 }, /* exact */
|
||||||
|
[HW_FREQ_8 ] = { .pllm = 15, .plln = 256 - 1, .pllp = 25 - 1, .mckdiv = 8 }, /* exact */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void sai_set_pll(const struct div_settings *div)
|
||||||
|
{
|
||||||
|
/* Disable the PLL so it can be reconfigured */
|
||||||
|
if (reg_readf(RCC_CR, PLL2RDY))
|
||||||
|
{
|
||||||
|
reg_writef(RCC_CR, PLL2ON(0));
|
||||||
|
while (reg_readf(RCC_CR, PLL2RDY));
|
||||||
|
while (reg_readf(RCC_CR, PLL2ON));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the PLL configuration */
|
||||||
|
uint32_t pllcfgr = reg_var(RCC_PLLCFGR);
|
||||||
|
|
||||||
|
reg_writef(RCC_PLLCKSELR,
|
||||||
|
DIVM2(div->pllm));
|
||||||
|
reg_writef(RCC_PLL2DIVR,
|
||||||
|
DIVN(div->plln),
|
||||||
|
DIVP(div->pllp),
|
||||||
|
DIVQ(0), DIVR(0));
|
||||||
|
reg_vwritef(pllcfgr, RCC_PLLCFGR,
|
||||||
|
DIVP2EN(1),
|
||||||
|
DIVQ2EN(0),
|
||||||
|
DIVR2EN(0),
|
||||||
|
PLL2FRACEN(0),
|
||||||
|
PLL2VCOSEL_V(WIDE));
|
||||||
|
|
||||||
|
if (div->pllm <= 6)
|
||||||
|
reg_vwritef(pllcfgr, RCC_PLLCFGR, PLL2RGE_V(4_8MHZ));
|
||||||
|
else if (div->pllm <= 12)
|
||||||
|
reg_vwritef(pllcfgr, RCC_PLLCFGR, PLL2RGE_V(2_4MHZ));
|
||||||
|
else
|
||||||
|
reg_vwritef(pllcfgr, RCC_PLLCFGR, PLL2RGE_V(1_2MHZ));
|
||||||
|
|
||||||
|
reg_var(RCC_PLLCFGR) = pllcfgr;
|
||||||
|
|
||||||
|
/* Enable the PLL again */
|
||||||
|
reg_writef(RCC_CR, PLL2ON(1));
|
||||||
|
while (!reg_readf(RCC_CR, PLL2RDY));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sai_set_frequency(int freq)
|
||||||
|
{
|
||||||
|
/* Can't change frequency while the SAI is active */
|
||||||
|
if (reg_readlf(sai1a, SAI_SUBBLOCK_CR1, SAIEN))
|
||||||
|
panicf("%s while SAI active", __func__);
|
||||||
|
|
||||||
|
const struct div_settings *div = &div_settings[freq];
|
||||||
|
const struct div_settings *old_div = NULL;
|
||||||
|
|
||||||
|
if (pcm_last_freq >= 0)
|
||||||
|
old_div = &div_settings[pcm_last_freq];
|
||||||
|
|
||||||
|
if (old_div == NULL ||
|
||||||
|
div->pllm != old_div->pllm ||
|
||||||
|
div->plln != old_div->plln ||
|
||||||
|
div->pllp != old_div->pllp)
|
||||||
|
{
|
||||||
|
sai_set_pll(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the MCK divider in SAI */
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_CR1, MCKDIV(div->mckdiv));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sink_dma_init(void)
|
||||||
|
{
|
||||||
|
sai_init();
|
||||||
|
audiohw_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sink_set_freq(uint16_t freq)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Muting here doesn't seem to help clicks when switching
|
||||||
|
* tracks of different frequencies; the audio may need to
|
||||||
|
* be soft-muted in software before the switch.
|
||||||
|
*/
|
||||||
|
audiohw_mute(true);
|
||||||
|
|
||||||
|
sai_set_frequency(freq);
|
||||||
|
pcm_last_freq = freq;
|
||||||
|
|
||||||
|
audiohw_mute(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sink_dma_start(const void *addr, size_t size)
|
||||||
|
{
|
||||||
|
play_active = true;
|
||||||
|
|
||||||
|
play_dma_start(addr, size);
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_CR1, SAIEN(1), DMAEN(1));
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_CR2, MUTE(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sink_dma_stop(void)
|
||||||
|
{
|
||||||
|
play_active = false;
|
||||||
|
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_CR2, MUTE(1));
|
||||||
|
reg_writelf(sai1a, SAI_SUBBLOCK_CR1, SAIEN(0), DMAEN(0));
|
||||||
|
reg_writelf(dma1_ch0, DMA_CHN_CR, EN(0));
|
||||||
|
|
||||||
|
/* Must wait for SAIEN bit to be cleared */
|
||||||
|
while (reg_readlf(sai1a, SAI_SUBBLOCK_CR1, SAIEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sink_lock(void)
|
||||||
|
{
|
||||||
|
/* Disable IRQ on first lock */
|
||||||
|
if (atomic_fetch_add_explicit(&play_lock, 1, memory_order_relaxed) == 0)
|
||||||
|
nvic_disable_irq_sync(NVIC_IRQN_DMA1_STR0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sink_unlock(void)
|
||||||
|
{
|
||||||
|
/* Enable IRQ on release of last lock */
|
||||||
|
if (atomic_fetch_sub_explicit(&play_lock, 1, memory_order_relaxed) == 1)
|
||||||
|
nvic_enable_irq(NVIC_IRQN_DMA1_STR0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pcm_sink builtin_pcm_sink = {
|
||||||
|
.caps = {
|
||||||
|
.samprs = hw_freq_sampr,
|
||||||
|
.num_samprs = HW_NUM_FREQ,
|
||||||
|
.default_freq = HW_FREQ_DEFAULT,
|
||||||
|
},
|
||||||
|
.ops = {
|
||||||
|
.init = sink_dma_init,
|
||||||
|
.postinit = audiohw_postinit,
|
||||||
|
.set_freq = sink_set_freq,
|
||||||
|
.lock = sink_lock,
|
||||||
|
.unlock = sink_unlock,
|
||||||
|
.play = sink_dma_start,
|
||||||
|
.stop = sink_dma_stop,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void dma1_ch0_irq_handler(void)
|
||||||
|
{
|
||||||
|
uint32_t lisr = reg_varl(dma1, DMA_LISR);
|
||||||
|
const void *addr;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (reg_vreadf(lisr, DMA_LISR, TEIF0))
|
||||||
|
pcm_dma_teif_count++;
|
||||||
|
|
||||||
|
if (reg_vreadf(lisr, DMA_LISR, DMEIF0))
|
||||||
|
pcm_dma_dmeif_count++;
|
||||||
|
|
||||||
|
if (reg_vreadf(lisr, DMA_LISR, FEIF0))
|
||||||
|
pcm_dma_feif_count++;
|
||||||
|
|
||||||
|
if (reg_vreadf(lisr, DMA_LISR, TEIF0) ||
|
||||||
|
reg_vreadf(lisr, DMA_LISR, DMEIF0) ||
|
||||||
|
reg_vreadf(lisr, DMA_LISR, FEIF0))
|
||||||
|
{
|
||||||
|
reg_assignlf(dma1, DMA_LIFCR, TEIF0(1), DMEIF0(1), FEIF0(1));
|
||||||
|
reg_writelf(dma1_ch0, DMA_CHN_CR, EN(0));
|
||||||
|
|
||||||
|
pcm_play_dma_status_callback(PCM_DMAST_ERR_DMA);
|
||||||
|
}
|
||||||
|
else if (reg_vreadf(lisr, DMA_LISR, TCIF0))
|
||||||
|
{
|
||||||
|
reg_assignlf(dma1, DMA_LIFCR, TCIF0(1));
|
||||||
|
|
||||||
|
/* If we call the complete callback while not playing
|
||||||
|
* it can cause the PCM layer to get stuck... somehow */
|
||||||
|
if (!play_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pcm_play_dma_complete_callback(PCM_DMAST_OK, &addr, &size))
|
||||||
|
play_dma_start(addr, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
panicf("%s: %08lx", __func__, lisr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sai1_irq_handler(void)
|
||||||
|
{
|
||||||
|
if (reg_readlf(sai1a, SAI_SUBBLOCK_SR, OVRUDR))
|
||||||
|
{
|
||||||
|
reg_assignlf(sai1a, SAI_SUBBLOCK_CLRFR, OVRUDR(1));
|
||||||
|
pcm_sai_xrun_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
* __________ __ ___.
|
|
||||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
||||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
||||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
||||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
||||||
* \/ \/ \/ \/ \/
|
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* Copyright (C) 2025 Aidan MacDonald
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
||||||
* KIND, either express or implied.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
#include "pcm.h"
|
|
||||||
#include "pcm-internal.h"
|
|
||||||
#include "pcm_sampr.h"
|
|
||||||
#include "pcm_sink.h"
|
|
||||||
|
|
||||||
static void sink_set_freq(uint16_t freq)
|
|
||||||
{
|
|
||||||
(void)freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sink_dma_init(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sink_dma_postinit(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sink_dma_start(const void *addr, size_t size)
|
|
||||||
{
|
|
||||||
(void)addr;
|
|
||||||
(void)size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sink_dma_stop(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sink_lock(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sink_unlock(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pcm_sink builtin_pcm_sink = {
|
|
||||||
.caps = {
|
|
||||||
.samprs = hw_freq_sampr,
|
|
||||||
.num_samprs = HW_NUM_FREQ,
|
|
||||||
.default_freq = HW_FREQ_DEFAULT,
|
|
||||||
},
|
|
||||||
.ops = {
|
|
||||||
.init = sink_dma_init,
|
|
||||||
.postinit = sink_dma_postinit,
|
|
||||||
.set_freq = sink_set_freq,
|
|
||||||
.lock = sink_lock,
|
|
||||||
.unlock = sink_unlock,
|
|
||||||
.play = sink_dma_start,
|
|
||||||
.stop = sink_dma_stop,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_RECORDING
|
|
||||||
void pcm_rec_dma_init(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcm_rec_dma_close(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcm_rec_dma_start(void *addr, size_t size)
|
|
||||||
{
|
|
||||||
(void)addr;
|
|
||||||
(void)size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcm_rec_dma_stop(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcm_rec_lock(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcm_rec_unlock(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const void *pcm_rec_dma_get_peak_buffer(void)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -493,7 +493,6 @@ static void set_playback_sampling_frequency(unsigned long f)
|
||||||
hw_freq_sampr[as_playback_freq_idx], f);
|
hw_freq_sampr[as_playback_freq_idx], f);
|
||||||
|
|
||||||
mixer_set_frequency(hw_freq_sampr[as_playback_freq_idx]);
|
mixer_set_frequency(hw_freq_sampr[as_playback_freq_idx]);
|
||||||
pcm_apply_settings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long usb_audio_get_playback_sampling_frequency(void)
|
unsigned long usb_audio_get_playback_sampling_frequency(void)
|
||||||
|
|
@ -706,7 +705,6 @@ static void usb_audio_start_playback(void)
|
||||||
#endif
|
#endif
|
||||||
logf("usbaudio: start playback at %lu Hz", hw_freq_sampr[as_playback_freq_idx]);
|
logf("usbaudio: start playback at %lu Hz", hw_freq_sampr[as_playback_freq_idx]);
|
||||||
mixer_set_frequency(hw_freq_sampr[as_playback_freq_idx]);
|
mixer_set_frequency(hw_freq_sampr[as_playback_freq_idx]);
|
||||||
pcm_apply_settings();
|
|
||||||
mixer_channel_set_amplitude(PCM_MIXER_CHAN_USBAUDIO, MIX_AMP_UNITY);
|
mixer_channel_set_amplitude(PCM_MIXER_CHAN_USBAUDIO, MIX_AMP_UNITY);
|
||||||
|
|
||||||
usb_drv_recv_nonblocking(EP_ISO_OUT, rx_buffer, BUFFER_SIZE);
|
usb_drv_recv_nonblocking(EP_ISO_OUT, rx_buffer, BUFFER_SIZE);
|
||||||
|
|
@ -787,7 +785,7 @@ int usb_audio_get_alt_intf(void)
|
||||||
{
|
{
|
||||||
return usb_as_playback_intf_alt;
|
return usb_as_playback_intf_alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t usb_audio_get_samplesperframe(void)
|
int32_t usb_audio_get_samplesperframe(void)
|
||||||
{
|
{
|
||||||
return samples_fb;
|
return samples_fb;
|
||||||
|
|
@ -1348,7 +1346,7 @@ bool usb_audio_fast_transfer_complete(int ep, int dir, int status, int length)
|
||||||
{
|
{
|
||||||
retval = false;
|
retval = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send feedback value every N frames!
|
// send feedback value every N frames!
|
||||||
// NOTE: important that we need to queue this up _the frame before_ it's needed - on MacOS especially!
|
// NOTE: important that we need to queue this up _the frame before_ it's needed - on MacOS especially!
|
||||||
if ((usb_drv_get_frame_number()+1) % FEEDBACK_UPDATE_RATE_FRAMES == 0 && send_fb)
|
if ((usb_drv_get_frame_number()+1) % FEEDBACK_UPDATE_RATE_FRAMES == 0 && send_fb)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue