Audio system on ersky9x ... another rewrite

Some flash saved on stock
GPS calculations flash saving (around 100bytes, needs to be tested)
This commit is contained in:
bsongis
2012-07-06 13:09:29 +00:00
parent e94db55b27
commit cb073fa549
10 changed files with 177 additions and 116 deletions
+118 -81
View File
@@ -141,6 +141,7 @@ AudioQueue audioQueue;
AudioQueue::AudioQueue()
{
memset(this, 0, sizeof(AudioQueue));
prioIdx = -1;
}
void audioTimerHandle(void)
@@ -156,6 +157,7 @@ extern uint16_t Sine_values[];
#define CODEC_ID_PCM_S16LE 1
#define CODEC_ID_PCM_ALAW 6
uint8_t pcmCodec;
uint16_t pcmFreq;
void audioTask(void* pdata)
{
@@ -168,27 +170,50 @@ void audioTask(void* pdata)
}
}
#define WAV_BUFFER_SIZE 512
uint16_t wavSamplesArray[3*WAV_BUFFER_SIZE];
uint16_t * wavSamplesBuffer = &wavSamplesArray[0];
uint16_t * nextAudioData = NULL;
uint16_t nextAudioSize = 0;
void AudioQueue::wakeup()
{
#if defined(SDCARD) && !defined(SIMU)
static FIL wavFile;
#endif
if (prioIdx >= 0) {
ridx = prioIdx;
prioIdx = -1;
toneStop();
nextAudioData = NULL;
memset(&current, 0, sizeof(current));
if (state == AUDIO_PLAYING_WAV) {
state = AUDIO_RESUMING;
CoSetTmrCnt(audioTimer, 5/*10ms*/ + (WAV_BUFFER_SIZE * 1000) / pcmFreq, 0);
CoStartTmr(audioTimer);
}
else if (state == AUDIO_PLAYING_TONE) {
state = AUDIO_RESUMING;
CoSetTmrCnt(audioTimer, 5/*10ms*/, 0);
CoStartTmr(audioTimer);
}
else {
CoSetFlag(audioFlag);
}
}
#if defined(SDCARD) && !defined(SIMU)
if (current.file[0]) {
else if (current.file[0]) {
FRESULT result = FR_OK;
UINT read = 0;
uint16_t * bufdata = wavSamplesBuffer;
if (current.file[1]) {
wavSamplesBuffer = wavSamplesArray;
result = f_open(&wavFile, current.file, FA_OPEN_EXISTING | FA_READ);
if (result == FR_OK) {
result = f_read(&wavFile, (uint8_t *)wavSamplesArray, WAV_HEADER_SIZE, &read);
if (result == FR_OK && read == WAV_HEADER_SIZE && !memcmp(wavSamplesArray, "RIFF", 4)) {
CoSetFlag(audioFlag);
bufdata = wavSamplesArray;
wavSamplesBuffer = wavSamplesArray + WAV_BUFFER_SIZE;
pcmCodec = wavSamplesArray[10];
setFrequency(wavSamplesArray[12]);
pcmFreq = wavSamplesArray[12];
if (pcmCodec != CODEC_ID_PCM_S16LE) {
result = f_read(&wavFile, (uint8_t *)wavSamplesArray, 12, &read);
}
@@ -198,53 +223,73 @@ void AudioQueue::wakeup()
}
}
}
else {
wavSamplesBuffer += WAV_BUFFER_SIZE;
if (wavSamplesBuffer >= wavSamplesArray + 3*WAV_BUFFER_SIZE)
wavSamplesBuffer = wavSamplesArray;
}
read = 0;
uint16_t bufsize = (pcmCodec == CODEC_ID_PCM_S16LE ? 2*WAV_BUFFER_SIZE : WAV_BUFFER_SIZE);
if (result != FR_OK || f_read(&wavFile, (uint8_t *)bufdata, bufsize, &read) != FR_OK || read != bufsize) {
uint16_t bufsize = (pcmCodec == CODEC_ID_PCM_S16LE ? WAV_BUFFER_SIZE*sizeof(uint16_t) : WAV_BUFFER_SIZE);
if (result != FR_OK || f_read(&wavFile, (uint8_t *)wavSamplesBuffer, bufsize, &read) != FR_OK || read == 0) {
toneStop();
current.file[0] = 0;
current.file[1] = 0;
if (pcmCodec == CODEC_ID_PCM_S16LE) {
DACC->DACC_TNCR = read/4;
}
else {
DACC->DACC_TNCR = read/2;
}
toneStop();
f_close(&wavFile);
CoSetFlag(audioFlag);
CoSetTmrCnt(audioTimer, (WAV_BUFFER_SIZE * 1000) / pcmFreq, 0);
CoStartTmr(audioTimer);
}
if (pcmCodec == CODEC_ID_PCM_S16LE) {
read /= 2;
uint32_t i = 0;
for (; i<read; i++)
bufdata[i] = ((uint16_t)0x8000 + ((int16_t)(bufdata[i]))) >> 4;
wavSamplesBuffer[i] = ((uint16_t)0x8000 + ((int16_t)(wavSamplesBuffer[i]))) >> 4;
for (; i<WAV_BUFFER_SIZE; i++)
bufdata[i] = 0x8000;
wavSamplesBuffer[i] = 0x8000;
}
else if (pcmCodec == CODEC_ID_PCM_ALAW) {
int32_t i;
for (i=read-1; i>=0; i--)
bufdata[i] = alawTable[((uint8_t *)bufdata)[i]];
wavSamplesBuffer[i] = alawTable[((uint8_t *)wavSamplesBuffer)[i]];
for (i=read; i<WAV_BUFFER_SIZE; i++)
bufdata[i] = 0x8000;
wavSamplesBuffer[i] = 0x8000;
}
read /= 2;
register Dacc *dacptr = DACC;
if (current.file[1]) {
state = AUDIO_PLAYING_WAV;
setFrequency(pcmFreq);
dacptr->DACC_TPR = CONVERT_PTR(wavSamplesBuffer);
dacptr->DACC_TCR = read;
current.file[1] = 0;
register Dacc *dacptr = DACC;
dacptr->DACC_TPR = CONVERT_PTR(wavSamplesArray);
dacptr->DACC_TNPR = CONVERT_PTR(wavSamplesBuffer);
dacptr->DACC_TCR = WAV_BUFFER_SIZE/2;
dacptr->DACC_TNCR = WAV_BUFFER_SIZE/2;
toneStart();
CoSetFlag(audioFlag);
}
else if (read) {
if (dacptr->DACC_TNCR == 0) {
dacptr->DACC_TNPR = CONVERT_PTR(wavSamplesBuffer);
dacptr->DACC_TNCR = read;
CoSetFlag(audioFlag);
}
else {
nextAudioSize = read;
nextAudioData = wavSamplesBuffer;
toneStart();
}
}
}
else
#endif
if (current.duration > 0) {
// TODO function for that ...
else if (current.duration > 0) {
if (state != AUDIO_PLAYING_TONE) {
state = AUDIO_PLAYING_TONE;
register Dacc *dacptr = DACC;
dacptr->DACC_TPR = CONVERT_PTR(Sine_values);
dacptr->DACC_TNPR = CONVERT_PTR(Sine_values);
dacptr->DACC_TCR = 50 ; // words, 100 16 bit values
dacptr->DACC_TNCR = 50 ; // words, 100 16 bit values
}
setFrequency(current.freq * 6100 / 2);
if (current.freqIncr) {
CoSetTmrCnt(audioTimer, 5/*10ms*/, 0);
@@ -252,14 +297,14 @@ void AudioQueue::wakeup()
current.duration--;
}
else {
CoSetTmrCnt(audioTimer, current.duration*5, 0);
CoSetTmrCnt(audioTimer, current.duration*2, 0);
current.duration = 0;
}
toneStart();
CoStartTmr(audioTimer);
}
else if (current.pause > 0) {
CoSetTmrCnt(audioTimer, current.pause*5, 0);
CoSetTmrCnt(audioTimer, current.pause*2, 0);
current.pause = 0;
toneStop();
CoStartTmr(audioTimer);
@@ -272,14 +317,25 @@ void AudioQueue::wakeup()
CoSetFlag(audioFlag);
}
else if (background.duration > 0) {
CoSetTmrCnt(audioTimer, background.duration*5, 0);
if (state != AUDIO_PLAYING_TONE) {
state = AUDIO_PLAYING_TONE;
register Dacc *dacptr = DACC;
dacptr->DACC_TPR = CONVERT_PTR(Sine_values);
dacptr->DACC_TNPR = CONVERT_PTR(Sine_values);
dacptr->DACC_TCR = 50 ; // words, 100 16 bit values
dacptr->DACC_TNCR = 50 ; // words, 100 16 bit values
}
CoSetTmrCnt(audioTimer, background.duration*2, 0);
background.duration = 0;
setFrequency(background.freq * 6100 / 2);
toneStart();
CoStartTmr(audioTimer);
}
else {
state = 0;
state = AUDIO_SLEEPING;
#ifndef SIMU
CoLeaveMutexSection(audioMutex);
#endif
toneStop();
}
}
@@ -315,8 +371,8 @@ void AudioQueue::play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlag
background.freq = tFreq;
background.duration = tLen;
background.pause = tPause;
if (state == 0) {
state = 1;
if (!busy()) {
state = AUDIO_RESUMING;
CoSetFlag(audioFlag);
}
}
@@ -325,32 +381,22 @@ void AudioQueue::play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlag
tFreq += g_eeGeneral.speakerPitch + BEEP_OFFSET; // add pitch compensator
}
tLen = getToneLength(tLen);
if ((tFlags & PLAY_NOW) || !busy()) {
state = 1;
current.file[0] = '\0';
current.freq = tFreq;
current.duration = tLen;
current.pause = tPause;
current.freqIncr = tFreqIncr;
widx = ridx;
CoSetFlag(audioFlag);
}
else {
tFlags++;
}
tFlags &= 0x0f;
if (tFlags) {
uint8_t next_widx = (widx + 1) % AUDIO_QUEUE_LENGTH;
if (next_widx != ridx) {
AudioFragment & fragment = fragments[widx];
memset(&fragment, 0, sizeof(fragment));
fragment.freq = tFreq;
fragment.duration = tLen;
fragment.pause = tPause;
fragment.repeat = tFlags - 1;
fragment.freqIncr = tFreqIncr;
widx = next_widx;
uint8_t next_widx = (widx + 1) % AUDIO_QUEUE_LENGTH;
if (next_widx != ridx) {
AudioFragment & fragment = fragments[widx];
memset(&fragment, 0, sizeof(fragment));
fragment.freq = tFreq;
fragment.duration = tLen;
fragment.pause = tPause;
fragment.repeat = tFlags & 0x0f;
fragment.freqIncr = tFreqIncr;
if (tFlags & PLAY_NOW)
prioIdx = widx;
widx = next_widx;
if (!busy()) {
state = AUDIO_RESUMING;
CoSetFlag(audioFlag);
}
}
}
@@ -366,29 +412,20 @@ void AudioQueue::playFile(const char *filename, uint8_t flags)
CoEnterMutexSection(audioMutex);
#endif
if ((flags & PLAY_NOW) || !busy()) {
state = 1;
memset(&current, 0, sizeof(current));
strcpy(current.file, filename);
widx = ridx;
CoSetFlag(audioFlag);
}
else {
flags++;
}
flags &= 0x0f;
if (flags) {
uint8_t next_widx = (widx + 1) % AUDIO_QUEUE_LENGTH;
if (next_widx != ridx) {
AudioFragment & fragment = fragments[widx];
memset(&fragment, 0, sizeof(fragment));
strcpy(current.file, filename);
fragment.repeat = flags - 1;
widx = next_widx;
uint8_t next_widx = (widx + 1) % AUDIO_QUEUE_LENGTH;
if (next_widx != ridx) {
AudioFragment & fragment = fragments[widx];
memset(&fragment, 0, sizeof(fragment));
strcpy(fragment.file, filename);
fragment.repeat = flags & 0x0f;
if (flags & PLAY_NOW)
prioIdx = widx;
widx = next_widx;
if (!busy()) {
state = AUDIO_RESUMING;
CoSetFlag(audioFlag);
}
}
CoSetFlag(audioFlag);
#ifndef SIMU
CoLeaveMutexSection(audioMutex);
+7 -1
View File
@@ -56,6 +56,11 @@ class AudioFragment : public ToneFragment {
extern "C" void DAC_IRQHandler();
#define AUDIO_SLEEPING 0
#define AUDIO_RESUMING 1
#define AUDIO_PLAYING_TONE 2
#define AUDIO_PLAYING_WAV 3
class AudioQueue {
friend void audioTask(void* pdata);
@@ -73,7 +78,7 @@ class AudioQueue {
bool busy()
{
return (state != 0);
return (state != AUDIO_SLEEPING);
}
protected:
@@ -83,6 +88,7 @@ class AudioQueue {
uint8_t state;
uint8_t ridx;
uint8_t widx;
int8_t prioIdx;
AudioFragment fragments[AUDIO_QUEUE_LENGTH];
ToneFragment background; // for vario
+12 -10
View File
@@ -171,19 +171,21 @@ void initDac()
NVIC_EnableIRQ(DACC_IRQn) ;
}
uint16_t wavSamplesArray[2*WAV_BUFFER_SIZE]; /* 2 buffers of 100ms at 12kHz */
uint16_t *wavSamplesBuffer;
extern "C" void DAC_IRQHandler()
{
// Data for PDC must NOT be in flash, PDC needs a RAM source.
if (audioQueue.current.file[0]) {
CoEnterISR(); // Enter the interrupt
CoSetFlag(audioFlag);
CoExitISR(); // Exit the interrupt
wavSamplesBuffer = (wavSamplesBuffer == wavSamplesArray) ? wavSamplesArray+WAV_BUFFER_SIZE : wavSamplesArray;
DACC->DACC_TNPR = CONVERT_PTR(wavSamplesBuffer);
DACC->DACC_TNCR = WAV_BUFFER_SIZE/2;
if (audioQueue.state == AUDIO_PLAYING_WAV) {
if (nextAudioData) {
DACC->DACC_TNPR = CONVERT_PTR(nextAudioData);
DACC->DACC_TNCR = nextAudioSize;
nextAudioData = NULL;
CoEnterISR(); // Enter the interrupt
CoSetFlag(audioFlag);
CoExitISR(); // Exit the interrupt
}
else {
toneStop();
}
}
else {
DACC->DACC_TNPR = CONVERT_PTR(Sine_values);
+2 -3
View File
@@ -46,9 +46,8 @@ extern void start_timer1( void ) ;
extern void initDac( void ) ;
extern void end_sound( void ) ;
#define WAV_BUFFER_SIZE 1200
extern uint16_t wavSamplesArray[2*WAV_BUFFER_SIZE]; /* 2 buffers of 100ms at 12kHz */
extern uint16_t *wavSamplesBuffer;
extern uint16_t *nextAudioData;
extern uint16_t nextAudioSize;
inline void toneStart()
{
+14 -6
View File
@@ -100,11 +100,19 @@ uint8_t frskyGetUserData(char *buffer, uint8_t bufSize)
#endif
#ifdef FRSKY_HUB
void extractLatitudeLongitude(uint32_t * latitude, uint32_t * longitude)
{
div_t qr = div(frskyData.hub.gpsLatitude_bp, 100);
*latitude = ((uint32_t)(qr.quot) * 1000000) + (((uint32_t)(qr.rem) * 10000 + frskyData.hub.gpsLatitude_ap) * 5) / 3;
qr = div(frskyData.hub.gpsLongitude_bp, 100);
*longitude = ((uint32_t)(qr.quot) * 1000000) + (((uint32_t)(qr.rem) * 10000 + frskyData.hub.gpsLongitude_ap) * 5) / 3;
}
inline void getGpsPilotPosition()
{
frskyData.hub.pilotLatitude = ((uint32_t)(frskyData.hub.gpsLatitude_bp / 100) * 1000000) + (((uint32_t)(frskyData.hub.gpsLatitude_bp % 100) * 10000 + frskyData.hub.gpsLatitude_ap) * 5) / 3;
frskyData.hub.pilotLongitude = ((uint32_t)(frskyData.hub.gpsLongitude_bp / 100) * 1000000) + (((uint32_t)(frskyData.hub.gpsLongitude_bp % 100) * 10000 + frskyData.hub.gpsLongitude_ap) * 5) / 3;
uint32_t lat = (uint32_t)(frskyData.hub.gpsLatitude_bp / 100) * 100 + ((uint32_t)(frskyData.hub.gpsLatitude_bp % 100) * 5) / 3;
extractLatitudeLongitude(&frskyData.hub.pilotLatitude, &frskyData.hub.pilotLongitude);
uint32_t lat = frskyData.hub.pilotLatitude / 10000;
uint32_t angle2 = (lat*lat) / 10000;
uint32_t angle4 = angle2 * angle2;
frskyData.hub.distFromEarthAxis = 139*(((uint32_t)10000000-((angle2*(uint32_t)123370)/81)+(angle4/25))/12500);
@@ -113,8 +121,9 @@ inline void getGpsPilotPosition()
inline void getGpsDistance()
{
uint32_t lat = ((uint32_t)(frskyData.hub.gpsLatitude_bp / 100) * 1000000) + (((uint32_t)(frskyData.hub.gpsLatitude_bp % 100) * 10000 + frskyData.hub.gpsLatitude_ap) * 5) / 3;
uint32_t lng = ((uint32_t)(frskyData.hub.gpsLongitude_bp / 100) * 1000000) + (((uint32_t)(frskyData.hub.gpsLongitude_bp % 100) * 10000 + frskyData.hub.gpsLongitude_ap) * 5) / 3;
uint32_t lat, lng;
extractLatitudeLongitude(&lat, &lng);
// printf("lat=%d (%d), long=%d (%d)\n", lat, abs(lat - frskyData.hub.pilotLatitude), lng, abs(lng - frskyData.hub.pilotLongitude));
@@ -1052,7 +1061,6 @@ void displayGpsCoord(uint8_t y, char direction, int16_t bp, int16_t ap)
{
if (frskyData.hub.gpsFix >= 0) {
if (!direction) direction = '-';
lcd_outdezAtt(10*FW, y, bp / 100, LEFT); // ddd before '.'
lcd_putc(lcdLastPos, y, '@');
uint8_t mn = bp % 100;
+2 -2
View File
@@ -643,9 +643,9 @@ void menuProcSd(uint8_t event)
#if defined(PCBARM)
else if (result == STR_PLAY_FILE) {
f_getcwd(lfn, SD_SCREEN_FILE_LENGTH);
strcat_P(lfn, PSTR("/"));
strcat(lfn, "/");
strcat(lfn, reusableBuffer.sd.lines[index]);
audioQueue.playFile(lfn);
audioQueue.playFile(lfn, PLAY_NOW);
}
#endif
}
+1 -1
View File
@@ -276,7 +276,7 @@ bool check(uint8_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTa
#define scrollUD 0
#endif
if(scrollRE || scrollLR || scrollUD || p1valdiff) g_LightOffCounter = g_eeGeneral.lightAutoOff*500; // on keypress turn the light on 5*100
if (scrollRE || scrollLR || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on
if (menuTab) {
uint8_t attr = 0;
+8 -6
View File
@@ -1239,12 +1239,14 @@ void deleteExpoMix(uint8_t expo, uint8_t idx)
{
pauseMixerCalculations();
if (expo) {
memmove(expoaddress(idx), expoaddress(idx+1), (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memset(expoaddress(MAX_EXPOS-1), 0, sizeof(ExpoData));
ExpoData *expo = expoaddress(idx);
memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memset(&g_model.expoData[MAX_EXPOS-1], 0, sizeof(ExpoData));
}
else {
memmove(mixaddress(idx), mixaddress(idx+1), (MAX_MIXERS-(idx+1))*sizeof(MixData));
memset(mixaddress(MAX_MIXERS-1), 0, sizeof(MixData));
MixData *mix = mixaddress(idx);
memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData));
memset(&g_model.mixData[MAX_MIXERS-1], 0, sizeof(MixData));
}
resumeMixerCalculations();
STORE_MODELVARS;
@@ -1257,7 +1259,7 @@ void insertExpoMix(uint8_t expo, uint8_t idx)
if (expo) {
ExpoData *expo = expoaddress(idx);
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memset(expo,0,sizeof(ExpoData));
memset(expo, 0, sizeof(ExpoData));
expo->mode = 3; // pos&neg
expo->chn = s_currCh - 1;
expo->weight = 100;
@@ -1265,7 +1267,7 @@ void insertExpoMix(uint8_t expo, uint8_t idx)
else {
MixData *mix = mixaddress(idx);
memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
memset(mix,0,sizeof(MixData));
memset(mix, 0, sizeof(MixData));
mix->destCh = s_currCh-1;
mix->srcRaw = (s_currCh > 4 ? s_currCh : channel_order(s_currCh));
mix->weight = 100;
+11 -6
View File
@@ -36,9 +36,9 @@ extern "C" {
#include <CoOS.h>
}
#define MIXER_STACK_SIZE 300
#define MENUS_STACK_SIZE 300
#define AUDIO_STACK_SIZE 300
#define MIXER_STACK_SIZE 500
#define MENUS_STACK_SIZE 1000
#define AUDIO_STACK_SIZE 500
#define BT_STACK_SIZE 100
OS_TID mixerTaskId;
@@ -2398,7 +2398,7 @@ void perMain()
// TODO port lightOnStickMove from er9x + flash saving, call checkBacklight()
if(g_LightOffCounter) g_LightOffCounter--;
if(evt) g_LightOffCounter = g_eeGeneral.lightAutoOff*500; // on keypress turn the light on 5*100
if(evt) backlightOn(); // on keypress turn the light on
if (getSwitch(g_eeGeneral.lightSw,0) || g_LightOffCounter)
BACKLIGHT_ON;
@@ -2901,7 +2901,7 @@ inline void open9xInit(OPEN9X_INIT_ARGS)
clearKeyEvents(); //make sure no keys are down before proceeding
lcdSetRefVolt(g_eeGeneral.contrast);
g_LightOffCounter = g_eeGeneral.lightAutoOff*500; //turn on light for x seconds - no need to press key Issue 152
backlightOn();
#if defined(PCBARM)
@@ -2916,6 +2916,11 @@ inline void open9xInit(OPEN9X_INIT_ARGS)
}
}
void backlightOn()
{
g_LightOffCounter = ((uint16_t)g_eeGeneral.lightAutoOff*250) << 1;
}
#if defined(PCBARM)
void mixerTask(void * pdata)
{
@@ -2930,7 +2935,7 @@ void mixerTask(void * pdata)
lastTMR = tmr10ms;
if (s_current_protocol < PROTO_NONE) {
checkTrims();
if (tick10ms) checkTrims();
doMixerCalculations(tmr10ms, tick10ms);
}
+2
View File
@@ -616,6 +616,8 @@ extern uint8_t s_eeDirtyMsk;
#define STORE_MODELVARS eeDirty(EE_MODEL)
#define STORE_GENERALVARS eeDirty(EE_GENERAL)
extern void backlightOn();
#if defined (PCBARM)
#define BACKLIGHT_ON (PWM->PWM_CH_NUM[0].PWM_CDTY = g_eeGeneral.backlightBright)
#define BACKLIGHT_OFF (PWM->PWM_CH_NUM[0].PWM_CDTY = 100)