diff --git a/openrtx/include/core/voicePromptUtils.h b/openrtx/include/core/voicePromptUtils.h index 8e538489..e8114e2a 100644 --- a/openrtx/include/core/voicePromptUtils.h +++ b/openrtx/include/core/voicePromptUtils.h @@ -69,7 +69,7 @@ void vp_announceBandwidth(const uint8_t bandwidth, const vpQueueFlags_t flags); * channelNumber is 1-based, channelIndex is 0-based. */ void vp_announceChannelSummary(const channel_t* channel, - const uint16_t channelNumber, const uint16_t bank, + const uint16_t channelNumber, const uint16_t bank, const vpSummaryInfoFlags_t infoFlags); /** @@ -149,7 +149,8 @@ void vp_announceBank(const uint16_t bank, const vpQueueFlags_t flags); /** * */ -void vp_announceM17Info(const channel_t* channel, bool isEditing, const vpQueueFlags_t flags); +void vp_announceM17Info(const channel_t* channel, bool isEditing, + const vpQueueFlags_t flags); /** * @@ -195,8 +196,7 @@ void vp_announceSettingsOnOffToggle(const char* const* stringTableStringPtr, * This is called to speak generic settings int values. */ void vp_announceSettingsInt(const char* const* stringTableStringPtr, - const vpQueueFlags_t flags, - int val); + const vpQueueFlags_t flags, int val); /** * This function is called from ui_updateFSM to speak informational screens. @@ -218,6 +218,10 @@ void vp_announceDisplayTimer(); * */ vpQueueFlags_t vp_getVoiceLevelQueueFlags(); + +/** + * + */ void vp_playMenuBeepIfNeeded(bool firstItem); #endif // VOICE_PROMPT_UTILS_H diff --git a/openrtx/include/core/voicePrompts.h b/openrtx/include/core/voicePrompts.h index 31c2b7cd..dd27588f 100644 --- a/openrtx/include/core/voicePrompts.h +++ b/openrtx/include/core/voicePrompts.h @@ -166,8 +166,8 @@ typedef enum PROMPT_CARET, // caret PROMPT_LEFT_BRACE, // left brace PROMPT_RIGHT_BRACE, // right brace -PROMPT_EDIT, // edit -PROMPT_CUSTOM1, // Hotspot + PROMPT_EDIT, // edit + PROMPT_CUSTOM1, // Hotspot PROMPT_CUSTOM2, // ClearNode PROMPT_CUSTOM3, // ShariNode PROMPT_CUSTOM4, // MicroHub @@ -226,44 +226,37 @@ typedef enum vpMedium, vpHigh } -VoicePromptVerbosity_T; +vpVerbosity_t; typedef enum { - vpChannelNameOrVFO = 0x01, - vpFrequencies = 0x02, - vpRadioMode = 0x04, - vpModeSpecificInfo = 0x08, - vpPower = 0x10, + vpChannelNameOrVFO = 0x01, + vpFrequencies = 0x02, + vpRadioMode = 0x04, + vpModeSpecificInfo = 0x08, + vpPower = 0x10, vpBankNameOrAllChannels = 0x20, - vpSplashInfo = 0x40, - vpAllInfoExceptSplash = 0x3f, - vpAllInfo = 0xff -} + vpSplashInfo = 0x40, + vpAllInfoExceptSplash = 0x3f, + vpAllInfo = 0xff +} vpSummaryInfoFlags_t; typedef enum { - vpGPSNone=0, - vpGPSIntro=0x01, + vpGPSNone = 0, + vpGPSIntro = 0x01, vpGPSFixQuality = 0x02, - vpGPSFixType = 0x04, - vpGPSLatitude = 0x08, - vpGPSLongitude = 0x10, - vpGPSSpeed = 0x20, - vpGPSAltitude = 0x40, - vpGPSDirection = 0x80, - vpGPSSatCount = 0x100, - vpGPSAll = 0x1ff, -} -vpGPSInfoFlags_t; - -typedef struct -{ - uint16_t freq; - uint16_t duration; + vpGPSFixType = 0x04, + vpGPSLatitude = 0x08, + vpGPSLongitude = 0x10, + vpGPSSpeed = 0x20, + vpGPSAltitude = 0x40, + vpGPSDirection = 0x80, + vpGPSSatCount = 0x100, + vpGPSAll = 0x1ff, } -beep_data_t; +vpGPSInfoFlags_t; /** @@ -342,9 +335,11 @@ bool vp_sequenceNotEmpty(); * play a beep at a given frequency for a given duration. */ void vp_beep(uint16_t freq, uint16_t duration); + /** - * play a series of beeps at a given frequency for a given duration. + * Play a series of beeps at a given frequency for a given duration. * Array is freq, duration, ... 0, 0 to terminate series. */ void vp_beepSeries(const uint16_t* beepSeries); + #endif diff --git a/openrtx/src/core/voicePromptUtils.c b/openrtx/src/core/voicePromptUtils.c index 5e7f97bb..9cc9332f 100644 --- a/openrtx/src/core/voicePromptUtils.c +++ b/openrtx/src/core/voicePromptUtils.c @@ -194,7 +194,7 @@ void vp_anouncePower(const float power, const vpQueueFlags_t flags) } void vp_announceChannelSummary(const channel_t* channel, - const uint16_t channelNumber, const uint16_t bank, + const uint16_t channelNumber, const uint16_t bank, const vpSummaryInfoFlags_t infoFlags) { if (channel == NULL) @@ -209,12 +209,13 @@ void vp_announceChannelSummary(const channel_t* channel, { localFlags |= vpqIncludeDescriptions; } - if (infoFlags&vpSplashInfo) + + if ((infoFlags & vpSplashInfo) != 0) vp_queueStringTableEntry(¤tLanguage->openRTX); // If VFO mode, announce VFO. // channelNumber will be 0 if called from VFO mode. - if (infoFlags&vpChannelNameOrVFO) + if ((infoFlags & vpChannelNameOrVFO) != 0) { if (channelNumber == 0) { @@ -226,54 +227,66 @@ void vp_announceChannelSummary(const channel_t* channel, } addSilenceIfNeeded(localFlags); } - if (infoFlags&vpFrequencies) + + if ((infoFlags & vpFrequencies) != 0) vp_announceFrequencies(channel->rx_frequency, channel->tx_frequency, localFlags); - - if (infoFlags&vpRadioMode) + + if ((infoFlags & vpRadioMode) != 0) { vp_announceRadioMode(channel->mode, localFlags); addSilenceIfNeeded(localFlags); } - if (infoFlags&vpModeSpecificInfo) + + if ((infoFlags & vpModeSpecificInfo) != 0) { - if (channel->mode == OPMODE_FM) + switch(channel->mode) { - vp_announceBandwidth(channel->bandwidth, localFlags); - addSilenceIfNeeded(localFlags); - - if (channel->fm.rxToneEn || channel->fm.txToneEn) + case OPMODE_FM: { - vp_announceCTCSS(channel->fm.rxToneEn, channel->fm.rxTone, - channel->fm.txToneEn, channel->fm.txTone, localFlags); - } - } - else if (channel->mode == OPMODE_M17) - { - vp_announceM17Info(channel, false, localFlags); - } - else if (channel->mode == OPMODE_DMR) - { - vp_announceContactWithIndex(channel->dmr.contact_index, localFlags); + vp_announceBandwidth(channel->bandwidth, localFlags); + addSilenceIfNeeded(localFlags); - // Force announcement of the words timeslot and colorcode to avoid - // ambiguity. - vp_announceTimeslot(channel->dmr.dmr_timeslot, - (localFlags | vpqIncludeDescriptions)); - vp_announceColorCode(channel->dmr.rxColorCode, channel->dmr.txColorCode, - (localFlags | vpqIncludeDescriptions)); + if (channel->fm.rxToneEn || channel->fm.txToneEn) + { + vp_announceCTCSS(channel->fm.rxToneEn, channel->fm.rxTone, + channel->fm.txToneEn, channel->fm.txTone, + localFlags); + } + } + break; + + case OPMODE_M17: + vp_announceM17Info(channel, false, localFlags); + break; + + case OPMODE_DMR: + { + vp_announceContactWithIndex(channel->dmr.contact_index, + localFlags); + + // Force announcement of the words timeslot and colorcode to avoid + // ambiguity. + vp_announceTimeslot(channel->dmr.dmr_timeslot, + (localFlags | vpqIncludeDescriptions)); + vp_announceColorCode(channel->dmr.rxColorCode, + channel->dmr.txColorCode, + (localFlags | vpqIncludeDescriptions)); + } + break; } addSilenceIfNeeded(localFlags); } - - if (infoFlags&vpPower) + + if ((infoFlags & vpPower) != 0) { float power = dBmToWatt(channel->power); vp_anouncePower(power, localFlags); addSilenceIfNeeded(localFlags); } - if ((infoFlags&vpBankNameOrAllChannels) &&(channelNumber > 0)) // i.e. not called from VFO. + + if (((infoFlags & vpBankNameOrAllChannels) != 0) && (channelNumber > 0)) // i.e. not called from VFO. { vp_announceBank(bank, localFlags); } @@ -352,6 +365,7 @@ void vp_announceCTCSS(const bool rxToneEnabled, const uint8_t rxTone, { if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_TONE); + vp_queueStringTableEntry(¤tLanguage->off); playIfNeeded(flags); return; @@ -392,7 +406,7 @@ void vp_announceCTCSS(const bool rxToneEnabled, const uint8_t rxTone, vp_queuePrompt(PROMPT_TRANSMIT); vp_queuePrompt(PROMPT_TONE); } - + snprintf(buffer, 16, "%3.1f", ctcss_tone[txTone] / 10.0f); vp_queueString(buffer, vpAnnounceCommonSymbols); vp_queuePrompt(PROMPT_HERTZ); @@ -444,7 +458,7 @@ bool vp_announceContactWithIndex(const uint16_t index, const vpQueueFlags_t flag return false; vp_announceContact(&contact, flags); - + return true; } @@ -504,15 +518,16 @@ void vp_announceBank(const uint16_t bank, const vpQueueFlags_t flags) playIfNeeded(flags); } -void vp_announceM17Info(const channel_t* channel, bool isEditing, const vpQueueFlags_t flags) +void vp_announceM17Info(const channel_t* channel, bool isEditing, + const vpQueueFlags_t flags) { clearCurrPromptIfNeeded(flags); - + if (flags & vpqIncludeDescriptions) { vp_queuePrompt(PROMPT_DEST_ID); } - + if (isEditing) { vp_queuePrompt(PROMPT_EDIT); @@ -530,7 +545,7 @@ void vp_announceM17Info(const channel_t* channel, bool isEditing, const vpQueueF { vp_queueStringTableEntry(¤tLanguage->broadcast); } - + playIfNeeded(flags); } @@ -541,15 +556,15 @@ void vp_announceM17Info(const channel_t* channel, bool isEditing, const vpQueueF static bool IsCompassCloseEnoughToCardinalPoint() { float tmg_true = state.gps_data.tmg_true; - - return (tmg_true < (0+margin) || tmg_true > (360-margin)) || // north - (tmg_true > (90-margin) && tmg_true < (90+margin)) || // east - (tmg_true > (180-margin) && tmg_true < (180+margin)) || // south - (tmg_true > (270-margin) && tmg_true < (270+margin)) || // west - (tmg_true > (45-margin) && tmg_true < (45+margin)) || // n.w. - (tmg_true > (135-margin) && tmg_true < (135+margin)) || // s.e. - (tmg_true > (225-margin) && tmg_true < (225+margin)) || // s.w. - (tmg_true > (315-margin) && tmg_true < (315+margin)); // n.w. + + return (tmg_true < (0 + margin) || tmg_true > (360 - margin)) || // north + (tmg_true > (90 - margin) && tmg_true < (90 + margin)) || // east + (tmg_true > (180 - margin) && tmg_true < (180 + margin)) || // south + (tmg_true > (270 - margin) && tmg_true < (270 + margin)) || // west + (tmg_true > (45 - margin) && tmg_true < (45 + margin)) || // n.w. + (tmg_true > (135 - margin) && tmg_true < (135 + margin)) || // s.e. + (tmg_true > (225 - margin) && tmg_true < (225 + margin)) || // s.w. + (tmg_true > (315 - margin) && tmg_true < (315 + margin)); // n.w. } void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) @@ -557,7 +572,7 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) vp_flush(); vpQueueFlags_t flags = vpqIncludeDescriptions | vpqAddSeparatingSilence; - + if (gpsInfoFlags & vpGPSIntro) { vp_queueStringTableEntry(¤tLanguage->gps); @@ -565,11 +580,11 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) { vp_queueStringTableEntry(¤tLanguage->off); vp_play(); - + return; } } - + if (gpsInfoFlags & vpGPSFixQuality) { switch (state.gps_data.fix_quality) @@ -604,7 +619,7 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) addSilenceIfNeeded(flags); } - + if (gpsInfoFlags & vpGPSFixType) { switch (state.gps_data.fix_type) @@ -620,9 +635,9 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) addSilenceIfNeeded(flags); } - + char buffer[17] = "\0"; - + if (gpsInfoFlags & vpGPSDirection) { vp_queuePrompt(PROMPT_COMPASS); @@ -632,36 +647,44 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) vp_queueString(buffer, vpAnnounceCommonSymbols); vp_queuePrompt(PROMPT_DEGREES); } - if (state.gps_data.tmg_true < (45+margin) || state.gps_data.tmg_true > (315-margin)) + + if ((state.gps_data.tmg_true < (45 + margin)) || + (state.gps_data.tmg_true > (315 - margin))) { vp_queuePrompt(PROMPT_NORTH); } - if (state.gps_data.tmg_true > (45-margin) && state.gps_data.tmg_true < (135+margin)) + + if ((state.gps_data.tmg_true > (45 - margin)) && + (state.gps_data.tmg_true < (135 + margin))) { vp_queuePrompt(PROMPT_EAST); } - if (state.gps_data.tmg_true > (135-margin) && state.gps_data.tmg_true < (225+margin)) + + if ((state.gps_data.tmg_true > (135 - margin)) && + (state.gps_data.tmg_true < (225 + margin))) { vp_queuePrompt(PROMPT_SOUTH); } - if (state.gps_data.tmg_true > (225-margin) && state.gps_data.tmg_true < (315+margin)) + + if ((state.gps_data.tmg_true > (225 - margin)) && + (state.gps_data.tmg_true < (315 + margin))) { vp_queuePrompt(PROMPT_WEST); } addSilenceIfNeeded(flags); } - - if (gpsInfoFlags & vpGPSSpeed) + + if ((gpsInfoFlags & vpGPSSpeed) != 0) { // speed/altitude: snprintf(buffer, 16, "%4.1fkm/h", state.gps_data.speed); vp_queuePrompt(PROMPT_SPEED); - vp_queueString(buffer, - vpAnnounceCommonSymbols|vpAnnounceLessCommonSymbols); + vp_queueString(buffer, vpAnnounceCommonSymbols | + vpAnnounceLessCommonSymbols); } - - if (gpsInfoFlags & vpGPSAltitude) + + if ((gpsInfoFlags & vpGPSAltitude) != 0) { vp_queuePrompt(PROMPT_ALTITUDE); @@ -669,8 +692,8 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) vp_queueString(buffer, vpAnnounceCommonSymbols); addSilenceIfNeeded(flags); } - - if (gpsInfoFlags & vpGPSLatitude) + + if ((gpsInfoFlags & vpGPSLatitude) != 0) { // lat/long snprintf(buffer, 16, "%8.6f", state.gps_data.latitude); @@ -679,8 +702,8 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) vp_queueString(buffer, vpAnnounceCommonSymbols); vp_queuePrompt(PROMPT_NORTH); } - - if (gpsInfoFlags & vpGPSLongitude) + + if ((gpsInfoFlags & vpGPSLongitude) != 0) { float longitude = state.gps_data.longitude; voicePrompt_t direction = (longitude < 0) ? PROMPT_WEST : PROMPT_EAST; @@ -693,12 +716,13 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) vp_queuePrompt(direction); addSilenceIfNeeded(flags); } - - if (gpsInfoFlags & vpGPSSatCount) + + if ((gpsInfoFlags & vpGPSSatCount) != 0) { vp_queuePrompt(PROMPT_SATELLITES); vp_queueInteger(state.gps_data.satellites_in_view); } + vp_play(); } #endif // GPS_PRESENT @@ -761,7 +785,7 @@ void vp_announceSettingsTimeDate() local_time.year); vp_queueString(buffer, vpAnnounceCommonSymbols | vpAnnounceLessCommonSymbols); - + vp_queuePrompt(PROMPT_SILENCE); vp_queuePrompt(PROMPT_SILENCE); @@ -793,6 +817,7 @@ void vp_announceSettingsVoiceLevel(const vpQueueFlags_t flags) vp_queuePrompt(PROMPT_VOICE_NAME); vp_queueStringTableEntry(¤tLanguage->level); } + vp_queueInteger(state.settings.vpLevel-vpBeep); break; } @@ -829,110 +854,126 @@ void vp_announceSettingsInt(const char* const* stringTableStringPtr, void vp_announceScreen(uint8_t ui_screen) { - const vpSummaryInfoFlags_t infoFlags = vpChannelNameOrVFO|vpFrequencies | - vpRadioMode; + const vpSummaryInfoFlags_t infoFlags = vpChannelNameOrVFO + | vpFrequencies + | vpRadioMode; switch (ui_screen) { - case MAIN_VFO: - vp_announceChannelSummary(&state.channel, 0, state.bank, infoFlags); - break; - case MAIN_MEM: - vp_announceChannelSummary(&state.channel, state.channel_index+1, - state.bank, infoFlags); - break; -#ifdef GPS_PRESENT - case MENU_GPS: - vp_announceGPSInfo(vpGPSAll); - break; -#endif // GPS_PRESENT - case MENU_BACKUP: - vp_announceBackupScreen(); - break; - case MENU_RESTORE: - vp_announceRestoreScreen(); - break; - case MENU_ABOUT: - vp_announceAboutScreen(); - break; - case SETTINGS_TIMEDATE: - vp_announceSettingsTimeDate(); - break; - case SETTINGS_M17: - vp_announceBuffer(¤tLanguage->callsign, - false, true, state.settings.callsign); - break; - } + case MAIN_VFO: + vp_announceChannelSummary(&state.channel, 0, state.bank, infoFlags); + break; + + case MAIN_MEM: + vp_announceChannelSummary(&state.channel, state.channel_index+1, + state.bank, infoFlags); + break; + + #ifdef GPS_PRESENT + case MENU_GPS: + vp_announceGPSInfo(vpGPSAll); + break; + #endif + + case MENU_BACKUP: + vp_announceBackupScreen(); + break; + + case MENU_RESTORE: + vp_announceRestoreScreen(); + break; + + case MENU_ABOUT: + vp_announceAboutScreen(); + break; + + case SETTINGS_TIMEDATE: + vp_announceSettingsTimeDate(); + break; + + case SETTINGS_M17: + vp_announceBuffer(¤tLanguage->callsign, + false, true, state.settings.callsign); + break; + } } -void vp_announceBuffer(const char* const* stringTableStringPtr, +void vp_announceBuffer(const char* const* stringTableStringPtr, bool editMode, bool callsign, const char* buffer) { - bool isPlaying=vp_isPlaying(); - + bool isPlaying = vp_isPlaying(); + vp_flush(); - + if (!isPlaying) { vp_queueStringTableEntry(stringTableStringPtr); - + if (editMode) vp_queuePrompt(PROMPT_EDIT); } - - vpFlags_t flags= vpAnnounceCommonSymbols; + + vpFlags_t flags = vpAnnounceCommonSymbols; // add edit mode flags to adjust what is spoken. // extra symbols not relevant when entering callsign. - if (editMode && !callsign) - flags |= vpAnnounceLessCommonSymbols | vpAnnounceSpace | vpAnnounceASCIIValueForUnknownChars; - + if ((editMode == true) && (callsign == false)) + flags |= vpAnnounceLessCommonSymbols + | vpAnnounceSpace + | vpAnnounceASCIIValueForUnknownChars; + vp_queueString(buffer, flags); - - vp_play(); + + vp_play(); } void vp_announceDisplayTimer() { - bool isPlaying=vp_isPlaying(); - + bool isPlaying = vp_isPlaying(); + vp_flush(); - - if (!isPlaying) + + if (isPlaying == false) vp_queueStringTableEntry(¤tLanguage->timer); + uint8_t seconds = 0; uint8_t minutes = 0; - + switch (state.settings.display_timer) { - case TIMER_OFF: - seconds=0; - break; - case TIMER_5S: - case TIMER_10S: - case TIMER_15S: - case TIMER_20S: - case TIMER_25S: - case TIMER_30S: - seconds=state.settings.display_timer*5; - break; - case TIMER_1M: - case TIMER_2M: - case TIMER_3M: - case TIMER_4M: - case TIMER_5M: - minutes = (state.settings.display_timer - (TIMER_1M - 1)); - break; - case TIMER_15M: - case TIMER_30M: - case TIMER_45M: - minutes = 15 * (state.settings.display_timer - (TIMER_15M - 1)); - break; - case TIMER_1H: - minutes = 60; - break; + case TIMER_OFF: + seconds = 0; + break; + + case TIMER_5S: + case TIMER_10S: + case TIMER_15S: + case TIMER_20S: + case TIMER_25S: + case TIMER_30S: + seconds = state.settings.display_timer * 5; + break; + + case TIMER_1M: + case TIMER_2M: + case TIMER_3M: + case TIMER_4M: + case TIMER_5M: + minutes = (state.settings.display_timer - (TIMER_1M - 1)); + break; + + case TIMER_15M: + case TIMER_30M: + case TIMER_45M: + minutes = 15 * (state.settings.display_timer - (TIMER_15M - 1)); + break; + + case TIMER_1H: + minutes = 60; + break; } - if (seconds==0 && minutes==0) + + if ((seconds == 0) && (minutes == 0)) { vp_queueStringTableEntry(¤tLanguage->off); } @@ -946,7 +987,7 @@ void vp_announceDisplayTimer() vp_queueInteger(minutes); vp_queuePrompt(PROMPT_MINUTES); } - + vp_play(); } @@ -985,7 +1026,7 @@ vpQueueFlags_t vp_getVoiceLevelQueueFlags() void vp_playMenuBeepIfNeeded(bool firstItem) { -// Since menus talk at levels above beep, there's no need to run this or you'll +// Since menus talk at levels above beep, there's no need to run this or you'll // get an unwanted click. if (state.settings.vpLevel != vpBeep) return; @@ -994,4 +1035,3 @@ void vp_playMenuBeepIfNeeded(bool firstItem) else vp_beep(BEEP_MENU_ITEM, SHORT_BEEP); } - diff --git a/openrtx/src/core/voicePrompts.c b/openrtx/src/core/voicePrompts.c index 03ae88b5..45d1e974 100644 --- a/openrtx/src/core/voicePrompts.c +++ b/openrtx/src/core/voicePrompts.c @@ -33,18 +33,12 @@ static const uint32_t VOICE_PROMPTS_DATA_MAGIC = 0x5056; //'VP' static const uint32_t VOICE_PROMPTS_DATA_VERSION = 0x1000; // v1000 OpenRTX -static uint16_t currentBeepDuration=0; -// max buff size for beep series (melody). -#define beepSeriesMax 256 +const uint16_t BOOT_MELODY[] = {400, 3, 600, 3, 800, 3, 0, 0}; -static beep_data_t beepSeriesBuffer[beepSeriesMax]; -static uint8_t beepSeriesIndex = 0; - static bool delayBeepUntilTick=false; - const uint16_t BOOT_MELODY[]={400, 3, 600, 3, 800, 3, 0, 0}; - #define VOICE_PROMPTS_TOC_SIZE 350 #define CODEC2_HEADER_SIZE 7 #define VP_SEQUENCE_BUF_SIZE 128 +#define BEEP_SEQ_BUF_SIZE 256 typedef struct { @@ -71,6 +65,14 @@ typedef struct } vpSequence_t; +typedef struct +{ + uint16_t freq; + uint16_t duration; +} +beepData_t; + + static const userDictEntry_t userDictionary[] = { {"hotspot", PROMPT_CUSTOM1}, // Hotspot @@ -99,6 +101,11 @@ static uint32_t tableOfContents[VOICE_PROMPTS_TOC_SIZE]; static bool vpDataLoaded = false; static bool voicePromptActive = false; +static beepData_t beepSeriesBuffer[BEEP_SEQ_BUF_SIZE]; +static uint16_t currentBeepDuration = 0; +static uint8_t beepSeriesIndex = 0; +static bool delayBeepUntilTick = false; + #ifdef VP_USE_FILESYSTEM static FILE *vpFile = NULL; #else @@ -250,6 +257,61 @@ static bool GetSymbolVPIfItShouldBeAnnounced(char symbol, (!commonSymbol && announceLessCommonSymbols)); } +/** + * \internal + * Stop an ongoing beep, if present, and clear all the beep management + * variables. + */ +static void beep_flush() +{ + if (currentBeepDuration > 0) + platform_beepStop(); + + memset(beepSeriesBuffer, 0, sizeof(beepSeriesBuffer)); + currentBeepDuration = 0; + beepSeriesIndex = 0; +} + +/** + * \internal + * Function managing beep update. + */ +static bool beep_tick() +{ + if (currentBeepDuration > 0) + { + if (delayBeepUntilTick) + { + platform_beepStart(beepSeriesBuffer[beepSeriesIndex].freq); + delayBeepUntilTick=false; + } + + currentBeepDuration--; + if (currentBeepDuration == 0) + { + platform_beepStop(); + + // see if there are any more in the series to play. + if ((beepSeriesBuffer[beepSeriesIndex+1].freq != 0) && + (beepSeriesBuffer[beepSeriesIndex+1].duration != 0)) + { + beepSeriesIndex++; + currentBeepDuration = beepSeriesBuffer[beepSeriesIndex].duration; + platform_beepStart(beepSeriesBuffer[beepSeriesIndex].freq); + } + else + { + // Clear all variables for beep management + beep_flush(); + } + } + + return true; + } + + return false; +} + void vp_init() { @@ -316,16 +378,6 @@ void vp_terminate() #endif } -static void beep_flush() -{ - if (currentBeepDuration > 0) - platform_beepStop(); - - currentBeepDuration = 0; - memset(beepSeriesBuffer, 0, sizeof(beepSeriesBuffer)); - beepSeriesIndex=0; -} - void vp_stop() { voicePromptActive = false; @@ -439,6 +491,7 @@ void vp_queueInteger(const int value) char buf[12] = {0}; // min: -2147483648, max: 2147483647 if (value < 0) vp_queuePrompt(PROMPT_MINUS); + snprintf(buf, 12, "%d", value); vp_queueString(buf, 0); } @@ -481,36 +534,6 @@ void vp_play() audio_enableAmp(); } -static bool beep_tick() -{ - if (currentBeepDuration > 0) - { - if (delayBeepUntilTick) - { - platform_beepStart(beepSeriesBuffer[beepSeriesIndex].freq); - delayBeepUntilTick=false; - } - currentBeepDuration--; - if (currentBeepDuration==0) - { - platform_beepStop(); - // see if there are any more in the series to play. - if (beepSeriesBuffer[beepSeriesIndex+1].freq && beepSeriesBuffer[beepSeriesIndex+1].duration) - { - beepSeriesIndex++; - currentBeepDuration=beepSeriesBuffer[beepSeriesIndex].duration; - platform_beepStart(beepSeriesBuffer[beepSeriesIndex].freq); - } - else - { - beep_flush(); - } - } - return true; - } - return false; -} - void vp_tick() { if (beep_tick()) @@ -573,55 +596,48 @@ bool vp_sequenceNotEmpty() return (vpCurrentSequence.length > 0); } -// Duration seems to be in tenths of a second. void vp_beep(uint16_t freq, uint16_t duration) { if (state.settings.vpLevel < vpBeep) return; - + // Do not play a new one if one is playing. - if (currentBeepDuration) - return ; + if (currentBeepDuration != 0) + return; + // avoid extra long beeps! if (duration > 20) - duration=20; - - currentBeepDuration=duration; + duration = 20; + + beepSeriesBuffer[0].freq = freq; + beepSeriesBuffer[0].duration = duration; + beepSeriesBuffer[1].freq = 0; + beepSeriesBuffer[1].duration = 0; + currentBeepDuration = duration; + beepSeriesIndex = 0; audio_enableAmp(); - beepSeriesBuffer[0].freq=freq; - beepSeriesBuffer[0].duration=duration; - beepSeriesBuffer[1].freq =0; - beepSeriesBuffer[1].duration =0; - beepSeriesIndex=0; platform_beepStart(freq); - // See BeepTick for termination. } -/* -We delay the playing of the melody until the first time vp_tick is called -because there is a sleep on the splash screen which would make the first note -play extra long. -*/ void vp_beepSeries(const uint16_t* beepSeries) { if (state.settings.vpLevel < vpBeep) return; - - if (currentBeepDuration) - return ; - + + if (currentBeepDuration != 0) + return; + audio_enableAmp(); - if (!beepSeries) return; - - memcpy(beepSeriesBuffer, beepSeries, beepSeriesMax*sizeof(beep_data_t)); + if (beepSeries == NULL) + return; + + memcpy(beepSeriesBuffer, beepSeries, BEEP_SEQ_BUF_SIZE*sizeof(beepData_t)); // Always ensure that the array is terminated! - beepSeriesBuffer[beepSeriesMax-1].freq = 0; - beepSeriesBuffer[beepSeriesMax-1].duration = 0; - - beepSeriesIndex=0; - currentBeepDuration=beepSeriesBuffer[0].duration; - delayBeepUntilTick = true; + beepSeriesBuffer[BEEP_SEQ_BUF_SIZE-1].freq = 0; + beepSeriesBuffer[BEEP_SEQ_BUF_SIZE-1].duration = 0; + + currentBeepDuration = beepSeriesBuffer[0].duration; + beepSeriesIndex = 0; + delayBeepUntilTick = true; } - -