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>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_PLAYTIME_ERROR
|
||||
desc: playing time screen
|
||||
user: core
|
||||
<source>
|
||||
*: "Error while gathering info"
|
||||
</source>
|
||||
<dest>
|
||||
*: "Сбой при сборе информации"
|
||||
</dest>
|
||||
<voice>
|
||||
*: "Сбой при сборе информации"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_CLEAR_ALL_RESUMES
|
||||
desc: in the mpegplayer settings menu
|
||||
|
|
@ -14389,7 +14375,7 @@
|
|||
user: core
|
||||
<source>
|
||||
*: "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."
|
||||
ihifi760,ihifi960: "Double tap RETURN to cancel."
|
||||
ihifi770,ihifi770c,ihifi800: "Press HOME to cancel."
|
||||
|
|
@ -14404,7 +14390,7 @@
|
|||
</source>
|
||||
<dest>
|
||||
*: "Нажмите ВЛЕВО для отмены."
|
||||
android,hifietma*,zenvision: "Нажмите НАЗАД для отмены."
|
||||
android,hifietma*: "Нажмите НАЗАД для отмены."
|
||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Нажмите ВКЛ. для отмены."
|
||||
ihifi760,ihifi960: "Дважды нажмите ВОЗВРАТ для отмены."
|
||||
ihifi770,ihifi770c,ihifi800: "Нажмите ДОМОЙ для отмены."
|
||||
|
|
@ -14419,7 +14405,7 @@
|
|||
</dest>
|
||||
<voice>
|
||||
*: "Нажмите кнопку Влево для отмены."
|
||||
android,hifietma*,zenvision: "Нажмите кнопку Назад для отмены."
|
||||
android,hifietma*: "Нажмите кнопку Назад для отмены."
|
||||
cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Нажмите кнопку включения для отмены."
|
||||
ihifi760,ihifi960: "Дважды нажмите кнопку Назад для отмены."
|
||||
ihifi770,ihifi770c,ihifi800: "Нажмите кнопку Домой для отмены."
|
||||
|
|
@ -15790,13 +15776,13 @@
|
|||
</phrase>
|
||||
<phrase>
|
||||
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
|
||||
<source>
|
||||
*: "dAY"
|
||||
</source>
|
||||
<dest>
|
||||
*: "~dAY"
|
||||
*: "dAy"
|
||||
</dest>
|
||||
<voice>
|
||||
*: ""
|
||||
|
|
@ -15872,20 +15858,6 @@
|
|||
*: "Браузер по умолчанию"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_AMAZE_MENU
|
||||
desc: Amaze game
|
||||
user: core
|
||||
<source>
|
||||
*: "Amaze Main Menu"
|
||||
</source>
|
||||
<dest>
|
||||
*: "Главное меню Amaze"
|
||||
</dest>
|
||||
<voice>
|
||||
*: "Главное меню Amaze"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_SET_MAZE_SIZE
|
||||
desc: Maze size in Amaze game
|
||||
|
|
@ -16138,34 +16110,6 @@
|
|||
*: "Настройки Mik mod"
|
||||
</voice>
|
||||
</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>
|
||||
id: VOICE_INVALID_VOICE_FILE
|
||||
desc: played if the voice file fails to load
|
||||
|
|
@ -16999,3 +16943,48 @@
|
|||
*: "Все трэки сортируются по альбому"
|
||||
</voice>
|
||||
</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
|
||||
|
||||
/* check range, set volume and save settings */
|
||||
/* set volume and save settings */
|
||||
void setvol(void)
|
||||
{
|
||||
const int min_vol = sound_min(SOUND_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);
|
||||
sound_set_volume(global_status.volume);
|
||||
global_status.last_volume_change = current_tick;
|
||||
status_save(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,13 @@
|
|||
.Trashes/: no
|
||||
.Spotlight-V100/: no
|
||||
.DS_Store: no
|
||||
__MACOSX/: no
|
||||
._*: no
|
||||
< Linux/BSD >: no
|
||||
.Trash-*/: no
|
||||
.dolphinview: no
|
||||
.d3lphinview: no
|
||||
< Android >: no
|
||||
Android/: no
|
||||
LOST.DIR/: no
|
||||
< Other >: no
|
||||
|
|
|
|||
|
|
@ -381,6 +381,8 @@
|
|||
|
||||
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 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? */
|
||||
|
|
@ -490,11 +492,56 @@ static void get_more(const void** start, size_t* size)
|
|||
*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)
|
||||
{
|
||||
int a, notes_used, vol;
|
||||
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)
|
||||
rb->cpu_boost(true);
|
||||
#endif
|
||||
|
|
@ -537,7 +584,7 @@ static int midimain(const void * filename)
|
|||
rb->dsp_set_timestretch(PITCH_SPEED_100);
|
||||
#endif
|
||||
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);
|
||||
|
||||
/*
|
||||
|
|
@ -553,14 +600,14 @@ static int midimain(const void * filename)
|
|||
midi_debug("Okay, starting sequencing");
|
||||
|
||||
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 */
|
||||
/* after the first note event */
|
||||
do
|
||||
{
|
||||
notes_used = 0;
|
||||
for (a = 0; a < MAX_VOICES; a++)
|
||||
for (a = 0; a < max_voices; a++)
|
||||
if (voices[a].isUsed)
|
||||
notes_used++;
|
||||
tick();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ struct GPatch * gusload(char *);
|
|||
struct GPatch * patchSet[128];
|
||||
struct GPatch * drumSet[128];
|
||||
|
||||
struct SynthObject voices[MAX_VOICES] IBSS_ATTR;
|
||||
struct SynthObject voices[48] IBSS_ATTR;
|
||||
|
||||
static void *alloc(int size)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,67 +27,6 @@
|
|||
#define NBUF 2
|
||||
#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
|
||||
|
||||
/* Data chunk ID types, returned by readID() */
|
||||
|
|
@ -189,7 +128,7 @@ void * readData(int file, int len);
|
|||
#define malloc(n) my_malloc(n)
|
||||
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 chPan[16]; /* Channel panning */
|
||||
|
|
@ -207,6 +146,8 @@ extern struct GPatch * drumSet[128];
|
|||
|
||||
extern struct MIDIfile * mf;
|
||||
|
||||
extern int sample_rate;
|
||||
extern int max_voices;
|
||||
extern int number_of_samples;
|
||||
extern int playing_time 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 */
|
||||
/* 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)
|
||||
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 = delta * wf->sampRate; /* approx 20000 - 44000 but can vary with tuning */
|
||||
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 */
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int a;
|
||||
for (a = 0; a < MAX_VOICES; a++)
|
||||
for (a = 0; a < max_voices; a++)
|
||||
{
|
||||
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;
|
||||
*/
|
||||
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)
|
||||
break;
|
||||
|
|
@ -218,7 +218,7 @@ static inline void pressNote(int ch, int note, int vol)
|
|||
if (!voices[a].isUsed)
|
||||
break;
|
||||
}
|
||||
if (a == MAX_VOICES)
|
||||
if (a == max_voices)
|
||||
{
|
||||
// midi_debug("\nVoice kill");
|
||||
// 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++)
|
||||
// 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++;
|
||||
if (lastKill == MAX_VOICES)
|
||||
if (lastKill == max_voices)
|
||||
lastKill = 0;
|
||||
a = lastKill;
|
||||
// return; /* None available */
|
||||
|
|
@ -263,7 +263,7 @@ static inline void pressNote(int ch, int note, int vol)
|
|||
|
||||
struct GWaveform * wf = drumSet[note]->waveforms[0];
|
||||
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)
|
||||
// midi_debug("\nWoah, a drum patch has a loop. Stripping the loop...");
|
||||
wf->mode = wf->mode & (255-28);
|
||||
|
|
@ -285,7 +285,7 @@ static void releaseNote(int ch, int note)
|
|||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -432,7 +432,7 @@ int tick(void)
|
|||
tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
|
||||
/* midi_debug("\nMeta-Event: Tempo Set = %d", 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;
|
||||
|
||||
while (samples_this_second >= SAMPLE_RATE)
|
||||
while (samples_this_second >= sample_rate)
|
||||
{
|
||||
samples_this_second -= SAMPLE_RATE;
|
||||
samples_this_second -= sample_rate;
|
||||
playing_time++;
|
||||
}
|
||||
|
||||
|
|
@ -471,7 +471,7 @@ void seekBackward(int nsec)
|
|||
|
||||
/* Set the tempo to defalt */
|
||||
bpm = mf->div*1000000/tempo;
|
||||
number_of_samples = SAMPLE_RATE/bpm;
|
||||
number_of_samples = sample_rate/bpm;
|
||||
|
||||
/* Reset the tracks to start */
|
||||
rewindFile();
|
||||
|
|
@ -484,7 +484,7 @@ void seekBackward(int nsec)
|
|||
do
|
||||
{
|
||||
notes_used = 0;
|
||||
for (a = 0; a < MAX_VOICES; a++)
|
||||
for (a = 0; a < max_voices; a++)
|
||||
if (voices[a].isUsed)
|
||||
notes_used++;
|
||||
tick();
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ static void readTextBlock(int file, char * buf)
|
|||
void resetControllers()
|
||||
{
|
||||
int a=0;
|
||||
for(a=0; a<MAX_VOICES; a++)
|
||||
for(a=0; a<max_voices; a++)
|
||||
{
|
||||
voices[a].cp=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)
|
||||
{
|
||||
unsigned int i;
|
||||
int i;
|
||||
struct SynthObject *voicept;
|
||||
size_t nsamples = MIN(num_samples, MAX_SAMPLES);
|
||||
|
||||
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];
|
||||
if(voicept->isUsed)
|
||||
|
|
|
|||
|
|
@ -395,19 +395,19 @@ static void start_sound(void)
|
|||
#endif
|
||||
|
||||
/* 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,
|
||||
rb->hw_freq_sampr, HW_NUM_FREQ, false);
|
||||
caps->samprs, caps->num_samprs, false);
|
||||
|
||||
if (rb->hw_freq_sampr[sr_index] < PREFERRED_SAMPLING_RATE
|
||||
&& sr_index > 0)
|
||||
if (caps->samprs[sr_index] < PREFERRED_SAMPLING_RATE && sr_index > 0)
|
||||
{
|
||||
/* Round up */
|
||||
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);
|
||||
|
||||
sound_playing = true;
|
||||
|
|
|
|||
|
|
@ -188,6 +188,26 @@ enum plugin_status plugin_start(const void* parameter)
|
|||
/* Set audio API. */
|
||||
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. */
|
||||
sys_open_audio(0, /* No sound input yet */
|
||||
sys_soundindevlist,
|
||||
|
|
@ -197,7 +217,7 @@ enum plugin_status plugin_start(const void* parameter)
|
|||
sys_soundoutdevlist,
|
||||
-1, /* Use the default amount (2) of channels */
|
||||
sys_choutlist,
|
||||
PD_SAMPLERATE, /* Sample rate */
|
||||
samplerate, /* Sample rate */
|
||||
DEFAULTADVANCE, /* Scheduler advance */
|
||||
1 /* Enable */);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,17 +40,9 @@
|
|||
#define calloc(elements, elem_size) tlsf_calloc(elements, elem_size)
|
||||
|
||||
/* Audio declarations. */
|
||||
#ifdef SIMULATOR
|
||||
#define PD_SAMPLERATE 44100
|
||||
#elif (HW_SAMPR_CAPS & SAMPR_CAP_22)
|
||||
#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
|
||||
/* Maximum sample rate; used for buffer sizing.
|
||||
* Actual rate is determined at runtime from pcm sink capabilities. */
|
||||
#define PD_SAMPLERATE 44100
|
||||
#define PD_SAMPLES_PER_HZ ((PD_SAMPLERATE / HZ) + \
|
||||
(PD_SAMPLERATE % HZ > 0 ? 1 : 0))
|
||||
#define PD_OUT_CHANNELS 2
|
||||
|
|
|
|||
|
|
@ -222,8 +222,8 @@ void syssnd_update(void)
|
|||
|
||||
if (!isAudioPlaying && fillCount > 0)
|
||||
{
|
||||
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
|
||||
isAudioPlaying = true;
|
||||
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -758,6 +758,8 @@ Ingmar Steen
|
|||
Lourenço Soares
|
||||
Yegor Chernyshov
|
||||
Javier Gutiérrez Gertrúdix
|
||||
Sergey Puskov
|
||||
Eivind Ødegård
|
||||
|
||||
The libmad team
|
||||
The wavpack team
|
||||
|
|
|
|||
|
|
@ -527,12 +527,11 @@ drivers/rds.c
|
|||
#endif /* HAVE_RDS_CAP */
|
||||
#endif /* PLATFORM_NATIVE */
|
||||
#endif /* CONFIG_TUNER */
|
||||
#endif /* BOOTLOADER */
|
||||
#endif /* !BOOTLOADER */
|
||||
|
||||
/* Sound */
|
||||
sound.c
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
sound.c
|
||||
pcm_sampr.c
|
||||
pcm.c
|
||||
pcm_mixer.c
|
||||
|
|
@ -544,7 +543,7 @@ enc_base.c
|
|||
#endif /* HAVE_RECORDING */
|
||||
|
||||
drivers/audio/audiohw-swcodec.c
|
||||
#endif /* BOOTLOADER */
|
||||
#endif /* !BOOTLOADER */
|
||||
|
||||
/* Audio codec */
|
||||
#if !defined(BOOTLOADER)
|
||||
|
|
|
|||
|
|
@ -1362,6 +1362,13 @@ Lyre prototype 1 */
|
|||
//#define USB_HAS_INTERRUPT -- seems to be broken
|
||||
#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 */
|
||||
#ifdef BOOTLOADER
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ struct pcm_sink {
|
|||
/* runtime states */
|
||||
unsigned long pending_freq;
|
||||
unsigned long configured_freq;
|
||||
unsigned long pcm_is_ready;
|
||||
};
|
||||
|
||||
enum pcm_sink_ids {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,23 @@ int usb_drv_deinit_endpoint(int endpoint);
|
|||
int usb_drv_get_frame_number(void);
|
||||
#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") */
|
||||
#define USB_STRING_INITIALIZER(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] = {
|
||||
[PCM_SINK_BUILTIN] = &builtin_pcm_sink,
|
||||
};
|
||||
|
|
@ -142,7 +139,7 @@ void pcm_play_stop_int(void)
|
|||
|
||||
static void pcm_wait_for_init(void)
|
||||
{
|
||||
while (!pcm_is_ready)
|
||||
while (!sinks[cur_sink]->pcm_is_ready)
|
||||
sleep(0);
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +202,7 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
|||
if (active)
|
||||
{
|
||||
struct pcm_sink* sink = sinks[cur_sink];
|
||||
if (sink->configured_freq == -1UL)
|
||||
if (sink->configured_freq == -1U)
|
||||
{
|
||||
logf("not configured yet");
|
||||
return;
|
||||
|
|
@ -251,9 +248,11 @@ void pcm_init(void)
|
|||
logf("pcm_init");
|
||||
|
||||
for(size_t i = 0; i < ARRAYLEN(sinks); i += 1) {
|
||||
sinks[i]->pending_freq = sinks[i]->caps.default_freq;
|
||||
sinks[i]->configured_freq = -1UL;
|
||||
sinks[i]->ops.init();
|
||||
struct pcm_sink* sink = sinks[i];
|
||||
sink->pending_freq = sink->caps.default_freq;
|
||||
sink->configured_freq = -1U;
|
||||
sink->pcm_is_ready = false;
|
||||
sink->ops.init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -263,15 +262,18 @@ void pcm_postinit(void)
|
|||
logf("pcm_postinit");
|
||||
|
||||
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)
|
||||
{
|
||||
return pcm_is_ready;
|
||||
return sinks[cur_sink]->pcm_is_ready;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
/* Define this to nonzero to add a marker pulse at each frame start */
|
||||
|
|
@ -266,7 +266,10 @@ static void mixer_start_pcm(void)
|
|||
#endif
|
||||
|
||||
/* 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 */
|
||||
mixer_buffer_callback(PCM_DMAST_STARTED);
|
||||
|
|
|
|||
|
|
@ -313,6 +313,16 @@ void sound_set_volume(int value)
|
|||
return;
|
||||
|
||||
#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;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ static void sink_dma_init(void)
|
|||
I2SOUT_CONTROL = (1<<6) | (1<<3); /* enable dma, stereo */
|
||||
|
||||
audiohw_preinit();
|
||||
sink_set_freq(HW_SAMPR_DEFAULT);
|
||||
sink_set_freq(builtin_pcm_sink.caps.default_freq);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PCM_DMA_ADDRESS
|
||||
|
|
|
|||
|
|
@ -89,8 +89,6 @@ static bool swd_menu(void)
|
|||
#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
|
||||
{
|
||||
|
|
@ -102,8 +100,6 @@ 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)
|
||||
|
|
|
|||
|
|
@ -36,19 +36,16 @@
|
|||
# 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"
|
||||
|
|
@ -67,8 +64,6 @@ 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)
|
||||
{
|
||||
|
|
@ -105,7 +100,7 @@ static void sai_init(void)
|
|||
/* 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 */
|
||||
PBURST_V(SINGLE), /* (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 */
|
||||
|
|
@ -117,10 +112,8 @@ static void sai_init(void)
|
|||
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 */
|
||||
TEIE(1)); /* transfer 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 */
|
||||
|
||||
|
|
@ -146,7 +139,7 @@ static void sai_init(void)
|
|||
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) */
|
||||
FTH_V(FULL)); /* 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 */
|
||||
|
|
@ -336,22 +329,12 @@ void dma1_ch0_irq_handler(void)
|
|||
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_dma_teif_count++;
|
||||
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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -362,6 +362,7 @@ static const unsigned int pipe2mask[USB_NUM_ENDPOINTS*2] = {
|
|||
/*-------------------------------------------------------------------------*/
|
||||
static void transfer_completed(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 void prepare_td(struct transfer_descriptor* td,
|
||||
struct transfer_descriptor* previous_td, void *ptr, int len,int pipe);
|
||||
|
|
@ -415,6 +416,14 @@ static void usb_drv_reset(void)
|
|||
#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 */
|
||||
void usb_drv_startup(void)
|
||||
{
|
||||
|
|
@ -544,6 +553,12 @@ void usb_drv_int(void)
|
|||
if (status & 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)
|
||||
|
|
@ -664,6 +679,183 @@ void usb_drv_set_test_mode(int mode)
|
|||
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 */
|
||||
|
|
@ -854,11 +1046,7 @@ static void prepare_td(struct transfer_descriptor* td,
|
|||
td->next_td_ptr = DTD_NEXT_TERMINATE;
|
||||
td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) |
|
||||
DTD_STATUS_ACTIVE | DTD_IOC;
|
||||
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;
|
||||
td_set_buf_ptr(td, ptr);
|
||||
td->reserved |= DTD_RESERVED_LENGTH_MASK & len;
|
||||
td->reserved |= DTD_RESERVED_IN_USE;
|
||||
td->reserved |= (pipe << DTD_RESERVED_PIPE_OFFSET);
|
||||
|
|
|
|||
|
|
@ -554,6 +554,64 @@ void usb_core_hotswap_event(int volume, bool inserted)
|
|||
}
|
||||
#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)
|
||||
{
|
||||
int i, id = 0;
|
||||
|
|
@ -1130,8 +1188,14 @@ void usb_core_bus_reset(void)
|
|||
/* called by usb_drv_transfer_completed() */
|
||||
void usb_core_transfer_complete(int endpoint, int dir, int status, int length)
|
||||
{
|
||||
struct usb_transfer_completion_event_data* completion_event =
|
||||
&ep_data[endpoint].completion_event[EP_DIR(dir)];
|
||||
#ifdef USB_BATCH_NON_NATIVE
|
||||
/* batch api */
|
||||
if(batch_ep != 0 && (endpoint | dir) == batch_ep) {
|
||||
batch_xfer_complete();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fast notification */
|
||||
fast_completion_handler_t handler = ep_data[endpoint].fast_completion_handler[EP_DIR(dir)];
|
||||
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
|
||||
|
||||
struct usb_transfer_completion_event_data* completion_event =
|
||||
&ep_data[endpoint].completion_event[EP_DIR(dir)];
|
||||
|
||||
completion_event->endpoint = endpoint;
|
||||
completion_event->dir = dir;
|
||||
completion_event->data[0] = data0;
|
||||
|
|
|
|||
|
|
@ -782,7 +782,7 @@ sub simbuilds {
|
|||
'norsk' => {
|
||||
'lang' => 'norsk',
|
||||
'name' => 'Norsk (Norwegian)',
|
||||
'short' => 'no',
|
||||
'short' => 'nb',
|
||||
'defengine' => 'piper',
|
||||
'engines' => {
|
||||
'espeak' => '-vno',
|
||||
|
|
@ -791,6 +791,18 @@ sub simbuilds {
|
|||
},
|
||||
'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' => {
|
||||
'lang' => 'moldoveneste',
|
||||
'name' => 'Moldovenească (Moldavian)',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue