mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-05-12 11:43:16 -04:00
Compare commits
24 commits
e923b354a6
...
0e7718ed4e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e7718ed4e | ||
|
|
a2f652cf1f | ||
|
|
6be230275e | ||
|
|
c5b171da41 | ||
|
|
65f2105445 | ||
|
|
78ba3211be | ||
|
|
96b5642c93 | ||
|
|
e677895e29 | ||
|
|
f235443ba1 | ||
|
|
03060090c9 | ||
|
|
f84003fa40 | ||
|
|
d2b76a99f3 | ||
|
|
3f4d5a527b | ||
|
|
42ad3c75d2 | ||
|
|
36f34089d6 | ||
|
|
5ce96b84d8 | ||
|
|
a84a38dd87 | ||
|
|
daef425c59 | ||
|
|
759ef2767a | ||
|
|
ae724ba5f3 | ||
|
|
9b207bfb91 | ||
|
|
da53cc0f14 | ||
|
|
2578411f00 | ||
|
|
9c708e3876 |
27 changed files with 8145 additions and 1436 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -13142,20 +13142,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_CLEAR_ALL_RESUMES
|
id: LANG_CLEAR_ALL_RESUMES
|
||||||
desc: in the mpegplayer settings menu
|
desc: in the mpegplayer settings menu
|
||||||
|
|
@ -14389,7 +14375,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."
|
||||||
|
|
@ -14404,7 +14390,7 @@
|
||||||
</source>
|
</source>
|
||||||
<dest>
|
<dest>
|
||||||
*: "Нажмите ВЛЕВО для отмены."
|
*: "Нажмите ВЛЕВО для отмены."
|
||||||
android,hifietma*,zenvision: "Нажмите НАЗАД для отмены."
|
android,hifietma*: "Нажмите НАЗАД для отмены."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Нажмите ВКЛ. для отмены."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Нажмите ВКЛ. для отмены."
|
||||||
ihifi760,ihifi960: "Дважды нажмите ВОЗВРАТ для отмены."
|
ihifi760,ihifi960: "Дважды нажмите ВОЗВРАТ для отмены."
|
||||||
ihifi770,ihifi770c,ihifi800: "Нажмите ДОМОЙ для отмены."
|
ihifi770,ihifi770c,ihifi800: "Нажмите ДОМОЙ для отмены."
|
||||||
|
|
@ -14419,7 +14405,7 @@
|
||||||
</dest>
|
</dest>
|
||||||
<voice>
|
<voice>
|
||||||
*: "Нажмите кнопку Влево для отмены."
|
*: "Нажмите кнопку Влево для отмены."
|
||||||
android,hifietma*,zenvision: "Нажмите кнопку Назад для отмены."
|
android,hifietma*: "Нажмите кнопку Назад для отмены."
|
||||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Нажмите кнопку включения для отмены."
|
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Нажмите кнопку включения для отмены."
|
||||||
ihifi760,ihifi960: "Дважды нажмите кнопку Назад для отмены."
|
ihifi760,ihifi960: "Дважды нажмите кнопку Назад для отмены."
|
||||||
ihifi770,ihifi770c,ihifi800: "Нажмите кнопку Домой для отмены."
|
ihifi770,ihifi770c,ihifi800: "Нажмите кнопку Домой для отмены."
|
||||||
|
|
@ -15790,13 +15776,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>
|
||||||
*: ""
|
*: ""
|
||||||
|
|
@ -15872,20 +15858,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
|
||||||
|
|
@ -16138,34 +16110,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>
|
|
||||||
*: "Меню Chessbox"
|
|
||||||
</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
|
||||||
|
|
@ -16999,3 +16943,48 @@
|
||||||
*: "Все трэки сортируются по альбому"
|
*: "Все трэки сортируются по альбому"
|
||||||
</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: "Использовать LED индикаторы"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: none
|
||||||
|
general_purpose_led: "Использовать 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>
|
||||||
|
|
|
||||||
14
apps/misc.c
14
apps/misc.c
|
|
@ -866,20 +866,10 @@ void check_bootfile(bool do_rolo)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check range, set volume and save settings */
|
/* set volume and save settings */
|
||||||
void setvol(void)
|
void setvol(void)
|
||||||
{
|
{
|
||||||
const int min_vol = sound_min(SOUND_VOLUME);
|
sound_set_volume(global_status.volume);
|
||||||
const int max_vol = sound_max(SOUND_VOLUME);
|
|
||||||
int volume = global_status.volume;
|
|
||||||
if (volume < min_vol)
|
|
||||||
volume = min_vol;
|
|
||||||
if (volume > max_vol)
|
|
||||||
volume = max_vol;
|
|
||||||
if (volume > global_settings.volume_limit)
|
|
||||||
volume = global_settings.volume_limit;
|
|
||||||
|
|
||||||
sound_set_volume(volume);
|
|
||||||
global_status.last_volume_change = current_tick;
|
global_status.last_volume_change = current_tick;
|
||||||
status_save(false);
|
status_save(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,13 @@
|
||||||
.Trashes/: no
|
.Trashes/: no
|
||||||
.Spotlight-V100/: no
|
.Spotlight-V100/: no
|
||||||
.DS_Store: no
|
.DS_Store: no
|
||||||
|
__MACOSX/: no
|
||||||
._*: no
|
._*: no
|
||||||
< Linux/BSD >: no
|
< Linux/BSD >: no
|
||||||
.Trash-*/: no
|
.Trash-*/: no
|
||||||
.dolphinview: no
|
.dolphinview: no
|
||||||
.d3lphinview: no
|
.d3lphinview: no
|
||||||
|
< Android >: no
|
||||||
|
Android/: no
|
||||||
|
LOST.DIR/: no
|
||||||
< Other >: no
|
< Other >: no
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,8 @@
|
||||||
|
|
||||||
struct MIDIfile * mf IBSS_ATTR;
|
struct MIDIfile * mf IBSS_ATTR;
|
||||||
|
|
||||||
|
int sample_rate IBSS_ATTR;
|
||||||
|
int max_voices IBSS_ATTR;
|
||||||
int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */
|
int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */
|
||||||
int playing_time IBSS_ATTR; /* How many seconds into the file have we been playing? */
|
int playing_time IBSS_ATTR; /* How many seconds into the file have we been playing? */
|
||||||
int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */
|
int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */
|
||||||
|
|
@ -490,11 +492,56 @@ static void get_more(const void** start, size_t* size)
|
||||||
*size = samples_in_buf*sizeof(int32_t);
|
*size = samples_in_buf*sizeof(int32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNUSED_ATTR static int find_min_sampr_ge_22(void)
|
||||||
|
{
|
||||||
|
const struct pcm_sink_caps* caps = rb->pcm_current_sink_caps();
|
||||||
|
int ret = caps->samprs[0];
|
||||||
|
for (size_t i = 1; i < caps->num_samprs; i += 1)
|
||||||
|
{
|
||||||
|
/* caps->samprs is in descending order */
|
||||||
|
if (caps->samprs[i] >= SAMPR_22)
|
||||||
|
ret = caps->samprs[i];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int midimain(const void * filename)
|
static int midimain(const void * filename)
|
||||||
{
|
{
|
||||||
int a, notes_used, vol;
|
int a, notes_used, vol;
|
||||||
bool is_playing = true; /* false = paused */
|
bool is_playing = true; /* false = paused */
|
||||||
|
|
||||||
|
/* decide sample_rate and max_voices */
|
||||||
|
#if defined(SIMULATOR) /* Simulator requires 44100Hz, and we can afford to use more voices */ || \
|
||||||
|
(CONFIG_PLATFORM & PLATFORM_HOSTED) /* All hosted targets have CPU to spare */ || \
|
||||||
|
defined(CPU_MIPS) /* All MIPS targets are pretty fast */
|
||||||
|
sample_rate = SAMPR_44;
|
||||||
|
max_voices = 48;
|
||||||
|
#elif defined(CPU_PP)
|
||||||
|
/* Some of the pp based targets can't handle too many voices
|
||||||
|
mainly because they have to use 44100Hz sample rate, this could be
|
||||||
|
improved to increase max_voices for targets that can do 22kHz */
|
||||||
|
sample_rate = find_min_sampr_ge_22();
|
||||||
|
max_voices = sample_rate == SAMPR_22 ? 24 : 16;
|
||||||
|
#elif defined(CPU_ARM)
|
||||||
|
/* ARMv4 targets are slow, but treat everything else as fast */
|
||||||
|
#if (ARM_ARCH >= 6)
|
||||||
|
sample_rate = SAMPR_44;
|
||||||
|
max_voices = 32;
|
||||||
|
#elif (ARM_ARCH >= 5)
|
||||||
|
sample_rate = find_min_sampr_ge_22();
|
||||||
|
max_voices = 32;
|
||||||
|
#else /* ie v4 */
|
||||||
|
sample_rate = find_min_sampr_ge_22();
|
||||||
|
max_voices = sample_rate == SAMPR_22 ? 24 : 16;
|
||||||
|
#endif
|
||||||
|
#else /* !CPU_ARM */
|
||||||
|
/* Treat everything else as slow */
|
||||||
|
sample_rate = find_min_sampr_ge_22();
|
||||||
|
max_voices = sample_rate == SAMPR_22 ? 24 : 16;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
|
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
|
||||||
rb->cpu_boost(true);
|
rb->cpu_boost(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -537,7 +584,7 @@ static int midimain(const void * filename)
|
||||||
rb->dsp_set_timestretch(PITCH_SPEED_100);
|
rb->dsp_set_timestretch(PITCH_SPEED_100);
|
||||||
#endif
|
#endif
|
||||||
rb->dsp_configure(dsp, DSP_SET_SAMPLE_DEPTH, 22);
|
rb->dsp_configure(dsp, DSP_SET_SAMPLE_DEPTH, 22);
|
||||||
rb->dsp_configure(dsp, DSP_SET_FREQUENCY, SAMPLE_RATE); /* 44100 22050 11025 */
|
rb->dsp_configure(dsp, DSP_SET_FREQUENCY, sample_rate); /* 44100 22050 11025 */
|
||||||
rb->dsp_configure(dsp, DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
|
rb->dsp_configure(dsp, DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -553,14 +600,14 @@ static int midimain(const void * filename)
|
||||||
midi_debug("Okay, starting sequencing");
|
midi_debug("Okay, starting sequencing");
|
||||||
|
|
||||||
bpm = mf->div*1000000/tempo;
|
bpm = mf->div*1000000/tempo;
|
||||||
number_of_samples = SAMPLE_RATE/bpm;
|
number_of_samples = sample_rate/bpm;
|
||||||
|
|
||||||
/* Skip over any junk in the beginning of the file, so start playing */
|
/* Skip over any junk in the beginning of the file, so start playing */
|
||||||
/* after the first note event */
|
/* after the first note event */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
notes_used = 0;
|
notes_used = 0;
|
||||||
for (a = 0; a < MAX_VOICES; a++)
|
for (a = 0; a < max_voices; a++)
|
||||||
if (voices[a].isUsed)
|
if (voices[a].isUsed)
|
||||||
notes_used++;
|
notes_used++;
|
||||||
tick();
|
tick();
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ struct GPatch * gusload(char *);
|
||||||
struct GPatch * patchSet[128];
|
struct GPatch * patchSet[128];
|
||||||
struct GPatch * drumSet[128];
|
struct GPatch * drumSet[128];
|
||||||
|
|
||||||
struct SynthObject voices[MAX_VOICES] IBSS_ATTR;
|
struct SynthObject voices[48] IBSS_ATTR;
|
||||||
|
|
||||||
static void *alloc(int size)
|
static void *alloc(int size)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,67 +27,6 @@
|
||||||
#define NBUF 2
|
#define NBUF 2
|
||||||
#define MAX_SAMPLES 512
|
#define MAX_SAMPLES 512
|
||||||
|
|
||||||
#ifdef SIMULATOR
|
|
||||||
|
|
||||||
/* Simulator requires 44100Hz, and we can afford to use more voices */
|
|
||||||
#define SAMPLE_RATE SAMPR_44
|
|
||||||
#define MAX_VOICES 48
|
|
||||||
|
|
||||||
#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
|
|
||||||
|
|
||||||
/* All hosted targets have CPU to spare */
|
|
||||||
#define MAX_VOICES 48
|
|
||||||
#define SAMPLE_RATE SAMPR_44
|
|
||||||
|
|
||||||
#elif defined(CPU_PP)
|
|
||||||
|
|
||||||
/* Some of the pp based targets can't handle too many voices
|
|
||||||
mainly because they have to use 44100Hz sample rate, this could be
|
|
||||||
improved to increase MAX_VOICES for targets that can do 22kHz */
|
|
||||||
#define SAMPLE_RATE HW_SAMPR_MIN_GE_22
|
|
||||||
#if HW_SAMPR_CAPS & SAMPR_CAP_22
|
|
||||||
#define MAX_VOICES 24 /* General MIDI minimum */
|
|
||||||
#else
|
|
||||||
#define MAX_VOICES 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(CPU_MIPS)
|
|
||||||
|
|
||||||
/* All MIPS targets are pretty fast */
|
|
||||||
#define MAX_VOICES 48
|
|
||||||
#define SAMPLE_RATE SAMPR_44
|
|
||||||
|
|
||||||
#elif defined(CPU_ARM)
|
|
||||||
|
|
||||||
/* ARMv4 targets are slow, but treat everything else as fast */
|
|
||||||
|
|
||||||
#if (ARM_ARCH >= 6)
|
|
||||||
#define MAX_VOICES 32
|
|
||||||
#define SAMPLE_RATE SAMPR_44
|
|
||||||
#elif (ARM_ARCH >= 5)
|
|
||||||
#define MAX_VOICES 32
|
|
||||||
#define SAMPLE_RATE HW_SAMPR_MIN_GE_22
|
|
||||||
#else /* ie v4 */
|
|
||||||
#define SAMPLE_RATE HW_SAMPR_MIN_GE_22
|
|
||||||
#if HW_SAMPR_CAPS & SAMPR_CAP_22
|
|
||||||
#define MAX_VOICES 24 /* General MIDI minimum */
|
|
||||||
#else
|
|
||||||
#define MAX_VOICES 16
|
|
||||||
#endif
|
|
||||||
#endif /* ARM_ARCH < 5*/
|
|
||||||
|
|
||||||
#else /* !CPU_ARM */
|
|
||||||
|
|
||||||
/* Treat everything else as slow */
|
|
||||||
#define SAMPLE_RATE HW_SAMPR_MIN_GE_22
|
|
||||||
#if HW_SAMPR_CAPS & SAMPR_CAP_22
|
|
||||||
#define MAX_VOICES 24 /* General MIDI minimum */
|
|
||||||
#else
|
|
||||||
#define MAX_VOICES 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* Wrap it up. */
|
|
||||||
|
|
||||||
#define BYTE unsigned char
|
#define BYTE unsigned char
|
||||||
|
|
||||||
/* Data chunk ID types, returned by readID() */
|
/* Data chunk ID types, returned by readID() */
|
||||||
|
|
@ -189,7 +128,7 @@ void * readData(int file, int len);
|
||||||
#define malloc(n) my_malloc(n)
|
#define malloc(n) my_malloc(n)
|
||||||
void * my_malloc(int size);
|
void * my_malloc(int size);
|
||||||
|
|
||||||
extern struct SynthObject voices[MAX_VOICES];
|
extern struct SynthObject voices[48]; /* 48: maximum possible max_voices */
|
||||||
|
|
||||||
extern int chVol[16]; /* Channel volume */
|
extern int chVol[16]; /* Channel volume */
|
||||||
extern int chPan[16]; /* Channel panning */
|
extern int chPan[16]; /* Channel panning */
|
||||||
|
|
@ -207,6 +146,8 @@ extern struct GPatch * drumSet[128];
|
||||||
|
|
||||||
extern struct MIDIfile * mf;
|
extern struct MIDIfile * mf;
|
||||||
|
|
||||||
|
extern int sample_rate;
|
||||||
|
extern int max_voices;
|
||||||
extern int number_of_samples;
|
extern int number_of_samples;
|
||||||
extern int playing_time IBSS_ATTR;
|
extern int playing_time IBSS_ATTR;
|
||||||
extern int samples_this_second IBSS_ATTR;
|
extern int samples_this_second IBSS_ATTR;
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ static inline void setVol(int ch, int vol)
|
||||||
|
|
||||||
/* If channel volume changes, we need to recalculate the volume scale */
|
/* If channel volume changes, we need to recalculate the volume scale */
|
||||||
/* factor for all voices active on this channel */
|
/* factor for all voices active on this channel */
|
||||||
for (a = 0; a < MAX_VOICES; a++)
|
for (a = 0; a < max_voices; a++)
|
||||||
if (voices[a].ch == ch)
|
if (voices[a].ch == ch)
|
||||||
setVolScale(a);
|
setVolScale(a);
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +156,7 @@ static void findDelta(struct SynthObject * so, int ch, int note)
|
||||||
delta = (((freqtable[note+chPBNoteOffset[ch]]))); /* anywhere from 8000 to 8000000 */
|
delta = (((freqtable[note+chPBNoteOffset[ch]]))); /* anywhere from 8000 to 8000000 */
|
||||||
delta = delta * wf->sampRate; /* approx 20000 - 44000 but can vary with tuning */
|
delta = delta * wf->sampRate; /* approx 20000 - 44000 but can vary with tuning */
|
||||||
delta = (delta * chPBFractBend[ch]); /* approx 60000 - 70000 */
|
delta = (delta * chPBFractBend[ch]); /* approx 60000 - 70000 */
|
||||||
delta = delta / (SAMPLE_RATE); /* 44100 or 22050 */
|
delta = delta / (sample_rate); /* 44100 or 22050 */
|
||||||
delta = delta / (wf->rootFreq); /* anywhere from 8000 to 8000000 */
|
delta = delta / (wf->rootFreq); /* anywhere from 8000 to 8000000 */
|
||||||
|
|
||||||
/* Pitch bend is encoded as a fractional of 16 bits, hence the 16 */
|
/* Pitch bend is encoded as a fractional of 16 bits, hence the 16 */
|
||||||
|
|
@ -167,7 +167,7 @@ static void findDelta(struct SynthObject * so, int ch, int note)
|
||||||
static inline void computeDeltas(int ch)
|
static inline void computeDeltas(int ch)
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
for (a = 0; a < MAX_VOICES; a++)
|
for (a = 0; a < max_voices; a++)
|
||||||
{
|
{
|
||||||
if (voices[a].isUsed && voices[a].ch == ch)
|
if (voices[a].isUsed && voices[a].ch == ch)
|
||||||
{
|
{
|
||||||
|
|
@ -210,7 +210,7 @@ static inline void pressNote(int ch, int note, int vol)
|
||||||
if(ch == 15) return;
|
if(ch == 15) return;
|
||||||
*/
|
*/
|
||||||
int a;
|
int a;
|
||||||
for (a = 0; a < MAX_VOICES; a++)
|
for (a = 0; a < max_voices; a++)
|
||||||
{
|
{
|
||||||
if (voices[a].ch == ch && voices[a].note == note)
|
if (voices[a].ch == ch && voices[a].note == note)
|
||||||
break;
|
break;
|
||||||
|
|
@ -218,7 +218,7 @@ static inline void pressNote(int ch, int note, int vol)
|
||||||
if (!voices[a].isUsed)
|
if (!voices[a].isUsed)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (a == MAX_VOICES)
|
if (a == max_voices)
|
||||||
{
|
{
|
||||||
// midi_debug("\nVoice kill");
|
// midi_debug("\nVoice kill");
|
||||||
// midi_debug("\nToo many voices playing at once. No more left");
|
// midi_debug("\nToo many voices playing at once. No more left");
|
||||||
|
|
@ -226,7 +226,7 @@ static inline void pressNote(int ch, int note, int vol)
|
||||||
// for(a=0; a<48; a++)
|
// for(a=0; a<48; a++)
|
||||||
// midi_debug("\n#%d Ch=%d Note=%d curRate=%d curOffset=%d curPoint=%d targetOffset=%d", a, voices[a].ch, voices[a].note, voices[a].curRate, voices[a].curOffset, voices[a].curPoint, voices[a].targetOffset);
|
// midi_debug("\n#%d Ch=%d Note=%d curRate=%d curOffset=%d curPoint=%d targetOffset=%d", a, voices[a].ch, voices[a].note, voices[a].curRate, voices[a].curOffset, voices[a].curPoint, voices[a].targetOffset);
|
||||||
lastKill++;
|
lastKill++;
|
||||||
if (lastKill == MAX_VOICES)
|
if (lastKill == max_voices)
|
||||||
lastKill = 0;
|
lastKill = 0;
|
||||||
a = lastKill;
|
a = lastKill;
|
||||||
// return; /* None available */
|
// return; /* None available */
|
||||||
|
|
@ -263,7 +263,7 @@ static inline void pressNote(int ch, int note, int vol)
|
||||||
|
|
||||||
struct GWaveform * wf = drumSet[note]->waveforms[0];
|
struct GWaveform * wf = drumSet[note]->waveforms[0];
|
||||||
voices[a].wf = wf;
|
voices[a].wf = wf;
|
||||||
voices[a].delta = (((freqtable[note]<<FRACTSIZE) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
|
voices[a].delta = (((freqtable[note]<<FRACTSIZE) / wf->rootFreq) * wf->sampRate / sample_rate);
|
||||||
if (wf->mode & 28)
|
if (wf->mode & 28)
|
||||||
// midi_debug("\nWoah, a drum patch has a loop. Stripping the loop...");
|
// midi_debug("\nWoah, a drum patch has a loop. Stripping the loop...");
|
||||||
wf->mode = wf->mode & (255-28);
|
wf->mode = wf->mode & (255-28);
|
||||||
|
|
@ -285,7 +285,7 @@ static void releaseNote(int ch, int note)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int a;
|
int a;
|
||||||
for (a = 0; a < MAX_VOICES; a++)
|
for (a = 0; a < max_voices; a++)
|
||||||
{
|
{
|
||||||
if (voices[a].ch == ch && voices[a].note == note)
|
if (voices[a].ch == ch && voices[a].note == note)
|
||||||
{
|
{
|
||||||
|
|
@ -432,7 +432,7 @@ int tick(void)
|
||||||
tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
|
tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
|
||||||
/* midi_debug("\nMeta-Event: Tempo Set = %d", tempo); */
|
/* midi_debug("\nMeta-Event: Tempo Set = %d", tempo); */
|
||||||
bpm=mf->div*1000000/tempo;
|
bpm=mf->div*1000000/tempo;
|
||||||
number_of_samples=SAMPLE_RATE/bpm;
|
number_of_samples=sample_rate/bpm;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -446,9 +446,9 @@ int tick(void)
|
||||||
|
|
||||||
samples_this_second += number_of_samples;
|
samples_this_second += number_of_samples;
|
||||||
|
|
||||||
while (samples_this_second >= SAMPLE_RATE)
|
while (samples_this_second >= sample_rate)
|
||||||
{
|
{
|
||||||
samples_this_second -= SAMPLE_RATE;
|
samples_this_second -= sample_rate;
|
||||||
playing_time++;
|
playing_time++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +471,7 @@ void seekBackward(int nsec)
|
||||||
|
|
||||||
/* Set the tempo to defalt */
|
/* Set the tempo to defalt */
|
||||||
bpm = mf->div*1000000/tempo;
|
bpm = mf->div*1000000/tempo;
|
||||||
number_of_samples = SAMPLE_RATE/bpm;
|
number_of_samples = sample_rate/bpm;
|
||||||
|
|
||||||
/* Reset the tracks to start */
|
/* Reset the tracks to start */
|
||||||
rewindFile();
|
rewindFile();
|
||||||
|
|
@ -484,7 +484,7 @@ void seekBackward(int nsec)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
notes_used = 0;
|
notes_used = 0;
|
||||||
for (a = 0; a < MAX_VOICES; a++)
|
for (a = 0; a < max_voices; a++)
|
||||||
if (voices[a].isUsed)
|
if (voices[a].isUsed)
|
||||||
notes_used++;
|
notes_used++;
|
||||||
tick();
|
tick();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ static void readTextBlock(int file, char * buf)
|
||||||
void resetControllers()
|
void resetControllers()
|
||||||
{
|
{
|
||||||
int a=0;
|
int a=0;
|
||||||
for(a=0; a<MAX_VOICES; a++)
|
for(a=0; a<max_voices; a++)
|
||||||
{
|
{
|
||||||
voices[a].cp=0;
|
voices[a].cp=0;
|
||||||
voices[a].vol=0;
|
voices[a].vol=0;
|
||||||
|
|
@ -448,13 +448,13 @@ static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned i
|
||||||
size_t synthSamples(int32_t *buf_ptr, size_t num_samples) ICODE_ATTR;
|
size_t synthSamples(int32_t *buf_ptr, size_t num_samples) ICODE_ATTR;
|
||||||
size_t synthSamples(int32_t *buf_ptr, size_t num_samples)
|
size_t synthSamples(int32_t *buf_ptr, size_t num_samples)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
int i;
|
||||||
struct SynthObject *voicept;
|
struct SynthObject *voicept;
|
||||||
size_t nsamples = MIN(num_samples, MAX_SAMPLES);
|
size_t nsamples = MIN(num_samples, MAX_SAMPLES);
|
||||||
|
|
||||||
rb->memset(buf_ptr, 0, nsamples * 2 * sizeof(int32_t));
|
rb->memset(buf_ptr, 0, nsamples * 2 * sizeof(int32_t));
|
||||||
|
|
||||||
for(i=0; i < MAX_VOICES; i++)
|
for(i=0; i < max_voices; i++)
|
||||||
{
|
{
|
||||||
voicept=&voices[i];
|
voicept=&voices[i];
|
||||||
if(voicept->isUsed)
|
if(voicept->isUsed)
|
||||||
|
|
|
||||||
|
|
@ -395,19 +395,19 @@ static void start_sound(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get the closest rate >= to what is preferred */
|
/* Get the closest rate >= to what is preferred */
|
||||||
|
const struct pcm_sink_caps* caps = rb->pcm_current_sink_caps();
|
||||||
sr_index = rb->round_value_to_list32(PREFERRED_SAMPLING_RATE,
|
sr_index = rb->round_value_to_list32(PREFERRED_SAMPLING_RATE,
|
||||||
rb->hw_freq_sampr, HW_NUM_FREQ, false);
|
caps->samprs, caps->num_samprs, false);
|
||||||
|
|
||||||
if (rb->hw_freq_sampr[sr_index] < PREFERRED_SAMPLING_RATE
|
if (caps->samprs[sr_index] < PREFERRED_SAMPLING_RATE && sr_index > 0)
|
||||||
&& sr_index > 0)
|
|
||||||
{
|
{
|
||||||
/* Round up */
|
/* Round up */
|
||||||
sr_index--;
|
sr_index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
wsg3_set_sampling_rate(rb->hw_freq_sampr[sr_index]);
|
wsg3_set_sampling_rate(caps->samprs[sr_index]);
|
||||||
|
|
||||||
rb->mixer_set_frequency(rb->hw_freq_sampr[sr_index]);
|
rb->mixer_set_frequency(caps->samprs[sr_index]);
|
||||||
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
|
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
|
||||||
|
|
||||||
sound_playing = true;
|
sound_playing = true;
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,26 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
/* Set audio API. */
|
/* Set audio API. */
|
||||||
sys_set_audio_api(API_ROCKBOX);
|
sys_set_audio_api(API_ROCKBOX);
|
||||||
|
|
||||||
|
/* Determine sample rate. */
|
||||||
|
#if defined(SIMULATOR)
|
||||||
|
#define PREFERRED_SAMPR SAMPR_44
|
||||||
|
#else
|
||||||
|
#define PREFERRED_SAMPR SAMPR_22
|
||||||
|
#endif
|
||||||
|
int samplerate;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const struct pcm_sink_caps* caps = rb->pcm_current_sink_caps();
|
||||||
|
for (i = 0; i < caps->num_samprs; i++) {
|
||||||
|
if (caps->samprs[i] == PREFERRED_SAMPR)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == caps->num_samprs)
|
||||||
|
samplerate = SAMPR_44;
|
||||||
|
else
|
||||||
|
samplerate = caps->samprs[i];
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize audio subsystem. */
|
/* Initialize audio subsystem. */
|
||||||
sys_open_audio(0, /* No sound input yet */
|
sys_open_audio(0, /* No sound input yet */
|
||||||
sys_soundindevlist,
|
sys_soundindevlist,
|
||||||
|
|
@ -197,7 +217,7 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
sys_soundoutdevlist,
|
sys_soundoutdevlist,
|
||||||
-1, /* Use the default amount (2) of channels */
|
-1, /* Use the default amount (2) of channels */
|
||||||
sys_choutlist,
|
sys_choutlist,
|
||||||
PD_SAMPLERATE, /* Sample rate */
|
samplerate, /* Sample rate */
|
||||||
DEFAULTADVANCE, /* Scheduler advance */
|
DEFAULTADVANCE, /* Scheduler advance */
|
||||||
1 /* Enable */);
|
1 /* Enable */);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,17 +40,9 @@
|
||||||
#define calloc(elements, elem_size) tlsf_calloc(elements, elem_size)
|
#define calloc(elements, elem_size) tlsf_calloc(elements, elem_size)
|
||||||
|
|
||||||
/* Audio declarations. */
|
/* Audio declarations. */
|
||||||
#ifdef SIMULATOR
|
/* Maximum sample rate; used for buffer sizing.
|
||||||
#define PD_SAMPLERATE 44100
|
* Actual rate is determined at runtime from pcm sink capabilities. */
|
||||||
#elif (HW_SAMPR_CAPS & SAMPR_CAP_22)
|
#define PD_SAMPLERATE 44100
|
||||||
#define PD_SAMPLERATE 22050
|
|
||||||
#elif (HW_SAMPR_CAPS & SAMPR_CAP_32)
|
|
||||||
#define PD_SAMPLERATE 32000
|
|
||||||
#elif (HW_SAMPR_CAPS & SAMPR_CAP_44)
|
|
||||||
#define PD_SAMPLERATE 44100
|
|
||||||
#else
|
|
||||||
#error No sufficient sample rate available!
|
|
||||||
#endif
|
|
||||||
#define PD_SAMPLES_PER_HZ ((PD_SAMPLERATE / HZ) + \
|
#define PD_SAMPLES_PER_HZ ((PD_SAMPLERATE / HZ) + \
|
||||||
(PD_SAMPLERATE % HZ > 0 ? 1 : 0))
|
(PD_SAMPLERATE % HZ > 0 ? 1 : 0))
|
||||||
#define PD_OUT_CHANNELS 2
|
#define PD_OUT_CHANNELS 2
|
||||||
|
|
|
||||||
|
|
@ -222,8 +222,8 @@ void syssnd_update(void)
|
||||||
|
|
||||||
if (!isAudioPlaying && fillCount > 0)
|
if (!isAudioPlaying && fillCount > 0)
|
||||||
{
|
{
|
||||||
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
|
|
||||||
isAudioPlaying = true;
|
isAudioPlaying = true;
|
||||||
|
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -758,6 +758,8 @@ Ingmar Steen
|
||||||
Lourenço Soares
|
Lourenço Soares
|
||||||
Yegor Chernyshov
|
Yegor Chernyshov
|
||||||
Javier Gutiérrez Gertrúdix
|
Javier Gutiérrez Gertrúdix
|
||||||
|
Sergey Puskov
|
||||||
|
Eivind Ødegård
|
||||||
|
|
||||||
The libmad team
|
The libmad team
|
||||||
The wavpack team
|
The wavpack team
|
||||||
|
|
|
||||||
|
|
@ -527,12 +527,11 @@ drivers/rds.c
|
||||||
#endif /* HAVE_RDS_CAP */
|
#endif /* HAVE_RDS_CAP */
|
||||||
#endif /* PLATFORM_NATIVE */
|
#endif /* PLATFORM_NATIVE */
|
||||||
#endif /* CONFIG_TUNER */
|
#endif /* CONFIG_TUNER */
|
||||||
#endif /* BOOTLOADER */
|
#endif /* !BOOTLOADER */
|
||||||
|
|
||||||
/* Sound */
|
/* Sound */
|
||||||
sound.c
|
|
||||||
|
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
|
sound.c
|
||||||
pcm_sampr.c
|
pcm_sampr.c
|
||||||
pcm.c
|
pcm.c
|
||||||
pcm_mixer.c
|
pcm_mixer.c
|
||||||
|
|
@ -544,7 +543,7 @@ enc_base.c
|
||||||
#endif /* HAVE_RECORDING */
|
#endif /* HAVE_RECORDING */
|
||||||
|
|
||||||
drivers/audio/audiohw-swcodec.c
|
drivers/audio/audiohw-swcodec.c
|
||||||
#endif /* BOOTLOADER */
|
#endif /* !BOOTLOADER */
|
||||||
|
|
||||||
/* Audio codec */
|
/* Audio codec */
|
||||||
#if !defined(BOOTLOADER)
|
#if !defined(BOOTLOADER)
|
||||||
|
|
|
||||||
|
|
@ -1362,6 +1362,13 @@ Lyre prototype 1 */
|
||||||
//#define USB_HAS_INTERRUPT -- seems to be broken
|
//#define USB_HAS_INTERRUPT -- seems to be broken
|
||||||
#endif /* CONFIG_USBOTG */
|
#endif /* CONFIG_USBOTG */
|
||||||
|
|
||||||
|
#if CONFIG_USBOTG == USBOTG_ARC
|
||||||
|
#define USB_BATCH_SLOTS 16
|
||||||
|
#else
|
||||||
|
#define USB_BATCH_NON_NATIVE
|
||||||
|
#define USB_BATCH_SLOTS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* define the class drivers to enable */
|
/* define the class drivers to enable */
|
||||||
#ifdef BOOTLOADER
|
#ifdef BOOTLOADER
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ struct pcm_sink {
|
||||||
/* runtime states */
|
/* runtime states */
|
||||||
unsigned long pending_freq;
|
unsigned long pending_freq;
|
||||||
unsigned long configured_freq;
|
unsigned long configured_freq;
|
||||||
|
unsigned long pcm_is_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pcm_sink_ids {
|
enum pcm_sink_ids {
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,23 @@ int usb_drv_deinit_endpoint(int endpoint);
|
||||||
int usb_drv_get_frame_number(void);
|
int usb_drv_get_frame_number(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* batched request api is for workloads that perform very high-frequency,
|
||||||
|
* performance-sensitive isochronous transactions continuously.
|
||||||
|
* this api allows multiple transaction requests to be buffered in udc driver.
|
||||||
|
* so that it can maximize the controller's performance. */
|
||||||
|
|
||||||
|
/* called when usb system requires more buffer */
|
||||||
|
typedef void(*usb_drv_batch_get_more)(const void** ptr, size_t* len);
|
||||||
|
|
||||||
|
/* prepare request queue */
|
||||||
|
int usb_drv_batch_init(int ep, usb_drv_batch_get_more get_more);
|
||||||
|
/* destroy request queue */
|
||||||
|
int usb_drv_batch_deinit(void);
|
||||||
|
/* start processing */
|
||||||
|
int usb_drv_batch_start(void);
|
||||||
|
/* stop processing */
|
||||||
|
int usb_drv_batch_stop(void);
|
||||||
|
|
||||||
/* USB_STRING_INITIALIZER(u"Example String") */
|
/* USB_STRING_INITIALIZER(u"Example String") */
|
||||||
#define USB_STRING_INITIALIZER(S) { \
|
#define USB_STRING_INITIALIZER(S) { \
|
||||||
sizeof(struct usb_string_descriptor) + sizeof(S) - sizeof(*S), \
|
sizeof(struct usb_string_descriptor) + sizeof(S) - sizeof(*S), \
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 'true' when all stages of pcm initialization have completed */
|
|
||||||
static bool pcm_is_ready = false;
|
|
||||||
|
|
||||||
static struct pcm_sink* sinks[1] = {
|
static struct pcm_sink* sinks[1] = {
|
||||||
[PCM_SINK_BUILTIN] = &builtin_pcm_sink,
|
[PCM_SINK_BUILTIN] = &builtin_pcm_sink,
|
||||||
};
|
};
|
||||||
|
|
@ -142,7 +139,7 @@ void pcm_play_stop_int(void)
|
||||||
|
|
||||||
static void pcm_wait_for_init(void)
|
static void pcm_wait_for_init(void)
|
||||||
{
|
{
|
||||||
while (!pcm_is_ready)
|
while (!sinks[cur_sink]->pcm_is_ready)
|
||||||
sleep(0);
|
sleep(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +202,7 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
||||||
if (active)
|
if (active)
|
||||||
{
|
{
|
||||||
struct pcm_sink* sink = sinks[cur_sink];
|
struct pcm_sink* sink = sinks[cur_sink];
|
||||||
if (sink->configured_freq == -1UL)
|
if (sink->configured_freq == -1U)
|
||||||
{
|
{
|
||||||
logf("not configured yet");
|
logf("not configured yet");
|
||||||
return;
|
return;
|
||||||
|
|
@ -251,9 +248,11 @@ void pcm_init(void)
|
||||||
logf("pcm_init");
|
logf("pcm_init");
|
||||||
|
|
||||||
for(size_t i = 0; i < ARRAYLEN(sinks); i += 1) {
|
for(size_t i = 0; i < ARRAYLEN(sinks); i += 1) {
|
||||||
sinks[i]->pending_freq = sinks[i]->caps.default_freq;
|
struct pcm_sink* sink = sinks[i];
|
||||||
sinks[i]->configured_freq = -1UL;
|
sink->pending_freq = sink->caps.default_freq;
|
||||||
sinks[i]->ops.init();
|
sink->configured_freq = -1U;
|
||||||
|
sink->pcm_is_ready = false;
|
||||||
|
sink->ops.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,15 +262,18 @@ void pcm_postinit(void)
|
||||||
logf("pcm_postinit");
|
logf("pcm_postinit");
|
||||||
|
|
||||||
for(size_t i = 0; i < ARRAYLEN(sinks); i += 1) {
|
for(size_t i = 0; i < ARRAYLEN(sinks); i += 1) {
|
||||||
sinks[i]->ops.postinit();
|
struct pcm_sink* sink = sinks[i];
|
||||||
|
sink->ops.postinit();
|
||||||
|
sink->pcm_is_ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm_is_ready = true;
|
/* Ensure mixer is in a sane state */
|
||||||
|
mixer_set_frequency(pcm_get_frequency());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pcm_is_initialized(void)
|
bool pcm_is_initialized(void)
|
||||||
{
|
{
|
||||||
return pcm_is_ready;
|
return sinks[cur_sink]->pcm_is_ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pcm_sink_ids pcm_current_sink(void)
|
enum pcm_sink_ids pcm_current_sink(void)
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
before the last samples are sent to the codec and so things are done in
|
before the last samples are sent to the codec and so things are done in
|
||||||
parallel (as much as possible) with sending-out data. */
|
parallel (as much as possible) with sending-out data. */
|
||||||
|
|
||||||
static unsigned int mixer_sampr = HW_SAMPR_DEFAULT;
|
static unsigned int mixer_sampr = -1U;
|
||||||
static unsigned int mix_frame_size = MIX_FRAME_SAMPLES*4;
|
static unsigned int mix_frame_size = MIX_FRAME_SAMPLES*4;
|
||||||
|
|
||||||
/* Define this to nonzero to add a marker pulse at each frame start */
|
/* Define this to nonzero to add a marker pulse at each frame start */
|
||||||
|
|
@ -266,7 +266,10 @@ static void mixer_start_pcm(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Requires a shared global sample rate for all channels */
|
/* Requires a shared global sample rate for all channels */
|
||||||
pcm_set_frequency(mixer_sampr);
|
if (mixer_sampr == -1U)
|
||||||
|
mixer_sampr = pcm_get_frequency();
|
||||||
|
else
|
||||||
|
pcm_set_frequency(mixer_sampr);
|
||||||
|
|
||||||
/* Prepare initial frames and set up the double buffer */
|
/* Prepare initial frames and set up the double buffer */
|
||||||
mixer_buffer_callback(PCM_DMAST_STARTED);
|
mixer_buffer_callback(PCM_DMAST_STARTED);
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,16 @@ void sound_set_volume(int value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
|
/* Apply limits */
|
||||||
|
const int min_vol = sound_min(SOUND_VOLUME);
|
||||||
|
const int max_vol = sound_max(SOUND_VOLUME);
|
||||||
|
if (value < min_vol)
|
||||||
|
value = min_vol;
|
||||||
|
if (value > max_vol)
|
||||||
|
value = max_vol;
|
||||||
|
if (value > global_settings.volume_limit)
|
||||||
|
value = global_settings.volume_limit;
|
||||||
|
|
||||||
global_status.volume = value;
|
global_status.volume = value;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ static void sink_dma_init(void)
|
||||||
I2SOUT_CONTROL = (1<<6) | (1<<3); /* enable dma, stereo */
|
I2SOUT_CONTROL = (1<<6) | (1<<3); /* enable dma, stereo */
|
||||||
|
|
||||||
audiohw_preinit();
|
audiohw_preinit();
|
||||||
sink_set_freq(HW_SAMPR_DEFAULT);
|
sink_set_freq(builtin_pcm_sink.caps.default_freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PCM_DMA_ADDRESS
|
#ifdef HAVE_PCM_DMA_ADDRESS
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,6 @@ static bool swd_menu(void)
|
||||||
#if defined(ECHO_R1)
|
#if defined(ECHO_R1)
|
||||||
extern volatile int pcm_sai_xrun_count;
|
extern volatile int pcm_sai_xrun_count;
|
||||||
extern volatile int pcm_dma_teif_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
|
struct pcmdebug_counter
|
||||||
{
|
{
|
||||||
|
|
@ -102,8 +100,6 @@ static const struct pcmdebug_counter pcmdebug_counters[] =
|
||||||
{
|
{
|
||||||
{"SAI xrun count", &pcm_sai_xrun_count},
|
{"SAI xrun count", &pcm_sai_xrun_count},
|
||||||
{"DMA TEIF count", &pcm_dma_teif_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)
|
static int pcmdebug_menu_action_cb(int action, struct gui_synclist *lists)
|
||||||
|
|
|
||||||
|
|
@ -36,19 +36,16 @@
|
||||||
# define PCM_NATIVE_SAMPLE_SIZE 4
|
# define PCM_NATIVE_SAMPLE_SIZE 4
|
||||||
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_32BIT
|
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_32BIT
|
||||||
# define SAI_DSIZE_VAL BV_SAI_SUBBLOCK_CR1_DS_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
|
# define SAI_FRL_VAL 64
|
||||||
#elif PCM_NATIVE_BITDEPTH == 24
|
#elif PCM_NATIVE_BITDEPTH == 24
|
||||||
# define PCM_NATIVE_SAMPLE_SIZE 4
|
# define PCM_NATIVE_SAMPLE_SIZE 4
|
||||||
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_32BIT
|
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_32BIT
|
||||||
# define SAI_DSIZE_VAL BV_SAI_SUBBLOCK_CR1_DS_24BIT
|
# 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
|
# define SAI_FRL_VAL 64
|
||||||
#elif PCM_NATIVE_BITDEPTH == 16
|
#elif PCM_NATIVE_BITDEPTH == 16
|
||||||
# define PCM_NATIVE_SAMPLE_SIZE 2
|
# define PCM_NATIVE_SAMPLE_SIZE 2
|
||||||
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_16BIT
|
# define DMA_PSIZE_VAL BV_DMA_CHN_CR_PSIZE_16BIT
|
||||||
# define SAI_DSIZE_VAL BV_SAI_SUBBLOCK_CR1_DS_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
|
# define SAI_FRL_VAL 32
|
||||||
#else
|
#else
|
||||||
# error "Unsupported PCM bit depth"
|
# error "Unsupported PCM bit depth"
|
||||||
|
|
@ -67,8 +64,6 @@ static int pcm_last_freq = -1;
|
||||||
|
|
||||||
volatile int pcm_sai_xrun_count;
|
volatile int pcm_sai_xrun_count;
|
||||||
volatile int pcm_dma_teif_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)
|
static void play_dma_start(const void *addr, size_t size)
|
||||||
{
|
{
|
||||||
|
|
@ -105,7 +100,7 @@ static void sai_init(void)
|
||||||
/* Configure DMA1 channel 0 */
|
/* Configure DMA1 channel 0 */
|
||||||
reg_writelf(dma1_ch0, DMA_CHN_CR,
|
reg_writelf(dma1_ch0, DMA_CHN_CR,
|
||||||
MBURST_V(INCR4), /* 32-bit x 4 burst = 16 bytes */
|
MBURST_V(INCR4), /* 32-bit x 4 burst = 16 bytes */
|
||||||
PBURST_V(INCR4), /* (16|32)-bit x 4 burst = 8-16 bytes */
|
PBURST_V(SINGLE), /* (16|32)-bit x 4 burst = 8-16 bytes */
|
||||||
TRBUFF(0), /* bufferable mode not used for SAI */
|
TRBUFF(0), /* bufferable mode not used for SAI */
|
||||||
DBM(0), /* double buffer mode off */
|
DBM(0), /* double buffer mode off */
|
||||||
PL_V(VERYHIGH), /* highest priority */
|
PL_V(VERYHIGH), /* highest priority */
|
||||||
|
|
@ -117,10 +112,8 @@ static void sai_init(void)
|
||||||
DIR_V(MEM_TO_PERIPH), /* read from memory, write to SAI */
|
DIR_V(MEM_TO_PERIPH), /* read from memory, write to SAI */
|
||||||
PFCTRL_V(DMA), /* DMA is flow controller */
|
PFCTRL_V(DMA), /* DMA is flow controller */
|
||||||
TCIE(1), /* transfer complete interrupt */
|
TCIE(1), /* transfer complete interrupt */
|
||||||
TEIE(1), /* transfer error interrupt */
|
TEIE(1)); /* transfer error interrupt */
|
||||||
DMEIE(1)); /* direct mode error interrupt */
|
|
||||||
reg_writelf(dma1_ch0, DMA_CHN_FCR,
|
reg_writelf(dma1_ch0, DMA_CHN_FCR,
|
||||||
FEIE(1), /* fifo error interrupt */
|
|
||||||
DMDIS(1), /* enable fifo mode */
|
DMDIS(1), /* enable fifo mode */
|
||||||
FTH_V(FULL)); /* fifo threshold = 4 words */
|
FTH_V(FULL)); /* fifo threshold = 4 words */
|
||||||
|
|
||||||
|
|
@ -146,7 +139,7 @@ static void sai_init(void)
|
||||||
MUTEVAL_V(ZERO_SAMPLE), /* send zero sample on mute */
|
MUTEVAL_V(ZERO_SAMPLE), /* send zero sample on mute */
|
||||||
MUTE(1), /* mute output initially */
|
MUTE(1), /* mute output initially */
|
||||||
TRIS(0), /* don't tri-state outputs */
|
TRIS(0), /* don't tri-state outputs */
|
||||||
FTH(SAI_FIFO_THRESH)); /* fifo threshold (2 or 4 samples) */
|
FTH_V(FULL)); /* fifo threshold (2 or 4 samples) */
|
||||||
reg_writelf(sai1a, SAI_SUBBLOCK_FRCR,
|
reg_writelf(sai1a, SAI_SUBBLOCK_FRCR,
|
||||||
FSOFF(1), FSPOL(0), FSDEF(1), /* I2S format */
|
FSOFF(1), FSPOL(0), FSDEF(1), /* I2S format */
|
||||||
FSALL(SAI_FRL_VAL/2 - 1), /* FS active for half the frame */
|
FSALL(SAI_FRL_VAL/2 - 1), /* FS active for half the frame */
|
||||||
|
|
@ -336,22 +329,12 @@ void dma1_ch0_irq_handler(void)
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
if (reg_vreadf(lisr, DMA_LISR, TEIF0))
|
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));
|
pcm_dma_teif_count++;
|
||||||
reg_writelf(dma1_ch0, DMA_CHN_CR, EN(0));
|
reg_assignlf(dma1, DMA_LIFCR, TEIF0(1));
|
||||||
|
|
||||||
pcm_play_dma_status_callback(PCM_DMAST_ERR_DMA);
|
/* TODO: this case may need additional handling */
|
||||||
|
pcm_play_dma_complete_callback(PCM_DMAST_ERR_DMA, NULL, NULL);
|
||||||
}
|
}
|
||||||
else if (reg_vreadf(lisr, DMA_LISR, TCIF0))
|
else if (reg_vreadf(lisr, DMA_LISR, TCIF0))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -362,6 +362,7 @@ static const unsigned int pipe2mask[USB_NUM_ENDPOINTS*2] = {
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
static void transfer_completed(void);
|
static void transfer_completed(void);
|
||||||
static void control_received(void);
|
static void control_received(void);
|
||||||
|
static void sof_received(void);
|
||||||
static int prime_transfer(int ep_num, void* ptr, int len, bool send, bool wait);
|
static int prime_transfer(int ep_num, void* ptr, int len, bool send, bool wait);
|
||||||
static void prepare_td(struct transfer_descriptor* td,
|
static void prepare_td(struct transfer_descriptor* td,
|
||||||
struct transfer_descriptor* previous_td, void *ptr, int len,int pipe);
|
struct transfer_descriptor* previous_td, void *ptr, int len,int pipe);
|
||||||
|
|
@ -415,6 +416,14 @@ static void usb_drv_reset(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void td_set_buf_ptr(struct transfer_descriptor* td, const void* ptr){
|
||||||
|
td->buff_ptr0 = (unsigned int)ptr;
|
||||||
|
td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000;
|
||||||
|
td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000;
|
||||||
|
td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000;
|
||||||
|
td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000;
|
||||||
|
}
|
||||||
|
|
||||||
/* One-time driver startup init */
|
/* One-time driver startup init */
|
||||||
void usb_drv_startup(void)
|
void usb_drv_startup(void)
|
||||||
{
|
{
|
||||||
|
|
@ -544,6 +553,12 @@ void usb_drv_int(void)
|
||||||
if (status & USBSTS_PORT_CHANGE) {
|
if (status & USBSTS_PORT_CHANGE) {
|
||||||
REG_USBSTS = USBSTS_PORT_CHANGE;
|
REG_USBSTS = USBSTS_PORT_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sof */
|
||||||
|
if (status & USBSTS_SOF) {
|
||||||
|
REG_USBSTS = USBSTS_SOF;
|
||||||
|
sof_received();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usb_drv_stalled(int endpoint,bool in)
|
bool usb_drv_stalled(int endpoint,bool in)
|
||||||
|
|
@ -664,6 +679,183 @@ void usb_drv_set_test_mode(int mode)
|
||||||
REG_USBCMD |= USBCMD_RUN;
|
REG_USBCMD |= USBCMD_RUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* batched request api */
|
||||||
|
static struct transfer_descriptor batch_td_array[USB_BATCH_SLOTS] USB_DEVBSS_ATTR __attribute__((aligned(32)));
|
||||||
|
|
||||||
|
static uint8_t batch_ep = 0;
|
||||||
|
static uint8_t batch_write_cursor;
|
||||||
|
static bool batch_stopped;
|
||||||
|
static usb_drv_batch_get_more batch_get_more;
|
||||||
|
|
||||||
|
static int ep_to_pipe_index(uint8_t ep) {
|
||||||
|
const int ep_num = EP_NUM(ep);
|
||||||
|
const int ep_dir = EP_DIR(ep);
|
||||||
|
const int pipe = ep_num * 2 + (ep_dir == DIR_IN ? 1 : 0);
|
||||||
|
return pipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_drv_batch_init(int ep, usb_drv_batch_get_more get_more) {
|
||||||
|
logf("batch init");
|
||||||
|
if(batch_ep != 0) {
|
||||||
|
logf("batch function not available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
batch_ep = ep;
|
||||||
|
batch_get_more = get_more;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_drv_batch_deinit() {
|
||||||
|
logf("batch deinit");
|
||||||
|
usb_drv_batch_stop();
|
||||||
|
batch_ep = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns whether priming is needed */
|
||||||
|
static bool batch_fill_tds(void) {
|
||||||
|
while(!(batch_td_array[batch_write_cursor].size_ioc_sts & DTD_STATUS_ACTIVE)) {
|
||||||
|
/* batch_get_more may call batch_stop() through:
|
||||||
|
* - batch_get_more()
|
||||||
|
* - pcm_play_dma_complete_callback()
|
||||||
|
* - sink_stop()
|
||||||
|
* - usb_drv_batch_stop() */
|
||||||
|
const void* ptr;
|
||||||
|
size_t len;
|
||||||
|
batch_get_more(&ptr, &len);
|
||||||
|
if(len == 0 || batch_stopped) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct transfer_descriptor* td = &batch_td_array[batch_write_cursor];
|
||||||
|
td_set_buf_ptr(td, ptr);
|
||||||
|
td->size_ioc_sts = (len << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE;
|
||||||
|
batch_write_cursor = (batch_write_cursor + 1) % USB_BATCH_SLOTS;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_drv_batch_start(void) {
|
||||||
|
logf("batch start");
|
||||||
|
|
||||||
|
/* reset variables */
|
||||||
|
batch_write_cursor = 0;
|
||||||
|
batch_stopped = false;
|
||||||
|
|
||||||
|
/* chain tds */
|
||||||
|
memset(batch_td_array, 0, sizeof(struct transfer_descriptor) * USB_BATCH_SLOTS);
|
||||||
|
for(int i = 0; i < USB_BATCH_SLOTS; i += 1) {
|
||||||
|
struct transfer_descriptor* td = &batch_td_array[i];
|
||||||
|
td->next_td_ptr = (unsigned int)&batch_td_array[(i + 1) % USB_BATCH_SLOTS];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* configure queue head */
|
||||||
|
const int pipe = ep_to_pipe_index(batch_ep);
|
||||||
|
struct queue_head* const qh = &qh_array[pipe];
|
||||||
|
|
||||||
|
qh->curr_dtd_ptr = (unsigned int)&batch_td_array[0]; /* or error check in sof_received may read random location */
|
||||||
|
qh->dtd.next_td_ptr = (unsigned int)&batch_td_array[0];
|
||||||
|
qh->dtd.size_ioc_sts = 0;
|
||||||
|
|
||||||
|
/* pull initial buffers */
|
||||||
|
batch_fill_tds();
|
||||||
|
|
||||||
|
/* monitor sof */
|
||||||
|
REG_USBINTR |= USBINTR_SOF_EN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_drv_batch_stop(void) {
|
||||||
|
batch_stopped = true;
|
||||||
|
|
||||||
|
/* disable sof interrupt */
|
||||||
|
REG_USBINTR &= ~USBINTR_SOF_EN;
|
||||||
|
|
||||||
|
/* break the chain */
|
||||||
|
/* terminating qh->dtd.next_td_ptr is not reliable */
|
||||||
|
for(int i = 0; i < USB_BATCH_SLOTS; i += 1) {
|
||||||
|
struct transfer_descriptor* td = &batch_td_array[i];
|
||||||
|
td->next_td_ptr = DTD_NEXT_TERMINATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* flush endpoint */
|
||||||
|
const int pipe = ep_to_pipe_index(batch_ep);
|
||||||
|
const unsigned int mask = pipe2mask[pipe];
|
||||||
|
|
||||||
|
REG_ENDPTFLUSH = mask;
|
||||||
|
while (REG_ENDPTFLUSH & mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LOGF_ENABLE) && defined(ROCKBOX_HAS_LOGF)
|
||||||
|
void usb_drv_dump_regs(void) {
|
||||||
|
logf("==== register dump %ld ====", current_tick);
|
||||||
|
logf("USBSTS 0x%08X", REG_USBSTS);
|
||||||
|
logf("ENDPTSETUPSTAT 0x%08X", REG_ENDPTSETUPSTAT);
|
||||||
|
logf("ENDPTPRIME 0x%08X", REG_ENDPTPRIME);
|
||||||
|
logf("ENDPTFLUSH 0x%08X", REG_ENDPTFLUSH);
|
||||||
|
logf("ENDPTSTATUS 0x%08X", REG_ENDPTSTATUS);
|
||||||
|
logf("ENDPTCOMPLETE 0x%08X", REG_ENDPTCOMPLETE);
|
||||||
|
logf("ENDPTCTRL0 0x%08X", REG_ENDPTCTRL0);
|
||||||
|
logf("ENDPTCTRL1 0x%08X", REG_ENDPTCTRL1);
|
||||||
|
logf("ENDPTCTRL2 0x%08X", REG_ENDPTCTRL2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_td_array(struct queue_head* qh, struct transfer_descriptor* tds, size_t size) {
|
||||||
|
void* current = (void*)qh->curr_dtd_ptr;
|
||||||
|
void* next = (void*)qh->dtd.next_td_ptr;
|
||||||
|
|
||||||
|
logf("==== td dump %ld n=%p c=%p ====", current_tick, next, current);
|
||||||
|
for(int i = 0; i < size; i += 1) {
|
||||||
|
int len = (tds[i].size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS;
|
||||||
|
char sts[] = {
|
||||||
|
&tds[i] == current ? 'c' : ' ',
|
||||||
|
&tds[i] == next ? 'n' : ' ',
|
||||||
|
i == batch_write_cursor ? 'w' : ' ',
|
||||||
|
'\0',
|
||||||
|
};
|
||||||
|
logf("%s td[%02d] status=0x%08X len=%d", sts, i, tds[i].size_ioc_sts, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_drv_dump_tds(int ep) {
|
||||||
|
const int pipe = ep_to_pipe_index(ep);
|
||||||
|
struct queue_head* const qh = &qh_array[pipe];
|
||||||
|
dump_td_array(qh, &td_array[pipe * NUM_TDS_PER_EP], NUM_TDS_PER_EP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_drv_batch_dump_tds(void) {
|
||||||
|
const int pipe = ep_to_pipe_index(batch_ep);
|
||||||
|
struct queue_head* const qh = &qh_array[pipe];
|
||||||
|
dump_td_array(qh, batch_td_array, USB_BATCH_SLOTS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void sof_received(void) {
|
||||||
|
if(batch_ep == 0) {
|
||||||
|
/* should not happen */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* error recovery */
|
||||||
|
const int pipe = ep_to_pipe_index(batch_ep);
|
||||||
|
const unsigned int mask = pipe2mask[pipe];
|
||||||
|
struct queue_head* const qh = &qh_array[pipe];
|
||||||
|
struct transfer_descriptor* const td = (void*)qh->curr_dtd_ptr;
|
||||||
|
if(td->size_ioc_sts & DTD_ERROR_MASK) {
|
||||||
|
logf("td error status=0x%08X", td->size_ioc_sts);
|
||||||
|
REG_ENDPTPRIME |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do refill */
|
||||||
|
if(batch_fill_tds()) {
|
||||||
|
const int pipe = ep_to_pipe_index(batch_ep);
|
||||||
|
const unsigned int mask = pipe2mask[pipe];
|
||||||
|
REG_ENDPTPRIME |= mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* manual: 32.14.5.2 */
|
/* manual: 32.14.5.2 */
|
||||||
|
|
@ -854,11 +1046,7 @@ static void prepare_td(struct transfer_descriptor* td,
|
||||||
td->next_td_ptr = DTD_NEXT_TERMINATE;
|
td->next_td_ptr = DTD_NEXT_TERMINATE;
|
||||||
td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) |
|
td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) |
|
||||||
DTD_STATUS_ACTIVE | DTD_IOC;
|
DTD_STATUS_ACTIVE | DTD_IOC;
|
||||||
td->buff_ptr0 = (unsigned int)ptr;
|
td_set_buf_ptr(td, ptr);
|
||||||
td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000;
|
|
||||||
td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000;
|
|
||||||
td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000;
|
|
||||||
td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000;
|
|
||||||
td->reserved |= DTD_RESERVED_LENGTH_MASK & len;
|
td->reserved |= DTD_RESERVED_LENGTH_MASK & len;
|
||||||
td->reserved |= DTD_RESERVED_IN_USE;
|
td->reserved |= DTD_RESERVED_IN_USE;
|
||||||
td->reserved |= (pipe << DTD_RESERVED_PIPE_OFFSET);
|
td->reserved |= (pipe << DTD_RESERVED_PIPE_OFFSET);
|
||||||
|
|
|
||||||
|
|
@ -554,6 +554,64 @@ void usb_core_hotswap_event(int volume, bool inserted)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USB_BATCH_NON_NATIVE
|
||||||
|
static uint8_t batch_ep = 0;
|
||||||
|
static bool batch_stopped;
|
||||||
|
static usb_drv_batch_get_more batch_get_more;
|
||||||
|
|
||||||
|
int usb_drv_batch_init(int ep, usb_drv_batch_get_more get_more)
|
||||||
|
{
|
||||||
|
if(batch_ep != 0) {
|
||||||
|
logf("usb_core: batch api in use user=0x%02X", batch_ep);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
batch_ep = ep;
|
||||||
|
batch_get_more = get_more;
|
||||||
|
batch_stopped = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_drv_batch_deinit(void)
|
||||||
|
{
|
||||||
|
logf("usb_core: batch deinit");
|
||||||
|
usb_drv_batch_stop();
|
||||||
|
batch_ep = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int batch_get_and_send(void)
|
||||||
|
{
|
||||||
|
const void* ptr;
|
||||||
|
size_t len;
|
||||||
|
batch_get_more(&ptr, &len);
|
||||||
|
if(len == 0 || batch_stopped) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return usb_drv_send_nonblocking(EP_NUM(batch_ep), (void*)ptr, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_drv_batch_start(void)
|
||||||
|
{
|
||||||
|
logf("usb_core: batch start");
|
||||||
|
batch_stopped = false;
|
||||||
|
return batch_get_and_send();
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_drv_batch_stop(void)
|
||||||
|
{
|
||||||
|
batch_stopped = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void batch_xfer_complete(void) {
|
||||||
|
if(batch_stopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
batch_get_and_send();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void usb_core_set_serial_function_id(void)
|
static void usb_core_set_serial_function_id(void)
|
||||||
{
|
{
|
||||||
int i, id = 0;
|
int i, id = 0;
|
||||||
|
|
@ -1130,8 +1188,14 @@ void usb_core_bus_reset(void)
|
||||||
/* called by usb_drv_transfer_completed() */
|
/* called by usb_drv_transfer_completed() */
|
||||||
void usb_core_transfer_complete(int endpoint, int dir, int status, int length)
|
void usb_core_transfer_complete(int endpoint, int dir, int status, int length)
|
||||||
{
|
{
|
||||||
struct usb_transfer_completion_event_data* completion_event =
|
#ifdef USB_BATCH_NON_NATIVE
|
||||||
&ep_data[endpoint].completion_event[EP_DIR(dir)];
|
/* batch api */
|
||||||
|
if(batch_ep != 0 && (endpoint | dir) == batch_ep) {
|
||||||
|
batch_xfer_complete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Fast notification */
|
/* Fast notification */
|
||||||
fast_completion_handler_t handler = ep_data[endpoint].fast_completion_handler[EP_DIR(dir)];
|
fast_completion_handler_t handler = ep_data[endpoint].fast_completion_handler[EP_DIR(dir)];
|
||||||
if(handler != NULL && handler(endpoint, dir, status, length))
|
if(handler != NULL && handler(endpoint, dir, status, length))
|
||||||
|
|
@ -1154,6 +1218,9 @@ void usb_core_transfer_complete(int endpoint, int dir, int status, int length)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct usb_transfer_completion_event_data* completion_event =
|
||||||
|
&ep_data[endpoint].completion_event[EP_DIR(dir)];
|
||||||
|
|
||||||
completion_event->endpoint = endpoint;
|
completion_event->endpoint = endpoint;
|
||||||
completion_event->dir = dir;
|
completion_event->dir = dir;
|
||||||
completion_event->data[0] = data0;
|
completion_event->data[0] = data0;
|
||||||
|
|
|
||||||
|
|
@ -782,7 +782,7 @@ sub simbuilds {
|
||||||
'norsk' => {
|
'norsk' => {
|
||||||
'lang' => 'norsk',
|
'lang' => 'norsk',
|
||||||
'name' => 'Norsk (Norwegian)',
|
'name' => 'Norsk (Norwegian)',
|
||||||
'short' => 'no',
|
'short' => 'nb',
|
||||||
'defengine' => 'piper',
|
'defengine' => 'piper',
|
||||||
'engines' => {
|
'engines' => {
|
||||||
'espeak' => '-vno',
|
'espeak' => '-vno',
|
||||||
|
|
@ -791,6 +791,18 @@ sub simbuilds {
|
||||||
},
|
},
|
||||||
'enabled' => 0,
|
'enabled' => 0,
|
||||||
},
|
},
|
||||||
|
'norsk-nynorsk' => {
|
||||||
|
'lang' => 'norsk-nynorsk',
|
||||||
|
'name' => 'Nynorsk (Norwegian Nynorsk)',
|
||||||
|
'short' => 'nn',
|
||||||
|
'defengine' => 'piper',
|
||||||
|
'engines' => {
|
||||||
|
'espeak' => '-vno',
|
||||||
|
'gtts' => '-l no',
|
||||||
|
'piper' => 'no_NO-talesyntese-medium.onnx',
|
||||||
|
},
|
||||||
|
'enabled' => 1,
|
||||||
|
},
|
||||||
'moldoveneste' => {
|
'moldoveneste' => {
|
||||||
'lang' => 'moldoveneste',
|
'lang' => 'moldoveneste',
|
||||||
'name' => 'Moldovenească (Moldavian)',
|
'name' => 'Moldovenească (Moldavian)',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue