diff --git a/src/ersky9x/audio.cpp b/src/ersky9x/audio.cpp index 42fd8fb03..82adb6b24 100644 --- a/src/ersky9x/audio.cpp +++ b/src/ersky9x/audio.cpp @@ -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(¤t, 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> 4; + wavSamplesBuffer[i] = ((uint16_t)0x8000 + ((int16_t)(wavSamplesBuffer[i]))) >> 4; for (; i=0; i--) - bufdata[i] = alawTable[((uint8_t *)bufdata)[i]]; + wavSamplesBuffer[i] = alawTable[((uint8_t *)wavSamplesBuffer)[i]]; for (i=read; iDACC_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(¤t, 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); diff --git a/src/ersky9x/audio.h b/src/ersky9x/audio.h index 08f921b64..f02e8504b 100644 --- a/src/ersky9x/audio.h +++ b/src/ersky9x/audio.h @@ -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 diff --git a/src/ersky9x/sound_driver.cpp b/src/ersky9x/sound_driver.cpp index 28fcd6af8..7fad878a4 100644 --- a/src/ersky9x/sound_driver.cpp +++ b/src/ersky9x/sound_driver.cpp @@ -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); diff --git a/src/ersky9x/sound_driver.h b/src/ersky9x/sound_driver.h index 81d7fa276..22cb65462 100644 --- a/src/ersky9x/sound_driver.h +++ b/src/ersky9x/sound_driver.h @@ -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() { diff --git a/src/frsky.cpp b/src/frsky.cpp index ed8a1dc76..1a8604842 100644 --- a/src/frsky.cpp +++ b/src/frsky.cpp @@ -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; diff --git a/src/general_menus.cpp b/src/general_menus.cpp index 0576e92fd..b0a9ac2b5 100644 --- a/src/general_menus.cpp +++ b/src/general_menus.cpp @@ -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 } diff --git a/src/menus.cpp b/src/menus.cpp index 258cea55c..bf2f32604 100644 --- a/src/menus.cpp +++ b/src/menus.cpp @@ -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; diff --git a/src/model_menus.cpp b/src/model_menus.cpp index 021b41e36..63f124503 100644 --- a/src/model_menus.cpp +++ b/src/model_menus.cpp @@ -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; diff --git a/src/open9x.cpp b/src/open9x.cpp index 404b2a31c..bd370d413 100644 --- a/src/open9x.cpp +++ b/src/open9x.cpp @@ -36,9 +36,9 @@ extern "C" { #include } -#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); } diff --git a/src/open9x.h b/src/open9x.h index c995e6425..ceb4ca5fb 100644 --- a/src/open9x.h +++ b/src/open9x.h @@ -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)