FreeTRX/MDUV380_firmware/application/include/functions/settings.h
Marcus Kida 1c59622a77 Release 0.2.0: fix Display Options crash with voice prompts on
Screen Dim passed a plain literal ('100%'/'50%'/...) to
voicePromptsAppendLanguageString(), which derives the prompt index from the
string's offset within the language table; a foreign pointer produced a garbage
index and crashed (only with voice on). Route the value through
voicePromptsAppendString() instead. Also move the 3-bit dim level's high bit off
legacy option bit 2 to bit 29 and clamp the level against the option arrays.

Bump version to 0.2.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 15:41:59 +02:00

441 lines
18 KiB
C

/*
* Copyright (C) 2019 Kai Ludwig, DG4KLU
* Copyright (C) 2019-2025 Roger Clark, VK3KYY / G4KYF
* Daniel Caujolle-Bert, F1RMB
*
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. Use of this source code or binary releases for commercial purposes is strictly forbidden. This includes, without limitation,
* incorporation in a commercial product or incorporation into a product or project which allows commercial use.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _OPENGD77_SETTINGS_H_
#define _OPENGD77_SETTINGS_H_
#include "functions/codeplug.h"
#include "functions/trx.h"
enum USB_MODE { USB_MODE_CPS, USB_MODE_HOTSPOT, USB_MODE_DEBUG };
enum SETTINGS_UI_MODE { SETTINGS_CHANNEL_MODE = 0, SETTINGS_VFO_A_MODE, SETTINGS_VFO_B_MODE };
enum BACKLIGHT_MODE { BACKLIGHT_MODE_AUTO = 0, BACKLIGHT_MODE_SQUELCH, BACKLIGHT_MODE_MANUAL, BACKLIGHT_MODE_BUTTONS, BACKLIGHT_MODE_NONE };
enum HOTSPOT_TYPE { HOTSPOT_TYPE_OFF = 0, HOTSPOT_TYPE_MMDVM, HOTSPOT_TYPE_BLUEDV };
enum CONTACT_DISPLAY_PRIO { CONTACT_DISPLAY_PRIO_CC_DB_TA = 0, CONTACT_DISPLAY_PRIO_DB_CC_TA, CONTACT_DISPLAY_PRIO_TA_CC_DB, CONTACT_DISPLAY_PRIO_TA_DB_CC };
enum SCAN_MODE { SCAN_MODE_HOLD = 0, SCAN_MODE_PAUSE, SCAN_MODE_STOP };
enum SPLIT_CONTACT { SPLIT_CONTACT_SINGLE_LINE_ONLY = 0, SPLIT_CONTACT_ON_TWO_LINES, SPLIT_CONTACT_AUTO };
enum ALLOW_PRIVATE_CALLS_MODE { ALLOW_PRIVATE_CALLS_OFF = 0, ALLOW_PRIVATE_CALLS_ON, ALLOW_PRIVATE_CALLS_PTT };//, ALLOW_PRIVATE_CALLS_AUTO };
enum BAND_LIMITS_ENUM { BAND_LIMITS_NONE = 0 , BAND_LIMITS_ON_LEGACY_DEFAULT, BAND_LIMITS_FROM_CPS };
enum INFO_ON_SCREEN { INFO_ON_SCREEN_OFF = 0x00, INFO_ON_SCREEN_TS = 0x01, INFO_ON_SCREEN_PWR = 0x02, INFO_ON_SCREEN_BOTH = 0x03 };
#if defined(HAS_GPS)
#define SETTINGS_GPS_MODE_GET(x) ((x).gpsModeAndBaudsIndex & 0x0F)
#define SETTINGS_GPS_BAUDRATE_GET(x) (((x).gpsModeAndBaudsIndex & 0xF0) >> 4)
#define SETTINGS_GPS_MODE_SET(x, m) (((x).gpsModeAndBaudsIndex & 0xF0) | ((m) & 0x0F))
#define SETTINGS_GPS_BAUDRATE_SET(x, b) ((((b) & 0x0F) << 4) | ((x).gpsModeAndBaudsIndex & 0x0F))
typedef enum
{
GPS_NOT_DETECTED,
GPS_MODE_OFF,
GPS_MODE_ON,
GPS_MODE_ON_NMEA,
#if defined(LOG_GPS_DATA)
GPS_MODE_ON_LOG,
#endif
NUM_GPS_MODES,
} gpsMode_t;
#endif
typedef enum
{
ROAMING_OFF = 0U,
ROAMING_MANUAL,
ROAMING_5KM,
ROAMING_10KM,
ROAMING_20KM,
ROAMING_MAX_NUM
} roaming_t;
#define ECO_LEVEL_MAX 5
#define SETTINGS_TIMEZONE_UTC 64
#define SETTINGS_UNITIALISED_LOCATION_LAT 0x7F000000U
// Bit patterns for DMR Beep
#define BEEP_TX_NONE 0x00
#define BEEP_TX_START 0x01
#define BEEP_TX_STOP 0x02
#define BEEP_RX_CARRIER 0x04
#define BEEP_RX_TALKER 0x08
#define BEEP_RX_TALKER_BEGIN 0x10
#if defined(PLATFORM_GD77) || defined(PLATFORM_GD77S) || defined(PLATFORM_DM1801) || defined(PLATFORM_DM1801A) || defined(PLATFORM_RD5R)
#define SETTINGS_DMR_MIC_ZERO 11U
#define SETTINGS_FM_MIC_ZERO 16U
#elif defined(PLATFORM_MD9600)
#define SETTINGS_DMR_MIC_ZERO 8U
#define SETTINGS_FM_MIC_ZERO 6U
#else
#define SETTINGS_DMR_MIC_ZERO 5U
#define SETTINGS_FM_MIC_ZERO 4U
#endif
#define LOCATION_DECIMAL_PART_MULIPLIER_FIXED_32 100000
#define LOCATION_DECIMAL_PART_MULIPLIER_FIXED_32_DOUBLE 1E-5
#define LOCATION_DECIMAL_PART_MULIPLIER_FIXED_24 10000
#define LOCATION_DECIMAL_PART_MULIPLIER_FIXED_24_DOUBLE 1E-4
extern int settingsCurrentChannelNumber;
extern int16_t *nextKeyBeepMelody;
extern CodeplugChannel_t settingsVFOChannel[2];
extern CodeplugGeneralSettings_t settingsCodeplugGeneralSettings;
#define SETTINGS_BITS_NUMBER_OF_BANKS 1U // Number of settings bits banks (max 4)
// bits #30 to #31 are used for storage bank index, settings bits are using the first 30 bits (#29 to #0)
#define SETTINGS_BITS_ARRAY_BANK(x) (((x) & 0xC0000000) >> 30)
#define SETTINGS_BITS_ARRAY_VALUE(x) ((x) & ~0xC0000000)
#define SETTINGS_BITS_BANK_0 (0 << 30) // 1
#if (SETTINGS_BITS_NUMBER_OF_BANKS >= 2U)
#define SETTINGS_BITS_BANK_1 (1 << 30) // 2
#if (SETTINGS_BITS_NUMBER_OF_BANKS >= 3U)
#define SETTINGS_BITS_BANK_2 (2 << 30) // 3
#if (SETTINGS_BITS_NUMBER_OF_BANKS == 4U)
#define SETTINGS_BITS_BANK_3 (3 << 30) // 4
#else
#error settings banks max value is 4
#endif
#endif
#endif
typedef enum
{
BIT_INVERSE_VIDEO = (SETTINGS_BITS_BANK_0 | (1 << 0)),
BIT_PTT_LATCH = (SETTINGS_BITS_BANK_0 | (1 << 1)),
BIT_UNUSED_2 = (SETTINGS_BITS_BANK_0 | (1 << 2)),
BIT_BATTERY_VOLTAGE_IN_HEADER = (SETTINGS_BITS_BANK_0 | (1 << 3)),
BIT_SETTINGS_UPDATED = (SETTINGS_BITS_BANK_0 | (1 << 4)),
BIT_TX_RX_FREQ_LOCK = (SETTINGS_BITS_BANK_0 | (1 << 5)),
BIT_ALL_LEDS_DISABLED = (SETTINGS_BITS_BANK_0 | (1 << 6)),
BIT_SCAN_ON_BOOT_ENABLED = (SETTINGS_BITS_BANK_0 | (1 << 7)),
#if !defined(STM32F405xx)
BIT_POWEROFF_SUSPEND = (SETTINGS_BITS_BANK_0 | (1 << 8)),
#endif
BIT_SATELLITE_MANUAL_AUTO = (SETTINGS_BITS_BANK_0 | (1 << 9)),
BIT_SCREEN_DIM_0 = (SETTINGS_BITS_BANK_0 | (1 << 10)), // low bit of the 3-bit screen-dim level
#if defined(PLATFORM_MD9600)
BIT_SPEAKER_CLICK_SUPPRESS = (SETTINGS_BITS_BANK_0 | (1 << 11)),
#endif
BIT_DMR_CRC_IGNORED = (SETTINGS_BITS_BANK_0 | (1 << 12)),
BIT_APO_WITH_RF = (SETTINGS_BITS_BANK_0 | (1 << 13)),
BIT_SAFE_POWER_ON = (SETTINGS_BITS_BANK_0 | (1 << 14)),
BIT_AUTO_NIGHT = (SETTINGS_BITS_BANK_0 | (1 << 15)),
BIT_AUTO_NIGHT_OVERRIDE = (SETTINGS_BITS_BANK_0 | (1 << 16)),
BIT_AUTO_NIGHT_DAYTIME = (SETTINGS_BITS_BANK_0 | (1 << 17)),
#if defined(HAS_SOFT_VOLUME)
BIT_VISUAL_VOLUME = (SETTINGS_BITS_BANK_0 | (1 << 18)),
#endif
BIT_SECONDARY_LANGUAGE = (SETTINGS_BITS_BANK_0 | (1 << 19)),
BIT_SCREEN_DIM_1 = (SETTINGS_BITS_BANK_0 | (1 << 20)), // middle bit of the 3-bit screen-dim level
BIT_SCREEN_DIM_2 = (SETTINGS_BITS_BANK_0 | (1 << 29)), // high bit of the 3-bit screen-dim level (kept off low legacy bits)
BIT_DISPLAY_CHANNEL_DISTANCE = (SETTINGS_BITS_BANK_0 | (1 << 21)),
#if defined(PLATFORM_MD2017)
BIT_TRACKBALL_ENABLED = (SETTINGS_BITS_BANK_0 | (1 << 22)),
BIT_TRACKBALL_FAST_MOTION = (SETTINGS_BITS_BANK_0 | (1 << 23)),
#endif
#if defined(PLATFORM_MDUV380) && !defined(PLATFORM_VARIANT_UV380_PLUS_10W)
BIT_FORCE_10W_RADIO = (SETTINGS_BITS_BANK_0 | (1 << 24)),
#endif
BIT_TX_INHIBIT = (SETTINGS_BITS_BANK_0 | (1 << 25)),
#if defined(HAS_COLOURS) || defined(PLATFORM_MD9600)
BIT_DISPLAY_TIME_IN_HEADER = (SETTINGS_BITS_BANK_0 | (1 << 26)),
#endif
BIT_CHANNELS_ARE_READ_ONLY = (SETTINGS_BITS_BANK_0 | (1 << 27)),
BIT_UI_USES_DOUBLE_HEIGHT = (SETTINGS_BITS_BANK_0 | (1 << 28)),
// Last usable bit is 29
//BIT_xxxxxxx_xxxxxxxxxxxx = (SETTINGS_BITS_BANK_1 | (1 << 0)),
//BIT_xxxxxxx_xxxxxxxxxxxx = (SETTINGS_BITS_BANK_2 | (1 << 0)),
//BIT_xxxxxxx_xxxxxxxxxxxx = (SETTINGS_BITS_BANK_3 | (1 << 0)),
} bitfieldOptions_t;
#if defined(PLATFORM_MD9600)
#define RADIO_BANDS_TOTAL_NUM_SQUELCH 2
#else
#define RADIO_BANDS_TOTAL_NUM_SQUELCH 3
#endif
typedef struct
{
uint32_t lat; // fixed point encoded as 1 sign bit, 8 bits integer, 23 bits as decimal
uint32_t lon; // fixed point encoded as 1 sign bit, 8 bits integer, 23 bits as decimal
} settingsLocation_t;
typedef struct
{
uint32_t magicNumber;
// The following settings won't be reset default from magicNumber 0x4761
settingsLocation_t location;
uint8_t timezone;// Lower 7 bits are the timezone. 64 = UTC, values < 64 are negative TZ values. Bit 8 is a flag which indicates TZ/UTC. 0 = UTC
// -----------------------------------------------
uint8_t beepOptions; // 2 pairs of bits + 1 (TX and RX beeps)
uint16_t vfoSweepSettings; // 3bits: channel step | 5 bits: RSSI noise floor | 7bits: gain
uint32_t overrideTG;
uint32_t vfoScanLow[2]; // low frequency for VFO Scanning
uint32_t vfoScanHigh[2]; // High frequency for VFO Scanning
uint32_t bitfieldOptions[SETTINGS_BITS_NUMBER_OF_BANKS]; // see bitfieldOptions_t
uint32_t aprsBeaconingSettingsPart1[2];
#if defined(LOG_GPS_DATA)
uint32_t gpsLogMemOffset; // Current offset from the NMEA logging flash memory address start.
#endif
int16_t currentIndexInTRxGroupList[3]; // Current Channel, VFO A and VFO B
int16_t currentZone;
uint16_t userPower;
uint16_t tsManualOverride;
#if (defined(PLATFORM_RD5R) || defined(PLATFORM_MD9600))
int16_t currentChannelIndexInZone;
int16_t currentChannelIndexInAllZone;
#else // These two has to be used on any platform but RD5R and MD-9600
int16_t UNUSED_1;
int16_t UNUSED_2;
#endif
uint16_t aprsBeaconingSettingsPart2;
uint8_t txPowerLevel;
uint8_t txTimeoutBeepX5Secs;
uint8_t beepVolumeDivider;
uint8_t micGainDMR;
uint8_t micGainFM;
uint8_t backlightMode; // see BACKLIGHT_MODE enum
uint8_t backLightTimeout; // 0 = never timeout. 1 - 255 time in seconds
int8_t displayContrast;
int8_t displayBacklightPercentage[NIGHT + 1];
int8_t displayBacklightPercentageOff; // backlight level when "off"
uint8_t initialMenuNumber;
uint8_t extendedInfosOnScreen;
uint8_t txFreqLimited;
uint8_t scanModePause;
uint8_t scanDelay;
uint8_t dmrRxAGC;
uint8_t hotspotType;
uint8_t scanStepTime;
uint8_t currentVFONumber;
uint8_t dmrDestinationFilter;
uint8_t dmrCaptureTimeout;
uint8_t dmrCcTsFilter;
uint8_t analogFilterLevel;
uint8_t privateCalls;
uint8_t contactDisplayPriority;
uint8_t splitContact;
uint8_t voxThreshold; // 0: disabled
uint8_t voxTailUnits; // 500ms units
uint8_t audioPromptMode;
int8_t temperatureCalibration;// Units of 0.5 deg C
uint8_t batteryCalibration; // Units of 0.01V (NOTE: only the 4 lower bits are used)
uint8_t squelchDefaults[RADIO_BANDS_TOTAL_NUM_SQUELCH]; // VHF, 200 and UHF
uint8_t ecoLevel;// Power saving / economy level
uint8_t apo; // unit: 30 minutes (max 24 => 12 hours)
uint8_t keypadTimerLong;
uint8_t keypadTimerRepeat;
uint8_t autolockTimer; // in minutes
roaming_t roaming;
#if defined(HAS_GPS)
// 4 lower bits: gpsMode_t,
//
// On STM32F405xx only:
// 4 higher bits: baudrate index (0U: value is undetected,
// otherwise value minus 1 is passed to gpsSetBaudRateByIndex())
// Use SETTINGS_GPS_*GET/SET macros.
uint8_t gpsModeAndBaudsIndex;
#endif
uint8_t lastTalkerOnScreenTimer; // in seconds, 0..30
} settingsStruct_t;
typedef enum DMR_DESTINATION_FILTER_TYPE
{
DMR_DESTINATION_FILTER_NONE = 0,
DMR_DESTINATION_FILTER_TG,
DMR_DESTINATION_FILTER_DC,
DMR_DESTINATION_FILTER_RXG,
NUM_DMR_DESTINATION_FILTER_LEVELS
} dmrDestinationFilter_t;
// Bit patterns
#define DMR_CC_FILTER_PATTERN 0x01
#define DMR_TS_FILTER_PATTERN 0x02
// NOTE. THIS ENUM IS USED AS BIT PATTERNS, DO NOT CHANGE THE DEFINED VALUES WITHOUT UPDATING ANY CODE WHICH USES THIS ENUM
typedef enum DMR_CCTS_FILTER_TYPE
{
DMR_CCTS_FILTER_NONE = 0,
DMR_CCTS_FILTER_CC = DMR_CC_FILTER_PATTERN,
DMR_CCTS_FILTER_TS = DMR_TS_FILTER_PATTERN,
DMR_CCTS_FILTER_CC_TS = DMR_CC_FILTER_PATTERN | DMR_TS_FILTER_PATTERN,
NUM_DMR_CCTS_FILTER_LEVELS
} dmrCcTsFilter_t;
typedef enum ANALOG_FILTER_TYPE
{
ANALOG_FILTER_NONE = 0,
ANALOG_FILTER_CSS,
NUM_ANALOG_FILTER_LEVELS
} analogFilter_t;
typedef enum AUDIO_PROMPT_MODE
{
AUDIO_PROMPT_MODE_SILENT = 0,
AUDIO_PROMPT_MODE_BEEP,
AUDIO_PROMPT_MODE_NO_KEY_BEEP,
AUDIO_PROMPT_MODE_VOICE_LEVEL_1,
AUDIO_PROMPT_MODE_VOICE_LEVEL_2,
AUDIO_PROMPT_MODE_VOICE_LEVEL_3 ,
NUM_AUDIO_PROMPT_MODES,
AUDIO_PROMPT_MODE_VOICE_THRESHOLD = AUDIO_PROMPT_MODE_VOICE_LEVEL_1
} audioPromptMode_t;
typedef enum PROMPT_AUTOPLAY_THRESHOLD
{
PROMPT_THRESHOLD_1 = AUDIO_PROMPT_MODE_VOICE_LEVEL_1,
PROMPT_THRESHOLD_2,
PROMPT_THRESHOLD_3,
PROMPT_THRESHOLD_NEVER_PLAY_IMMEDIATELY
} audioPromptThreshold_t;
typedef struct
{
volatile bool triggered;
volatile bool isEnabled;
volatile bool qsoInfoUpdated;
volatile bool dmrIsValid;
int dmrTimeout;
uint8_t dmrFrameSkip;
int savedRadioMode;
uint8_t savedSquelch;
int savedDMRCcTsFilter;
int savedDMRDestinationFilter;
uint8_t savedDMRCc;
int savedDMRTs;
} monitorModeSettingsStruct_t;
extern settingsStruct_t nonVolatileSettings;
extern CodeplugChannel_t *currentChannelData;
extern CodeplugChannel_t channelScreenChannelData;
extern CodeplugContact_t contactListContactData;
extern CodeplugDTMFContact_t contactListDTMFContactData;
extern int contactListContactIndex;
extern volatile int settingsUsbMode;
extern monitorModeSettingsStruct_t monitorModeData;
// Do not use the following settingsSet<TYPE>(...) functions, use settingsSet() instead
void settingsSetBOOL(bool *s, bool v);
void settingsSetINT8(int8_t *s, int8_t v);
void settingsSetUINT8(uint8_t *s, uint8_t v);
void settingsSetINT16(int16_t *s, int16_t v);
void settingsSetUINT16(uint16_t *s, uint16_t v);
void settingsSetINT32(int32_t *s, int32_t v);
void settingsSetUINT32(uint32_t *s, uint32_t v);
// Do not use the following settingsInc/Dec<TYPE>(...) functions, use settingsIncrement/Decrement() instead
void settingsIncINT8(int8_t *s, int8_t v);
void settingsIncUINT8(uint8_t *s, uint8_t v);
void settingsIncINT16(int16_t *s, int16_t v);
void settingsIncUINT16(uint16_t *s, uint16_t v);
void settingsIncINT32(int32_t *s, int32_t v);
void settingsIncUINT32(uint32_t *s, uint32_t v);
void settingsDecINT8(int8_t *s, int8_t v);
void settingsDecUINT8(uint8_t *s, uint8_t v);
void settingsDecINT16(int16_t *s, int16_t v);
void settingsDecUINT16(uint16_t *s, uint16_t v);
void settingsDecINT32(int32_t *s, int32_t v);
void settingsDecUINT32(uint32_t *s, uint32_t v);
// Workaround for Eclipse's CDT parser angriness because it doesn't support C11 yet
#ifdef __CDT_PARSER__
#define settingsSet(S, V) do { /* It uses C11's _Generic() at compile time */ S = V; } while(0)
#else
#define settingsSet(S, V) _Generic((S), \
bool: settingsSetBOOL, \
int8_t: settingsSetINT8, \
uint8_t: settingsSetUINT8, \
int16_t: settingsSetINT16, \
uint16_t: settingsSetUINT16, \
int32_t: settingsSetINT32, \
uint32_t: settingsSetUINT32 \
)(&S, V)
#endif
#ifdef __CDT_PARSER__
#define settingsIncrement(S, V) do { /* It uses C11's _Generic() at compile time */ S += V; } while(0)
#else
#define settingsIncrement(S, V) _Generic((S), \
int8_t: settingsIncINT8, \
uint8_t: settingsIncUINT8, \
int16_t: settingsIncINT16, \
uint16_t: settingsIncUINT16, \
int32_t: settingsIncINT32, \
uint32_t: settingsIncUINT32 \
)(&S, V)
#endif
#ifdef __CDT_PARSER__
#define settingsDecrement(S, V) do { /* It uses C11's _Generic() at compile time */ S -= V; } while(0)
#else
#define settingsDecrement(S, V) _Generic((S), \
int8_t: settingsDecINT8, \
uint8_t: settingsDecUINT8, \
int16_t: settingsDecINT16, \
uint16_t: settingsDecUINT16, \
int32_t: settingsDecINT32, \
uint32_t: settingsDecUINT32 \
)(&S, V)
#endif
void settingsSetOptionBit(bitfieldOptions_t bit, bool set);
bool settingsIsOptionBitSetFromSettings(settingsStruct_t *sets, bitfieldOptions_t bit);
bool settingsIsOptionBitSet(bitfieldOptions_t bit);
void settingsSetDirty(void);
void settingsSetVFODirty(void);
void settingsSaveIfNeeded(bool immediately);
// Screen dimming: idle backlight as a fraction of the configured brightness.
typedef enum
{
SCREEN_DIM_OFF = 0, // feature disabled (use the normal backlight-off level)
SCREEN_DIM_100, // stay at 100% of configured brightness when idle
SCREEN_DIM_50, // dim to 50%
SCREEN_DIM_30, // dim to 30%
SCREEN_DIM_15, // dim to 15%
SCREEN_DIM_NUM
} screenDimLevel_t;
uint8_t settingsGetScreenDimLevel(void);
void settingsSetScreenDimLevel(uint8_t level);
bool settingsSaveSettings(bool includeVFOs);
bool settingsLoadSettings(bool reset);
bool settingsRestoreDefaultSettings(void);
void settingsEraseCustomContent(void);
//void settingsInitVFOChannel(int vfoNumber);
void enableVoicePromptsIfLoaded(bool enableFullPrompts);
int settingsGetScanStepTimeMilliseconds(void);
bool settingsLocationIsValid(void);
double settingsLocationGetLatitude(void);
double settingsLocationGetLongitude(void);
#endif