Code cleanup and refactoring of voice prompts code
This commit is contained in:
parent
c7c9c3afc5
commit
5fb11322ac
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue