Refactored voicePromptUtils.h and voicePromptUtils.c

md1702
Silvano Seva 2022-08-16 21:20:51 +02:00
rodzic c5f109efa5
commit 42b262c437
7 zmienionych plików z 457 dodań i 260 usunięć

Wyświetl plik

@ -16,10 +16,8 @@
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
// This file contains functions for announcing radio operations using the
// building blocks in voicePrompts.h/c.
#ifndef VOICE_PROMPT_UTILS_H_INCLUDED
#define VOICE_PROMPT_UTILS_H_INCLUDED
#ifndef VOICE_PROMPT_UTILS_H
#define VOICE_PROMPT_UTILS_H
#include "cps.h"
#include "ui/ui_strings.h"
@ -37,47 +35,162 @@ When an announceXX function is called in isolation, vpqInit|vpqPlayImmediately
should be used to ensure that the message interupts the current prompt and
plays immediately.
*/
void announceVFO();
void announceChannelName(channel_t* channel, uint16_t channelIndex,
VoicePromptQueueFlags_T flags);
void vpQueueFrequency(freq_t freq);
void announceFrequencies(freq_t rx, freq_t tx, VoicePromptQueueFlags_T flags);
void announceRadioMode(uint8_t mode, VoicePromptQueueFlags_T flags);
void announceBandwidth(uint8_t bandwidth, VoicePromptQueueFlags_T flags);
void announceChannelSummary(channel_t* channel, uint16_t channelIndex,
uint16_t bank);
void AnnounceInputChar(char ch);
void announceInputReceiveOrTransmit(bool tx, VoicePromptQueueFlags_T flags);
void ReplayLastPrompt();
void announceError(VoicePromptQueueFlags_T flags);
/**
*
*/
void vp_announceVFO();
/**
*
*/
void vp_announceChannelName(const channel_t* channel,
const uint16_t channelIndex,
const vpQueueFlags_t flags);
/**
*
*/
void vp_queueFrequency(const freq_t freq);
/**
*
*/
void vp_announceFrequencies(const freq_t rx, const freq_t tx,
const vpQueueFlags_t flags);
/**
*
*/
void vp_announceRadioMode(const uint8_t mode, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceBandwidth(const uint8_t bandwidth, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceChannelSummary(const channel_t* channel,
const uint16_t channelIndex, const uint16_t bank);
/**
*
*/
void vp_announceInputChar(const char ch);
/**
*
*/
void vp_announceInputReceiveOrTransmit(const bool tx, const vpQueueFlags_t flags);
/**
*
*/
void vp_replayLastPrompt();
/**
*
*/
void vp_announceError(const vpQueueFlags_t flags);
/*
This function first tries to see if we have a prompt for the text
passed in and if so, queues it, but if not, just spells the text
character by character.
*/
void announceText(char* text, VoicePromptQueueFlags_T flags);
void announceCTCSS(bool rxToneEnabled, uint8_t rxTone, bool txToneEnabled,
uint8_t txTone, VoicePromptQueueFlags_T flags);
void anouncePower(float power, VoicePromptQueueFlags_T flags);
void announceBrightness(uint8_t brightness, VoicePromptQueueFlags_T flags);
void announceSquelch(uint8_t squelch, VoicePromptQueueFlags_T flags);
void announceContact(contact_t* contact, VoicePromptQueueFlags_T flags);
void announceContactWithIndex(uint16_t index, VoicePromptQueueFlags_T flags);
void announceTimeslot(uint8_t timeslot, VoicePromptQueueFlags_T flags);
void announceColorCode(uint8_t rxColorCode, uint8_t txColorCode,
VoicePromptQueueFlags_T flags);
void announceBank(uint16_t bank, VoicePromptQueueFlags_T flags);
void announceM17Info(channel_t* channel, VoicePromptQueueFlags_T flags);
#ifdef GPS_PRESENT
void announceGPSInfo();
#endif // GPS_PRESENT
void announceAboutScreen();
void announceBackupScreen();
void announceRestoreScreen();
#ifdef RTC_PRESENT
void announceSettingsTimeDate();
#endif // RTC_PRESENT
VoicePromptQueueFlags_T GetQueueFlagsForVoiceLevel();
#endif // VOICE_PROMPT_UTILS_H_INCLUDED
/**
*
*/
void vp_announceText(const char* text, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceCTCSS(const bool rxToneEnabled, const uint8_t rxTone,
const bool txToneEnabled, const uint8_t txTone,
const vpQueueFlags_t flags);
/**
*
*/
void vp_anouncePower(const float power, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceBrightness(const uint8_t brightness, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceSquelch(const uint8_t squelch,const vpQueueFlags_t flags);
/**
*
*/
void vp_announceContact(const contact_t* contact, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceContactWithIndex(const uint16_t index, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceTimeslot(const uint8_t timeslot, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceColorCode(const uint8_t rxColorCode, const uint8_t txColorCode,
const vpQueueFlags_t flags);
/**
*
*/
void vp_announceBank(const uint16_t bank, const vpQueueFlags_t flags);
/**
*
*/
void vp_announceM17Info(const channel_t* channel, const vpQueueFlags_t flags);
/**
*
*/
#ifdef GPS_PRESENT
void vp_announceGPSInfo();
#endif
/**
*
*/
void vp_announceAboutScreen();
/**
*
*/
void vp_announceBackupScreen();
/**
*
*/
void vp_announceRestoreScreen();
/**
*
*/
#ifdef RTC_PRESENT
void vp_announceSettingsTimeDate();
#endif
/**
*
*/
vpQueueFlags_t vp_getVoiceLevelQueueFlags();
#endif // VOICE_PROMPT_UTILS_H

Wyświetl plik

@ -184,6 +184,7 @@ voicePrompt_t;
*/
typedef enum
{
vpDefault = 0x00,
vpAnnounceCaps = 0x01,
vpAnnounceCustomPrompts = 0x02,
vpAnnounceSpace = 0x04,
@ -192,7 +193,7 @@ typedef enum
vpAnnounceASCIIValueForUnknownChars = 0x20,
vpAnnouncePhoneticRendering = 0x40,
}
VoicePromptFlags_T;
vpFlags_t;
/**
* Queuing flags determining if speech is interrupted, played immediately,
@ -207,7 +208,7 @@ typedef enum
vpqIncludeDescriptions = 0x08,
vpqAddSeparatingSilence = 0x10
}
VoicePromptQueueFlags_T;
vpQueueFlags_t;
/**
* Voice prompt verbosity levels.
@ -251,7 +252,7 @@ void vp_queuePrompt(const uint16_t prompt);
* @param string: string to be spelled.
* @param flags: control flags.
*/
void vp_queueString(const char* string, VoicePromptFlags_T flags);
void vp_queueString(const char* string, vpFlags_t flags);
/**
* Append a signed integer to the queue.

Wyświetl plik

@ -31,12 +31,13 @@
#include "interfaces/cps_io.h"
static void vp_clearCurrPromptIfNeeded(VoicePromptQueueFlags_T flags)
static void clearCurrPromptIfNeeded(const vpQueueFlags_t flags)
{
if (flags & vpqInit) vp_clearCurrPrompt();
if (flags & vpqInit)
vp_clearCurrPrompt();
}
static void vp_playIfNeeded(VoicePromptQueueFlags_T flags)
static void playIfNeeded(const vpQueueFlags_t flags)
{
uint8_t vpLevel = state.settings.vpLevel;
@ -45,9 +46,10 @@ static void vp_playIfNeeded(VoicePromptQueueFlags_T flags)
vp_play();
}
static void addSilenceIfNeeded(VoicePromptQueueFlags_T flags)
static void addSilenceIfNeeded(const vpQueueFlags_t flags)
{
if ((flags & vpqAddSeparatingSilence) == 0) return;
if ((flags & vpqAddSeparatingSilence) == 0)
return;
vp_queuePrompt(PROMPT_SILENCE);
vp_queuePrompt(PROMPT_SILENCE);
@ -61,209 +63,242 @@ static void removeUnnecessaryZerosFromVoicePrompts(char* str)
{
if ((str[i - 1] != '0') || (str[i - (NUM_DECIMAL_PLACES + 1)] == '.'))
{
str[i] = 0;
str[i] = '\0';
return;
}
}
}
void announceVFO()
void vp_announceVFO()
{
vp_clearCurrPrompt();
vp_queuePrompt(PROMPT_VFO);
vp_play();
}
void announceChannelName(channel_t* channel, uint16_t channelIndex,
VoicePromptQueueFlags_T flags)
void vp_announceChannelName(const channel_t* channel,
const uint16_t channelIndex,
const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_CHANNEL);
}
vp_queueInteger(channelIndex);
// Only queue the name if it is not the same as the raw number.
// Otherwise the radio will say channel 1 1 for channel 1.
char numAsStr[16] = "\0";
snprintf(numAsStr, 16, "%d", channelIndex);
if (strcmp(numAsStr, channel->name) != 0)
vp_queueString(channel->name, vpAnnounceCommonSymbols);
vp_playIfNeeded(flags);
if (strcmp(numAsStr, channel->name) != 0)
{
vp_queueString(channel->name, vpAnnounceCommonSymbols);
}
playIfNeeded(flags);
}
void vpQueueFrequency(freq_t freq)
void vp_queueFrequency(const freq_t freq)
{
char buffer[16];
int mhz = (freq / 1000000);
int khz = ((freq % 1000000) / 10);
int MHz = (freq / 1000000);
int kHz = ((freq % 1000000) / 10);
snprintf(buffer, 16, "%d.%05d", MHz, kHz);
snprintf(buffer, 16, "%d.%05d", mhz, khz);
removeUnnecessaryZerosFromVoicePrompts(buffer);
vp_queueString(buffer, vpAnnounceCommonSymbols);
vp_queuePrompt(PROMPT_MEGAHERTZ);
}
void announceFrequencies(freq_t rx, freq_t tx, VoicePromptQueueFlags_T flags)
void vp_announceFrequencies(const freq_t rx, const freq_t tx,
const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
// If rx and tx frequencies differ, announce both, otherwise just one
if (rx == tx)
vpQueueFrequency(rx);
{
vp_queueFrequency(rx);
}
else
{
vp_queuePrompt(PROMPT_RECEIVE);
vpQueueFrequency(rx);
vp_queueFrequency(rx);
vp_queuePrompt(PROMPT_TRANSMIT);
vpQueueFrequency(tx);
vp_queueFrequency(tx);
}
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceRadioMode(uint8_t mode, VoicePromptQueueFlags_T flags)
void vp_announceRadioMode(const uint8_t mode, const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_MODE);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_MODE);
}
switch (mode)
{
case OPMODE_DMR:
vp_queueStringTableEntry(&currentLanguage->dmr);
break;
case OPMODE_FM:
vp_queueStringTableEntry(&currentLanguage->fm);
break;
case OPMODE_M17:
vp_queueStringTableEntry(&currentLanguage->m17);
break;
}
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceBandwidth(uint8_t bandwidth, VoicePromptQueueFlags_T flags)
void vp_announceBandwidth(const uint8_t bandwidth, const vpQueueFlags_t flags)
{
if (bandwidth > BW_25) bandwidth = BW_25; // Should probably never happen!
clearCurrPromptIfNeeded(flags);
vp_clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_BANDWIDTH);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_BANDWIDTH);
}
char* bandwidths[] = {"12.5", "20", "25"};
vp_queueString(bandwidths[bandwidth], vpAnnounceCommonSymbols);
vp_queuePrompt(PROMPT_KILOHERTZ);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void anouncePower(float power, VoicePromptQueueFlags_T flags)
void vp_anouncePower(const float power, const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_POWER);
}
char buffer[16] = "\0";
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_POWER);
snprintf(buffer, 16, "%1.1f", power);
vp_queueString(buffer, vpAnnounceCommonSymbols);
vp_queuePrompt(PROMPT_WATTS);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceChannelSummary(channel_t* channel, uint16_t channelIndex,
uint16_t bank)
void vp_announceChannelSummary(const channel_t* channel,
const uint16_t channelIndex, const uint16_t bank)
{
if (!channel) return;
if (channel == NULL)
return;
vp_clearCurrPrompt();
VoicePromptQueueFlags_T localFlags = vpqAddSeparatingSilence;
vpQueueFlags_t localFlags = vpqAddSeparatingSilence;
// Force on the descriptions for level 3.
if (state.settings.vpLevel == vpHigh) localFlags |= vpqIncludeDescriptions;
if (state.settings.vpLevel == vpHigh)
{
localFlags |= vpqIncludeDescriptions;
}
// If VFO mode, announce VFO.
// channelIndex will be 0 if called from VFO mode.
if (channelIndex == 0)
{
vp_queuePrompt(PROMPT_VFO);
}
else
announceChannelName(channel, channelIndex, localFlags);
announceFrequencies(channel->rx_frequency, channel->tx_frequency,
{
vp_announceChannelName(channel, channelIndex, localFlags);
}
vp_announceFrequencies(channel->rx_frequency, channel->tx_frequency,
localFlags);
announceRadioMode(channel->mode, localFlags);
vp_announceRadioMode(channel->mode, localFlags);
if (channel->mode == OPMODE_FM)
{
announceBandwidth(channel->bandwidth, localFlags);
vp_announceBandwidth(channel->bandwidth, localFlags);
addSilenceIfNeeded(localFlags);
if (channel->fm.rxToneEn || channel->fm.txToneEn)
{
announceCTCSS(channel->fm.rxToneEn, channel->fm.rxTone,
channel->fm.txToneEn, channel->fm.txTone, localFlags);
vp_announceCTCSS(channel->fm.rxToneEn, channel->fm.rxTone,
channel->fm.txToneEn, channel->fm.txTone, localFlags);
}
}
else if (channel->mode == OPMODE_M17)
{
addSilenceIfNeeded(localFlags);
announceM17Info(channel, localFlags);
vp_announceM17Info(channel, localFlags);
}
else if (channel->mode == OPMODE_DMR)
{
addSilenceIfNeeded(localFlags);
announceContactWithIndex(channel->dmr.contact_index, localFlags);
vp_announceContactWithIndex(channel->dmr.contact_index, localFlags);
// Force announcement of the words timeslot and colorcode to avoid
// ambiguity.
announceTimeslot(channel->dmr.dmr_timeslot,
vp_announceTimeslot(channel->dmr.dmr_timeslot,
(localFlags | vpqIncludeDescriptions));
announceColorCode(channel->dmr.rxColorCode, channel->dmr.txColorCode,
vp_announceColorCode(channel->dmr.rxColorCode, channel->dmr.txColorCode,
(localFlags | vpqIncludeDescriptions));
}
addSilenceIfNeeded(localFlags);
anouncePower(channel->power, localFlags);
addSilenceIfNeeded(localFlags);
vp_anouncePower(channel->power, localFlags);
addSilenceIfNeeded(localFlags);
if (channelIndex > 0) // i.e. not called from VFO.
announceBank(bank, localFlags);
{
vp_announceBank(bank, localFlags);
}
vp_play();
}
void AnnounceInputChar(char ch)
void vp_announceInputChar(const char ch)
{
char buf[2] = "\0";
buf[0] = ch;
vp_clearCurrPrompt();
uint8_t flags = vpAnnounceCaps | vpAnnounceSpace | vpAnnounceCommonSymbols |
vpAnnounceLessCommonSymbols;
uint8_t flags = vpAnnounceCaps
| vpAnnounceSpace
| vpAnnounceCommonSymbols
| vpAnnounceLessCommonSymbols;
vp_queueString(buf, flags);
vp_play();
}
void announceInputReceiveOrTransmit(bool tx, VoicePromptQueueFlags_T flags)
void vp_announceInputReceiveOrTransmit(const bool tx, const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (tx)
vp_queuePrompt(PROMPT_TRANSMIT);
else
vp_queuePrompt(PROMPT_RECEIVE);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void ReplayLastPrompt()
void vp_replayLastPrompt()
{
if (vp_isPlaying())
vp_terminate();
@ -271,20 +306,20 @@ void ReplayLastPrompt()
vp_play();
}
void announceError(VoicePromptQueueFlags_T flags)
void vp_announceError(const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
vp_queueStringTableEntry(&currentLanguage->error);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceText(char* text, VoicePromptQueueFlags_T flags)
void vp_announceText(const char* text, const vpQueueFlags_t flags)
{
if (!text || !*text) return;
if ((text == NULL) || (*text == '\0'))
return;
clearCurrPromptIfNeeded(flags);
vp_clearCurrPromptIfNeeded(flags);
// See if we have a prompt for this string.
int offset = GetEnglishStringTableOffset(text);
@ -294,19 +329,20 @@ void announceText(char* text, VoicePromptQueueFlags_T flags)
else // Just spell it out
vp_queueString(text, vpAnnounceCommonSymbols);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceCTCSS(bool rxToneEnabled, uint8_t rxTone, bool txToneEnabled,
uint8_t txTone, VoicePromptQueueFlags_T flags)
void vp_announceCTCSS(const bool rxToneEnabled, const uint8_t rxTone,
const bool txToneEnabled, const uint8_t txTone,
const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (!rxToneEnabled && !txToneEnabled)
if ((rxToneEnabled == false) && (txToneEnabled == false))
{
vp_queuePrompt(PROMPT_TONE);
vp_queueStringTableEntry(&currentLanguage->off);
vp_playIfNeeded(flags);
playIfNeeded(flags);
return;
}
@ -316,97 +352,118 @@ void announceCTCSS(bool rxToneEnabled, uint8_t rxTone, bool txToneEnabled,
if ((rxToneEnabled && txToneEnabled) && (rxTone == txTone))
{
vp_queuePrompt(PROMPT_TONE);
snprintf(buffer, 16, "%3.1f", ctcss_tone[rxTone] / 10.0f);
vp_queueString(buffer, vpqDefault);
vp_queueString(buffer, vpDefault);
vp_queuePrompt(PROMPT_HERTZ);
vp_playIfNeeded(flags);
playIfNeeded(flags);
return;
}
// Speak the individual rx and tx tones.
if (rxToneEnabled)
{
vp_queuePrompt(PROMPT_RECEIVE);
vp_queuePrompt(PROMPT_TONE);
snprintf(buffer, 16, "%3.1f", ctcss_tone[rxTone] / 10.0f);
vp_queueString(buffer, vpqDefault);
vp_queueString(buffer, vpDefault);
vp_queuePrompt(PROMPT_HERTZ);
}
if (txToneEnabled)
{
vp_queuePrompt(PROMPT_TRANSMIT);
vp_queuePrompt(PROMPT_TONE);
snprintf(buffer, 16, "%3.1f", ctcss_tone[txTone] / 10.0f);
vp_queueString(buffer, vpqDefault);
vp_queueString(buffer, vpDefault);
vp_queuePrompt(PROMPT_HERTZ);
}
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceBrightness(uint8_t brightness, VoicePromptQueueFlags_T flags)
void vp_announceBrightness(const uint8_t brightness, const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions)
{
vp_queueStringTableEntry(&currentLanguage->brightness);
}
vp_queueInteger(brightness);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceSquelch(uint8_t squelch, VoicePromptQueueFlags_T flags)
void vp_announceSquelch(const uint8_t squelch, const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_SQUELCH);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_SQUELCH);
}
vp_queueInteger(squelch);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceContact(contact_t* contact, VoicePromptQueueFlags_T flags)
void vp_announceContact(const contact_t* contact, const vpQueueFlags_t flags)
{
if (!contact) return;
if (contact == NULL)
return;
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_CONTACT);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_CONTACT);
}
if (contact->name[0]) vp_queueString(contact->name, vpAnnounceCommonSymbols);
if (contact->name[0] != '\0')
{
vp_queueString(contact->name, vpAnnounceCommonSymbols);
}
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceContactWithIndex(uint16_t index, VoicePromptQueueFlags_T flags)
void vp_announceContactWithIndex(const uint16_t index, const vpQueueFlags_t flags)
{
if (index == 0) return;
if (index == 0)
return;
contact_t contact;
if (cps_readContact(&contact, index) == -1)
return;
if (cps_readContact(&contact, index) == -1) return;
announceContact(&contact, flags);
vp_announceContact(&contact, flags);
}
void announceTimeslot(uint8_t timeslot, VoicePromptQueueFlags_T flags)
void vp_announceTimeslot(const uint8_t timeslot, const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_TIMESLOT);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_TIMESLOT);
}
vp_queueInteger(timeslot);
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceColorCode(uint8_t rxColorCode, uint8_t txColorCode,
VoicePromptQueueFlags_T flags)
void vp_announceColorCode(const uint8_t rxColorCode, const uint8_t txColorCode,
const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_COLORCODE);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_COLORCODE);
}
if (rxColorCode == txColorCode)
{
@ -420,14 +477,17 @@ void announceColorCode(uint8_t rxColorCode, uint8_t txColorCode,
vp_queueInteger(txColorCode);
}
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceBank(uint16_t bank, VoicePromptQueueFlags_T flags)
void vp_announceBank(const uint16_t bank, const vpQueueFlags_t flags)
{
vp_clearCurrPromptIfNeeded(flags);
clearCurrPromptIfNeeded(flags);
if (flags & vpqIncludeDescriptions)
{
vp_queueStringTableEntry(&currentLanguage->banks);
}
if (state.bank_enabled)
{
@ -436,35 +496,46 @@ void announceBank(uint16_t bank, VoicePromptQueueFlags_T flags)
vp_queueString(bank_hdr.name, vpAnnounceCommonSymbols);
}
else
{
vp_queueStringTableEntry(&currentLanguage->allChannels);
}
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
void announceM17Info(channel_t* channel, VoicePromptQueueFlags_T flags)
void vp_announceM17Info(const channel_t* channel, const vpQueueFlags_t flags)
{
if (!channel) return;
if (channel == NULL)
return;
vp_clearCurrPromptIfNeeded(flags);
if (state.m17_data.dst_addr[0])
clearCurrPromptIfNeeded(flags);
if (state.m17_data.dst_addr[0] != '\0')
{
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_DEST_ID);
if (flags & vpqIncludeDescriptions)
{
vp_queuePrompt(PROMPT_DEST_ID);
}
vp_queueString(state.m17_data.dst_addr, vpAnnounceCommonSymbols);
}
else if (channel->m17.contact_index)
announceContactWithIndex(channel->m17.contact_index, flags);
else if (channel->m17.contact_index != 0)
{
vp_announceContactWithIndex(channel->m17.contact_index, flags);
}
vp_playIfNeeded(flags);
playIfNeeded(flags);
}
#ifdef GPS_PRESENT
void announceGPSInfo()
void vp_announceGPSInfo()
{
if (!state.settings.gps_enabled) return;
if (!state.settings.gps_enabled)
return;
vp_clearCurrPrompt();
VoicePromptQueueFlags_T flags =
vpqIncludeDescriptions | vpqAddSeparatingSilence;
vpQueueFlags_t flags = vpqIncludeDescriptions
| vpqAddSeparatingSilence;
vp_queueStringTableEntry(&currentLanguage->gps);
@ -473,18 +544,23 @@ void announceGPSInfo()
case 0:
vp_queueStringTableEntry(&currentLanguage->noFix);
break;
case 1:
vp_queueString("SPS", vpAnnounceCommonSymbols);
break;
case 2:
vp_queueString("DGPS", vpAnnounceCommonSymbols);
break;
case 3:
vp_queueString("PPS", vpAnnounceCommonSymbols);
break;
case 6:
vp_queueStringTableEntry(&currentLanguage->fixLost);
break;
default:
vp_queueStringTableEntry(&currentLanguage->error);
@ -492,6 +568,7 @@ void announceGPSInfo()
return;
}
addSilenceIfNeeded(flags);
switch (state.gps_data.fix_type)
@ -499,36 +576,43 @@ void announceGPSInfo()
case 2:
vp_queueString("2D", vpAnnounceCommonSymbols);
break;
case 3:
vp_queueString("3D", vpAnnounceCommonSymbols);
break;
}
addSilenceIfNeeded(flags);
// lat/long
char buffer[16] = "\0";
vp_queuePrompt(PROMPT_LATITUDE);
snprintf(buffer, 16, "%8.6f", state.gps_data.latitude);
vp_queuePrompt(PROMPT_LATITUDE);
vp_queueString(buffer, vpAnnounceCommonSymbols);
vp_queuePrompt(PROMPT_NORTH);
float longitude = state.gps_data.longitude;
voicePrompt_t direction = (longitude < 0) ? PROMPT_WEST : PROMPT_EAST;
longitude = (longitude < 0) ? -longitude : longitude;
snprintf(buffer, 16, "%8.6f", longitude);
vp_queuePrompt(PROMPT_LONGITUDE);
vp_queueString(buffer, vpAnnounceCommonSymbols);
vp_queuePrompt(direction);
addSilenceIfNeeded(flags);
// speed/altitude:
vp_queuePrompt(PROMPT_SPEED);
snprintf(buffer, 16, "%4.1fkm/h", state.gps_data.speed);
vp_queuePrompt(PROMPT_SPEED);
vp_queueString(buffer, vpAnnounceCommonSymbols);
vp_queuePrompt(PROMPT_ALTITUDE);
snprintf(buffer, 16, "%4.1fm", state.gps_data.altitude);
vp_queueString(buffer, vpAnnounceCommonSymbols);
addSilenceIfNeeded(flags);
vp_queuePrompt(PROMPT_COMPASS);
snprintf(buffer, 16, "%3.1f", state.gps_data.tmg_true);
vp_queuePrompt(PROMPT_COMPASS);
vp_queueString(buffer, vpAnnounceCommonSymbols);
vp_queuePrompt(PROMPT_DEGREES);
addSilenceIfNeeded(flags);
@ -540,7 +624,7 @@ void announceGPSInfo()
}
#endif // GPS_PRESENT
void announceAboutScreen()
void vp_announceAboutScreen()
{
vp_clearCurrPrompt();
@ -555,7 +639,7 @@ void announceAboutScreen()
vp_play();
}
void announceBackupScreen()
void vp_announceBackupScreen()
{
vp_clearCurrPrompt();
@ -569,7 +653,7 @@ void announceBackupScreen()
vp_play();
}
void announceRestoreScreen()
void vp_announceRestoreScreen()
{
vp_clearCurrPrompt();
@ -584,70 +668,58 @@ void announceRestoreScreen()
}
#ifdef RTC_PRESENT
void announceSettingsTimeDate()
void vp_announceSettingsTimeDate()
{
vp_clearCurrPrompt();
vp_queueStringTableEntry(&currentLanguage->timeAndDate);
datetime_t local_time = utcToLocalTime(state.time, state.settings.utc_timezone);
datetime_t local_time = utcToLocalTime(state.time,
state.settings.utc_timezone);
char buffer[16] = "\0";
snprintf(buffer, 16, "%02d/%02d/%02d", local_time.date, local_time.month,
local_time.year);
vp_queueString(buffer,
(vpAnnounceCommonSymbols | vpAnnounceLessCommonSymbols));
local_time.year);
vp_queueString(buffer, vpAnnounceCommonSymbols |
vpAnnounceLessCommonSymbols);
snprintf(buffer, 16, "%02d:%02d:%02d", local_time.hour, local_time.minute,
local_time.second);
vp_queueString(buffer,
(vpAnnounceCommonSymbols | vpAnnounceLessCommonSymbols));
local_time.second);
vp_queueString(buffer, vpAnnounceCommonSymbols |
vpAnnounceLessCommonSymbols);
vp_play();
}
#endif // RTC_PRESENT
/*
* There are 5 levels of verbosity:
*
* vpNone: no voice or beeps.
* vpBeep: beeps only.
* vpLow: menus talk, but channel and frequency changes are indicated with a
* beep and only voiced on demand with f1.
* vpMedium: menus, channel and frequency changes talk but with extra
* descriptions eliminated unless ambiguity would result. E.g. We'd say "FM"
* rather than "Mode: FM" in the channel summary.
* vpHigh: like vpMedium except with extra descriptions: e.g. "Mode fm".
*
* Also, if a voice prompt is in progress, e.g. changing a menu item, the
* descriptions are eliminated, e.g., changing ctcss tones would not repeat
* "ctcss" when arrowing through the options rapidly.
*/
VoicePromptQueueFlags_T GetQueueFlagsForVoiceLevel()
vpQueueFlags_t vp_getVoiceLevelQueueFlags()
{
VoicePromptQueueFlags_T flags = vpqInit | vpqAddSeparatingSilence;
uint8_t vpLevel = state.settings.vpLevel;
vpQueueFlags_t flags = vpqInit
| vpqAddSeparatingSilence;
switch (vpLevel)
{
case vpNone:
case vpBeep:
return vpqDefault;
// Play some immediately, other things on demand.
case vpLow:
// Play some immediately, other things on demand.
flags |= vpqPlayImmediatelyAtMediumOrHigher;
break;
// Play all immediately but without extra descriptions
case vpMedium:
{
// Play all immediately but without extra descriptions
flags |= vpqPlayImmediately;
break;
}
// Play immediately with descriptions unless speech is in progress.
case vpHigh:
// Play immediately with descriptions unless speech is in progress.
flags |= vpqPlayImmediately;
if (!vp_isPlaying()) flags |= vpqIncludeDescriptions;
if (!vp_isPlaying())
flags |= vpqIncludeDescriptions;
break;
}

Wyświetl plik

@ -163,7 +163,7 @@ static uint16_t UserDictLookup(const char* ptr, int* advanceBy)
}
static bool GetSymbolVPIfItShouldBeAnnounced(char symbol,
VoicePromptFlags_T flags,
vpFlags_t flags,
voicePrompt_t* vp)
{
*vp = PROMPT_SILENCE;
@ -274,7 +274,7 @@ void vp_queuePrompt(const uint16_t prompt)
}
}
void vp_queueString(const char* string, VoicePromptFlags_T flags)
void vp_queueString(const char* string, vpFlags_t flags)
{
if (state.settings.vpLevel < vpLow)
return;

Wyświetl plik

@ -624,10 +624,10 @@ void _ui_fsm_confirmVFOInput(bool *sync_rtx)
// Reset input position
ui_state.input_position = 0;
// announce the rx frequency just confirmed with Enter.
vpQueueFrequency(ui_state.new_rx_frequency);
vp_queueFrequency(ui_state.new_rx_frequency);
// defer playing till the end.
// indicate that the user has moved to the tx freq field.
announceInputReceiveOrTransmit(true, vpqDefault);
vp_announceInputReceiveOrTransmit(true, vpqDefault);
}
else if(ui_state.input_set == SET_TX)
{
@ -647,10 +647,10 @@ void _ui_fsm_confirmVFOInput(bool *sync_rtx)
// force init to clear any prompts in progress.
// defer play because play is called at the end of the function
//due to above freq queuing.
announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, vpqInit);
vp_announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, vpqInit);
}
else
announceError(vpqInit);
vp_announceError(vpqInit);
state.ui_screen = MAIN_VFO;
}
vp_play();
@ -679,7 +679,7 @@ void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
ui_state.input_position, ui_state.input_number);
if(ui_state.input_position >= FREQ_DIGITS)
{// queue the rx freq just completed.
vpQueueFrequency(ui_state.new_rx_frequency);
vp_queueFrequency(ui_state.new_rx_frequency);
/// now queue tx as user has changed fields.
vp_queuePrompt(PROMPT_TRANSMIT);
// Switch to TX input
@ -707,7 +707,7 @@ void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
state.channel.tx_frequency = ui_state.new_tx_frequency;
*sync_rtx = true;
// play is called at end.
announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, vpqInit);
vp_announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, vpqInit);
}
state.ui_screen = MAIN_VFO;
}
@ -835,7 +835,7 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
bool tone_tx_enable = state.channel.fm.txToneEn;
bool tone_rx_enable = state.channel.fm.rxToneEn;
uint8_t tone_flags = tone_tx_enable << 1 | tone_rx_enable;
VoicePromptQueueFlags_T queueFlags=GetQueueFlagsForVoiceLevel();
vpQueueFlags_t queueFlags=vp_getVoiceLevelQueueFlags();
switch(ui_state.input_number)
{
@ -846,7 +846,7 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
state.channel.fm.txTone %= MAX_TONE_INDEX;
state.channel.fm.rxTone = state.channel.fm.txTone;
*sync_rtx = true;
announceCTCSS(state.channel.fm.rxToneEn, state.channel.fm.rxTone,
vp_announceCTCSS(state.channel.fm.rxToneEn, state.channel.fm.rxTone,
state.channel.fm.txToneEn, state.channel.fm.txTone,
queueFlags);
}
@ -870,7 +870,7 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
state.channel.fm.txToneEn = tone_tx_enable;
state.channel.fm.rxToneEn = tone_rx_enable;
*sync_rtx = true;
announceCTCSS(state.channel.fm.rxToneEn, state.channel.fm.rxTone,
vp_announceCTCSS(state.channel.fm.rxToneEn, state.channel.fm.rxTone,
state.channel.fm.txToneEn, state.channel.fm.txTone,
queueFlags);
}
@ -881,7 +881,7 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
state.channel.bandwidth++;
state.channel.bandwidth %= 3;
*sync_rtx = true;
announceBandwidth(state.channel.bandwidth, queueFlags);
vp_announceBandwidth(state.channel.bandwidth, queueFlags);
}
break;
case 5:
@ -893,7 +893,7 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
else //catch any invalid states so they don't get locked out
state.channel.mode = OPMODE_FM;
*sync_rtx = true;
announceRadioMode(state.channel.mode, queueFlags);
vp_announceRadioMode(state.channel.mode, queueFlags);
break;
case 6:
if (state.channel.power == 100)
@ -901,16 +901,16 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
else
state.channel.power = 100;
*sync_rtx = true;
anouncePower(state.channel.power, queueFlags);
vp_anouncePower(state.channel.power, queueFlags);
break;
break;
case 7:
_ui_changeBrightness(-5);
announceBrightness(state.settings.brightness, queueFlags);
vp_announceBrightness(state.settings.brightness, queueFlags);
break;
case 8:
_ui_changeBrightness(+5);
announceBrightness(state.settings.brightness, queueFlags);
vp_announceBrightness(state.settings.brightness, queueFlags);
break;
}
@ -932,7 +932,7 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
{
state.settings.sqlLevel -= 1;
*sync_rtx = true;
announceSquelch(state.settings.sqlLevel, queueFlags);
vp_announceSquelch(state.settings.sqlLevel, queueFlags);
RestartFunctionLatchTimer(); // reset the timer.
}
}
@ -947,7 +947,7 @@ void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
{
state.settings.sqlLevel += 1;
*sync_rtx = true;
announceSquelch(state.settings.sqlLevel, queueFlags);
vp_announceSquelch(state.settings.sqlLevel, queueFlags);
RestartFunctionLatchTimer(); // reset the timer.
}
}
@ -1031,7 +1031,7 @@ void _ui_textInputKeypad(char *buf, uint8_t max_len, kbd_msg_t msg, bool callsig
buf[ui_state.input_position] = symbols_ITU_T_E161[num_key][ui_state.input_set];
}
// Announce the character
AnnounceInputChar(buf[ui_state.input_position]);
vp_announceInputChar(buf[ui_state.input_position]);
// Update reference values
ui_state.input_number = num_key;
ui_state.last_keypress = now;
@ -1049,7 +1049,7 @@ void _ui_textInputDel(char *buf)
if(ui_state.input_position > 0)
{
ui_state.input_position--;
AnnounceInputChar(buf[ui_state.input_position]);
vp_announceInputChar(buf[ui_state.input_position]);
// If we deleted the initial character, reset starting condition
}
else
@ -1100,7 +1100,7 @@ void ui_updateFSM(bool *sync_rtx)
kbd_msg_t msg;
msg.value = event.payload;
bool f1Handled = false;
VoicePromptQueueFlags_T queueFlags = GetQueueFlagsForVoiceLevel();
vpQueueFlags_t queueFlags = vp_getVoiceLevelQueueFlags();
// If we get out of standby, we ignore the kdb event
// unless is the MONI key for the MACRO functions
if (_ui_exitStandby(now) && !(msg.keys & KEY_MONI))
@ -1183,7 +1183,7 @@ void ui_updateFSM(bool *sync_rtx)
// Switch to MEM screen
state.ui_screen = MAIN_MEM;
// anounce the active channel name.
announceChannelName(&state.channel, state.channel_index, queueFlags);
vp_announceChannelName(&state.channel, state.channel_index, queueFlags);
}
}
else if(msg.keys & KEY_HASH)
@ -1202,7 +1202,7 @@ void ui_updateFSM(bool *sync_rtx)
state.channel.rx_frequency += 12500;
state.channel.tx_frequency += 12500;
*sync_rtx = true;
announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, queueFlags);
vp_announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, queueFlags);
}
}
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT)
@ -1214,10 +1214,21 @@ void ui_updateFSM(bool *sync_rtx)
state.channel.rx_frequency -= 12500;
state.channel.tx_frequency -= 12500;
*sync_rtx = true;
announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, queueFlags);
vp_announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, queueFlags);
}
}
else if(msg.keys & KEY_F1)
{
if (state.settings.vpLevel > vpBeep)
{// quick press repeat vp, long press summary.
if (msg.long_press)
vp_announceChannelSummary(&state.channel, 0, state.bank);
else
vp_replayLastPrompt();
f1Handled = true;
}
}
else if(msg.keys & KEY_F1)
{
if (state.settings.vpLevel > vpBeep)
{// quick press repeat vp, long press summary.
@ -1236,14 +1247,14 @@ void ui_updateFSM(bool *sync_rtx)
ui_state.input_position = 1;
ui_state.input_set = SET_RX;
// do not play because we will also announce the number just entered.
announceInputReceiveOrTransmit(false, vpqInit);
vp_announceInputReceiveOrTransmit(false, vpqInit);
ui_state.new_rx_frequency = 0;
ui_state.new_tx_frequency = 0;
// Save pressed number to calculare frequency and show in GUI
ui_state.input_number = input_getPressedNumber(msg);
// Calculate portion of the new frequency
ui_state.new_rx_frequency = _ui_freq_add_digit(ui_state.new_rx_frequency,
ui_state.input_position, ui_state.input_number);
ui_state.input_position, ui_state.input_number);
}
}
break;
@ -1263,12 +1274,12 @@ void ui_updateFSM(bool *sync_rtx)
if(ui_state.input_set == SET_RX)
{
ui_state.input_set = SET_TX;
announceInputReceiveOrTransmit(true, queueFlags);
vp_announceInputReceiveOrTransmit(true, queueFlags);
}
else if(ui_state.input_set == SET_TX)
{
ui_state.input_set = SET_RX;
announceInputReceiveOrTransmit(false, queueFlags);
vp_announceInputReceiveOrTransmit(false, queueFlags);
}
// Reset input position
ui_state.input_position = 0;
@ -1308,9 +1319,9 @@ void ui_updateFSM(bool *sync_rtx)
if (state.settings.vpLevel > vpBeep)
{// quick press repeat vp, long press summary.
if (msg.long_press)
announceChannelSummary(&state.channel, state.channel_index, state.bank);
vp_announceChannelSummary(&state.channel, state.channel_index, state.bank);
else
ReplayLastPrompt();
vp_replayLastPrompt();
f1Handled=true;
}
}
@ -1490,9 +1501,9 @@ void ui_updateFSM(bool *sync_rtx)
if ((msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
{// quick press repeat vp, long press summary.
if (msg.long_press)
announceGPSInfo();
vp_announceGPSInfo();
else
ReplayLastPrompt();
vp_replayLastPrompt();
f1Handled = true;
}
else if(msg.keys & KEY_ESC)
@ -1581,9 +1592,9 @@ void ui_updateFSM(bool *sync_rtx)
if ((msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
{// quick press repeat vp, long press summary.
if (msg.long_press)
announceAboutScreen();
vp_announceAboutScreen();
else
ReplayLastPrompt();
vp_replayLastPrompt();
f1Handled = true;
}
else if(msg.keys & KEY_ESC)
@ -1595,9 +1606,9 @@ void ui_updateFSM(bool *sync_rtx)
if ((msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
{// quick press repeat vp, long press summary.
if (msg.long_press)
announceSettingsTimeDate();
vp_announceSettingsTimeDate();
else
ReplayLastPrompt();
vp_replayLastPrompt();
f1Handled = true;
}
else if(msg.keys & KEY_ENTER)
@ -1833,7 +1844,7 @@ void ui_updateFSM(bool *sync_rtx)
}
if (!f1Handled && (msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
{
ReplayLastPrompt();
vp_replayLastPrompt();
}
}

Wyświetl plik

@ -104,10 +104,10 @@ static void announceMenuItemIfNeeded(char* name, char* value)
vp_clearCurrPrompt();
// If no value is supplied, or, no prompt is in progress, announce the name.
if (!voicePromptWasPlaying || !value || !*value)
announceText(name, vpqDefault);
vp_announceText(name, vpqDefault);
if (value && *value)
announceText(value, vpqDefault);
vp_announceText(value, vpqDefault);
vp_play();
}
@ -568,7 +568,7 @@ void _ui_drawMenuBackup(ui_state_t* ui_state)
color_white, currentLanguage->pressPTTToStart);
// read this screen.
announceBackupScreen();
vp_announceBackupScreen();
if (!platform_getPttStatus())
return;
@ -595,7 +595,7 @@ void _ui_drawMenuRestore(ui_state_t* ui_state)
gfx_print(line, FONT_SIZE_8PT, TEXT_ALIGN_CENTER,
color_white, currentLanguage->pressPTTToStart);
announceRestoreScreen();
vp_announceRestoreScreen();
if (!platform_getPttStatus())
return;

Wyświetl plik

@ -32,7 +32,7 @@
int main()
{
state.settings.vpLevel = 3;
VoicePromptQueueFlags_T flags = GetQueueFlagsForVoiceLevel();
vpQueueFlags_t flags = vp_getVoiceLevelQueueFlags();
vp_init();
vp_clearCurrPrompt();