Code cleanup and refactoring of voice prompts code

This commit is contained in:
Silvano Seva 2022-09-25 19:55:23 +02:00
parent c7c9c3afc5
commit 5fb11322ac
4 changed files with 319 additions and 264 deletions

View File

@ -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. * This is called to speak generic settings int values.
*/ */
void vp_announceSettingsInt(const char* const* stringTableStringPtr, void vp_announceSettingsInt(const char* const* stringTableStringPtr,
const vpQueueFlags_t flags, const vpQueueFlags_t flags, int val);
int val);
/** /**
* This function is called from ui_updateFSM to speak informational screens. * This function is called from ui_updateFSM to speak informational screens.
@ -218,6 +218,10 @@ void vp_announceDisplayTimer();
* *
*/ */
vpQueueFlags_t vp_getVoiceLevelQueueFlags(); vpQueueFlags_t vp_getVoiceLevelQueueFlags();
/**
*
*/
void vp_playMenuBeepIfNeeded(bool firstItem); void vp_playMenuBeepIfNeeded(bool firstItem);
#endif // VOICE_PROMPT_UTILS_H #endif // VOICE_PROMPT_UTILS_H

View File

@ -166,8 +166,8 @@ typedef enum
PROMPT_CARET, // caret PROMPT_CARET, // caret
PROMPT_LEFT_BRACE, // left brace PROMPT_LEFT_BRACE, // left brace
PROMPT_RIGHT_BRACE, // right brace PROMPT_RIGHT_BRACE, // right brace
PROMPT_EDIT, // edit PROMPT_EDIT, // edit
PROMPT_CUSTOM1, // Hotspot PROMPT_CUSTOM1, // Hotspot
PROMPT_CUSTOM2, // ClearNode PROMPT_CUSTOM2, // ClearNode
PROMPT_CUSTOM3, // ShariNode PROMPT_CUSTOM3, // ShariNode
PROMPT_CUSTOM4, // MicroHub PROMPT_CUSTOM4, // MicroHub
@ -226,7 +226,7 @@ typedef enum
vpMedium, vpMedium,
vpHigh vpHigh
} }
VoicePromptVerbosity_T; vpVerbosity_t;
typedef enum typedef enum
{ {
@ -244,8 +244,8 @@ vpSummaryInfoFlags_t;
typedef enum typedef enum
{ {
vpGPSNone=0, vpGPSNone = 0,
vpGPSIntro=0x01, vpGPSIntro = 0x01,
vpGPSFixQuality = 0x02, vpGPSFixQuality = 0x02,
vpGPSFixType = 0x04, vpGPSFixType = 0x04,
vpGPSLatitude = 0x08, vpGPSLatitude = 0x08,
@ -258,13 +258,6 @@ typedef enum
} }
vpGPSInfoFlags_t; vpGPSInfoFlags_t;
typedef struct
{
uint16_t freq;
uint16_t duration;
}
beep_data_t;
/** /**
* Initialise the voice prompt system and load vp table of contents. * Initialise the voice prompt system and load vp table of contents.
@ -342,9 +335,11 @@ bool vp_sequenceNotEmpty();
* play a beep at a given frequency for a given duration. * play a beep at a given frequency for a given duration.
*/ */
void vp_beep(uint16_t freq, uint16_t 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. * Array is freq, duration, ... 0, 0 to terminate series.
*/ */
void vp_beepSeries(const uint16_t* beepSeries); void vp_beepSeries(const uint16_t* beepSeries);
#endif #endif

View File

@ -209,12 +209,13 @@ void vp_announceChannelSummary(const channel_t* channel,
{ {
localFlags |= vpqIncludeDescriptions; localFlags |= vpqIncludeDescriptions;
} }
if (infoFlags&vpSplashInfo)
if ((infoFlags & vpSplashInfo) != 0)
vp_queueStringTableEntry(&currentLanguage->openRTX); vp_queueStringTableEntry(&currentLanguage->openRTX);
// If VFO mode, announce VFO. // If VFO mode, announce VFO.
// channelNumber will be 0 if called from VFO mode. // channelNumber will be 0 if called from VFO mode.
if (infoFlags&vpChannelNameOrVFO) if ((infoFlags & vpChannelNameOrVFO) != 0)
{ {
if (channelNumber == 0) if (channelNumber == 0)
{ {
@ -226,18 +227,22 @@ void vp_announceChannelSummary(const channel_t* channel,
} }
addSilenceIfNeeded(localFlags); addSilenceIfNeeded(localFlags);
} }
if (infoFlags&vpFrequencies)
if ((infoFlags & vpFrequencies) != 0)
vp_announceFrequencies(channel->rx_frequency, channel->tx_frequency, vp_announceFrequencies(channel->rx_frequency, channel->tx_frequency,
localFlags); localFlags);
if (infoFlags&vpRadioMode) if ((infoFlags & vpRadioMode) != 0)
{ {
vp_announceRadioMode(channel->mode, localFlags); vp_announceRadioMode(channel->mode, localFlags);
addSilenceIfNeeded(localFlags); addSilenceIfNeeded(localFlags);
} }
if (infoFlags&vpModeSpecificInfo)
if ((infoFlags & vpModeSpecificInfo) != 0)
{ {
if (channel->mode == OPMODE_FM) switch(channel->mode)
{
case OPMODE_FM:
{ {
vp_announceBandwidth(channel->bandwidth, localFlags); vp_announceBandwidth(channel->bandwidth, localFlags);
addSilenceIfNeeded(localFlags); addSilenceIfNeeded(localFlags);
@ -245,35 +250,43 @@ void vp_announceChannelSummary(const channel_t* channel,
if (channel->fm.rxToneEn || channel->fm.txToneEn) if (channel->fm.rxToneEn || channel->fm.txToneEn)
{ {
vp_announceCTCSS(channel->fm.rxToneEn, channel->fm.rxTone, vp_announceCTCSS(channel->fm.rxToneEn, channel->fm.rxTone,
channel->fm.txToneEn, channel->fm.txTone, localFlags); channel->fm.txToneEn, channel->fm.txTone,
localFlags);
} }
} }
else if (channel->mode == OPMODE_M17) break;
{
case OPMODE_M17:
vp_announceM17Info(channel, false, localFlags); vp_announceM17Info(channel, false, localFlags);
} break;
else if (channel->mode == OPMODE_DMR)
case OPMODE_DMR:
{ {
vp_announceContactWithIndex(channel->dmr.contact_index, localFlags); vp_announceContactWithIndex(channel->dmr.contact_index,
localFlags);
// Force announcement of the words timeslot and colorcode to avoid // Force announcement of the words timeslot and colorcode to avoid
// ambiguity. // ambiguity.
vp_announceTimeslot(channel->dmr.dmr_timeslot, vp_announceTimeslot(channel->dmr.dmr_timeslot,
(localFlags | vpqIncludeDescriptions)); (localFlags | vpqIncludeDescriptions));
vp_announceColorCode(channel->dmr.rxColorCode, channel->dmr.txColorCode, vp_announceColorCode(channel->dmr.rxColorCode,
channel->dmr.txColorCode,
(localFlags | vpqIncludeDescriptions)); (localFlags | vpqIncludeDescriptions));
} }
break;
}
addSilenceIfNeeded(localFlags); addSilenceIfNeeded(localFlags);
} }
if (infoFlags&vpPower) if ((infoFlags & vpPower) != 0)
{ {
float power = dBmToWatt(channel->power); float power = dBmToWatt(channel->power);
vp_anouncePower(power, localFlags); vp_anouncePower(power, localFlags);
addSilenceIfNeeded(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); vp_announceBank(bank, localFlags);
} }
@ -352,6 +365,7 @@ void vp_announceCTCSS(const bool rxToneEnabled, const uint8_t rxTone,
{ {
if (flags & vpqIncludeDescriptions) if (flags & vpqIncludeDescriptions)
vp_queuePrompt(PROMPT_TONE); vp_queuePrompt(PROMPT_TONE);
vp_queueStringTableEntry(&currentLanguage->off); vp_queueStringTableEntry(&currentLanguage->off);
playIfNeeded(flags); playIfNeeded(flags);
return; return;
@ -504,7 +518,8 @@ void vp_announceBank(const uint16_t bank, const vpQueueFlags_t flags)
playIfNeeded(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); clearCurrPromptIfNeeded(flags);
@ -542,14 +557,14 @@ static bool IsCompassCloseEnoughToCardinalPoint()
{ {
float tmg_true = state.gps_data.tmg_true; float tmg_true = state.gps_data.tmg_true;
return (tmg_true < (0+margin) || tmg_true > (360-margin)) || // north return (tmg_true < (0 + margin) || tmg_true > (360 - margin)) || // north
(tmg_true > (90-margin) && tmg_true < (90+margin)) || // east (tmg_true > (90 - margin) && tmg_true < (90 + margin)) || // east
(tmg_true > (180-margin) && tmg_true < (180+margin)) || // south (tmg_true > (180 - margin) && tmg_true < (180 + margin)) || // south
(tmg_true > (270-margin) && tmg_true < (270+margin)) || // west (tmg_true > (270 - margin) && tmg_true < (270 + margin)) || // west
(tmg_true > (45-margin) && tmg_true < (45+margin)) || // n.w. (tmg_true > (45 - margin) && tmg_true < (45 + margin)) || // n.w.
(tmg_true > (135-margin) && tmg_true < (135+margin)) || // s.e. (tmg_true > (135 - margin) && tmg_true < (135 + margin)) || // s.e.
(tmg_true > (225-margin) && tmg_true < (225+margin)) || // s.w. (tmg_true > (225 - margin) && tmg_true < (225 + margin)) || // s.w.
(tmg_true > (315-margin) && tmg_true < (315+margin)); // n.w. (tmg_true > (315 - margin) && tmg_true < (315 + margin)); // n.w.
} }
void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags) void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
@ -632,19 +647,27 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
vp_queueString(buffer, vpAnnounceCommonSymbols); vp_queueString(buffer, vpAnnounceCommonSymbols);
vp_queuePrompt(PROMPT_DEGREES); 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); 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); 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); 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); vp_queuePrompt(PROMPT_WEST);
} }
@ -652,16 +675,16 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
addSilenceIfNeeded(flags); addSilenceIfNeeded(flags);
} }
if (gpsInfoFlags & vpGPSSpeed) if ((gpsInfoFlags & vpGPSSpeed) != 0)
{ {
// speed/altitude: // speed/altitude:
snprintf(buffer, 16, "%4.1fkm/h", state.gps_data.speed); snprintf(buffer, 16, "%4.1fkm/h", state.gps_data.speed);
vp_queuePrompt(PROMPT_SPEED); vp_queuePrompt(PROMPT_SPEED);
vp_queueString(buffer, vp_queueString(buffer, vpAnnounceCommonSymbols |
vpAnnounceCommonSymbols|vpAnnounceLessCommonSymbols); vpAnnounceLessCommonSymbols);
} }
if (gpsInfoFlags & vpGPSAltitude) if ((gpsInfoFlags & vpGPSAltitude) != 0)
{ {
vp_queuePrompt(PROMPT_ALTITUDE); vp_queuePrompt(PROMPT_ALTITUDE);
@ -670,7 +693,7 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
addSilenceIfNeeded(flags); addSilenceIfNeeded(flags);
} }
if (gpsInfoFlags & vpGPSLatitude) if ((gpsInfoFlags & vpGPSLatitude) != 0)
{ {
// lat/long // lat/long
snprintf(buffer, 16, "%8.6f", state.gps_data.latitude); snprintf(buffer, 16, "%8.6f", state.gps_data.latitude);
@ -680,7 +703,7 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
vp_queuePrompt(PROMPT_NORTH); vp_queuePrompt(PROMPT_NORTH);
} }
if (gpsInfoFlags & vpGPSLongitude) if ((gpsInfoFlags & vpGPSLongitude) != 0)
{ {
float longitude = state.gps_data.longitude; float longitude = state.gps_data.longitude;
voicePrompt_t direction = (longitude < 0) ? PROMPT_WEST : PROMPT_EAST; voicePrompt_t direction = (longitude < 0) ? PROMPT_WEST : PROMPT_EAST;
@ -694,11 +717,12 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
addSilenceIfNeeded(flags); addSilenceIfNeeded(flags);
} }
if (gpsInfoFlags & vpGPSSatCount) if ((gpsInfoFlags & vpGPSSatCount) != 0)
{ {
vp_queuePrompt(PROMPT_SATELLITES); vp_queuePrompt(PROMPT_SATELLITES);
vp_queueInteger(state.gps_data.satellites_in_view); vp_queueInteger(state.gps_data.satellites_in_view);
} }
vp_play(); vp_play();
} }
#endif // GPS_PRESENT #endif // GPS_PRESENT
@ -793,6 +817,7 @@ void vp_announceSettingsVoiceLevel(const vpQueueFlags_t flags)
vp_queuePrompt(PROMPT_VOICE_NAME); vp_queuePrompt(PROMPT_VOICE_NAME);
vp_queueStringTableEntry(&currentLanguage->level); vp_queueStringTableEntry(&currentLanguage->level);
} }
vp_queueInteger(state.settings.vpLevel-vpBeep); vp_queueInteger(state.settings.vpLevel-vpBeep);
break; break;
} }
@ -829,35 +854,43 @@ void vp_announceSettingsInt(const char* const* stringTableStringPtr,
void vp_announceScreen(uint8_t ui_screen) void vp_announceScreen(uint8_t ui_screen)
{ {
const vpSummaryInfoFlags_t infoFlags = vpChannelNameOrVFO|vpFrequencies | const vpSummaryInfoFlags_t infoFlags = vpChannelNameOrVFO
vpRadioMode; | vpFrequencies
| vpRadioMode;
switch (ui_screen) switch (ui_screen)
{ {
case MAIN_VFO: case MAIN_VFO:
vp_announceChannelSummary(&state.channel, 0, state.bank, infoFlags); vp_announceChannelSummary(&state.channel, 0, state.bank, infoFlags);
break; break;
case MAIN_MEM: case MAIN_MEM:
vp_announceChannelSummary(&state.channel, state.channel_index+1, vp_announceChannelSummary(&state.channel, state.channel_index+1,
state.bank, infoFlags); state.bank, infoFlags);
break; break;
#ifdef GPS_PRESENT
#ifdef GPS_PRESENT
case MENU_GPS: case MENU_GPS:
vp_announceGPSInfo(vpGPSAll); vp_announceGPSInfo(vpGPSAll);
break; break;
#endif // GPS_PRESENT #endif
case MENU_BACKUP: case MENU_BACKUP:
vp_announceBackupScreen(); vp_announceBackupScreen();
break; break;
case MENU_RESTORE: case MENU_RESTORE:
vp_announceRestoreScreen(); vp_announceRestoreScreen();
break; break;
case MENU_ABOUT: case MENU_ABOUT:
vp_announceAboutScreen(); vp_announceAboutScreen();
break; break;
case SETTINGS_TIMEDATE: case SETTINGS_TIMEDATE:
vp_announceSettingsTimeDate(); vp_announceSettingsTimeDate();
break; break;
case SETTINGS_M17: case SETTINGS_M17:
vp_announceBuffer(&currentLanguage->callsign, vp_announceBuffer(&currentLanguage->callsign,
false, true, state.settings.callsign); false, true, state.settings.callsign);
@ -869,7 +902,7 @@ void vp_announceBuffer(const char* const* stringTableStringPtr,
bool editMode, bool callsign, bool editMode, bool callsign,
const char* buffer) const char* buffer)
{ {
bool isPlaying=vp_isPlaying(); bool isPlaying = vp_isPlaying();
vp_flush(); vp_flush();
@ -881,11 +914,13 @@ void vp_announceBuffer(const char* const* stringTableStringPtr,
vp_queuePrompt(PROMPT_EDIT); vp_queuePrompt(PROMPT_EDIT);
} }
vpFlags_t flags= vpAnnounceCommonSymbols; vpFlags_t flags = vpAnnounceCommonSymbols;
// add edit mode flags to adjust what is spoken. // add edit mode flags to adjust what is spoken.
// extra symbols not relevant when entering callsign. // extra symbols not relevant when entering callsign.
if (editMode && !callsign) if ((editMode == true) && (callsign == false))
flags |= vpAnnounceLessCommonSymbols | vpAnnounceSpace | vpAnnounceASCIIValueForUnknownChars; flags |= vpAnnounceLessCommonSymbols
| vpAnnounceSpace
| vpAnnounceASCIIValueForUnknownChars;
vp_queueString(buffer, flags); vp_queueString(buffer, flags);
@ -894,28 +929,31 @@ void vp_announceBuffer(const char* const* stringTableStringPtr,
void vp_announceDisplayTimer() void vp_announceDisplayTimer()
{ {
bool isPlaying=vp_isPlaying(); bool isPlaying = vp_isPlaying();
vp_flush(); vp_flush();
if (!isPlaying) if (isPlaying == false)
vp_queueStringTableEntry(&currentLanguage->timer); vp_queueStringTableEntry(&currentLanguage->timer);
uint8_t seconds = 0; uint8_t seconds = 0;
uint8_t minutes = 0; uint8_t minutes = 0;
switch (state.settings.display_timer) switch (state.settings.display_timer)
{ {
case TIMER_OFF: case TIMER_OFF:
seconds=0; seconds = 0;
break; break;
case TIMER_5S: case TIMER_5S:
case TIMER_10S: case TIMER_10S:
case TIMER_15S: case TIMER_15S:
case TIMER_20S: case TIMER_20S:
case TIMER_25S: case TIMER_25S:
case TIMER_30S: case TIMER_30S:
seconds=state.settings.display_timer*5; seconds = state.settings.display_timer * 5;
break; break;
case TIMER_1M: case TIMER_1M:
case TIMER_2M: case TIMER_2M:
case TIMER_3M: case TIMER_3M:
@ -923,16 +961,19 @@ void vp_announceDisplayTimer()
case TIMER_5M: case TIMER_5M:
minutes = (state.settings.display_timer - (TIMER_1M - 1)); minutes = (state.settings.display_timer - (TIMER_1M - 1));
break; break;
case TIMER_15M: case TIMER_15M:
case TIMER_30M: case TIMER_30M:
case TIMER_45M: case TIMER_45M:
minutes = 15 * (state.settings.display_timer - (TIMER_15M - 1)); minutes = 15 * (state.settings.display_timer - (TIMER_15M - 1));
break; break;
case TIMER_1H: case TIMER_1H:
minutes = 60; minutes = 60;
break; break;
} }
if (seconds==0 && minutes==0)
if ((seconds == 0) && (minutes == 0))
{ {
vp_queueStringTableEntry(&currentLanguage->off); vp_queueStringTableEntry(&currentLanguage->off);
} }
@ -994,4 +1035,3 @@ void vp_playMenuBeepIfNeeded(bool firstItem)
else else
vp_beep(BEEP_MENU_ITEM, SHORT_BEEP); vp_beep(BEEP_MENU_ITEM, SHORT_BEEP);
} }

View File

@ -33,18 +33,12 @@
static const uint32_t VOICE_PROMPTS_DATA_MAGIC = 0x5056; //'VP' static const uint32_t VOICE_PROMPTS_DATA_MAGIC = 0x5056; //'VP'
static const uint32_t VOICE_PROMPTS_DATA_VERSION = 0x1000; // v1000 OpenRTX static const uint32_t VOICE_PROMPTS_DATA_VERSION = 0x1000; // v1000 OpenRTX
static uint16_t currentBeepDuration=0; const uint16_t BOOT_MELODY[] = {400, 3, 600, 3, 800, 3, 0, 0};
// max buff size for beep series (melody).
#define beepSeriesMax 256
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 VOICE_PROMPTS_TOC_SIZE 350
#define CODEC2_HEADER_SIZE 7 #define CODEC2_HEADER_SIZE 7
#define VP_SEQUENCE_BUF_SIZE 128 #define VP_SEQUENCE_BUF_SIZE 128
#define BEEP_SEQ_BUF_SIZE 256
typedef struct typedef struct
{ {
@ -71,6 +65,14 @@ typedef struct
} }
vpSequence_t; vpSequence_t;
typedef struct
{
uint16_t freq;
uint16_t duration;
}
beepData_t;
static const userDictEntry_t userDictionary[] = static const userDictEntry_t userDictionary[] =
{ {
{"hotspot", PROMPT_CUSTOM1}, // Hotspot {"hotspot", PROMPT_CUSTOM1}, // Hotspot
@ -99,6 +101,11 @@ static uint32_t tableOfContents[VOICE_PROMPTS_TOC_SIZE];
static bool vpDataLoaded = false; static bool vpDataLoaded = false;
static bool voicePromptActive = 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 #ifdef VP_USE_FILESYSTEM
static FILE *vpFile = NULL; static FILE *vpFile = NULL;
#else #else
@ -250,6 +257,61 @@ static bool GetSymbolVPIfItShouldBeAnnounced(char symbol,
(!commonSymbol && announceLessCommonSymbols)); (!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() void vp_init()
{ {
@ -316,16 +378,6 @@ void vp_terminate()
#endif #endif
} }
static void beep_flush()
{
if (currentBeepDuration > 0)
platform_beepStop();
currentBeepDuration = 0;
memset(beepSeriesBuffer, 0, sizeof(beepSeriesBuffer));
beepSeriesIndex=0;
}
void vp_stop() void vp_stop()
{ {
voicePromptActive = false; voicePromptActive = false;
@ -439,6 +491,7 @@ void vp_queueInteger(const int value)
char buf[12] = {0}; // min: -2147483648, max: 2147483647 char buf[12] = {0}; // min: -2147483648, max: 2147483647
if (value < 0) if (value < 0)
vp_queuePrompt(PROMPT_MINUS); vp_queuePrompt(PROMPT_MINUS);
snprintf(buf, 12, "%d", value); snprintf(buf, 12, "%d", value);
vp_queueString(buf, 0); vp_queueString(buf, 0);
} }
@ -481,36 +534,6 @@ void vp_play()
audio_enableAmp(); 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() void vp_tick()
{ {
if (beep_tick()) if (beep_tick())
@ -573,55 +596,48 @@ bool vp_sequenceNotEmpty()
return (vpCurrentSequence.length > 0); return (vpCurrentSequence.length > 0);
} }
// Duration seems to be in tenths of a second.
void vp_beep(uint16_t freq, uint16_t duration) void vp_beep(uint16_t freq, uint16_t duration)
{ {
if (state.settings.vpLevel < vpBeep) if (state.settings.vpLevel < vpBeep)
return; return;
// Do not play a new one if one is playing. // Do not play a new one if one is playing.
if (currentBeepDuration) if (currentBeepDuration != 0)
return ; return;
// avoid extra long beeps! // avoid extra long beeps!
if (duration > 20) if (duration > 20)
duration=20; duration = 20;
currentBeepDuration=duration; beepSeriesBuffer[0].freq = freq;
beepSeriesBuffer[0].duration = duration;
beepSeriesBuffer[1].freq = 0;
beepSeriesBuffer[1].duration = 0;
currentBeepDuration = duration;
beepSeriesIndex = 0;
audio_enableAmp(); audio_enableAmp();
beepSeriesBuffer[0].freq=freq;
beepSeriesBuffer[0].duration=duration;
beepSeriesBuffer[1].freq =0;
beepSeriesBuffer[1].duration =0;
beepSeriesIndex=0;
platform_beepStart(freq); 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) void vp_beepSeries(const uint16_t* beepSeries)
{ {
if (state.settings.vpLevel < vpBeep) if (state.settings.vpLevel < vpBeep)
return; return;
if (currentBeepDuration) if (currentBeepDuration != 0)
return ; return;
audio_enableAmp(); audio_enableAmp();
if (!beepSeries) return; if (beepSeries == NULL)
return;
memcpy(beepSeriesBuffer, beepSeries, beepSeriesMax*sizeof(beep_data_t)); memcpy(beepSeriesBuffer, beepSeries, BEEP_SEQ_BUF_SIZE*sizeof(beepData_t));
// Always ensure that the array is terminated! // Always ensure that the array is terminated!
beepSeriesBuffer[beepSeriesMax-1].freq = 0; beepSeriesBuffer[BEEP_SEQ_BUF_SIZE-1].freq = 0;
beepSeriesBuffer[beepSeriesMax-1].duration = 0; beepSeriesBuffer[BEEP_SEQ_BUF_SIZE-1].duration = 0;
beepSeriesIndex=0; currentBeepDuration = beepSeriesBuffer[0].duration;
currentBeepDuration=beepSeriesBuffer[0].duration; beepSeriesIndex = 0;
delayBeepUntilTick = true; delayBeepUntilTick = true;
} }