Refactored voicePrompts.h, aligned function names of voice prompt API to OpenRTX coding style
This commit is contained in:
parent
5840f459fa
commit
df5341e103
|
|
@ -16,25 +16,20 @@
|
||||||
* You should have received a copy of the GNU General Public License *
|
* You should have received a copy of the GNU General Public License *
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#ifndef voice_prompts_h_included
|
#ifndef VOICEPROMPTS_H
|
||||||
#define voice_prompts_h_included
|
#define VOICEPROMPTS_H
|
||||||
|
|
||||||
#include <datatypes.h>
|
#include <datatypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
// Voice prompts are encoded using the codec2 file format used by ffmpeg
|
/**
|
||||||
#define CODEC2_HEADER_SIZE 7
|
* List of voice prompts for spoken words or phrases which are not in the UI
|
||||||
|
* string table. The voice prompt data file stores these first, then after the
|
||||||
/*
|
* data for these prompts, the data for the indexed string table phrases.
|
||||||
Please note, these prompts represent spoken words or phrases which are not in
|
*
|
||||||
the UI string table, for example letters of the alphabet, digits, and
|
* WARNING: this enum must match the order of prompts defined in the
|
||||||
descriptive words not displayed in the UI.
|
* wordlist.csv file in the voicePrompts generator project.
|
||||||
The voice prompt data file stores these first, then after the data for these
|
*/
|
||||||
prompts, the data for the indexed string table phrases.
|
|
||||||
*/
|
|
||||||
/* Please note! this enum must match the order of prompts defined in the
|
|
||||||
wordlist.csv file in the voicePrompts generator project.
|
|
||||||
*/
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
PROMPT_SILENCE, //
|
PROMPT_SILENCE, //
|
||||||
|
|
@ -181,19 +176,12 @@ typedef enum
|
||||||
PROMPT_CUSTOM9, // parrot
|
PROMPT_CUSTOM9, // parrot
|
||||||
PROMPT_CUSTOM10, // unused
|
PROMPT_CUSTOM10, // unused
|
||||||
NUM_VOICE_PROMPTS,
|
NUM_VOICE_PROMPTS,
|
||||||
} voicePrompt_t;
|
}
|
||||||
|
voicePrompt_t;
|
||||||
|
|
||||||
// PROMPT_VOICE_NAME is always the very last prompt after the indexed prompts
|
/**
|
||||||
// from the strings table.
|
* Flags controlling how vp_queueString operates.
|
||||||
#define PROMPT_VOICE_NAME \
|
*/
|
||||||
(NUM_VOICE_PROMPTS + (sizeof(stringsTable_t) / sizeof(char*)))
|
|
||||||
/*
|
|
||||||
These flags govern how vpQueueString operates.
|
|
||||||
For example, when editing, it is desireable to hear spaces, capitals and
|
|
||||||
extended symbols.
|
|
||||||
When just arrowing through menus, spaces, extended symbols etc should not be
|
|
||||||
announced.
|
|
||||||
*/
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
vpAnnounceCaps = 0x01,
|
vpAnnounceCaps = 0x01,
|
||||||
|
|
@ -203,30 +191,27 @@ typedef enum
|
||||||
vpAnnounceLessCommonSymbols = 0x10,
|
vpAnnounceLessCommonSymbols = 0x10,
|
||||||
vpAnnounceASCIIValueForUnknownChars = 0x20,
|
vpAnnounceASCIIValueForUnknownChars = 0x20,
|
||||||
vpAnnouncePhoneticRendering = 0x40,
|
vpAnnouncePhoneticRendering = 0x40,
|
||||||
} VoicePromptFlags_T;
|
}
|
||||||
/*
|
VoicePromptFlags_T;
|
||||||
These queuing flags determine if speech is interrupted, played
|
|
||||||
immediately, whether prompts are queued for values, etc.
|
/**
|
||||||
They are necessary because for example if you call the announceXX functions
|
* Queuing flags determining if speech is interrupted, played immediately,
|
||||||
consecutively, it is only desireable to initially stop speech in
|
* whether prompts are queued for values, etc.
|
||||||
progress and only play after the last prompt is queued.
|
*/
|
||||||
If however calling an announceXX function in isolation, normally any prompt in
|
|
||||||
progress should be interrupted and play should be called immediately.
|
|
||||||
At Voice level 1, changing channels in memory mode or frequencies in VFO mode
|
|
||||||
is indicated by a beep however if F1 is pressed, we will still say the current
|
|
||||||
channel name or frequency. This is accomplished by queueing but not playing a
|
|
||||||
prompt.
|
|
||||||
*/
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
vpqDefault = 0,
|
vpqDefault = 0,
|
||||||
vpqInit = 0x01, // stop any voice prompts already in progress.
|
vpqInit = 0x01, // stop any voice prompts already in progress.
|
||||||
vpqPlayImmediately = 0x02, // call play after queue at all levels.
|
vpqPlayImmediately = 0x02, // call play after queue at all levels.
|
||||||
vpqPlayImmediatelyAtMediumOrHigher = 0x04,
|
vpqPlayImmediatelyAtMediumOrHigher = 0x04,
|
||||||
vpqIncludeDescriptions = 0x08,
|
vpqIncludeDescriptions = 0x08,
|
||||||
vpqAddSeparatingSilence = 0x10
|
vpqAddSeparatingSilence = 0x10
|
||||||
} VoicePromptQueueFlags_T;
|
}
|
||||||
|
VoicePromptQueueFlags_T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Voice prompt verbosity levels.
|
||||||
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
vpNone = 0,
|
vpNone = 0,
|
||||||
|
|
@ -234,43 +219,74 @@ typedef enum
|
||||||
vpLow,
|
vpLow,
|
||||||
vpMedium,
|
vpMedium,
|
||||||
vpHigh
|
vpHigh
|
||||||
} VoicePromptVerbosity_T;
|
}
|
||||||
|
VoicePromptVerbosity_T;
|
||||||
|
|
||||||
typedef struct
|
/**
|
||||||
{
|
* Initialise the voice prompt system and load vp table of contents.
|
||||||
const char* userWord;
|
*/
|
||||||
const voicePrompt_t vp;
|
void vp_init();
|
||||||
} userDictEntry;
|
|
||||||
|
|
||||||
extern bool vpDataIsLoaded;
|
/**
|
||||||
extern const uint32_t VOICE_PROMPTS_FLASH_HEADER_ADDRESS;
|
* Terminate the currently ongoing prompt and shutdown the voice prompt system.
|
||||||
extern VoicePromptVerbosity_T vpLevel;
|
*/
|
||||||
// Loads just the TOC from Flash and stores in RAM for fast access.
|
void vp_terminate();
|
||||||
void vpCacheInit(void);
|
|
||||||
// Call before building the prompt sequence to clear prompt in progress.
|
|
||||||
void vpInit(void);
|
|
||||||
// This function appends an individual prompt item to the prompt queue.
|
|
||||||
// This can be a single letter, number, or a phrase.
|
|
||||||
void vpQueuePrompt(uint16_t prompt);
|
|
||||||
// This function appends the spelling of a complete string to the queue.
|
|
||||||
// It is used to pronounce strings for which we do not have a recorded voice
|
|
||||||
// prompt.
|
|
||||||
void vpQueueString(char* promptString, VoicePromptFlags_T flags);
|
|
||||||
// This function appends a signed integer to the queue.
|
|
||||||
void vpQueueInteger(int32_t value);
|
|
||||||
// This function appends a text string from the current language to the queue.
|
|
||||||
// e.g. currentLanguage->off
|
|
||||||
// These are recorded prompts which correspond to the strings in the strings
|
|
||||||
// table.
|
|
||||||
void vpQueueStringTableEntry(const char* const*);
|
|
||||||
|
|
||||||
void vpPlay(void); // Starts prompt playback
|
/**
|
||||||
void vpTick(); // called to process vp data being decoded.
|
* Clear the currently in-progress prompt, to be called before building a new
|
||||||
extern bool vpIsPlaying(void);
|
* voice prompt sequence.
|
||||||
bool vpHasDataToPlay(void);
|
*/
|
||||||
void vpTerminate(void);
|
void vp_clearCurrPrompt();
|
||||||
bool vpCheckHeader(uint32_t* bufferAddress);
|
|
||||||
int vp_open(char *vp_name);
|
/**
|
||||||
void vp_close();
|
* Append an individual prompt item to the prompt queue.
|
||||||
|
*
|
||||||
|
* @param prompt: voice prompt ID.
|
||||||
|
*/
|
||||||
|
void vp_queuePrompt(const uint16_t prompt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the spelling of a complete string to the queue.
|
||||||
|
*
|
||||||
|
* @param promptString: string to be spelled.
|
||||||
|
* @param flags: control flags.
|
||||||
|
*/
|
||||||
|
void vp_queueString(char* promptString, VoicePromptFlags_T flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a signed integer to the queue.
|
||||||
|
*
|
||||||
|
* @param value: value to be appended.
|
||||||
|
*/
|
||||||
|
void vp_queueInteger(const int32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a text string from the current language to the queue.
|
||||||
|
*/
|
||||||
|
void vp_queueStringTableEntry(const char* const* stringTableStringPtr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start prompt playback.
|
||||||
|
*/
|
||||||
|
void vp_play();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function handling vp data decoding, to be called periodically.
|
||||||
|
*/
|
||||||
|
void vp_tick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a voice prompt is being played.
|
||||||
|
*
|
||||||
|
* @return true if a voice prompt is being played.
|
||||||
|
*/
|
||||||
|
bool vp_isPlaying();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the voice prompt sequence is empty.
|
||||||
|
*
|
||||||
|
* @return true if the voice prompt sequence is empty.
|
||||||
|
*/
|
||||||
|
bool vp_sequenceNotEmpty();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ void openrtx_init()
|
||||||
gfx_init(); // Initialize display and graphics driver
|
gfx_init(); // Initialize display and graphics driver
|
||||||
kbd_init(); // Initialize keyboard driver
|
kbd_init(); // Initialize keyboard driver
|
||||||
ui_init(); // Initialize user interface
|
ui_init(); // Initialize user interface
|
||||||
vpCacheInit(); // Checks to see if voice prompts are loaded and initializes them
|
vp_init(); // Initialize voice prompts
|
||||||
#ifdef SCREEN_CONTRAST
|
#ifdef SCREEN_CONTRAST
|
||||||
display_setContrast(state.settings.contrast);
|
display_setContrast(state.settings.contrast);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ void *ui_threadFunc(void *arg)
|
||||||
ui_saveState(); // Save local state copy
|
ui_saveState(); // Save local state copy
|
||||||
pthread_mutex_unlock(&state_mutex); // Unlock r/w access to radio state
|
pthread_mutex_unlock(&state_mutex); // Unlock r/w access to radio state
|
||||||
|
|
||||||
vpTick(); // continue playing voice prompts in progress if any.
|
vp_tick(); // continue playing voice prompts in progress if any.
|
||||||
|
|
||||||
// If synchronization needed take mutex and update RTX configuration
|
// If synchronization needed take mutex and update RTX configuration
|
||||||
if(sync_rtx)
|
if(sync_rtx)
|
||||||
|
|
|
||||||
|
|
@ -31,26 +31,26 @@
|
||||||
|
|
||||||
#include "interfaces/cps_io.h"
|
#include "interfaces/cps_io.h"
|
||||||
|
|
||||||
static void vpInitIfNeeded(VoicePromptQueueFlags_T flags)
|
static void vp_clearCurrPromptIfNeeded(VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
if (flags & vpqInit) vpInit();
|
if (flags & vpqInit) vp_clearCurrPrompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vpPlayIfNeeded(VoicePromptQueueFlags_T flags)
|
static void vp_playIfNeeded(VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
uint8_t vpLevel = state.settings.vpLevel;
|
uint8_t vpLevel = state.settings.vpLevel;
|
||||||
|
|
||||||
if ((flags & vpqPlayImmediately) ||
|
if ((flags & vpqPlayImmediately) ||
|
||||||
((flags & vpqPlayImmediatelyAtMediumOrHigher) && (vpLevel >= vpMedium)))
|
((flags & vpqPlayImmediatelyAtMediumOrHigher) && (vpLevel >= vpMedium)))
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addSilenceIfNeeded(VoicePromptQueueFlags_T flags)
|
static void addSilenceIfNeeded(VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
if ((flags & vpqAddSeparatingSilence) == 0) return;
|
if ((flags & vpqAddSeparatingSilence) == 0) return;
|
||||||
|
|
||||||
vpQueuePrompt(PROMPT_SILENCE);
|
vp_queuePrompt(PROMPT_SILENCE);
|
||||||
vpQueuePrompt(PROMPT_SILENCE);
|
vp_queuePrompt(PROMPT_SILENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void removeUnnecessaryZerosFromVoicePrompts(char* str)
|
static void removeUnnecessaryZerosFromVoicePrompts(char* str)
|
||||||
|
|
@ -69,32 +69,32 @@ static void removeUnnecessaryZerosFromVoicePrompts(char* str)
|
||||||
|
|
||||||
void announceVFO()
|
void announceVFO()
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
|
|
||||||
vpQueuePrompt(PROMPT_VFO);
|
vp_queuePrompt(PROMPT_VFO);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceChannelName(channel_t* channel, uint16_t channelIndex,
|
void announceChannelName(channel_t* channel, uint16_t channelIndex,
|
||||||
VoicePromptQueueFlags_T flags)
|
VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions)
|
if (flags & vpqIncludeDescriptions)
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_CHANNEL);
|
vp_queuePrompt(PROMPT_CHANNEL);
|
||||||
}
|
}
|
||||||
vpQueueInteger(channelIndex);
|
vp_queueInteger(channelIndex);
|
||||||
|
|
||||||
// Only queue the name if it is not the same as the raw number.
|
// 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.
|
// Otherwise the radio will say channel 1 1 for channel 1.
|
||||||
char numAsStr[16] = "\0";
|
char numAsStr[16] = "\0";
|
||||||
snprintf(numAsStr, 16, "%d", channelIndex);
|
snprintf(numAsStr, 16, "%d", channelIndex);
|
||||||
if (strcmp(numAsStr, channel->name) != 0)
|
if (strcmp(numAsStr, channel->name) != 0)
|
||||||
vpQueueString(channel->name, vpAnnounceCommonSymbols);
|
vp_queueString(channel->name, vpAnnounceCommonSymbols);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpQueueFrequency(freq_t freq)
|
void vpQueueFrequency(freq_t freq)
|
||||||
|
|
@ -106,77 +106,77 @@ void vpQueueFrequency(freq_t freq)
|
||||||
snprintf(buffer, 16, "%d.%05d", mhz, khz);
|
snprintf(buffer, 16, "%d.%05d", mhz, khz);
|
||||||
removeUnnecessaryZerosFromVoicePrompts(buffer);
|
removeUnnecessaryZerosFromVoicePrompts(buffer);
|
||||||
|
|
||||||
vpQueueString(buffer, vpAnnounceCommonSymbols);
|
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||||
|
|
||||||
vpQueuePrompt(PROMPT_MEGAHERTZ);
|
vp_queuePrompt(PROMPT_MEGAHERTZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceFrequencies(freq_t rx, freq_t tx, VoicePromptQueueFlags_T flags)
|
void announceFrequencies(freq_t rx, freq_t tx, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
// If rx and tx frequencies differ, announce both, otherwise just one
|
// If rx and tx frequencies differ, announce both, otherwise just one
|
||||||
if (rx == tx)
|
if (rx == tx)
|
||||||
vpQueueFrequency(rx);
|
vpQueueFrequency(rx);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_RECEIVE);
|
vp_queuePrompt(PROMPT_RECEIVE);
|
||||||
vpQueueFrequency(rx);
|
vpQueueFrequency(rx);
|
||||||
vpQueuePrompt(PROMPT_TRANSMIT);
|
vp_queuePrompt(PROMPT_TRANSMIT);
|
||||||
vpQueueFrequency(tx);
|
vpQueueFrequency(tx);
|
||||||
}
|
}
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceRadioMode(uint8_t mode, VoicePromptQueueFlags_T flags)
|
void announceRadioMode(uint8_t mode, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_MODE);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_MODE);
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case OPMODE_DMR:
|
case OPMODE_DMR:
|
||||||
vpQueueStringTableEntry(¤tLanguage->dmr);
|
vp_queueStringTableEntry(¤tLanguage->dmr);
|
||||||
break;
|
break;
|
||||||
case OPMODE_FM:
|
case OPMODE_FM:
|
||||||
vpQueueStringTableEntry(¤tLanguage->fm);
|
vp_queueStringTableEntry(¤tLanguage->fm);
|
||||||
break;
|
break;
|
||||||
case OPMODE_M17:
|
case OPMODE_M17:
|
||||||
vpQueueStringTableEntry(¤tLanguage->m17);
|
vp_queueStringTableEntry(¤tLanguage->m17);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceBandwidth(uint8_t bandwidth, VoicePromptQueueFlags_T flags)
|
void announceBandwidth(uint8_t bandwidth, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
if (bandwidth > BW_25) bandwidth = BW_25; // Should probably never happen!
|
if (bandwidth > BW_25) bandwidth = BW_25; // Should probably never happen!
|
||||||
|
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_BANDWIDTH);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_BANDWIDTH);
|
||||||
|
|
||||||
char* bandwidths[] = {"12.5", "20", "25"};
|
char* bandwidths[] = {"12.5", "20", "25"};
|
||||||
vpQueueString(bandwidths[bandwidth], vpAnnounceCommonSymbols);
|
vp_queueString(bandwidths[bandwidth], vpAnnounceCommonSymbols);
|
||||||
vpQueuePrompt(PROMPT_KILOHERTZ);
|
vp_queuePrompt(PROMPT_KILOHERTZ);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void anouncePower(float power, VoicePromptQueueFlags_T flags)
|
void anouncePower(float power, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
char buffer[16] = "\0";
|
char buffer[16] = "\0";
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_POWER);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_POWER);
|
||||||
|
|
||||||
snprintf(buffer, 16, "%1.1f", power);
|
snprintf(buffer, 16, "%1.1f", power);
|
||||||
vpQueueString(buffer, vpAnnounceCommonSymbols);
|
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||||
vpQueuePrompt(PROMPT_WATTS);
|
vp_queuePrompt(PROMPT_WATTS);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceChannelSummary(channel_t* channel, uint16_t channelIndex,
|
void announceChannelSummary(channel_t* channel, uint16_t channelIndex,
|
||||||
|
|
@ -184,7 +184,7 @@ void announceChannelSummary(channel_t* channel, uint16_t channelIndex,
|
||||||
{
|
{
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
|
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
|
|
||||||
VoicePromptQueueFlags_T localFlags = vpqAddSeparatingSilence;
|
VoicePromptQueueFlags_T localFlags = vpqAddSeparatingSilence;
|
||||||
// Force on the descriptions for level 3.
|
// Force on the descriptions for level 3.
|
||||||
|
|
@ -192,7 +192,7 @@ void announceChannelSummary(channel_t* channel, uint16_t channelIndex,
|
||||||
// If VFO mode, announce VFO.
|
// If VFO mode, announce VFO.
|
||||||
// channelIndex will be 0 if called from VFO mode.
|
// channelIndex will be 0 if called from VFO mode.
|
||||||
if (channelIndex == 0)
|
if (channelIndex == 0)
|
||||||
vpQueuePrompt(PROMPT_VFO);
|
vp_queuePrompt(PROMPT_VFO);
|
||||||
else
|
else
|
||||||
announceChannelName(channel, channelIndex, localFlags);
|
announceChannelName(channel, channelIndex, localFlags);
|
||||||
announceFrequencies(channel->rx_frequency, channel->tx_frequency,
|
announceFrequencies(channel->rx_frequency, channel->tx_frequency,
|
||||||
|
|
@ -233,7 +233,7 @@ void announceChannelSummary(channel_t* channel, uint16_t channelIndex,
|
||||||
if (channelIndex > 0) // i.e. not called from VFO.
|
if (channelIndex > 0) // i.e. not called from VFO.
|
||||||
announceBank(bank, localFlags);
|
announceBank(bank, localFlags);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnnounceInputChar(char ch)
|
void AnnounceInputChar(char ch)
|
||||||
|
|
@ -241,72 +241,72 @@ void AnnounceInputChar(char ch)
|
||||||
char buf[2] = "\0";
|
char buf[2] = "\0";
|
||||||
buf[0] = ch;
|
buf[0] = ch;
|
||||||
|
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
|
|
||||||
uint8_t flags = vpAnnounceCaps | vpAnnounceSpace | vpAnnounceCommonSymbols |
|
uint8_t flags = vpAnnounceCaps | vpAnnounceSpace | vpAnnounceCommonSymbols |
|
||||||
vpAnnounceLessCommonSymbols;
|
vpAnnounceLessCommonSymbols;
|
||||||
|
|
||||||
vpQueueString(buf, flags);
|
vp_queueString(buf, flags);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceInputReceiveOrTransmit(bool tx, VoicePromptQueueFlags_T flags)
|
void announceInputReceiveOrTransmit(bool tx, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (tx)
|
if (tx)
|
||||||
vpQueuePrompt(PROMPT_TRANSMIT);
|
vp_queuePrompt(PROMPT_TRANSMIT);
|
||||||
else
|
else
|
||||||
vpQueuePrompt(PROMPT_RECEIVE);
|
vp_queuePrompt(PROMPT_RECEIVE);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplayLastPrompt()
|
void ReplayLastPrompt()
|
||||||
{
|
{
|
||||||
if (vpIsPlaying())
|
if (vp_isPlaying())
|
||||||
vpTerminate();
|
vp_terminate();
|
||||||
else
|
else
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceError(VoicePromptQueueFlags_T flags)
|
void announceError(VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->error);
|
vp_queueStringTableEntry(¤tLanguage->error);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceText(char* text, VoicePromptQueueFlags_T flags)
|
void announceText(char* text, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
if (!text || !*text) return;
|
if (!text || !*text) return;
|
||||||
|
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
// See if we have a prompt for this string.
|
// See if we have a prompt for this string.
|
||||||
int offset = GetEnglishStringTableOffset(text);
|
int offset = GetEnglishStringTableOffset(text);
|
||||||
|
|
||||||
if (offset != -1)
|
if (offset != -1)
|
||||||
vpQueueStringTableEntry(
|
vp_queueStringTableEntry(
|
||||||
(const char* const*)(¤tLanguage->languageName + offset));
|
(const char* const*)(¤tLanguage->languageName + offset));
|
||||||
else // Just spell it out
|
else // Just spell it out
|
||||||
vpQueueString(text, vpAnnounceCommonSymbols);
|
vp_queueString(text, vpAnnounceCommonSymbols);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceCTCSS(bool rxToneEnabled, uint8_t rxTone, bool txToneEnabled,
|
void announceCTCSS(bool rxToneEnabled, uint8_t rxTone, bool txToneEnabled,
|
||||||
uint8_t txTone, VoicePromptQueueFlags_T flags)
|
uint8_t txTone, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (!rxToneEnabled && !txToneEnabled)
|
if (!rxToneEnabled && !txToneEnabled)
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_TONE);
|
vp_queuePrompt(PROMPT_TONE);
|
||||||
vpQueueStringTableEntry(¤tLanguage->off);
|
vp_queueStringTableEntry(¤tLanguage->off);
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,68 +315,68 @@ void announceCTCSS(bool rxToneEnabled, uint8_t rxTone, bool txToneEnabled,
|
||||||
// If the rx and tx tones are the same and both are enabled, just say Tone.
|
// If the rx and tx tones are the same and both are enabled, just say Tone.
|
||||||
if ((rxToneEnabled && txToneEnabled) && (rxTone == txTone))
|
if ((rxToneEnabled && txToneEnabled) && (rxTone == txTone))
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_TONE);
|
vp_queuePrompt(PROMPT_TONE);
|
||||||
snprintf(buffer, 16, "%3.1f", ctcss_tone[rxTone] / 10.0f);
|
snprintf(buffer, 16, "%3.1f", ctcss_tone[rxTone] / 10.0f);
|
||||||
vpQueueString(buffer, vpqDefault);
|
vp_queueString(buffer, vpqDefault);
|
||||||
vpQueuePrompt(PROMPT_HERTZ);
|
vp_queuePrompt(PROMPT_HERTZ);
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Speak the individual rx and tx tones.
|
// Speak the individual rx and tx tones.
|
||||||
if (rxToneEnabled)
|
if (rxToneEnabled)
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_RECEIVE);
|
vp_queuePrompt(PROMPT_RECEIVE);
|
||||||
vpQueuePrompt(PROMPT_TONE);
|
vp_queuePrompt(PROMPT_TONE);
|
||||||
snprintf(buffer, 16, "%3.1f", ctcss_tone[rxTone] / 10.0f);
|
snprintf(buffer, 16, "%3.1f", ctcss_tone[rxTone] / 10.0f);
|
||||||
vpQueueString(buffer, vpqDefault);
|
vp_queueString(buffer, vpqDefault);
|
||||||
vpQueuePrompt(PROMPT_HERTZ);
|
vp_queuePrompt(PROMPT_HERTZ);
|
||||||
}
|
}
|
||||||
if (txToneEnabled)
|
if (txToneEnabled)
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_TRANSMIT);
|
vp_queuePrompt(PROMPT_TRANSMIT);
|
||||||
vpQueuePrompt(PROMPT_TONE);
|
vp_queuePrompt(PROMPT_TONE);
|
||||||
snprintf(buffer, 16, "%3.1f", ctcss_tone[txTone] / 10.0f);
|
snprintf(buffer, 16, "%3.1f", ctcss_tone[txTone] / 10.0f);
|
||||||
vpQueueString(buffer, vpqDefault);
|
vp_queueString(buffer, vpqDefault);
|
||||||
vpQueuePrompt(PROMPT_HERTZ);
|
vp_queuePrompt(PROMPT_HERTZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceBrightness(uint8_t brightness, VoicePromptQueueFlags_T flags)
|
void announceBrightness(uint8_t brightness, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions)
|
if (flags & vpqIncludeDescriptions)
|
||||||
vpQueueStringTableEntry(¤tLanguage->brightness);
|
vp_queueStringTableEntry(¤tLanguage->brightness);
|
||||||
|
|
||||||
vpQueueInteger(brightness);
|
vp_queueInteger(brightness);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceSquelch(uint8_t squelch, VoicePromptQueueFlags_T flags)
|
void announceSquelch(uint8_t squelch, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_SQUELCH);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_SQUELCH);
|
||||||
|
|
||||||
vpQueueInteger(squelch);
|
vp_queueInteger(squelch);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceContact(contact_t* contact, VoicePromptQueueFlags_T flags)
|
void announceContact(contact_t* contact, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
if (!contact) return;
|
if (!contact) return;
|
||||||
|
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_CONTACT);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_CONTACT);
|
||||||
|
|
||||||
if (contact->name[0]) vpQueueString(contact->name, vpAnnounceCommonSymbols);
|
if (contact->name[0]) vp_queueString(contact->name, vpAnnounceCommonSymbols);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceContactWithIndex(uint16_t index, VoicePromptQueueFlags_T flags)
|
void announceContactWithIndex(uint16_t index, VoicePromptQueueFlags_T flags)
|
||||||
|
|
@ -392,69 +392,69 @@ void announceContactWithIndex(uint16_t index, VoicePromptQueueFlags_T flags)
|
||||||
|
|
||||||
void announceTimeslot(uint8_t timeslot, VoicePromptQueueFlags_T flags)
|
void announceTimeslot(uint8_t timeslot, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_TIMESLOT);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_TIMESLOT);
|
||||||
|
|
||||||
vpQueueInteger(timeslot);
|
vp_queueInteger(timeslot);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceColorCode(uint8_t rxColorCode, uint8_t txColorCode,
|
void announceColorCode(uint8_t rxColorCode, uint8_t txColorCode,
|
||||||
VoicePromptQueueFlags_T flags)
|
VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
|
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_COLORCODE);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_COLORCODE);
|
||||||
|
|
||||||
if (rxColorCode == txColorCode)
|
if (rxColorCode == txColorCode)
|
||||||
{
|
{
|
||||||
vpQueueInteger(rxColorCode);
|
vp_queueInteger(rxColorCode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_RECEIVE);
|
vp_queuePrompt(PROMPT_RECEIVE);
|
||||||
vpQueueInteger(rxColorCode);
|
vp_queueInteger(rxColorCode);
|
||||||
vpQueuePrompt(PROMPT_TRANSMIT);
|
vp_queuePrompt(PROMPT_TRANSMIT);
|
||||||
vpQueueInteger(txColorCode);
|
vp_queueInteger(txColorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceBank(uint16_t bank, VoicePromptQueueFlags_T flags)
|
void announceBank(uint16_t bank, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
if (flags & vpqIncludeDescriptions)
|
if (flags & vpqIncludeDescriptions)
|
||||||
vpQueueStringTableEntry(¤tLanguage->banks);
|
vp_queueStringTableEntry(¤tLanguage->banks);
|
||||||
|
|
||||||
if (state.bank_enabled)
|
if (state.bank_enabled)
|
||||||
{
|
{
|
||||||
bankHdr_t bank_hdr = {0};
|
bankHdr_t bank_hdr = {0};
|
||||||
cps_readBankHeader(&bank_hdr, bank);
|
cps_readBankHeader(&bank_hdr, bank);
|
||||||
vpQueueString(bank_hdr.name, vpAnnounceCommonSymbols);
|
vp_queueString(bank_hdr.name, vpAnnounceCommonSymbols);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vpQueueStringTableEntry(¤tLanguage->allChannels);
|
vp_queueStringTableEntry(¤tLanguage->allChannels);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceM17Info(channel_t* channel, VoicePromptQueueFlags_T flags)
|
void announceM17Info(channel_t* channel, VoicePromptQueueFlags_T flags)
|
||||||
{
|
{
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
|
|
||||||
vpInitIfNeeded(flags);
|
vp_clearCurrPromptIfNeeded(flags);
|
||||||
if (state.m17_data.dst_addr[0])
|
if (state.m17_data.dst_addr[0])
|
||||||
{
|
{
|
||||||
if (flags & vpqIncludeDescriptions) vpQueuePrompt(PROMPT_DEST_ID);
|
if (flags & vpqIncludeDescriptions) vp_queuePrompt(PROMPT_DEST_ID);
|
||||||
vpQueueString(state.m17_data.dst_addr, vpAnnounceCommonSymbols);
|
vp_queueString(state.m17_data.dst_addr, vpAnnounceCommonSymbols);
|
||||||
}
|
}
|
||||||
else if (channel->m17.contact_index)
|
else if (channel->m17.contact_index)
|
||||||
announceContactWithIndex(channel->m17.contact_index, flags);
|
announceContactWithIndex(channel->m17.contact_index, flags);
|
||||||
|
|
||||||
vpPlayIfNeeded(flags);
|
vp_playIfNeeded(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GPS_PRESENT
|
#ifdef GPS_PRESENT
|
||||||
|
|
@ -462,33 +462,33 @@ void announceGPSInfo()
|
||||||
{
|
{
|
||||||
if (!state.settings.gps_enabled) return;
|
if (!state.settings.gps_enabled) return;
|
||||||
|
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
VoicePromptQueueFlags_T flags =
|
VoicePromptQueueFlags_T flags =
|
||||||
vpqIncludeDescriptions | vpqAddSeparatingSilence;
|
vpqIncludeDescriptions | vpqAddSeparatingSilence;
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->gps);
|
vp_queueStringTableEntry(¤tLanguage->gps);
|
||||||
|
|
||||||
switch (state.gps_data.fix_quality)
|
switch (state.gps_data.fix_quality)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
vpQueueStringTableEntry(¤tLanguage->noFix);
|
vp_queueStringTableEntry(¤tLanguage->noFix);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
vpQueueString("SPS", vpAnnounceCommonSymbols);
|
vp_queueString("SPS", vpAnnounceCommonSymbols);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
vpQueueString("DGPS", vpAnnounceCommonSymbols);
|
vp_queueString("DGPS", vpAnnounceCommonSymbols);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
vpQueueString("PPS", vpAnnounceCommonSymbols);
|
vp_queueString("PPS", vpAnnounceCommonSymbols);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
vpQueueStringTableEntry(¤tLanguage->fixLost);
|
vp_queueStringTableEntry(¤tLanguage->fixLost);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vpQueueStringTableEntry(¤tLanguage->error);
|
vp_queueStringTableEntry(¤tLanguage->error);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -497,113 +497,113 @@ void announceGPSInfo()
|
||||||
switch (state.gps_data.fix_type)
|
switch (state.gps_data.fix_type)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
vpQueueString("2D", vpAnnounceCommonSymbols);
|
vp_queueString("2D", vpAnnounceCommonSymbols);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
vpQueueString("3D", vpAnnounceCommonSymbols);
|
vp_queueString("3D", vpAnnounceCommonSymbols);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
addSilenceIfNeeded(flags);
|
addSilenceIfNeeded(flags);
|
||||||
// lat/long
|
// lat/long
|
||||||
char buffer[16] = "\0";
|
char buffer[16] = "\0";
|
||||||
vpQueuePrompt(PROMPT_LATITUDE);
|
vp_queuePrompt(PROMPT_LATITUDE);
|
||||||
snprintf(buffer, 16, "%8.6f", state.gps_data.latitude);
|
snprintf(buffer, 16, "%8.6f", state.gps_data.latitude);
|
||||||
vpQueueString(buffer, vpAnnounceCommonSymbols);
|
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||||
vpQueuePrompt(PROMPT_NORTH);
|
vp_queuePrompt(PROMPT_NORTH);
|
||||||
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;
|
||||||
longitude = (longitude < 0) ? -longitude : longitude;
|
longitude = (longitude < 0) ? -longitude : longitude;
|
||||||
snprintf(buffer, 16, "%8.6f", longitude);
|
snprintf(buffer, 16, "%8.6f", longitude);
|
||||||
vpQueuePrompt(PROMPT_LONGITUDE);
|
vp_queuePrompt(PROMPT_LONGITUDE);
|
||||||
vpQueueString(buffer, vpAnnounceCommonSymbols);
|
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||||
vpQueuePrompt(direction);
|
vp_queuePrompt(direction);
|
||||||
addSilenceIfNeeded(flags);
|
addSilenceIfNeeded(flags);
|
||||||
// speed/altitude:
|
// speed/altitude:
|
||||||
vpQueuePrompt(PROMPT_SPEED);
|
vp_queuePrompt(PROMPT_SPEED);
|
||||||
snprintf(buffer, 16, "%4.1fkm/h", state.gps_data.speed);
|
snprintf(buffer, 16, "%4.1fkm/h", state.gps_data.speed);
|
||||||
vpQueueString(buffer, vpAnnounceCommonSymbols);
|
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||||
vpQueuePrompt(PROMPT_ALTITUDE);
|
vp_queuePrompt(PROMPT_ALTITUDE);
|
||||||
snprintf(buffer, 16, "%4.1fm", state.gps_data.altitude);
|
snprintf(buffer, 16, "%4.1fm", state.gps_data.altitude);
|
||||||
vpQueueString(buffer, vpAnnounceCommonSymbols);
|
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||||
addSilenceIfNeeded(flags);
|
addSilenceIfNeeded(flags);
|
||||||
|
|
||||||
vpQueuePrompt(PROMPT_COMPASS);
|
vp_queuePrompt(PROMPT_COMPASS);
|
||||||
snprintf(buffer, 16, "%3.1f", state.gps_data.tmg_true);
|
snprintf(buffer, 16, "%3.1f", state.gps_data.tmg_true);
|
||||||
vpQueueString(buffer, vpAnnounceCommonSymbols);
|
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||||
vpQueuePrompt(PROMPT_DEGREES);
|
vp_queuePrompt(PROMPT_DEGREES);
|
||||||
addSilenceIfNeeded(flags);
|
addSilenceIfNeeded(flags);
|
||||||
|
|
||||||
vpQueuePrompt(PROMPT_SATELLITES);
|
vp_queuePrompt(PROMPT_SATELLITES);
|
||||||
vpQueueInteger(__builtin_popcount(state.gps_data.active_sats));
|
vp_queueInteger(__builtin_popcount(state.gps_data.active_sats));
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
#endif // GPS_PRESENT
|
#endif // GPS_PRESENT
|
||||||
|
|
||||||
void announceAboutScreen()
|
void announceAboutScreen()
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->openRTX);
|
vp_queueStringTableEntry(¤tLanguage->openRTX);
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->Niccolo);
|
vp_queueStringTableEntry(¤tLanguage->Niccolo);
|
||||||
vpQueueStringTableEntry(¤tLanguage->Silvano);
|
vp_queueStringTableEntry(¤tLanguage->Silvano);
|
||||||
vpQueueStringTableEntry(¤tLanguage->Federico);
|
vp_queueStringTableEntry(¤tLanguage->Federico);
|
||||||
vpQueueStringTableEntry(¤tLanguage->Fred);
|
vp_queueStringTableEntry(¤tLanguage->Fred);
|
||||||
vpQueueStringTableEntry(¤tLanguage->Joseph);
|
vp_queueStringTableEntry(¤tLanguage->Joseph);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceBackupScreen()
|
void announceBackupScreen()
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->flashBackup);
|
vp_queueStringTableEntry(¤tLanguage->flashBackup);
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->connectToRTXTool);
|
vp_queueStringTableEntry(¤tLanguage->connectToRTXTool);
|
||||||
vpQueueStringTableEntry(¤tLanguage->toBackupFlashAnd);
|
vp_queueStringTableEntry(¤tLanguage->toBackupFlashAnd);
|
||||||
vpQueueStringTableEntry(¤tLanguage->pressPTTToStart);
|
vp_queueStringTableEntry(¤tLanguage->pressPTTToStart);
|
||||||
vpQueuePrompt(PROMPT_VP_UNAVAILABLE);
|
vp_queuePrompt(PROMPT_VP_UNAVAILABLE);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void announceRestoreScreen()
|
void announceRestoreScreen()
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->flashRestore);
|
vp_queueStringTableEntry(¤tLanguage->flashRestore);
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->connectToRTXTool);
|
vp_queueStringTableEntry(¤tLanguage->connectToRTXTool);
|
||||||
vpQueueStringTableEntry(¤tLanguage->toRestoreFlashAnd);
|
vp_queueStringTableEntry(¤tLanguage->toRestoreFlashAnd);
|
||||||
vpQueueStringTableEntry(¤tLanguage->pressPTTToStart);
|
vp_queueStringTableEntry(¤tLanguage->pressPTTToStart);
|
||||||
vpQueuePrompt(PROMPT_VP_UNAVAILABLE);
|
vp_queuePrompt(PROMPT_VP_UNAVAILABLE);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RTC_PRESENT
|
#ifdef RTC_PRESENT
|
||||||
void announceSettingsTimeDate()
|
void announceSettingsTimeDate()
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
|
|
||||||
vpQueueStringTableEntry(¤tLanguage->timeAndDate);
|
vp_queueStringTableEntry(¤tLanguage->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";
|
char buffer[16] = "\0";
|
||||||
snprintf(buffer, 16, "%02d/%02d/%02d", local_time.date, local_time.month,
|
snprintf(buffer, 16, "%02d/%02d/%02d", local_time.date, local_time.month,
|
||||||
local_time.year);
|
local_time.year);
|
||||||
vpQueueString(buffer,
|
vp_queueString(buffer,
|
||||||
(vpAnnounceCommonSymbols | vpAnnounceLessCommonSymbols));
|
(vpAnnounceCommonSymbols | vpAnnounceLessCommonSymbols));
|
||||||
|
|
||||||
snprintf(buffer, 16, "%02d:%02d:%02d", local_time.hour, local_time.minute,
|
snprintf(buffer, 16, "%02d:%02d:%02d", local_time.hour, local_time.minute,
|
||||||
local_time.second);
|
local_time.second);
|
||||||
vpQueueString(buffer,
|
vp_queueString(buffer,
|
||||||
(vpAnnounceCommonSymbols | vpAnnounceLessCommonSymbols));
|
(vpAnnounceCommonSymbols | vpAnnounceLessCommonSymbols));
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
#endif // RTC_PRESENT
|
#endif // RTC_PRESENT
|
||||||
|
|
||||||
|
|
@ -647,7 +647,7 @@ VoicePromptQueueFlags_T GetQueueFlagsForVoiceLevel()
|
||||||
// Play immediately with descriptions unless speech is in progress.
|
// Play immediately with descriptions unless speech is in progress.
|
||||||
case vpHigh:
|
case vpHigh:
|
||||||
flags |= vpqPlayImmediately;
|
flags |= vpqPlayImmediately;
|
||||||
if (!vpIsPlaying()) flags |= vpqIncludeDescriptions;
|
if (!vp_isPlaying()) flags |= vpqIncludeDescriptions;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,16 @@ const uint32_t VOICE_PROMPTS_DATA_VERSION = 0x1000; // v1000 OpenRTX
|
||||||
// The length is the length in bytes of the data.
|
// The length is the length in bytes of the data.
|
||||||
static void GetCodec2Data(int offset, int length);
|
static void GetCodec2Data(int offset, int length);
|
||||||
|
|
||||||
|
#define CODEC2_HEADER_SIZE 7
|
||||||
|
|
||||||
static FILE *voice_prompt_file = NULL;
|
static FILE *voice_prompt_file = NULL;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char* userWord;
|
||||||
|
const voicePrompt_t vp;
|
||||||
|
} userDictEntry;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
|
|
@ -50,7 +58,7 @@ typedef struct
|
||||||
// offset into voice prompt vpc file where actual codec2 data starts.
|
// offset into voice prompt vpc file where actual codec2 data starts.
|
||||||
static uint32_t vpDataOffset = 0;
|
static uint32_t vpDataOffset = 0;
|
||||||
// Each codec2 frame is 8 bytes.
|
// Each codec2 frame is 8 bytes.
|
||||||
// 256 x 8 bytes
|
// 256 x 8 bytes
|
||||||
#define Codec2DataBufferSize 2048
|
#define Codec2DataBufferSize 2048
|
||||||
|
|
||||||
bool vpDataIsLoaded = false;
|
bool vpDataIsLoaded = false;
|
||||||
|
|
@ -70,7 +78,7 @@ typedef struct
|
||||||
uint16_t buffer[VOICE_PROMPTS_SEQUENCE_BUFFER_SIZE];
|
uint16_t buffer[VOICE_PROMPTS_SEQUENCE_BUFFER_SIZE];
|
||||||
int pos; // index into above buffer.
|
int pos; // index into above buffer.
|
||||||
int length; // number of entries in above buffer.
|
int length; // number of entries in above buffer.
|
||||||
int codec2DataIndex; // index into current codec2 data
|
int codec2DataIndex; // index into current codec2 data
|
||||||
//(buffer content sent in lots of 8 byte frames.)
|
//(buffer content sent in lots of 8 byte frames.)
|
||||||
int codec2DataLength; // length of codec2 data for current prompt.
|
int codec2DataLength; // length of codec2 data for current prompt.
|
||||||
} vpSequence_t;
|
} vpSequence_t;
|
||||||
|
|
@ -106,17 +114,25 @@ void vp_close()
|
||||||
fclose(voice_prompt_file);
|
fclose(voice_prompt_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpCacheInit(void)
|
bool vpCheckHeader(uint32_t* bufferAddress)
|
||||||
|
{
|
||||||
|
voicePromptsDataHeader_t* header = (voicePromptsDataHeader_t*)bufferAddress;
|
||||||
|
|
||||||
|
return ((header->magic == VOICE_PROMPTS_DATA_MAGIC) &&
|
||||||
|
(header->version == VOICE_PROMPTS_DATA_VERSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
void vp_init(void)
|
||||||
{
|
{
|
||||||
voicePromptsDataHeader_t header;
|
voicePromptsDataHeader_t header;
|
||||||
vpDataOffset=0;
|
vpDataOffset=0;
|
||||||
|
|
||||||
if (!voice_prompt_file)
|
if (!voice_prompt_file)
|
||||||
vp_open(NULL);
|
vp_open(NULL);
|
||||||
|
|
||||||
if (!voice_prompt_file)
|
if (!voice_prompt_file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fseek(voice_prompt_file, 0L, SEEK_SET);
|
fseek(voice_prompt_file, 0L, SEEK_SET);
|
||||||
fread((void*)&header, sizeof(header), 1, voice_prompt_file);
|
fread((void*)&header, sizeof(header), 1, voice_prompt_file);
|
||||||
|
|
||||||
|
|
@ -141,26 +157,20 @@ void vpCacheInit(void)
|
||||||
codec_init();
|
codec_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vpCheckHeader(uint32_t* bufferAddress)
|
|
||||||
{
|
|
||||||
voicePromptsDataHeader_t* header = (voicePromptsDataHeader_t*)bufferAddress;
|
|
||||||
|
|
||||||
return ((header->magic == VOICE_PROMPTS_DATA_MAGIC) &&
|
|
||||||
(header->version == VOICE_PROMPTS_DATA_VERSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GetCodec2Data(int offset, int length)
|
static void GetCodec2Data(int offset, int length)
|
||||||
{
|
{
|
||||||
if (!voice_prompt_file || (vpDataOffset < (sizeof(voicePromptsDataHeader_t) + sizeof(tableOfContents))))
|
if (!voice_prompt_file || (vpDataOffset < (sizeof(voicePromptsDataHeader_t) + sizeof(tableOfContents))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((offset < 0) || (length > Codec2DataBufferSize))
|
if ((offset < 0) || (length > Codec2DataBufferSize))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Skip codec2 header
|
// Skip codec2 header
|
||||||
fseek(voice_prompt_file, vpDataOffset+offset+CODEC2_HEADER_SIZE, SEEK_SET);
|
fseek(voice_prompt_file, vpDataOffset+offset+CODEC2_HEADER_SIZE, SEEK_SET);
|
||||||
fread((void*)&Codec2Data, length, 1, voice_prompt_file);
|
fread((void*)&Codec2Data, length, 1, voice_prompt_file);
|
||||||
// zero buffer from length to the next multiple of 8 to avoid garbage
|
// zero buffer from length to the next multiple of 8 to avoid garbage
|
||||||
// being played back, since codec2 frames are pushed in lots of 8 bytes.
|
// being played back, since codec2 frames are pushed in lots of 8 bytes.
|
||||||
if ((length % 8) != 0)
|
if ((length % 8) != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -169,7 +179,7 @@ static void GetCodec2Data(int offset, int length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpTerminate(void)
|
void vp_terminate(void)
|
||||||
{
|
{
|
||||||
if (voicePromptIsActive)
|
if (voicePromptIsActive)
|
||||||
{
|
{
|
||||||
|
|
@ -182,7 +192,7 @@ void vpTerminate(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpInit(void)
|
void vp_clearCurrPrompt(void)
|
||||||
{
|
{
|
||||||
vpCurrentSequence.length = 0;
|
vpCurrentSequence.length = 0;
|
||||||
vpCurrentSequence.pos = 0;
|
vpCurrentSequence.pos = 0;
|
||||||
|
|
@ -190,13 +200,13 @@ void vpInit(void)
|
||||||
vpCurrentSequence.codec2DataLength = 0;
|
vpCurrentSequence.codec2DataLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpQueuePrompt(uint16_t prompt)
|
void vp_queuePrompt(const uint16_t prompt)
|
||||||
{
|
{
|
||||||
if (state.settings.vpLevel < vpLow) return;
|
if (state.settings.vpLevel < vpLow) return;
|
||||||
|
|
||||||
if (voicePromptIsActive)
|
if (voicePromptIsActive)
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
}
|
}
|
||||||
if (vpCurrentSequence.length < VOICE_PROMPTS_SEQUENCE_BUFFER_SIZE)
|
if (vpCurrentSequence.length < VOICE_PROMPTS_SEQUENCE_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
|
|
@ -254,13 +264,13 @@ static bool GetSymbolVPIfItShouldBeAnnounced(char symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function spells out a string letter by letter.
|
// This function spells out a string letter by letter.
|
||||||
void vpQueueString(char* promptString, VoicePromptFlags_T flags)
|
void vp_queueString(char* promptString, VoicePromptFlags_T flags)
|
||||||
{
|
{
|
||||||
if (state.settings.vpLevel < vpLow) return;
|
if (state.settings.vpLevel < vpLow) return;
|
||||||
|
|
||||||
if (voicePromptIsActive)
|
if (voicePromptIsActive)
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.settings.vpPhoneticSpell) flags |= vpAnnouncePhoneticRendering;
|
if (state.settings.vpPhoneticSpell) flags |= vpAnnouncePhoneticRendering;
|
||||||
|
|
@ -270,70 +280,70 @@ void vpQueueString(char* promptString, VoicePromptFlags_T flags)
|
||||||
voicePrompt_t vp = UserDictLookup(promptString, &advanceBy);
|
voicePrompt_t vp = UserDictLookup(promptString, &advanceBy);
|
||||||
if (vp)
|
if (vp)
|
||||||
{
|
{
|
||||||
vpQueuePrompt(vp);
|
vp_queuePrompt(vp);
|
||||||
promptString += advanceBy;
|
promptString += advanceBy;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if ((*promptString >= '0') && (*promptString <= '9'))
|
else if ((*promptString >= '0') && (*promptString <= '9'))
|
||||||
{
|
{
|
||||||
vpQueuePrompt(*promptString - '0' + PROMPT_0);
|
vp_queuePrompt(*promptString - '0' + PROMPT_0);
|
||||||
}
|
}
|
||||||
else if ((*promptString >= 'A') && (*promptString <= 'Z'))
|
else if ((*promptString >= 'A') && (*promptString <= 'Z'))
|
||||||
{
|
{
|
||||||
if (flags & vpAnnounceCaps) vpQueuePrompt(PROMPT_CAP);
|
if (flags & vpAnnounceCaps) vp_queuePrompt(PROMPT_CAP);
|
||||||
if (flags & vpAnnouncePhoneticRendering)
|
if (flags & vpAnnouncePhoneticRendering)
|
||||||
vpQueuePrompt((*promptString - 'A') + PROMPT_A_PHONETIC);
|
vp_queuePrompt((*promptString - 'A') + PROMPT_A_PHONETIC);
|
||||||
else
|
else
|
||||||
vpQueuePrompt(*promptString - 'A' + PROMPT_A);
|
vp_queuePrompt(*promptString - 'A' + PROMPT_A);
|
||||||
}
|
}
|
||||||
else if ((*promptString >= 'a') && (*promptString <= 'z'))
|
else if ((*promptString >= 'a') && (*promptString <= 'z'))
|
||||||
{
|
{
|
||||||
if (flags & vpAnnouncePhoneticRendering)
|
if (flags & vpAnnouncePhoneticRendering)
|
||||||
vpQueuePrompt((*promptString - 'a') + PROMPT_A_PHONETIC);
|
vp_queuePrompt((*promptString - 'a') + PROMPT_A_PHONETIC);
|
||||||
else
|
else
|
||||||
vpQueuePrompt(*promptString - 'a' + PROMPT_A);
|
vp_queuePrompt(*promptString - 'a' + PROMPT_A);
|
||||||
}
|
}
|
||||||
else if ((*promptString == ' ') && (flags & vpAnnounceSpace))
|
else if ((*promptString == ' ') && (flags & vpAnnounceSpace))
|
||||||
{
|
{
|
||||||
vpQueuePrompt(PROMPT_SPACE);
|
vp_queuePrompt(PROMPT_SPACE);
|
||||||
}
|
}
|
||||||
else if (GetSymbolVPIfItShouldBeAnnounced(*promptString, flags, &vp))
|
else if (GetSymbolVPIfItShouldBeAnnounced(*promptString, flags, &vp))
|
||||||
{
|
{
|
||||||
if (vp != PROMPT_SILENCE)
|
if (vp != PROMPT_SILENCE)
|
||||||
vpQueuePrompt(vp);
|
vp_queuePrompt(vp);
|
||||||
else // announce ASCII
|
else // announce ASCII
|
||||||
{
|
{
|
||||||
int32_t val = *promptString;
|
int32_t val = *promptString;
|
||||||
vpQueuePrompt(PROMPT_CHARACTER); // just the word "code" as we
|
vp_queuePrompt(PROMPT_CHARACTER); // just the word "code" as we
|
||||||
// don't have character.
|
// don't have character.
|
||||||
vpQueueInteger(val);
|
vp_queueInteger(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// otherwise just add silence
|
// otherwise just add silence
|
||||||
vpQueuePrompt(PROMPT_SILENCE);
|
vp_queuePrompt(PROMPT_SILENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
promptString++;
|
promptString++;
|
||||||
}
|
}
|
||||||
if (flags & vpqAddSeparatingSilence) vpQueuePrompt(PROMPT_SILENCE);
|
if (flags & vpqAddSeparatingSilence) vp_queuePrompt(PROMPT_SILENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpQueueInteger(int32_t value)
|
void vp_queueInteger(const int32_t value)
|
||||||
{
|
{
|
||||||
if (state.settings.vpLevel < vpLow) return;
|
if (state.settings.vpLevel < vpLow) return;
|
||||||
|
|
||||||
char buf[12] = {0}; // min: -2147483648, max: 2147483647
|
char buf[12] = {0}; // min: -2147483648, max: 2147483647
|
||||||
snprintf(buf, 12, "%d", value);
|
snprintf(buf, 12, "%d", value);
|
||||||
vpQueueString(buf, 0);
|
vp_queueString(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function looks up a voice prompt corresponding to a string table entry.
|
// This function looks up a voice prompt corresponding to a string table entry.
|
||||||
// These are stored in the voice data after the voice prompts with no
|
// These are stored in the voice data after the voice prompts with no
|
||||||
// corresponding string table entry, hence the offset calculation:
|
// corresponding string table entry, hence the offset calculation:
|
||||||
// NUM_VOICE_PROMPTS + (stringTableStringPtr - currentLanguage->languageName)
|
// NUM_VOICE_PROMPTS + (stringTableStringPtr - currentLanguage->languageName)
|
||||||
void vpQueueStringTableEntry(const char* const* stringTableStringPtr)
|
void vp_queueStringTableEntry(const char* const* stringTableStringPtr)
|
||||||
{
|
{
|
||||||
if (state.settings.vpLevel < vpLow) return;
|
if (state.settings.vpLevel < vpLow) return;
|
||||||
|
|
||||||
|
|
@ -341,31 +351,31 @@ void vpQueueStringTableEntry(const char* const* stringTableStringPtr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vpQueuePrompt(NUM_VOICE_PROMPTS + 1 +
|
vp_queuePrompt(NUM_VOICE_PROMPTS + 1 +
|
||||||
(stringTableStringPtr - ¤tLanguage->languageName)
|
(stringTableStringPtr - ¤tLanguage->languageName)
|
||||||
/ sizeof(const char *));
|
/ sizeof(const char *));
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpPlay(void)
|
void vp_play(void)
|
||||||
{
|
{
|
||||||
if (state.settings.vpLevel < vpLow) return;
|
if (state.settings.vpLevel < vpLow) return;
|
||||||
|
|
||||||
if (voicePromptIsActive) return;
|
if (voicePromptIsActive) return;
|
||||||
|
|
||||||
if (vpCurrentSequence.length <= 0) return;
|
if (vpCurrentSequence.length <= 0) return;
|
||||||
|
|
||||||
voicePromptIsActive = true; // Start the playback
|
voicePromptIsActive = true; // Start the playback
|
||||||
|
|
||||||
codec_startDecode(SINK_SPK);
|
codec_startDecode(SINK_SPK);
|
||||||
|
|
||||||
audio_enableAmp();
|
audio_enableAmp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this from the main timer thread to continue voice prompt playback.
|
// Call this from the main timer thread to continue voice prompt playback.
|
||||||
void vpTick()
|
void vp_tick()
|
||||||
{
|
{
|
||||||
if (!voicePromptIsActive) return;
|
if (!voicePromptIsActive) return;
|
||||||
|
|
||||||
while (vpCurrentSequence.pos < vpCurrentSequence.length)
|
while (vpCurrentSequence.pos < vpCurrentSequence.length)
|
||||||
{// get the codec2 data for the current prompt if needed.
|
{// get the codec2 data for the current prompt if needed.
|
||||||
if (vpCurrentSequence.codec2DataLength == 0)
|
if (vpCurrentSequence.codec2DataLength == 0)
|
||||||
|
|
@ -374,16 +384,16 @@ void vpTick()
|
||||||
|
|
||||||
vpCurrentSequence.codec2DataLength =
|
vpCurrentSequence.codec2DataLength =
|
||||||
tableOfContents[promptNumber + 1] - tableOfContents[promptNumber];
|
tableOfContents[promptNumber + 1] - tableOfContents[promptNumber];
|
||||||
|
|
||||||
GetCodec2Data(tableOfContents[promptNumber], vpCurrentSequence.codec2DataLength);
|
GetCodec2Data(tableOfContents[promptNumber], vpCurrentSequence.codec2DataLength);
|
||||||
|
|
||||||
vpCurrentSequence.codec2DataIndex = 0;
|
vpCurrentSequence.codec2DataIndex = 0;
|
||||||
}
|
}
|
||||||
// push the codec2 data in lots of 8 byte frames.
|
// push the codec2 data in lots of 8 byte frames.
|
||||||
while (vpCurrentSequence.codec2DataIndex < vpCurrentSequence.codec2DataLength)
|
while (vpCurrentSequence.codec2DataIndex < vpCurrentSequence.codec2DataLength)
|
||||||
{
|
{
|
||||||
if (!codec_pushFrame(Codec2Data+vpCurrentSequence.codec2DataIndex, false))
|
if (!codec_pushFrame(Codec2Data+vpCurrentSequence.codec2DataIndex, false))
|
||||||
return; // wait until there is room, perhaps next vpTick call.
|
return; // wait until there is room, perhaps next vp_tick call.
|
||||||
vpCurrentSequence.codec2DataIndex += 8;
|
vpCurrentSequence.codec2DataIndex += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,12 +406,12 @@ void vpTick()
|
||||||
voicePromptIsActive=false;
|
voicePromptIsActive=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool vpIsPlaying(void)
|
bool vp_isPlaying(void)
|
||||||
{
|
{
|
||||||
return voicePromptIsActive;
|
return voicePromptIsActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vpHasDataToPlay(void)
|
bool vp_sequenceNotEmpty(void)
|
||||||
{
|
{
|
||||||
return (vpCurrentSequence.length > 0);
|
return (vpCurrentSequence.length > 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -616,7 +616,7 @@ int _ui_fsm_loadChannel(int16_t channel_index, bool *sync_rtx) {
|
||||||
|
|
||||||
void _ui_fsm_confirmVFOInput(bool *sync_rtx)
|
void _ui_fsm_confirmVFOInput(bool *sync_rtx)
|
||||||
{
|
{
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
// Switch to TX input
|
// Switch to TX input
|
||||||
if(ui_state.input_set == SET_RX)
|
if(ui_state.input_set == SET_RX)
|
||||||
{
|
{
|
||||||
|
|
@ -653,7 +653,7 @@ void _ui_fsm_confirmVFOInput(bool *sync_rtx)
|
||||||
announceError(vpqInit);
|
announceError(vpqInit);
|
||||||
state.ui_screen = MAIN_VFO;
|
state.ui_screen = MAIN_VFO;
|
||||||
}
|
}
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
|
void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
|
||||||
|
|
@ -661,14 +661,14 @@ void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
|
||||||
// Advance input position
|
// Advance input position
|
||||||
ui_state.input_position += 1;
|
ui_state.input_position += 1;
|
||||||
// clear any prompts in progress.
|
// clear any prompts in progress.
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
// Save pressed number to calculate frequency and show in GUI
|
// Save pressed number to calculate frequency and show in GUI
|
||||||
ui_state.input_number = input_getPressedNumber(msg);
|
ui_state.input_number = input_getPressedNumber(msg);
|
||||||
// queue the digit just pressed.
|
// queue the digit just pressed.
|
||||||
vpQueueInteger(ui_state.input_number);
|
vp_queueInteger(ui_state.input_number);
|
||||||
// queue point if user has entered three digits.
|
// queue point if user has entered three digits.
|
||||||
if (ui_state.input_position==3)
|
if (ui_state.input_position==3)
|
||||||
vpQueuePrompt(PROMPT_POINT);
|
vp_queuePrompt(PROMPT_POINT);
|
||||||
|
|
||||||
if(ui_state.input_set == SET_RX)
|
if(ui_state.input_set == SET_RX)
|
||||||
{
|
{
|
||||||
|
|
@ -681,7 +681,7 @@ void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
|
||||||
{// queue the rx freq just completed.
|
{// queue the rx freq just completed.
|
||||||
vpQueueFrequency(ui_state.new_rx_frequency);
|
vpQueueFrequency(ui_state.new_rx_frequency);
|
||||||
/// now queue tx as user has changed fields.
|
/// now queue tx as user has changed fields.
|
||||||
vpQueuePrompt(PROMPT_TRANSMIT);
|
vp_queuePrompt(PROMPT_TRANSMIT);
|
||||||
// Switch to TX input
|
// Switch to TX input
|
||||||
ui_state.input_set = SET_TX;
|
ui_state.input_set = SET_TX;
|
||||||
// Reset input position
|
// Reset input position
|
||||||
|
|
@ -712,7 +712,7 @@ void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
|
||||||
state.ui_screen = MAIN_VFO;
|
state.ui_screen = MAIN_VFO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ui_changeBrightness(int variation)
|
void _ui_changeBrightness(int variation)
|
||||||
|
|
|
||||||
|
|
@ -99,9 +99,9 @@ static void announceMenuItemIfNeeded(char* name, char* value)
|
||||||
// See if we are already in the middle of speaking a menu item.
|
// See if we are already in the middle of speaking a menu item.
|
||||||
// e.g. when changing a value with left or right, we don't want to repeat the
|
// e.g. when changing a value with left or right, we don't want to repeat the
|
||||||
// prompt if arrowing rapidly.
|
// prompt if arrowing rapidly.
|
||||||
bool voicePromptWasPlaying=vpIsPlaying();
|
bool voicePromptWasPlaying=vp_isPlaying();
|
||||||
// Stop any prompt in progress and clear the buffer.
|
// Stop any prompt in progress and clear the buffer.
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
// If no value is supplied, or, no prompt is in progress, announce the name.
|
// If no value is supplied, or, no prompt is in progress, announce the name.
|
||||||
if (!voicePromptWasPlaying || !value || !*value)
|
if (!voicePromptWasPlaying || !value || !*value)
|
||||||
announceText(name, vpqDefault);
|
announceText(name, vpqDefault);
|
||||||
|
|
@ -109,7 +109,7 @@ static void announceMenuItemIfNeeded(char* name, char* value)
|
||||||
if (value && *value)
|
if (value && *value)
|
||||||
announceText(value, vpqDefault);
|
announceText(value, vpqDefault);
|
||||||
|
|
||||||
vpPlay();
|
vp_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ui_drawMenuList(uint8_t selected, int (*getCurrentEntry)(char *buf, uint8_t max_len, uint8_t index))
|
void _ui_drawMenuList(uint8_t selected, int (*getCurrentEntry)(char *buf, uint8_t max_len, uint8_t index))
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,12 @@ int main()
|
||||||
state.settings.vpLevel = 3;
|
state.settings.vpLevel = 3;
|
||||||
VoicePromptQueueFlags_T flags = GetQueueFlagsForVoiceLevel();
|
VoicePromptQueueFlags_T flags = GetQueueFlagsForVoiceLevel();
|
||||||
|
|
||||||
vpCacheInit();
|
vp_init();
|
||||||
vpInit();
|
vp_clearCurrPrompt();
|
||||||
vpQueueStringTableEntry(¤tLanguage->allChannels);
|
vp_queueStringTableEntry(¤tLanguage->allChannels);
|
||||||
vpPlay();
|
vp_play();
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
vpTick();
|
vp_tick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue