UHSDR/UHSDR-active-devel/mchf-eclipse/drivers/ui/ui_configuration.c
2022-11-08 16:13:55 +01:00

1144 lines
57 KiB
C

/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#include "ui_configuration.h"
#include "config_storage.h"
#include "ui_driver.h"
#include "audio_driver.h"
#include "audio_agc.h"
#include "cw_decoder.h"
#include "ui_spectrum.h"
#include "radio_management.h"
#include "audio_management.h"
#include "ui.h" // bandInfo
#include "uhsdr_hw_i2c.h"
#include "uhsdr_rtc.h"
#if (MAX_VAR_ADDR > NB_OF_VAR)
#error "Too many eeprom variables defined in ui_configuration.h (MAX_VAR_ADDR > NB_OF_VAR ). Please change maximum number of vars in eeprom.h"
#endif
static int32_t UiConfiguration_CompareConfigBuildVersions(uint major, uint32_t minor, uint32_t release);
// If more EEPROM variables are added, make sure that you add to this table - and the index to it in "eeprom.h"
// and correct MAX_VAR_ADDR in uhsdr_board.h
static uint16_t number_of_entries_cur_fw; // we need this to be able to read config values without modifying anything
#define CONFIG_UINT8x2_COMBINE(a,b) ((((a) << 8) | (b)))
#define UI_C_EEPROM_BAND_5W_PF(bandNo,bandName1,bandName2) { ConfigEntry_UInt8 | Calib_Val, EEPROM_BAND##bandNo##_5W,&ts.pwr_adj[ADJ_REF_PWR][BAND_MODE_##bandName1],TX_POWER_FACTOR_##bandName1##_DEFAULT,0,TX_POWER_FACTOR_MAX },
#define UI_C_EEPROM_BAND_FULL_PF(bandNo,bandName1,bandName2) { ConfigEntry_UInt8 | Calib_Val, EEPROM_BAND##bandNo##_FULL,&ts.pwr_adj[ADJ_FULL_POWER][BAND_MODE_##bandName1],TX_POWER_FACTOR_##bandName1##_DEFAULT,0,TX_POWER_FACTOR_MAX },
// here all simple configuration values are defined
// in order to have a new configuration value being stored in nonvolatile memory
// just add an entry. It is important to specify the addres of a ram location from where to read/write the
// respective value. As these configuration descriptors are constant values, the address has to be the address
// of a global (or static variable) the compiler know about.
// It is also important to use the matching typeId otherwise data will not be (re)store in a number of cases
// Some configuration values are currently not in this structure since saving them is more complex. See LoadEeprom/SaveEeprom functions.
// What means: INT DEFAULT PROBLEM: When using the EEPROM as configuration value store, we cannot distinguish the deleted (read never used) state from the normal state.
// This leads in a number of cases to the problem of initializing the parameter with its default value when it is first introduced. Since we simply read the storage location
// from eeprom, we read -1 from the new location and leave it there. Unless -1 is the default value or the range of the int configuration parameter does not include -1
// we will not automatically set the default value, which can be a problem.
const ConfigEntryDescriptor ConfigEntryInfo[] =
{
// { ConfigEntry_UInt16, EEPROM_ZERO_LOC,&dummy_value16,0xffff,0,0xffff},
// disable since we don't want to handle the eeprom signature here.
{ ConfigEntry_UInt16, EEPROM_FLAGS2,&ts.flags2,0,0,0xff},
{ ConfigEntry_UInt8, EEPROM_SPEC_SCOPE_SPEED,&ts.scope_speed,SPECTRUM_SCOPE_SPEED_DEFAULT,0,SPECTRUM_SCOPE_SPEED_MAX},
{ ConfigEntry_UInt32_16, EEPROM_FREQ_STEP,&df.selected_idx,3,0,T_STEP_MAX_STEPS-2},
{ ConfigEntry_UInt8, EEPROM_TX_AUDIO_SRC,&ts.tx_audio_source,0,0,TX_AUDIO_MAX_ITEMS},
{ ConfigEntry_UInt8, EEPROM_TCXO_STATE,&df.temp_enabled,TCXO_ON,0,TCXO_MODE_MASK|TCXO_UNIT_MASK}, // we use
{ ConfigEntry_UInt8, EEPROM_AUDIO_GAIN,&ts.rx_gain[RX_AUDIO_SPKR].value,AUDIO_GAIN_DEFAULT,0,AUDIO_GAIN_MAX},
{ ConfigEntry_UInt8, EEPROM_RX_CODEC_GAIN,&ts.rf_codec_gain,DEFAULT_RF_CODEC_GAIN_VAL,0,MAX_RF_CODEC_GAIN_VAL},
{ ConfigEntry_UInt8, EEPROM_NB_SETTING,&ts.dsp.nb_setting,0,0,MAX_NB_SETTING},
{ ConfigEntry_UInt8, EEPROM_TX_POWER_LEVEL,&ts.power_level,PA_LEVEL_DEFAULT,0,PA_LEVEL_TUNE_KEEP_CURRENT},
{ ConfigEntry_UInt8, EEPROM_CW_KEYER_SPEED,&ts.cw_keyer_speed,CW_KEYER_SPEED_DEFAULT,CW_KEYER_SPEED_MIN, CW_KEYER_SPEED_MAX},
{ ConfigEntry_UInt8, EEPROM_CW_KEYER_MODE,&ts.cw_keyer_mode,CW_KEYER_MODE_IAM_B, 0, CW_KEYER_MAX_MODE},
{ ConfigEntry_UInt8, EEPROM_CW_KEYER_WEIGHT,&ts.cw_keyer_weight,CW_KEYER_WEIGHT_DEFAULT, CW_KEYER_WEIGHT_MIN, CW_KEYER_WEIGHT_MAX},
{ ConfigEntry_UInt8, EEPROM_CW_SIDETONE_GAIN,&ts.cw_sidetone_gain,DEFAULT_SIDETONE_GAIN,0, SIDETONE_MAX_GAIN},
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_FREQ_CAL,&ts.freq_cal,0,MIN_FREQ_CAL,MAX_FREQ_CAL}, // MINOR INT DEFAULT PROBLEM
{ ConfigEntry_UInt8, EEPROM_AGC_WDSP_MODE,&agc_wdsp_conf.mode, 2,0,5},
{ ConfigEntry_UInt8, EEPROM_AGC_WDSP_HANG,&agc_wdsp_conf.hang_enable, 0,0,1},
{ ConfigEntry_Int32_16, EEPROM_AGC_WDSP_THRESH,&agc_wdsp_conf.thresh, 20,-20,120}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_UInt8, EEPROM_AGC_WDSP_SLOPE,&agc_wdsp_conf.slope, 70,0,200},
{ ConfigEntry_Int32_16, EEPROM_AGC_WDSP_TAU_DECAY_0,&agc_wdsp_conf.tau_decay[0], 4000,100,5000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_AGC_WDSP_TAU_DECAY_1,&agc_wdsp_conf.tau_decay[1], 2000,100,5000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_AGC_WDSP_TAU_DECAY_2,&agc_wdsp_conf.tau_decay[2], 500,100,5000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_AGC_WDSP_TAU_DECAY_3,&agc_wdsp_conf.tau_decay[3], 250,100,5000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_AGC_WDSP_TAU_DECAY_4,&agc_wdsp_conf.tau_decay[4], 50,100,5000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_AGC_WDSP_TAU_HANG_DECAY,&agc_wdsp_conf.tau_hang_decay, 500,100,5000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_MIC_BOOST,&ts.tx_mic_boost, MIC_BOOST_DEFAULT,MIC_BOOST_MIN,MIC_BOOST_MAX},
{ ConfigEntry_UInt8, EEPROM_MIC_GAIN,&ts.tx_gain[TX_AUDIO_MIC],MIC_GAIN_DEFAULT,MIC_GAIN_MIN,MIC_GAIN_MAX},
{ ConfigEntry_UInt8, EEPROM_LINE_GAIN,&ts.tx_gain[TX_AUDIO_LINEIN_L],LINE_GAIN_DEFAULT,LINE_GAIN_MIN,LINE_GAIN_MAX},
{ ConfigEntry_UInt32_16, EEPROM_SIDETONE_FREQ,&ts.cw_sidetone_freq,CW_SIDETONE_FREQ_DEFAULT,CW_SIDETONE_FREQ_MIN,CW_SIDETONE_FREQ_MAX},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_FILTER,&ts.spectrum_filter,SPECTRUM_FILTER_DEFAULT,SPECTRUM_FILTER_MIN,SPECTRUM_FILTER_MAX},
#ifdef OBSOLETE_AGC
{ ConfigEntry_UInt8, EEPROM_AGC_CUSTOM_DECAY,&ts.agc_custom_decay,AGC_CUSTOM_DEFAULT,0,AGC_CUSTOM_MAX},
#endif
{ ConfigEntry_UInt8, EEPROM_METER_COLOUR_UP,&ts.meter_colour_up,SPEC_BLUE, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_METER_COLOUR_DOWN,&ts.meter_colour_down,SPEC_CYAN, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_BOX_COLOUR,&ts.box_colour,SPEC_BLUE, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_TXTLINE_COLOUR,&ts.txtline_colour,SPEC_YELLOW, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_TRACE_COLOUR,&ts.scope_trace_colour,SPEC_COLOUR_TRACE_DEFAULT, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_GRID_COLOUR,&ts.scope_grid_colour,SPEC_COLOUR_GRID_DEFAULT, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_CENTRE_LINE_COLOUR,&ts.spectrum_centre_line_colour,SPEC_COLOUR_GRID_DEFAULT, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_SCALE_COLOUR,&ts.spectrum_freqscale_colour,SPEC_COLOUR_SCALE_DEFAULT, 0, SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_PADDLE_REVERSE,&ts.cw_paddle_reverse,0,0,1},
{ ConfigEntry_UInt8, EEPROM_CW_RX_DELAY,&ts.cw_rx_delay,CW_TX2RX_DELAY_DEFAULT,0,CW_RX_DELAY_MAX},
{ ConfigEntry_UInt8, EEPROM_MAX_VOLUME,&ts.rx_gain[RX_AUDIO_SPKR].max,MAX_VOLUME_DEFAULT,MAX_VOLUME_MIN,MAX_VOLUME_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_PA_BIAS,&ts.pa_bias,PA_BIAS_DEFAULT,0,PA_BIAS_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_PA_CW_BIAS,&ts.pa_cw_bias,PA_BIAS_DEFAULT,0,PA_BIAS_MAX},
{ ConfigEntry_UInt8, EEPROM_IQ_AUTO_CORRECTION,&ts.iq_auto_correction,1, 0, 1},
#define UI_C_TX_IQ_ADJ(bandName) \
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_TX_IQ_##bandName##_GAIN_BALANCE,&iq_adjust[IQ_##bandName].adj.tx[IQ_TRANS_ON].gain,IQ_BALANCE_OFF, MIN_IQ_GAIN_BALANCE, MAX_IQ_GAIN_BALANCE}, \
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_TX_IQ_##bandName##_PHASE_BALANCE,&iq_adjust[IQ_##bandName].adj.tx[IQ_TRANS_ON].phase,IQ_BALANCE_OFF, MIN_IQ_PHASE_BALANCE, MAX_IQ_PHASE_BALANCE}, \
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_TX_IQ_##bandName##_GAIN_BALANCE_TRANS_OFF,&iq_adjust[IQ_##bandName].adj.tx[IQ_TRANS_OFF].gain,IQ_BALANCE_OFF, MIN_IQ_GAIN_BALANCE, MAX_IQ_GAIN_BALANCE}, \
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_TX_IQ_##bandName##_PHASE_BALANCE_TRANS_OFF,&iq_adjust[IQ_##bandName].adj.tx[IQ_TRANS_OFF].phase,IQ_BALANCE_OFF, MIN_IQ_PHASE_BALANCE, MAX_IQ_PHASE_BALANCE},
UI_C_TX_IQ_ADJ(80M)
UI_C_TX_IQ_ADJ(20M)
UI_C_TX_IQ_ADJ(15M)
UI_C_TX_IQ_ADJ(10M)
UI_C_TX_IQ_ADJ(10M_UP)
UI_C_TX_IQ_ADJ(6M)
UI_C_TX_IQ_ADJ(160M)
UI_C_TX_IQ_ADJ(40M)
UI_C_TX_IQ_ADJ(30M)
UI_C_TX_IQ_ADJ(17M)
UI_C_TX_IQ_ADJ(12M)
#define UI_C_RX_IQ_ADJ(bandName) \
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_RX_IQ_##bandName##_GAIN_BALANCE,&iq_adjust[IQ_##bandName].adj.rx.gain,IQ_BALANCE_OFF, MIN_IQ_GAIN_BALANCE, MAX_IQ_GAIN_BALANCE}, \
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_RX_IQ_##bandName##_PHASE_BALANCE,&iq_adjust[IQ_##bandName].adj.rx.phase,IQ_BALANCE_OFF, MIN_IQ_PHASE_BALANCE, MAX_IQ_PHASE_BALANCE},
UI_C_RX_IQ_ADJ(80M)
UI_C_RX_IQ_ADJ(10M)
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_SENSOR_NULL,&swrm.sensor_null,SENSOR_NULL_DEFAULT,SENSOR_NULL_MIN,SENSOR_NULL_MAX},
// { ConfigEntry_UInt8, EEPROM_XVERTER_DISP,&ts.xverter_mode,0,0,XVERTER_MULT_MAX},
{ ConfigEntry_UInt32_16, EEPROM_XVERTER_DISP,&ts.xverter_mode,0,0,XVERTER_MULT_MAX},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_MAGNIFY,&sd.magnify,MAGNIFY_DEFAULT,MAGNIFY_MIN,MAGNIFY_MAX},
// { ConfigEntry_UInt8, EEPROM_WIDE_FILT_CW_DISABLE,&ts.filter_cw_wide_disable,1,0,1},
// { ConfigEntry_UInt8, EEPROM_NARROW_FILT_SSB_DISABLE,&ts.filter_ssb_narrow_disable,1,0,1},
{ ConfigEntry_UInt16, EEPROM_AM_MODE_DISABLE,&ts.demod_mode_disable,1,0,7},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_DB_DIV,&ts.spectrum_db_scale,DB_DIV_ADJUST_DEFAULT,DB_DIV_ADJUST_MIN, DB_DIV_ADJUST_MAX},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_AGC_RATE,&ts.spectrum_agc_rate,SPECTRUM_SCOPE_AGC_DEFAULT,SPECTRUM_SCOPE_AGC_MIN, SPECTRUM_SCOPE_AGC_MAX},
{ ConfigEntry_UInt8, EEPROM_METER_MODE,&ts.tx_meter_mode,METER_SWR,0,METER_MAX},
{ ConfigEntry_UInt32_16, EEPROM_ALC_DECAY_TIME,&ts.alc_decay,ALC_DECAY_DEFAULT,0,ALC_DECAY_MAX },
{ ConfigEntry_UInt32_16, EEPROM_ALC_POSTFILT_TX_GAIN,&ts.alc_tx_postfilt_gain,ALC_POSTFILT_GAIN_DEFAULT, ALC_POSTFILT_GAIN_MIN, ALC_POSTFILT_GAIN_MAX},
{ ConfigEntry_UInt16, EEPROM_STEP_SIZE_CONFIG,&ts.freq_step_config,0,0,255},
{ ConfigEntry_UInt8, EEPROM_DSP_MODE,&ts.dsp.active,0,0,255},
{ ConfigEntry_UInt8, EEPROM_DSP_NR_STRENGTH,&ts.dsp.nr_strength,DSP_NR_STRENGTH_DEFAULT,0, DSP_NR_STRENGTH_MAX},
#ifdef OBSOLETE_NR
{ ConfigEntry_UInt32_16, EEPROM_DSP_NR_DECOR_BUFLEN,&ts.dsp.nr_delaybuf_len,DSP_NR_BUFLEN_DEFAULT, DSP_NR_BUFLEN_MIN, DSP_NR_BUFLEN_MAX},
{ ConfigEntry_UInt8, EEPROM_DSP_NR_FFT_NUMTAPS,&ts.dsp.nr_numtaps,DSP_NR_NUMTAPS_DEFAULT, DSP_NR_NUMTAPS_MIN, DSP_NOTCH_NUMTAPS_MAX},
{ ConfigEntry_UInt8, EEPROM_DSP_NOTCH_DECOR_BUFLEN,&ts.dsp.notch_delaybuf_len,DSP_NOTCH_DELAYBUF_DEFAULT,DSP_NOTCH_BUFLEN_MIN,DSP_NOTCH_BUFLEN_MAX},
{ ConfigEntry_UInt8, EEPROM_DSP_NOTCH_FFT_NUMTAPS,&ts.dsp.notch_numtaps,DSP_NOTCH_NUMTAPS_DEFAULT, DSP_NOTCH_NUMTAPS_MIN,DSP_NOTCH_NUMTAPS_MAX},
{ ConfigEntry_UInt8, EEPROM_DSP_NOTCH_CONV_RATE,&ts.dsp.notch_mu,DSP_NOTCH_MU_DEFAULT,0,DSP_NOTCH_MU_MAX},
#endif
#ifdef USE_LMS_AUTONOTCH
{ ConfigEntry_UInt8, EEPROM_DSP_NOTCH_DECOR_BUFLEN,&ts.dsp.notch_delaybuf_len,DSP_NOTCH_DELAYBUF_DEFAULT,DSP_NOTCH_BUFLEN_MIN,DSP_NOTCH_BUFLEN_MAX},
{ ConfigEntry_UInt8, EEPROM_DSP_NOTCH_FFT_NUMTAPS,&ts.dsp.notch_numtaps,DSP_NOTCH_NUMTAPS_DEFAULT, DSP_NOTCH_NUMTAPS_MIN,DSP_NOTCH_NUMTAPS_MAX},
{ ConfigEntry_UInt8, EEPROM_DSP_NOTCH_CONV_RATE,&ts.dsp.notch_mu,DSP_NOTCH_MU_DEFAULT,0,DSP_NOTCH_MU_MAX},
#endif
// { ConfigEntry_UInt8, EEPROM_MAX_RX_GAIN,&ts.max_rf_gain,MAX_RF_GAIN_DEFAULT,0,MAX_RF_GAIN_MAX},
{ ConfigEntry_Int16, EEPROM_TX_AUDIO_COMPRESS,&ts.tx_comp_level,TX_AUDIO_COMPRESSION_DEFAULT,TX_AUDIO_COMPRESSION_MIN,TX_AUDIO_COMPRESSION_MAX}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_UInt8, EEPROM_TX_DISABLE,&ts.tx_disable,0,0,1},
{ ConfigEntry_UInt16, EEPROM_FLAGS1,&ts.flags1,FLAGS1_CONFIG_DEFAULT,0,0xffff},
{ ConfigEntry_UInt16, EEPROM_FLAGS2,&ts.flags2,FLAGS2_CONFIG_DEFAULT,0,0xffff},
{ ConfigEntry_UInt16, EEPROM_VERSION_MINOR,&ts.version_number_minor,0,0,255},
{ ConfigEntry_UInt16, EEPROM_VERSION_RELEASE,&ts.version_number_release,0,0,255},
{ ConfigEntry_UInt16, EEPROM_VERSION_MAJOR,&ts.version_number_major,0,0,255},
// { ConfigEntry_UInt8, EEPROM_NB_AGC_TIME_CONST,&ts.nb_agc_time_const,NB_AGC_DEFAULT,0,NB_MAX_AGC_SETTING},
{ ConfigEntry_UInt8, EEPROM_CW_OFFSET_MODE,&ts.cw_offset_mode,CW_OFFSET_MODE_DEFAULT,0,CW_OFFSET_NUM-1},
{ ConfigEntry_Int32_16, EEPROM_FREQ_CONV_MODE,&ts.iq_freq_mode,FREQ_IQ_CONV_MODE_DEFAULT,0,FREQ_IQ_CONV_MODE_MAX}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_UInt8, EEPROM_LSB_USB_AUTO_SELECT,&ts.lsb_usb_auto_select,AUTO_LSB_USB_DEFAULT,0,AUTO_LSB_USB_MAX},
{ ConfigEntry_UInt8, EEPROM_LCD_BLANKING_CONFIG,&ts.lcd_backlight_blanking,0,0,255},
{ ConfigEntry_UInt32_16, EEPROM_VFO_MEM_MODE,&ts.vfo_mem_mode,0,0,255},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_2200M,&swrm.coupling_calc[COUPLING_2200M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_630M,&swrm.coupling_calc[COUPLING_630M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_160M,&swrm.coupling_calc[COUPLING_160M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_80M,&swrm.coupling_calc[COUPLING_80M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_40M,&swrm.coupling_calc[COUPLING_40M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_20M,&swrm.coupling_calc[COUPLING_20M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_15M,&swrm.coupling_calc[COUPLING_15M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_10M,&swrm.coupling_calc[COUPLING_10M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_DETECTOR_COUPLING_COEFF_6M,&swrm.coupling_calc[COUPLING_6M],SWR_COUPLING_DEFAULT,SWR_COUPLING_MIN,SWR_COUPLING_MAX},
{ ConfigEntry_UInt32_16 | Calib_Val, EEPROM_VOLTMETER_CALIBRATE,&ts.voltmeter_calibrate,POWER_VOLTMETER_CALIBRATE_DEFAULT,POWER_VOLTMETER_CALIBRATE_MIN,POWER_VOLTMETER_CALIBRATE_MAX},
{ ConfigEntry_UInt8 | Calib_Val, EEPROM_LOW_POWER_CONFIG,&ts.low_power_config,LOW_POWER_CONFIG_DEFAULT,LOW_POWER_CONFIG_MIN,LOW_POWER_CONFIG_MAX},
{ ConfigEntry_UInt8, EEPROM_WATERFALL_COLOR_SCHEME,&ts.waterfall.color_scheme,WATERFALL_COLOR_DEFAULT,WATERFALL_COLOR_MIN,WATERFALL_COLOR_MAX},
{ ConfigEntry_UInt8, EEPROM_WATERFALL_VERTICAL_STEP_SIZE,&ts.waterfall.vert_step_size,WATERFALL_STEP_SIZE_DEFAULT,WATERFALL_STEP_SIZE_MIN,WATERFALL_STEP_SIZE_MAX},
//{ ConfigEntry_Int32_16, EEPROM_WATERFALL_OFFSET,&ts.waterfall.offset,WATERFALL_OFFSET_DEFAULT,WATERFALL_OFFSET_MIN,WATERFALL_OFFSET_MAX},
{ ConfigEntry_UInt8, EEPROM_SPECTRUM_SIZE,&ts.spectrum_size,SPECTRUM_SIZE_DEFAULT,0,SPECTRUM_BIG},
{ ConfigEntry_UInt32_16, EEPROM_WATERFALL_CONTRAST,&ts.waterfall.contrast,WATERFALL_CONTRAST_DEFAULT,WATERFALL_CONTRAST_MIN,WATERFALL_CONTRAST_MAX},
{ ConfigEntry_UInt8, EEPROM_WATERFALL_SPEED,&ts.waterfall.speed,WATERFALL_SPEED_DEFAULT,0,WATERFALL_SPEED_MAX},
//{ ConfigEntry_UInt8, EEPROM_SPECTRUM_SCOPE_NOSIG_ADJUST,&ts.spectrum_scope_nosig_adjust,SPECTRUM_SCOPE_NOSIG_ADJUST_DEFAULT,SPECTRUM_SCOPE_NOSIG_ADJUST_MIN,SPECTRUM_SCOPE_NOSIG_ADJUST_MAX},
//{ ConfigEntry_UInt8, EEPROM_WATERFALL_NOSIG_ADJUST,&ts.waterfall.nosig_adjust,SPECTRUM_SCOPE_NOSIG_ADJUST_DEFAULT,WATERFALL_NOSIG_ADJUST_MIN,WATERFALL_NOSIG_ADJUST_MAX},
//{ ConfigEntry_UInt8, EEPROM_FFT_WINDOW,&ts.fft_window_type,FFT_WINDOW_DEFAULT,0,FFT_WINDOW_MAX},
{ ConfigEntry_UInt8, EEPROM_TXRX_SWITCH_AUDIO_MUTE_DELAY,&ts.txrx_switch_audio_muting_timing,TXRX_SWITCH_AUDIO_MUTE_DELAY_DEFAULT,0,TXRX_SWITCH_AUDIO_MUTE_DELAY_MAX},
{ ConfigEntry_UInt8, EEPROM_FILTER_DISP_COLOUR,&ts.filter_disp_colour,0,0,SPEC_MAX_COLOUR},
{ ConfigEntry_UInt32_16, EEPROM_FM_SUBAUDIBLE_TONE_GEN,&ts.fm_subaudible_tone_gen_select,FM_SUBAUDIBLE_TONE_OFF,0,NUM_SUBAUDIBLE_TONES},
{ ConfigEntry_UInt32_16, EEPROM_FM_SUBAUDIBLE_TONE_DET,&ts.fm_subaudible_tone_det_select,FM_SUBAUDIBLE_TONE_OFF,0,NUM_SUBAUDIBLE_TONES},
{ ConfigEntry_UInt8, EEPROM_FM_TONE_BURST_MODE,&ts.fm_tone_burst_mode,FM_TONE_BURST_OFF,0,FM_TONE_BURST_MAX},
{ ConfigEntry_UInt8, EEPROM_FM_SQUELCH_SETTING,&ts.fm_sql_threshold,FM_SQUELCH_DEFAULT,0,FM_SQUELCH_MAX},
{ ConfigEntry_UInt32_16, EEPROM_KEYBOARD_BEEP_FREQ,&ts.beep_frequency,DEFAULT_BEEP_FREQUENCY,MIN_BEEP_FREQUENCY,MAX_BEEP_FREQUENCY},
{ ConfigEntry_UInt8, EEPROM_BEEP_LOUDNESS,&ts.beep_loudness,DEFAULT_BEEP_LOUDNESS,0,MAX_BEEP_LOUDNESS},
{ ConfigEntry_UInt8, EEPROM_TUNE_POWER_LEVEL,&ts.tune_power_level,PA_LEVEL_TUNE_KEEP_CURRENT,PA_LEVEL_FULL,PA_LEVEL_TUNE_KEEP_CURRENT},
{ ConfigEntry_UInt8, EEPROM_CAT_XLAT,&ts.xlat,1,0,1},
{ ConfigEntry_UInt32_16, EEPROM_MANUAL_NOTCH,&ts.dsp.notch_frequency,800,200,5000},
{ ConfigEntry_UInt32_16, EEPROM_MANUAL_PEAK,&ts.dsp.peak_frequency,750,200,5000},
{ ConfigEntry_UInt8, EEPROM_DISPLAY_DBM,&ts.display_dbm,0,0,2},
{ ConfigEntry_Int32_16 | Calib_Val, EEPROM_DBM_CALIBRATE,&ts.dbm_constant,0,-100,100}, // MINOR INT DEFAULT PROBLEM,see above
// { ConfigEntry_UInt8, EEPROM_S_METER,&ts.s_meter,0,0,2},
{ ConfigEntry_UInt8, EEPROM_DIGI_MODE_CONF,&ts.digital_mode,DigitalMode_None,0,DigitalMode_Num_Modes-1},
{ ConfigEntry_Int32_16, EEPROM_BASS_GAIN,&ts.dsp.bass_gain,2,-20,20}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32_16, EEPROM_TREBLE_GAIN,&ts.dsp.treble_gain,0,-20,20}, // MINOR INT DEFAULT PROBLEM,see above
{ ConfigEntry_UInt8, EEPROM_TX_FILTER,&ts.tx_filter,0,0,TX_FILTER_ESSB_6k},
// { ConfigEntry_Int32_16, EEPROM_TX_BASS_GAIN,&ts.dsp.tx_bass_gain,4,-20,6}, // INT DEFAULT PROBLEM,see above
// { ConfigEntry_Int32_16, EEPROM_TX_TREBLE_GAIN,&ts.dsp.tx_treble_gain,4,-20,6}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32_16, EEPROM_TX_EQ0_GAIN,&ts.dsp.tx_eq_gain[0],4, MIN_TX_EQ, MAX_TX_EQ}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32_16, EEPROM_TX_EQ1_GAIN,&ts.dsp.tx_eq_gain[1],4, MIN_TX_EQ, MAX_TX_EQ}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32_16, EEPROM_TX_EQ2_GAIN,&ts.dsp.tx_eq_gain[2],4, MIN_TX_EQ, MAX_TX_EQ}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32_16, EEPROM_TX_EQ3_GAIN,&ts.dsp.tx_eq_gain[3],4, MIN_TX_EQ, MAX_TX_EQ}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32_16, EEPROM_TX_EQ4_GAIN,&ts.dsp.tx_eq_gain[4],4, MIN_TX_EQ, MAX_TX_EQ}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32_16, EEPROM_SAM_PLL_LOCKING_RANGE,&ads.pll_fmax_int,2500,50,8000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_SAM_PLL_STEP_RESPONSE,&ads.zeta_int,65,1,100}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_SAM_PLL_BANDWIDTH,&ads.omegaN_int, 250,15,1000}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_I2C1_SPEED,&ts.i2c_speed[0], I2C1_SPEED_DEFAULT,1,20}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_I2C2_SPEED,&ts.i2c_speed[1], I2C2_SPEED_DEFAULT,1,20}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_UInt8, EEPROM_SAM_FADE_LEVELER,&ads.fade_leveler,1,0,1},
{ ConfigEntry_UInt8, EEPROM_LINEOUT_GAIN,&ts.lineout_gain,LINEOUT_GAIN_DEFAULT,LINEOUT_GAIN_MIN,LINEOUT_GAIN_MAX},
{ ConfigEntry_Int16 | Calib_Val, EEPROM_RTC_CALIB,&ts.rtc_calib,RTC_CALIB_PPM_DEFAULT, RTC_CALIB_PPM_MIN, RTC_CALIB_PPM_MAX},
{ ConfigEntry_UInt8, EEPROM_CW_DECODER_ENABLE,&ts.cw_decoder_enable,1,0,1},
{ ConfigEntry_UInt8, EEPROM_PEAK_IND_TUNE,&ts.peak_ind_tune,3,0,24},
{ ConfigEntry_UInt16, EEPROM_Scope_Graticule_Ypos,&ts.graticulePowerupYpos,0,0,480},
{ ConfigEntry_UInt8, EEPROM_Freq_Display_Font,&ts.FreqDisplayFont,0,0,1},
UI_C_EEPROM_BAND_5W_PF( 0,80,m)
UI_C_EEPROM_BAND_5W_PF(1,60,m)
UI_C_EEPROM_BAND_5W_PF(2,40,m)
UI_C_EEPROM_BAND_5W_PF(3,30,m)
UI_C_EEPROM_BAND_5W_PF(4,20,m)
UI_C_EEPROM_BAND_5W_PF(5,17,m)
UI_C_EEPROM_BAND_5W_PF(6,15,m)
UI_C_EEPROM_BAND_5W_PF(7,12,m)
UI_C_EEPROM_BAND_5W_PF(8,10,m)
UI_C_EEPROM_BAND_5W_PF(9,6,m)
UI_C_EEPROM_BAND_5W_PF(10,4,m)
UI_C_EEPROM_BAND_5W_PF(11,2,m)
UI_C_EEPROM_BAND_5W_PF(12,70,cm)
UI_C_EEPROM_BAND_5W_PF(13,23,cm)
UI_C_EEPROM_BAND_5W_PF(14,2200,m)
UI_C_EEPROM_BAND_5W_PF(15,630,m)
UI_C_EEPROM_BAND_5W_PF(16,160,m)
UI_C_EEPROM_BAND_FULL_PF(0,80,m)
UI_C_EEPROM_BAND_FULL_PF(1,60,m)
UI_C_EEPROM_BAND_FULL_PF(2,40,m)
UI_C_EEPROM_BAND_FULL_PF(3,30,m)
UI_C_EEPROM_BAND_FULL_PF(4,20,m)
UI_C_EEPROM_BAND_FULL_PF(5,17,m)
UI_C_EEPROM_BAND_FULL_PF(6,15,m)
UI_C_EEPROM_BAND_FULL_PF(7,12,m)
UI_C_EEPROM_BAND_FULL_PF(8,10,m)
UI_C_EEPROM_BAND_FULL_PF(9,6,m)
UI_C_EEPROM_BAND_FULL_PF(10,4,m)
UI_C_EEPROM_BAND_FULL_PF(11,2,m)
UI_C_EEPROM_BAND_FULL_PF(12,70,cm)
UI_C_EEPROM_BAND_FULL_PF(13,23,cm)
UI_C_EEPROM_BAND_FULL_PF(14,2200,m)
UI_C_EEPROM_BAND_FULL_PF(15,630,m)
UI_C_EEPROM_BAND_FULL_PF(16,160,m)
{ ConfigEntry_UInt8, EEPROM_Scope_TRACE_HL_BW,&ts.scope_trace_BW_colour,SPEC_COLOUR_TRACEBW_DEFAULT,0,SPEC_MAX_COLOUR},
{ ConfigEntry_UInt8, EEPROM_Scope_TRACE_HL_BW_BGR,&ts.scope_backgr_BW_colour,SPEC_COLOUR_BACKGRBW_DEFAULT,0,100},
{ ConfigEntry_Int32 | Calib_Val, EEPROM_TScal0_High,&mchf_touchscreen.cal[0], 72816, INT32_MIN,INT32_MAX}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32 | Calib_Val, EEPROM_TScal1_High,&mchf_touchscreen.cal[1], -5,INT32_MIN,INT32_MAX}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32 | Calib_Val, EEPROM_TScal2_High,&mchf_touchscreen.cal[2], -1615424,INT32_MIN,INT32_MAX}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32 | Calib_Val, EEPROM_TScal3_High,&mchf_touchscreen.cal[3], -1,INT32_MIN,INT32_MAX}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32 | Calib_Val, EEPROM_TScal4_High,&mchf_touchscreen.cal[4], 74886,INT32_MIN,INT32_MAX}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_Int32 | Calib_Val, EEPROM_TScal5_High,&mchf_touchscreen.cal[5], -1630326,INT32_MIN,INT32_MAX}, // INT DEFAULT PROBLEM,see above
{ ConfigEntry_UInt16, EEPROM_NUMBER_OF_ENTRIES,&number_of_entries_cur_fw,EEPROM_FIRST_UNUSED,EEPROM_FIRST_UNUSED,EEPROM_FIRST_UNUSED},
{ ConfigEntry_UInt16, EEPROM_DSP_MODE_MASK,&ts.dsp.mode_mask,DSP_SWITCH_MODEMASK_ENABLE_DEFAULT,DSP_SWITCH_MODEMASK_ENABLE_DSPOFF,DSP_SWITCH_MODEMASK_ENABLE_MASK},
{ ConfigEntry_UInt8, EEPROM_ENABLE_PTT_RTS,&ts.enable_ptt_rts,0,0,1},
{ ConfigEntry_Int32_16, EEPROM_CW_DECODER_THRESH,&cw_decoder_config.thresh,CW_DECODER_THRESH_DEFAULT,CW_DECODER_THRESH_MIN,CW_DECODER_THRESH_MAX}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_Int32_16, EEPROM_CW_DECODER_BLOCKSIZE,&cw_decoder_config.blocksize,CW_DECODER_BLOCKSIZE_DEFAULT,CW_DECODER_BLOCKSIZE_MIN,CW_DECODER_BLOCKSIZE_MAX}, // NO INT DEFAULT PROBLEM
{ ConfigEntry_UInt8x2, EEPROM_SMETER_ALPHAS,&sm.config.alphaCombined,CONFIG_UINT8x2_COMBINE(SMETER_ALPHA_ATTACK_DEFAULT, SMETER_ALPHA_DECAY_DEFAULT), CONFIG_UINT8x2_COMBINE(SMETER_ALPHA_MIN, SMETER_ALPHA_MIN), CONFIG_UINT8x2_COMBINE(SMETER_ALPHA_MAX,SMETER_ALPHA_MAX) },
{ ConfigEntry_UInt8, EEPROM_VSWR_PROTECTION_THRESHOLD,&ts.debug_vswr_protection_threshold,1,1,10},
{ ConfigEntry_UInt16, EEPROM_EXPFLAGS1,&ts.expflags1,EXPFLAGS1_CONFIG_DEFAULT,0,0xffff},
{ ConfigEntry_UInt16, EEPROM_EXPFLAGS2,&ts.expflags2,EXPFLAGS2_CONFIG_DEFAULT,0,0xffff},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_0,&ts.cal_lo_tx_supr0[0], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_1,&ts.cal_lo_tx_supr0[1], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_2,&ts.cal_lo_tx_supr0[2], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_3,&ts.cal_lo_tx_supr0[3], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_4,&ts.cal_lo_tx_supr0[4], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_5,&ts.cal_lo_tx_supr0[5], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_6,&ts.cal_lo_tx_supr0[6], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_7,&ts.cal_lo_tx_supr0[7], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_8,&ts.cal_lo_tx_supr0[8], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_9,&ts.cal_lo_tx_supr0[9], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_10,&ts.cal_lo_tx_supr0[10], 2048, 0, 4096}, //160m
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_11,&ts.cal_lo_tx_supr0[11], 2048, 0, 4096}, //CB26Mc
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_12,&ts.cal_lo_tx_supr0[12], 2048, 0, 4096}, //CB27Mc
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_13,&ts.cal_lo_tx_supr0[13], 2048, 0, 4096}, //Wild zone
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR0_14,&ts.cal_lo_tx_supr0[14], 2048, 0, 4096}, //28Mc_Up
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_0,&ts.cal_lo_tx_supr1[0], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_1,&ts.cal_lo_tx_supr1[1], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_2,&ts.cal_lo_tx_supr1[2], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_3,&ts.cal_lo_tx_supr1[3], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_4,&ts.cal_lo_tx_supr1[4], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_5,&ts.cal_lo_tx_supr1[5], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_6,&ts.cal_lo_tx_supr1[6], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_7,&ts.cal_lo_tx_supr1[7], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_8,&ts.cal_lo_tx_supr1[8], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_9,&ts.cal_lo_tx_supr1[9], 2048, 0, 4096},
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_10,&ts.cal_lo_tx_supr1[10], 2048, 0, 4096}, //160m
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_11,&ts.cal_lo_tx_supr1[11], 2048, 0, 4096}, //CB26Mc
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_12,&ts.cal_lo_tx_supr1[12], 2048, 0, 4096}, //CB27Mc
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_13,&ts.cal_lo_tx_supr1[13], 2048, 0, 4096}, //Wild zone
{ ConfigEntry_Int16, EEPROM_LO_TX_SUPR1_14,&ts.cal_lo_tx_supr1[14], 2048, 0, 4096}, //28Mc_Up
{ ConfigEntry_UInt8, EEPROM_CW_SMOOTH,&ts.cw_smooth,1, 0, 3},
{ ConfigEntry_UInt8, EEPROM_PWR_SCALE_GEN,&ts.power_scale_gen,100, 3, 200},
{ ConfigEntry_UInt8, EEPROM_PWR_SCALE_GEN_FULL,&ts.power_scale_gen_full,100, 3, 250},
#ifdef SDR_AMBER
{ ConfigEntry_UInt8, EEPROM_AMBER_BANDCODE,&ts.amber_pa_bandcode_mode,0, 0, 255},
#else
{ ConfigEntry_UInt8, EEPROM_AMBER_BANDCODE,0,0, 0, 255},
#endif
{ ConfigEntry_UInt8, EEPROM_ANR_N_TAPS,&ts.anr_n_taps,64, 1, 192},
{ ConfigEntry_UInt8, EEPROM_ANR_DELAY,&ts.anr_delay,16, 1, 64},
{ ConfigEntry_Int16, EEPROM_ANR_TWO_MU_INT,&ts.anr_two_mu_int, 100, 1, 10000},
{ ConfigEntry_Int16, EEPROM_ANR_GAMMA_INT,&ts.anr_gamma_int, 100, 1, 1000},
{ ConfigEntry_UInt16, EEPROM_CW_DECODER_FLAGS,&cw_decoder_config.flags,CW_DECODER_FLAGS_DEFAULT,0,0x7fff},
// { ConfigEntry_UInt8, EEPROM_BAND_REGION,&bandinfo_idx,0,0,0x7f},
{ ConfigEntry_UInt8, EEPROM_BAND_REGION, &bandinfo_idx, BAND_INFO_SET_DEFAULT, 0, 0x7f}, // we need to validate the range later as we cannot do it here due to C shortcomings
{ ConfigEntry_UInt8, EEPROM_TX_REVERB_GAIN, &ts.reverb_gain, 0, 0, 100},
{ ConfigEntry_UInt8, EEPROM_TX_REVERB_DELAY, &ts.reverb_delay, 25, 25, 100},
{ ConfigEntry_Int32_16, EEPROM_IQ_FREQ_DELTA, &ts.iq_freq_delta, 1000, -18000, 18000},
{ ConfigEntry_UInt16, EEPROM_EXPFLAGS3,&ts.expflags3,EXPFLAGS3_CONFIG_DEFAULT,0,0xffff},
{ ConfigEntry_UInt8, EEPROM_INPUT_STATE,&ts.amber_input_state,0,0,3},
// { ConfigEntry_UInt16, EEPROM_CQ_COLOUR,&ts.cq_colour,3,0,SPEC_MAX_COLOUR},
// the entry below MUST be the last entry, and only at the last position Stop is allowed
{
ConfigEntry_Stop
}
};
// TODO: LINEAR SEARCH IS VERY BAD FOR LARGER SETS, replace with more clever strategy.
// for use case in menu this acceptable, however
const ConfigEntryDescriptor* UiConfiguration_GetEntry(uint16_t id)
{
int idx;
const ConfigEntryDescriptor* retval = NULL;
for (idx = 0; ConfigEntryInfo[idx].typeId != ConfigEntry_Stop; idx++)
{
if (ConfigEntryInfo[idx].id == id)
{
retval = &ConfigEntryInfo[idx];
break;
}
}
return retval;
}
/*
static void __attribute__ ((noinline)) UiReadSettingEEPROM_Bool(uint16_t addr, volatile bool* val_ptr, uint16_t default_val, uint16_t min_val, uint16_t max_val ) {
uint16_t value;
if(Read_EEPROM(addr, &value) == 0)
{
*val_ptr = value;
if (*val_ptr < min_val || *val_ptr > max_val || load_default) {
*val_ptr = default_val;
}
}
}
*/
static void __attribute__ ((noinline)) UiReadSettingEEPROM_UInt8(uint16_t addr, volatile uint8_t* val_ptr, uint16_t default_val, uint16_t min_val, uint16_t max_val, bool load_default)
{
uint16_t value;
if(ConfigStorage_ReadVariable(addr, &value) == 0)
{
*val_ptr = value;
if (*val_ptr < min_val || *val_ptr > max_val || load_default)
{
*val_ptr = default_val;
}
}
else
{
*val_ptr = default_val;
}
}
static void __attribute__ ((noinline)) UiReadSettingEEPROM_UInt8x2_Split(uint16_t addr, volatile uint8_t* val_ptr_high, uint8_t default_val_high, uint8_t min_val_high, uint8_t max_val_high,
volatile uint8_t* val_ptr_low, uint8_t default_val_low, uint8_t min_val_low, uint8_t max_val_low, bool load_default)
{
uint16_t value;
if(ConfigStorage_ReadVariable(addr, &value) == 0)
{
*val_ptr_high = value >> 8;
*val_ptr_low = value & 0xff;
if ((*val_ptr_high < min_val_high) || (*val_ptr_high > max_val_high) || load_default)
{
*val_ptr_high = default_val_high;
}
if ((*val_ptr_low < min_val_low) || (*val_ptr_low > max_val_low) || load_default)
{
*val_ptr_low = default_val_low;
}
}
else
{
*val_ptr_low = default_val_low;
*val_ptr_high = default_val_high;
}
}
static void __attribute__ ((noinline)) UiReadSettingEEPROM_UInt8x2(uint16_t addr, volatile uint16_t* val_ptr, uint16_t default_val, uint16_t min_val, uint16_t max_val, bool load_default)
{
uint16_t value;
if(ConfigStorage_ReadVariable(addr, &value) == 0)
{
*val_ptr = value;
if ( (((*val_ptr >> 8) & 0xff) < ((min_val >> 8) & 0xff)) || (((*val_ptr >> 8) & 0xff) > ((max_val >> 8) & 0xff)) || load_default)
{
*val_ptr = (*val_ptr & 0xff) | (default_val & 0xff00);
}
if ( ((*val_ptr & 0xff) < (min_val & 0xff)) || ((*val_ptr & 0xff) > (max_val & 0xff)) || load_default)
{
*val_ptr = (*val_ptr & 0xff00) | (default_val & 0x00ff);
}
}
else
{
*val_ptr = default_val;
}
}
static void __attribute__ ((noinline)) UiReadSettingEEPROM_UInt16(uint16_t addr, volatile uint16_t* val_ptr, uint16_t default_val, uint16_t min_val, uint16_t max_val, bool load_default)
{
uint16_t value;
if(ConfigStorage_ReadVariable(addr, &value) == 0)
{
*val_ptr = value;
if (*val_ptr < min_val || *val_ptr > max_val || load_default)
{
*val_ptr = default_val;
}
}
else
{
*val_ptr = default_val;
}
}
static void __attribute__ ((noinline)) UiReadSettingEEPROM_Int16(uint16_t addr, volatile int16_t* val_ptr, int16_t default_val, int16_t min_val, int16_t max_val, bool load_default)
{
int16_t value;
if(ConfigStorage_ReadVariable(addr, (uint16_t*)&value) == 0)
{
*val_ptr = value;
if (*val_ptr < min_val || *val_ptr > max_val || load_default)
{
*val_ptr = default_val;
}
}
else
{
*val_ptr = default_val;
}
}
static void __attribute__ ((noinline)) UiReadSettingEEPROM_UInt32_16(uint16_t addr, volatile uint32_t* val_ptr, uint16_t default_val, uint16_t min_val, uint16_t max_val, bool load_default)
{
uint16_t value;
if(ConfigStorage_ReadVariable(addr, &value) == 0)
{
*val_ptr = value;
if (*val_ptr < min_val || *val_ptr > max_val || load_default)
{
*val_ptr = default_val;
}
}
else
{
*val_ptr = default_val;
}
}
static void __attribute__ ((noinline)) UiReadSettingEEPROM_Int32_16(uint16_t addr, volatile int32_t* val_ptr, int default_val, int min_val, int max_val, bool load_default)
{
uint16_t value;
if(ConfigStorage_ReadVariable(addr, &value) == 0)
{
*val_ptr = (int16_t)value;
if (*val_ptr < min_val || *val_ptr > max_val || load_default)
{
*val_ptr = default_val;
}
}
else
{
*val_ptr = default_val;
}
}
static void UiReadSettingEEPROM_UInt32(uint16_t addrH, uint16_t addrL, volatile uint32_t* val_ptr, uint32_t default_val, uint32_t min_val, uint32_t max_val, bool load_default)
{
uint16_t valueH,valueL;
if(ConfigStorage_ReadVariable(addrH, &valueH) == 0 && ConfigStorage_ReadVariable(addrL, &valueL) == 0)
{
*val_ptr = valueH;
*val_ptr <<=16;
*val_ptr |= valueL;
if (*val_ptr < min_val || *val_ptr > max_val || load_default)
{
*val_ptr = default_val;
}
}
else
{
*val_ptr = default_val;
}
}
static uint16_t UiWriteSettingEEPROM_UInt16(uint16_t addr, uint16_t set_val)
{
return ConfigStorage_WriteVariable(addr, set_val);
}
static uint16_t UiWriteSettingEEPROM_UInt8x2(uint16_t addr, uint16_t set_val)
{
return ConfigStorage_WriteVariable(addr, set_val);
}
static uint16_t UiWriteSettingEEPROM_Int16(uint16_t addr, int16_t set_val)
{
return ConfigStorage_WriteVariable(addr, (uint16_t)set_val);
}
static uint16_t UiWriteSettingEEPROM_UInt32(uint16_t addrH, uint16_t addrL, uint32_t set_val)
{
uint16_t retval = ConfigStorage_WriteVariable(addrH, (uint16_t)(set_val >> 16));
if (retval == HAL_OK)
{
retval = ConfigStorage_WriteVariable(addrL, (uint16_t)(set_val));
}
return retval;
}
static uint32_t UiConfiguration_LimitFrequency(BandInfo_c* bandInfo, const uint32_t freq, bool set_to_default)
{
uint32_t retval = freq;
bool do_reset = false;
#ifndef USE_MEMORY_MODE
// Load default for this band
const uint32_t resetval = bandInfo->tune + DEFAULT_FREQ_OFFSET;
#else
const uint32_t resetval = DEFAULT_MEMORY_FREQ;
#endif
// this code handles the migration of stored frequency settings from the older approach to/from the newer
// approach. We will have to introduce the newer approach with firmware 2.11.0 in order not to cause
// issues when using older firmware with this migration code already built in.
// stored configuration is older than 2.11.0, dial frequencies are stored as multiples of 4 * dial frequency
// we have to scale them down with our old TUNE_MULT
if (UiConfiguration_CompareConfigBuildVersions(2,11,00) == 1)
{
retval /= 4;
}
if(set_to_default)
{
do_reset = true;
}
else
{
if((ts.flags2 & FLAGS2_FREQ_MEM_LIMIT_RELAX) == 0)
{
#ifndef USE_MEMORY_MODE
do_reset = RadioManagement_FreqIsInBand(bandInfo,retval) == false; // xxxx relax memory-save frequency restrictions and is it within the allowed range?
#else
do_reset = RadioManagement_FreqIsInEnabledBand(retval) == false;
#endif
}
}
return do_reset == true? resetval : retval;
}
void UiReadSettingsBandMode(const uint8_t i, const uint16_t band_mode, const uint16_t band_freq_high, const uint16_t band_freq_low, VfoReg* vforeg, bool load_default)
{
uint32_t value32;
UiReadSettingEEPROM_UInt8x2_Split(band_mode + i,
&vforeg->decod_mode, DEMOD_LSB, 0, DEMOD_MAX_MODE,
&vforeg->digital_mode, DigitalMode_None, 0, DigitalMode_Num_Modes-1,
load_default);
// Try to read Freq saved values
UiReadSettingEEPROM_UInt32(band_freq_high + i, band_freq_low + i,&value32,bandInfo[i]->tune + DEFAULT_FREQ_OFFSET,0,0xffffffff, load_default);
{
// We make sure to read only frequency which are permitted for band in given
// configuration.
vforeg->dial_value = UiConfiguration_LimitFrequency(bandInfo[i],value32, load_default);
}
}
/*
static void __attribute__ ((noinline)) UiWriteSettingEEPROM_Bool(uint16_t addr, bool set_val, bool default_val ) {
UiWriteSettingEEPROM_UInt16(addr,(uint16_t)set_val,(uint16_t)default_val);
}
*/
static uint16_t __attribute__ ((noinline)) UiWriteSettingEEPROM_UInt32_16(uint16_t addr, uint32_t set_val)
{
return UiWriteSettingEEPROM_UInt16(addr,set_val);
}
static uint16_t __attribute__ ((noinline)) UiWriteSettingEEPROM_Int32_16(uint16_t addr, int32_t set_val)
{
return UiWriteSettingEEPROM_UInt16(addr,(uint16_t)(int16_t)set_val);
}
static uint16_t UiWriteSettingsBandMode(const uint16_t i,const uint16_t band_mode, const uint16_t band_freq_high, const uint16_t band_freq_low, VfoReg* vforeg)
{
// ------------------------------------------------------------------------------------
// Read Band and Mode saved values - update if changed
uint16_t value = (vforeg->decod_mode << 8) | (vforeg->digital_mode);
uint16_t retval = UiWriteSettingEEPROM_UInt8x2(band_mode + i, value);
// Try to read Freq saved values - update if changed
if (retval == HAL_OK)
{
retval = UiWriteSettingEEPROM_UInt32(band_freq_high+i,band_freq_low+i, vforeg->dial_value);
}
return retval;
}
#if 0
static uint16_t UiWriteSettingEEPROM_UInt16_Array_2_Dim(uint16_t* array_ptr, const uint16_t base_idx, const size_t dim1, const size_t dim2)
{
uint16_t retval = HAL_OK;
for (uint16_t idx1 = 0; retval == HAL_OK && idx1 < dim1; idx1++)
{
for (uint16_t idx2 = 0; retval == HAL_OK && idx2 < dim2; idx2++)
{
retval = UiWriteSettingEEPROM_UInt16(base_idx+(idx1*dim2)+idx2, array_ptr+(idx1*dim2)+idx2);
}
}
return retval;
}
#endif
static uint16_t UiWriteSettingEEPROM_Filter(void)
{
uint16_t retval = HAL_OK;
for (uint16_t idx = 0; retval == HAL_OK && idx < FILTER_MODE_MAX; idx++)
{
for (uint16_t mem_idx = 0; retval == HAL_OK && mem_idx < FILTER_PATH_MEM_MAX; mem_idx++)
{
retval = UiWriteSettingEEPROM_UInt16(EEPROM_FILTER_PATH_MAP_BASE+idx*FILTER_PATH_MEM_MAX+mem_idx,ts.filter_path_mem[idx][mem_idx]);
}
}
return retval;
}
void UiReadSettingEEPROM_Filter(bool load_default)
{
int idx, mem_idx;
for (idx = 0; idx < FILTER_MODE_MAX; idx++)
{
for (mem_idx = 0; mem_idx < FILTER_PATH_MEM_MAX; mem_idx++)
{
UiReadSettingEEPROM_UInt16(EEPROM_FILTER_PATH_MAP_BASE+idx*FILTER_PATH_MEM_MAX+mem_idx,&(ts.filter_path_mem[idx][mem_idx]),0,0,AUDIO_FILTER_PATH_NUM-1, load_default);
}
}
}
/**
* compares the firmware version which saved the parameters to volatile memory and the given version number.
* @param major range 0..255
* @param minor range 0..255
* @param release range 0..255
* @return 0 if stored parameters have been saved by firmware identified by parameter, 1 if parameter were stored by older firmware, -1 if by newer
*/
static int32_t UiConfiguration_CompareConfigBuildVersions(uint major, uint32_t minor, uint32_t release)
{
int32_t retval = 0;
static uint16_t config_major = 0, config_minor = 0, config_release = 0;
if (config_major == 0)
{
UiReadSettingEEPROM_UInt16(EEPROM_VERSION_MAJOR,&config_major,0,0,255, false);
UiReadSettingEEPROM_UInt16(EEPROM_VERSION_MINOR,&config_minor,0,0,255, false);
UiReadSettingEEPROM_UInt16(EEPROM_VERSION_RELEASE,&config_release,0,0,255, false);
}
if (major < config_major)
{
retval = -1;
}
else if (major > config_major)
{
retval = 1;
}
else if (minor < config_minor)
{
retval = -1;
}
else if (minor > config_minor)
{
retval = 1;
}
else if (release < config_release)
{
retval = -1;
} else if (release > config_release)
{
retval = 1;
}
return retval;
}
void UiConfiguration_ReadConfigEntryData(const ConfigEntryDescriptor* ced_ptr, bool load_default)
{
switch(ced_ptr->typeId & ConfigEntry_TypeMask)
{
case ConfigEntry_UInt8:
UiReadSettingEEPROM_UInt8(ced_ptr->id,ced_ptr->val_ptr,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
break;
case ConfigEntry_UInt16:
UiReadSettingEEPROM_UInt16(ced_ptr->id,ced_ptr->val_ptr,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
break;
case ConfigEntry_UInt32_16:
UiReadSettingEEPROM_UInt32_16(ced_ptr->id,ced_ptr->val_ptr,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
break;
case ConfigEntry_Int32_16:
UiReadSettingEEPROM_Int32_16(ced_ptr->id,ced_ptr->val_ptr,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
break;
case ConfigEntry_Int16:
UiReadSettingEEPROM_Int16(ced_ptr->id,ced_ptr->val_ptr,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
break;
case ConfigEntry_UInt8x2:
UiReadSettingEEPROM_UInt8x2(ced_ptr->id,ced_ptr->val_ptr,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
break;
case ConfigEntry_Int32:
{
uint32_t Data;
uint16_t DataLo,DataHi;
UiReadSettingEEPROM_UInt16(ced_ptr->id,&DataHi,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
UiReadSettingEEPROM_UInt16(ced_ptr->id+1,&DataLo,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
Data=DataHi<<16|DataLo;
*(int32_t*)ced_ptr->val_ptr=(int32_t)Data;
}
break;
// case ConfigEntry_Bool:
// UiReadSettingEEPROM_Bool(ced_ptr->id,ced_ptr->val_ptr,ced_ptr->val_default,ced_ptr->val_min,ced_ptr->val_max, load_default);
// break;
}
}
uint16_t UiConfiguration_WriteConfigEntryData(const ConfigEntryDescriptor* ced_ptr)
{
uint16_t retval = HAL_ERROR;
switch(ced_ptr->typeId & ConfigEntry_TypeMask)
{
case ConfigEntry_UInt8:
retval = UiWriteSettingEEPROM_UInt16(ced_ptr->id,*(uint8_t*)ced_ptr->val_ptr);
break;
case ConfigEntry_UInt8x2:
retval = UiWriteSettingEEPROM_UInt8x2(ced_ptr->id,*(uint16_t*)ced_ptr->val_ptr);
break;
case ConfigEntry_UInt16:
retval = UiWriteSettingEEPROM_UInt16(ced_ptr->id,*(uint16_t*)ced_ptr->val_ptr);
break;
case ConfigEntry_UInt32_16:
retval = UiWriteSettingEEPROM_UInt32_16(ced_ptr->id,*(uint32_t*)ced_ptr->val_ptr);
break;
case ConfigEntry_Int32_16:
retval = UiWriteSettingEEPROM_Int32_16(ced_ptr->id,*(int32_t*)ced_ptr->val_ptr);
break;
case ConfigEntry_Int16:
retval = UiWriteSettingEEPROM_Int16(ced_ptr->id,*(int16_t*)ced_ptr->val_ptr);
break;
case ConfigEntry_Int32:
{
int32_t Data=*(int32_t*)ced_ptr->val_ptr;
uint16_t DataHi,DataLo;
DataHi=(uint16_t)((Data>>16)&0xffff);
DataLo=(uint16_t)(Data&0xffff);
retval = UiWriteSettingEEPROM_UInt16(ced_ptr->id,DataHi);
retval = UiWriteSettingEEPROM_UInt16(ced_ptr->id+1,DataLo);
}
break;
// case ConfigEntry_Bool:
// UiWriteSettingEEPROM_Bool(ced_ptr->id,*(bool*)ced_ptr->val_ptr,ced_ptr->val_default);
// break;
}
return retval;
}
uint16_t UiConfiguration_WriteConfigEntries()
{
uint16_t retval = HAL_OK;
int idx;
for (idx = 0; ConfigEntryInfo[idx].typeId != ConfigEntry_Stop ; idx++)
{
retval = UiConfiguration_WriteConfigEntryData(&ConfigEntryInfo[idx]);
}
return retval;
}
/**
*
* @param load_default shall we load defaults instead of the value from storage? true -> do it
* @param force_default_above from which parameter index on shall we force loading defaults even if load_defaults is false
*
*/
static void __attribute__ ((noinline)) UiConfiguration_ReadConfigEntries(bool load_default, int32_t force_default_above)
{
int idx;
for (idx = 0; ConfigEntryInfo[idx].typeId != ConfigEntry_Stop ; idx++)
{
UiConfiguration_ReadConfigEntryData(&ConfigEntryInfo[idx], (ConfigEntryInfo[idx].id>force_default_above) ? true : load_default);
}
}
void UiConfiguration_UpdateMacroCap(void)
{
for (int i = 0; i < KEYER_BUTTONS; i++)
{
if (*ts.keyer_mode.macro[i] != '\0')
{
// Make button label from start of the macro
uint8_t* pmacro = (uint8_t *)ts.keyer_mode.macro[i];
int c = 0;
while(*pmacro != ' ' && *pmacro != '\0' && c < KEYER_CAP_LEN)
{
char lc = *pmacro++;
lc = lc >' ' ? lc : '_';
// ts.keyer_mode.cap[i][c++] = *pmacro++;
ts.keyer_mode.cap[i][c++] = lc;
}
ts.keyer_mode.cap[i][c] = '\0';
}
else
{
// strcpy((char *) ts.keyer_mode.cap[i], "BTN");
strcpy((char *) ts.keyer_mode.cap[i], "EMPTY");
}
}
}
/**
* Calculate based on current firmware version and stored configuration values, which parameters were not present in the stored configuration and
* do need to be initialized / reset to the default value.
* Code uses the stored parameter count (EEPROM_NUMBER_OF_ENTRIES and the version identifiers) to calculate a safe choice but useful value.
* For older firmwares which did not support the EEPROM_NUMBER_OF_ENTRIES parameter, the initialization only covers parameters introduced after EEPROM_NUMBER_OF_ENTRIES.
* This is mostly relevant for I2C EEPROM based parameter storage.
*
* @return the lowest parameter number, which does not need to reset/initialized to its default value. -1 indicates all values to default, INT32_MAX none
*/
static int32_t UiConfiguration_NeedsDefaultIndex(void)
{
int32_t retval = INT32_MAX;
uint16_t num_of_entries;
if (ts.configstore_in_use == CONFIGSTORE_IN_USE_I2C)
{
UiReadSettingEEPROM_UInt16(EEPROM_NUMBER_OF_ENTRIES,&num_of_entries,0,0,0xfffe, false);
if (num_of_entries == 0)
{
// we have a system which may be either uninitialized OR too old.
if (UiConfiguration_CompareConfigBuildVersions(0,0,0) == 0)
{
// this is a new system, we can initialize it from the beginning
retval = -1;
}
else
{
retval = EEPROM_NUMBER_OF_ENTRIES;
// the index of the number of entries is as low as we can go here
// anything above this entry can be initialized, since it did not exist before
}
}
else
{
retval = num_of_entries;
// the number of entries the currently stored configuration uses
// must not be initialized, but anything above can.
}
}
return retval;
}
/**
* Fixes an specific issue with iq correction defaults not initialized correctly in version 2.9.85 / 2.9.86
*/
void UiConfiguration_FixDefaultsNotLoadedIssue()
{
// we fix here an issue of our configuration approach which appears if you store int values and have the lower range below -1
if (UiConfiguration_CompareConfigBuildVersions(2,9,87) == 1 && ts.configstore_in_use == CONFIGSTORE_IN_USE_I2C)
{
// values have been stored by older version of firmware
uint32_t values[] = { IQ_20M, IQ_15M, IQ_10M_UP };
bool not_all_minus_one = false;
for (uint32_t i = 0; i < sizeof(values)/sizeof(values[0]) && not_all_minus_one == false ; i++)
{
not_all_minus_one = not_all_minus_one || (iq_adjust[values[i]].adj.tx[IQ_TRANS_ON].gain != -1 || iq_adjust[values[i]].adj.tx[IQ_TRANS_ON].phase != -1);
not_all_minus_one = not_all_minus_one || (iq_adjust[values[i]].adj.tx[IQ_TRANS_OFF].gain != -1 || iq_adjust[values[i]].adj.tx[IQ_TRANS_OFF].phase != -1);
}
// okay, we have every value at -1 AND values stored in an older firmware than 2.9.86, we can safely rewrite all values to the right default
if (not_all_minus_one == false)
{
for (uint32_t i = 0; i < sizeof(values)/sizeof(values[0]); i++)
{
iq_adjust[values[i]].adj.tx[IQ_TRANS_ON].gain = IQ_BALANCE_OFF;
iq_adjust[values[i]].adj.tx[IQ_TRANS_ON].phase = IQ_BALANCE_OFF;
iq_adjust[values[i]].adj.tx[IQ_TRANS_OFF].gain = IQ_BALANCE_OFF;
iq_adjust[values[i]].adj.tx[IQ_TRANS_OFF].phase = IQ_BALANCE_OFF;
}
}
}
}
/**
* Loads values stored in non-volatile memory into ram.
* @param load_freq_mode_defaults if true, frequency default values will be loaded instead of EEPROM values, all other values are untouched.
* @param load_eeprom_defaults if true, default values will be loaded instead of EEPROM values.
*/
void UiConfiguration_LoadEepromValues(bool load_freq_mode_defaults, bool load_eeprom_defaults)
{
ts.dsp.inhibit++; // disable dsp while loading EEPROM data
uint32_t value32;
UiConfiguration_ReadConfigEntries(load_eeprom_defaults, UiConfiguration_NeedsDefaultIndex());
// ------------------------------------------------------------------------------------
// Try to read Band and Mode saved values, but read freq-limit-settings before
uint8_t band_mem_idx;
UiReadSettingEEPROM_UInt8x2_Split(EEPROM_BAND_MODE,
&ts.dmod_mode, DEMOD_LSB, 0, DEMOD_MAX_MODE,
&band_mem_idx, BAND_MODE_80, 0, MAX_BANDS -1,
load_eeprom_defaults);
// restore the bandInfo for a given band info set and band memory index
if (bandinfo_idx >= BAND_INFO_SET_NUM)
{
// if the stored band index is not available, we need to handle this
// we cannot do this during reading as C does not allow us to use a const int as initializer constant
bandinfo_idx = BAND_INFO_SET_DEFAULT; // reset to default
}
bandInfo = bandInfos[bandinfo_idx].bands;
ts.band = RadioManagement_GetBandInfo(band_mem_idx);
// demodulator mode might not be right for saved band!
if(load_freq_mode_defaults) // freq defaults to be loaded?
{
ts.dmod_mode = DEMOD_LSB; // yes - set to LSB
}
// ------------------------------------------------------------------------------------
// Try to read Freq saved values
UiReadSettingEEPROM_UInt32(EEPROM_FREQ_HIGH,EEPROM_FREQ_LOW,&value32,0,0,0xffffffff, load_eeprom_defaults);
{
// We have loaded from eeprom the last used band, but can't just
// load saved frequency, as it could be out of band, so do a
// boundary check first (also check to see if defaults should be loaded)
df.tune_new = UiConfiguration_LimitFrequency(ts.band, value32, load_eeprom_defaults || load_freq_mode_defaults);
}
// Try to read saved per-band values for frequency, mode and filter
for(int i = 0; i < MAX_BANDS; i++)
{
// read from stored bands
UiReadSettingsBandMode(i,EEPROM_BAND0_MODE_A,EEPROM_BAND0_FREQ_HIGH_A,EEPROM_BAND0_FREQ_LOW_A, &vfo[VFO_A].band[i], load_eeprom_defaults || load_freq_mode_defaults);
UiReadSettingsBandMode(i,EEPROM_BAND0_MODE_B,EEPROM_BAND0_FREQ_HIGH_B,EEPROM_BAND0_FREQ_LOW_B, &vfo[VFO_B].band[i], load_eeprom_defaults || load_freq_mode_defaults);
}
UiReadSettingEEPROM_UInt32( EEPROM_XVERTER_OFFSET_HIGH,EEPROM_XVERTER_OFFSET_LOW,&ts.xverter_offset,0,0,XVERTER_OFFSET_MAX, load_eeprom_defaults);
UiReadSettingEEPROM_UInt32( EEPROM_XVERTER_OFFSET_TX_HIGH,EEPROM_XVERTER_OFFSET_TX_LOW,&ts.xverter_offset_tx,0,0,XVERTER_OFFSET_MAX, load_eeprom_defaults);
UiReadSettingEEPROM_Filter(load_eeprom_defaults);
ConfigStorage_CopySerial2Array(EEPROM_KEYER_MEMORY_ADDRESS, (uint8_t *)ts.keyer_mode.macro, sizeof(ts.keyer_mode.macro));
ConfigStorage_CopySerial2Array(EEPROM_MEMS_MEMORY_ADDRESS, (uint8_t *)mem_data, sizeof(mem_data));
ConfigStorage_CopySerial2Array(EEPROM_XVTR_MEMORY_ADDRESS, (uint8_t *)xvtr_data, sizeof(xvtr_data));
UiConfiguration_UpdateMacroCap();
// post configuration loading actions below
df.tuning_step = tune_steps[df.selected_idx];
ts.tx_gain[TX_AUDIO_LINEIN_R] = ts.tx_gain[TX_AUDIO_LINEIN_L];
// this fixes an issue with bad initialization which happens if you had version 2.9.85 installed.
UiConfiguration_FixDefaultsNotLoadedIssue();
// TODO: Find a better solution: We need the negated setting for the menu to not display
// disable rx iq settings in menu when autocorr is enabled
ts.display_rx_iq = ts.iq_auto_correction == 0;
if (ts.dsp.inhibit) { ts.dsp.inhibit--; } // restore setting
}
// ********************************************************************************************************************
//
//*----------------------------------------------------------------------------
//* Function Name : UiDriverSaveEepromValues
//* Object : save all values to EEPROM - called on power-down. Does not check to see if they have changed
//* Input Parameters :
//* Output Parameters :
//* Functions called :
//*----------------------------------------------------------------------------
uint16_t UiConfiguration_SaveEepromValues(void)
{
uint16_t i, retval = 0x0;
if(ts.txrx_mode != TRX_MODE_RX)
{
retval = 0xFF00;
}
else
{
const uint8_t dmod_mode = ts.dmod_mode;
// TODO: THIS IS UGLY: We are switching to RAM based storage in order to gain speed
// because we then can bulk write the data into the I2C later.
// we don't do this for flash, since we cannot gain anything here.
if(ts.configstore_in_use == CONFIGSTORE_IN_USE_I2C)
{
ConfigStorage_CopySerial2RAMCache();
}
if(RadioManagement_IsGenericBand(ts.band) == false && ts.cat_band_index == 255) // not in a sandbox
{
// save current band/frequency/mode settings
vfo[get_active_vfo()].band[ts.band->band_mode].dial_value = df.tune_new;
// Save decode mode
vfo[get_active_vfo()].band[ts.band->band_mode].decod_mode = dmod_mode;
// TODO: move value to a static variable, so that it can be read/written with standard approach
retval = UiWriteSettingEEPROM_UInt8x2(EEPROM_BAND_MODE,
((uint16_t)ts.band->band_mode| dmod_mode << 8));
// TODO: move value to a static variable, so that it can be read/written with standard approach
if (retval == HAL_OK)
{
retval = UiWriteSettingEEPROM_UInt32(EEPROM_FREQ_HIGH,EEPROM_FREQ_LOW, df.tune_new);
}
}
else
{
ts.cat_band_index = 255;
}
// Save stored band/mode/frequency memory from RAM
for(i = 0; retval == HAL_OK && i < MAX_BANDS; i++) // scan through each band's frequency/mode data
{
// UiWriteSettingsBandMode(i,EEPROM_BAND0_MODE,EEPROM_BAND0_FREQ_HIGH,EEPROM_BAND0_FREQ_LOW, &vfo[VFO_WORK].band[i]);
retval = UiWriteSettingsBandMode(i,EEPROM_BAND0_MODE_A,EEPROM_BAND0_FREQ_HIGH_A,EEPROM_BAND0_FREQ_LOW_A, &vfo[VFO_A].band[i]);
if (retval == HAL_OK)
{
UiWriteSettingsBandMode(i,EEPROM_BAND0_MODE_B,EEPROM_BAND0_FREQ_HIGH_B,EEPROM_BAND0_FREQ_LOW_B, &vfo[VFO_B].band[i]);
}
}
if (retval == HAL_OK)
{
retval = UiConfiguration_WriteConfigEntries();
}
if (retval == HAL_OK)
{
retval = UiWriteSettingEEPROM_UInt32(EEPROM_XVERTER_OFFSET_HIGH,EEPROM_XVERTER_OFFSET_LOW,ts.xverter_offset);
}
if (retval == HAL_OK)
{
retval = UiWriteSettingEEPROM_UInt32(EEPROM_XVERTER_OFFSET_TX_HIGH,EEPROM_XVERTER_OFFSET_TX_LOW,ts.xverter_offset_tx);
}
if (retval == HAL_OK)
{
retval = UiWriteSettingEEPROM_Filter();
}
if(retval == HAL_OK && ts.configstore_in_use == CONFIGSTORE_IN_USE_RAMCACHE)
{
retval = ConfigStorage_CopyRAMCache2Serial();
// write ram cache to EEPROM and switch back to I2C EEPROM use
}
retval = ConfigStorage_CopyArray2Serial(EEPROM_KEYER_MEMORY_ADDRESS, (uint8_t *)ts.keyer_mode.macro, sizeof(ts.keyer_mode.macro));
retval = ConfigStorage_CopyArray2Serial(EEPROM_MEMS_MEMORY_ADDRESS, (uint8_t *)mem_data, sizeof(mem_data));
retval = ConfigStorage_CopyArray2Serial(EEPROM_XVTR_MEMORY_ADDRESS, (uint8_t *)xvtr_data, sizeof(xvtr_data));
}
return retval;
}