2022-04-18 16:53:10 +00:00
# include "settings.h"
# include "stm32f4xx_hal.h"
# include <stdio.h>
# include <stdlib.h>
# include "functions.h"
# include "trx_manager.h"
# include "lcd.h"
# include "fpga.h"
# include "main.h"
# include "bands.h"
# include "front_unit.h"
char version_string [ 19 ] = " 1.0.0 " ; //1.2.3-yymmdd.hhmm (concatinate)
//W25Q16
static uint8_t Write_Enable = W25Q16_COMMAND_Write_Enable ;
static uint8_t Sector_Erase = W25Q16_COMMAND_Sector_Erase ;
static uint8_t Page_Program = W25Q16_COMMAND_Page_Program ;
static uint8_t Read_Data = W25Q16_COMMAND_Read_Data ;
static uint8_t Power_Down = W25Q16_COMMAND_Power_Down ;
static uint8_t Get_Status = W25Q16_COMMAND_GetStatus ;
static uint8_t Write_Status = W25Q16_COMMAND_WriteStatus ;
static uint8_t Write_Status_REG = 0 ;
static uint8_t Power_Up = W25Q16_COMMAND_Power_Up ;
static uint8_t Address [ 3 ] = { 0x00 } ;
struct TRX_SETTINGS TRX ;
struct TRX_CALIBRATE CALIBRATE = { 0 } ;
static uint8_t settings_bank = 1 ;
static uint8_t write_clone [ sizeof ( TRX ) ] = { 0 } ;
static uint8_t read_clone [ sizeof ( TRX ) ] = { 0 } ;
static uint8_t verify_clone [ sizeof ( TRX ) ] = { 0 } ;
volatile bool NeedSaveSettings = false ;
volatile bool NeedSaveCalibration = false ;
volatile bool EEPROM_Busy = false ;
static bool EEPROM_Enabled = true ;
static void LoadSettingsFromEEPROM ( void ) ;
static bool EEPROM_Sector_Erase ( uint8_t sector , bool force ) ;
static bool EEPROM_Write_Data ( uint8_t * Buffer , uint16_t size , uint8_t sector , bool verify , bool force ) ;
static bool EEPROM_Read_Data ( uint8_t * Buffer , uint16_t size , uint8_t sector , bool verif , bool force ) ;
static void EEPROM_PowerDown ( void ) ;
static void EEPROM_PowerUp ( void ) ;
static void EEPROM_WaitWrite ( void ) ;
static uint8_t calculateCSUM ( void ) ;
static uint8_t calculateCSUM_EEPROM ( void ) ;
//static uint16_t freq_correctur = 0;
const char * MODE_DESCR [ TRX_MODE_COUNT ] = {
" LSB " ,
" USB " ,
" CW-L " ,
" CW-U " ,
" NFM " ,
" WFM " ,
" AM " ,
" DIGL " ,
" DIGU " ,
" IQ " ,
" LOOP " ,
" NOTX " ,
} ;
void InitSettings ( void )
{
static bool already_inited = false ;
if ( already_inited ) return ;
already_inited = true ;
//concat build date to version -yymmdd.hhmm
uint8_t cur_len = ( uint8_t ) strlen ( version_string ) ;
strcat ( version_string , " - " ) ;
version_string [ + + cur_len ] = BUILD_YEAR_CH2 ;
version_string [ + + cur_len ] = BUILD_YEAR_CH3 ;
version_string [ + + cur_len ] = BUILD_MONTH_CH0 ;
version_string [ + + cur_len ] = BUILD_MONTH_CH1 ;
version_string [ + + cur_len ] = BUILD_DAY_CH0 ;
version_string [ + + cur_len ] = BUILD_DAY_CH1 ;
version_string [ + + cur_len ] = ' . ' ;
version_string [ + + cur_len ] = BUILD_HOUR_CH0 ;
version_string [ + + cur_len ] = BUILD_HOUR_CH1 ;
version_string [ + + cur_len ] = BUILD_MIN_CH0 ;
version_string [ + + cur_len ] = BUILD_MIN_CH1 ;
version_string [ + + cur_len ] = ' \0 ' ;
sendToDebug_strln ( version_string ) ;
}
void LoadSettings ( bool clear )
{
BKPSRAM_Enable ( ) ;
memcpy ( & TRX , ( uint32_t * ) BACKUP_SRAM_BANK1_ADDR , sizeof ( TRX ) ) ;
// Check, the data in the backup sram is correct, otherwise we use the second bank
if ( TRX . ENDBit ! = 100 | | TRX . flash_id ! = SETT_VERSION | | TRX . csum ! = calculateCSUM ( ) )
{
memcpy ( & TRX , BACKUP_SRAM_BANK2_ADDR , sizeof ( TRX ) ) ;
if ( TRX . ENDBit ! = 100 | | TRX . flash_id ! = SETT_VERSION | | TRX . csum ! = calculateCSUM ( ) )
{
sendToDebug_strln ( " [ERR] BACKUP SRAM data incorrect " ) ;
LoadSettingsFromEEPROM ( ) ;
if ( TRX . ENDBit ! = 100 | | TRX . flash_id ! = SETT_VERSION | | TRX . csum ! = calculateCSUM ( ) )
{
sendToDebug_strln ( " [ERR] EEPROM Settings data incorrect " ) ;
}
else
{
SaveSettings ( ) ;
sendToDebug_strln ( " [OK] Settings data succesfully loaded from EEPROM " ) ;
}
}
else
{
sendToDebug_strln ( " [OK] Settings data succesfully loaded from BACKUP SRAM bank 2 " ) ;
}
}
else
{
sendToDebug_strln ( " [OK] Settings data succesfully loaded from BACKUP SRAM bank 1 " ) ;
}
BKPSRAM_Disable ( ) ;
if ( TRX . flash_id ! = SETT_VERSION | | clear | | TRX . ENDBit ! = 100 ) // code to trace new clean flash
{
if ( clear )
sendToDebug_strln ( " [OK] Soft reset TRX " ) ;
memset ( & TRX , 0x00 , sizeof ( TRX ) ) ;
TRX . flash_id = SETT_VERSION ; // Firmware ID in SRAM, if it doesn't match, use the default
TRX . VFO_A . Freq = 7100000 ; // stored VFO-A frequency
TRX . VFO_A . Mode = TRX_MODE_LSB ; // saved VFO-A mode
TRX . VFO_A . RX_LPF_Filter_Width = 2700 ; // saved bandwidth for VFO-A
TRX . VFO_A . TX_LPF_Filter_Width = 2700 ; // saved bandwidth for VFO-A
TRX . VFO_A . HPF_Filter_Width = 300 ; // saved bandwidth for VFO-A
TRX . VFO_A . AutoNotchFilter = false ; // notch filter to cut out noise
TRX . VFO_A . NotchFC = 1000 ; // cutoff frequency of the notch filter
TRX . VFO_A . AGC = true ; // AGC
TRX . VFO_B . Freq = 14150000 ; // stored VFO-B frequency
TRX . VFO_B . Mode = TRX_MODE_USB ; // saved VFO-B mode
TRX . VFO_B . RX_LPF_Filter_Width = 2700 ; // saved bandwidth for VFO-B
TRX . VFO_B . TX_LPF_Filter_Width = 2700 ; // saved bandwidth for VFO-B
TRX . VFO_B . HPF_Filter_Width = 300 ; // saved bandwidth for VFO-B
TRX . VFO_B . AutoNotchFilter = false ; // notch filter to cut out noise
TRX . VFO_B . NotchFC = 1000 ; // cutoff frequency of the notch filter
TRX . VFO_B . AGC = true ; // AGC
TRX . current_vfo = false ; // current VFO (false - A)
TRX . ADC_Driver = true ; // preamplifier (ADC driver)
TRX . ATT = false ; // attenuator
TRX . ATT_DB = 12.0f ; // suppress the attenuator
TRX . ATT_STEP = 6.0f ; // step of tuning the attenuator
TRX . FM_SQL_threshold = 4 ; // FM noise reduction
TRX . Fast = true ; // accelerated frequency change when the encoder rotates
for ( uint8_t i = 0 ; i < BANDS_COUNT ; i + + )
{
TRX . BANDS_SAVED_SETTINGS [ i ] . Freq = BANDS [ i ] . startFreq + ( BANDS [ i ] . endFreq - BANDS [ i ] . startFreq ) / 2 ; // saved frequencies by bands
TRX . BANDS_SAVED_SETTINGS [ i ] . Mode = ( uint8_t ) getModeFromFreq ( TRX . BANDS_SAVED_SETTINGS [ i ] . Freq ) ;
TRX . BANDS_SAVED_SETTINGS [ i ] . ATT = TRX . ATT ;
TRX . BANDS_SAVED_SETTINGS [ i ] . ATT_DB = TRX . ATT_DB ;
TRX . BANDS_SAVED_SETTINGS [ i ] . ADC_Driver = TRX . ADC_Driver ;
TRX . BANDS_SAVED_SETTINGS [ i ] . FM_SQL_threshold = TRX . FM_SQL_threshold ;
TRX . BANDS_SAVED_SETTINGS [ i ] . AGC = true ;
2022-05-06 20:14:25 +00:00
TRX . BANDS_SAVED_SETTINGS [ i ] . IF_Gain = TRX . IF_Gain ;
2022-04-25 19:12:05 +00:00
// TRX.BANDS_SAVED_SETTINGS[i].AutoGain_Stage = 6;
2022-04-18 16:53:10 +00:00
}
TRX . AutoGain = false ; // auto-control preamp and attenuator
TRX . InputType_MIC = true ; // type of input to transfer
TRX . InputType_LINE = false ;
TRX . InputType_USB = false ;
TRX . CW_LPF_Filter = 700 ; // default value of CW filter width
TRX . CW_HPF_Filter = 0 ; // default value of CW filter width
TRX . RX_SSB_LPF_Filter = 2700 ; // default value of SSB filter width
TRX . TX_SSB_LPF_Filter = 2700 ; // default value of SSB filter width
TRX . SSB_HPF_Filter = 300 ; // default value of SSB filter width
TRX . RX_AM_LPF_Filter = 4000 ; // default value of AM filter width
TRX . TX_AM_LPF_Filter = 4000 ; // default value of AM filter width
TRX . RX_FM_LPF_Filter = 15000 ; // default value of the FM filter width
TRX . TX_FM_LPF_Filter = 15000 ; // default value of the FM filter width
TRX . RF_Power = 20 ; // output power (%)
TRX . RX_AGC_SSB_speed = 10 ; // AGC receive rate on SSB
TRX . RX_AGC_CW_speed = 1 ; // AGC receive rate on CW
TRX . TX_AGC_speed = 3 ; // AGC transfer rate
TRX . BandMapEnabled = true ; // automatic change of mode according to the range map
TRX . CW_GENERATOR_SHIFT_HZ = 500 ; // LO offset in CW mode
TRX . CW_Key_timeout = 500 ; // time of releasing transmission after the last character on the key
TRX . CW_SelfHear = true ; // self-control CW
TRX . ADC_SHDN = false ; // ADC disable
TRX . Locked = false ; // Lock control
TRX . CLAR = false ; // Split frequency mode (receive one VFO, transmit another)
TRX . TWO_SIGNAL_TUNE = false ; // Two-signal generator in TUNE mode (1 + 2kHz)
TRX . IF_Gain = 40 ; // IF gain, dB (before all processing and AGC)
TRX . CW_KEYER = true ; // Automatic key
TRX . CW_KEYER_WPM = 30 ; // Automatic key speed
TRX . Debug_Console = false ; // Debug output to DEBUG / UART port
TRX . FFT_Zoom = 1 ; // approximation of the FFT spectrum
TRX . ColorThemeId = 0 ; // Selected Color theme
TRX . Freq_Font = 1 ; // Freq Font select
TRX . FFT_Grid = 0 ; // FFT grid style
TRX . FFT_Background = false ; // FFT gradient background
TRX . FFT_Enabled = true ;
TRX . FFT_Compressor = true ; //Compress FFT Peaks
TRX . FFT_Averaging = 3 ; // averaging the FFT to make it smoother
TRX . FFT_Window = 1 ;
2022-05-09 20:15:49 +00:00
TRX . FFT_Automatic = true ; //Automatic FFT Scale
TRX . FFT_Sensitivity = 8 ; //Threshold of FFT autocalibrate
2022-04-18 16:53:10 +00:00
TRX . ShiftEnabled = false ; // activate the SHIFT mode
2022-04-23 14:40:36 +00:00
TRX . SHIFT_INTERVAL = 1000 ; // Detune range with the SHIFT knob (5000 = -5000hz / + 5000hz)
2022-04-18 16:53:10 +00:00
TRX . DNR_SNR_THRESHOLD = 50 ; // Digital noise reduction level
TRX . DNR_AVERAGE = 2 ; // DNR averaging when looking for average magnitude
TRX . DNR_MINIMAL = 99 ; // DNR averaging when searching for minimum magnitude
TRX . FRQ_STEP = 10 ; // frequency tuning step by the main encoder
TRX . FRQ_FAST_STEP = 100 ; // frequency tuning step by the main encoder in FAST mode
2022-04-22 08:49:25 +00:00
TRX . FRQ_ENC_STEP = 2500 ; // frequency tuning step by main add. encoder
TRX . FRQ_ENC_FAST_STEP = 5000 ; // frequency tuning step by main add. encoder in FAST mode
2022-04-18 16:53:10 +00:00
TRX . AGC_GAIN_TARGET = - 25 ; // Maximum (target) AGC gain
2022-05-08 12:16:50 +00:00
TRX . RX_AGC_Max_gain = 25 ; //Maximum AGC gain
2022-04-18 16:53:10 +00:00
TRX . TX_Compressor_speed_SSB = 3 ; // TX <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> SSB
TRX . TX_Compressor_maxgain_SSB = 10 ; // TX <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> SSB
TRX . TX_Compressor_speed_AMFM = 3 ; // TX <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> AM/FM
TRX . TX_Compressor_maxgain_AMFM = 10 ; // TX <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> AM/FM
2022-05-08 12:16:50 +00:00
TRX . TX_func_mode = 0 ; //
2022-04-18 16:53:10 +00:00
TRX . MIC_GAIN = 3 ; // Microphone gain
TRX . MIC_BOOST = false ; // Microphone boost +20dB
TRX . RX_EQ_LOW = 0 ; // Receiver Equalizer (Low)
TRX . RX_EQ_MID = 0 ; // Receiver EQ (mids)
TRX . RX_AGC_Hold = 700 ; // AGC Hold time on peaks
TRX . RX_EQ_HIG = 0 ; // Receiver EQ (high)
TRX . MIC_EQ_LOW = 0 ; // Mic EQ (Low)
TRX . MIC_EQ_MID = 0 ; // Mic Equalizer (Mids)
TRX . MIC_EQ_HIG = 0 ; // Mic EQ (high)
TRX . Beeper = true ; // Keyboard beeper
TRX . Encoder_Accelerate = true ; // Accelerate Encoder on fast rate
TRX . Encoder_OFF = false ; // Encoder ON/OFF TX
strcpy ( TRX . CALLSIGN , " HamRad " ) ; // Callsign
TRX . Transverter_Enabled = false ; // Enable transverter mode
TRX . Transverter_Offset_Mhz = 120 ; // Offset from VFO
TRX . Volume = 50 ; // AF Volume
TRX . Volume_Step = 1 ; // Adjusting the volume pitch
TRX . CW_GaussFilter = true ; // Gauss responce LPF filter
// TRX.LCD_position = 2; // LCD_position
TRX . ENDBit = 100 ; // Bit for the end of a successful write to eeprom
sendToDebug_strln ( " [OK] Loaded default settings " ) ;
SaveSettings ( ) ;
SaveSettingsToEEPROM ( ) ;
}
}
static void LoadSettingsFromEEPROM ( void )
{
EEPROM_PowerUp ( ) ;
uint8_t tryes = 0 ;
while ( tryes < EEPROM_REPEAT_TRYES & & ! EEPROM_Read_Data ( ( uint8_t * ) & TRX , sizeof ( TRX ) , EEPROM_SECTOR_SETTINGS , true , false ) )
{
tryes + + ;
}
if ( tryes > = EEPROM_REPEAT_TRYES )
sendToDebug_strln ( " [ERR] Read EEPROM SETTINGS multiple errors " ) ;
EEPROM_PowerDown ( ) ;
}
void LoadCalibration ( bool clear )
{
EEPROM_PowerUp ( ) ;
uint8_t tryes = 0 ;
while ( tryes < EEPROM_REPEAT_TRYES & & ! EEPROM_Read_Data ( ( uint8_t * ) & CALIBRATE , sizeof ( CALIBRATE ) , EEPROM_SECTOR_CALIBRATION , true , false ) )
{
tryes + + ;
}
if ( tryes > = EEPROM_REPEAT_TRYES )
sendToDebug_strln ( " [ERR] Read EEPROM CALIBRATE multiple errors " ) ;
if ( CALIBRATE . ENDBit ! = 100 | | CALIBRATE . flash_id ! = CALIB_VERSION | | clear | | CALIBRATE . csum ! = calculateCSUM_EEPROM ( ) ) // code for checking the firmware in the eeprom, if it does not match, we use the default
{
sendToDebug_str ( " [ERR] CALIBRATE Flash check " ) ;
sendToDebug_uint8 ( CALIBRATE . ENDBit , false ) ;
sendToDebug_uint8 ( CALIBRATE . flash_id , false ) ;
sendToDebug_uint8 ( CALIB_VERSION , false ) ;
sendToDebug_uint8 ( clear , false ) ;
sendToDebug_uint8 ( CALIBRATE . csum , false ) ;
sendToDebug_uint8 ( calculateCSUM_EEPROM ( ) , false ) ;
CALIBRATE . flash_id = CALIB_VERSION ; // code for checking the firmware in the eeprom, if it does not match, we use the default
CALIBRATE . ENCODER_INVERT = false ; // invert left-right rotation of the main encoder
CALIBRATE . ENCODER2_INVERT = false ; // invert left-right rotation of the optional encoder
CALIBRATE . ENCODER_DEBOUNCE = 0 ; // time to eliminate contact bounce at the main encoder, ms
2022-04-22 08:49:25 +00:00
CALIBRATE . ENCODER2_DEBOUNCE = 30 ; // time to eliminate contact bounce at the additional encoder, ms
2022-04-18 16:53:10 +00:00
CALIBRATE . ENCODER_SLOW_RATE = 25 ; // slow down the encoder for high resolutions
2022-04-22 08:49:25 +00:00
CALIBRATE . ENCODER2_SLOW_RATE = 2 ; // slow down the encoder for high resolutions
2022-04-18 16:53:10 +00:00
CALIBRATE . ENCODER_ON_FALLING = false ; // encoder only triggers when level A falls
CALIBRATE . CICFIR_GAINER_val = 35 ; // Offset from the output of the CIC compensator
CALIBRATE . TXCICFIR_GAINER_val = 27 ; // Offset from the TX-CIC output of the compensator
CALIBRATE . DAC_GAINER_val = 26 ; // DAC offset offset
// Calibrate the maximum output power for each band
CALIBRATE . rf_out_power_160m = 22 ; //160m
CALIBRATE . rf_out_power_80m = 22 ; //80m
CALIBRATE . rf_out_power_40m = 22 ; //40m
CALIBRATE . rf_out_power_30m = 22 ; //30m
CALIBRATE . rf_out_power_20m = 22 ; //20m
CALIBRATE . rf_out_power_17m = 22 ; //17m
CALIBRATE . rf_out_power_15m = 22 ; //15m
CALIBRATE . rf_out_power_12m = 22 ; //12m
CALIBRATE . rf_out_power_10m = 22 ; //10m
CALIBRATE . rf_out_power_lf = 40 ; // <2mhz
CALIBRATE . rf_out_power_hf_low = 45 ; // <5mhz
CALIBRATE . rf_out_power_hf = 26 ; // <30mhz
CALIBRATE . rf_out_power_hf_high = 80 ; // >30mhz
CALIBRATE . smeter_calibration = - 10 ; // S-Meter calibration, set when calibrating the transceiver to S9
CALIBRATE . swr_trans_rate = 11.0f ; // SWR Transormator rate
CALIBRATE . volt_cal_rate = 11.0f ; // VOLTAGE
CALIBRATE . vcxo_calibration = 0 ; // VCXO PWM
CALIBRATE . ENDBit = 100 ;
sendToDebug_strln ( " [OK] Loaded default calibrate settings " ) ;
SaveCalibration ( ) ;
}
EEPROM_PowerDown ( ) ;
}
inline VFO * CurrentVFO ( void )
{
if ( ! TRX . current_vfo )
return & TRX . VFO_A ;
else
return & TRX . VFO_B ;
}
inline VFO * SecondaryVFO ( void )
{
if ( ! TRX . current_vfo )
return & TRX . VFO_B ;
else
return & TRX . VFO_A ;
}
void SaveSettings ( void )
{
BKPSRAM_Enable ( ) ;
TRX . csum = calculateCSUM ( ) ;
if ( settings_bank = = 1 )
{
memcpy ( BACKUP_SRAM_BANK1_ADDR , & TRX , sizeof ( TRX ) ) ;
memset ( BACKUP_SRAM_BANK2_ADDR , 0x00 , sizeof ( TRX ) ) ;
}
else
{
memcpy ( BACKUP_SRAM_BANK2_ADDR , & TRX , sizeof ( TRX ) ) ;
memset ( BACKUP_SRAM_BANK1_ADDR , 0x00 , sizeof ( TRX ) ) ;
}
BKPSRAM_Disable ( ) ;
NeedSaveSettings = false ;
//sendToDebug_str("[OK] Settings Saved to bank ");
//sendToDebug_uint8(settings_bank, false);
//sendToDebug_uint32(sizeof(TRX), false);
if ( settings_bank = = 1 )
settings_bank = 2 ;
else
settings_bank = 1 ;
}
void SaveSettingsToEEPROM ( void )
{
if ( EEPROM_Busy )
return ;
EEPROM_PowerUp ( ) ;
EEPROM_Busy = true ;
TRX . csum = calculateCSUM ( ) ;
uint8_t tryes = 0 ;
while ( tryes < EEPROM_REPEAT_TRYES & & ! EEPROM_Sector_Erase ( EEPROM_SECTOR_SETTINGS , false ) )
{
tryes + + ;
}
if ( tryes > = EEPROM_REPEAT_TRYES )
{
sendToDebug_strln ( " [ERR] Erase EEPROM Settings multiple errors " ) ;
sendToDebug_flush ( ) ;
EEPROM_Busy = false ;
return ;
}
tryes = 0 ;
while ( tryes < EEPROM_REPEAT_TRYES & & ! EEPROM_Write_Data ( ( uint8_t * ) & TRX , sizeof ( TRX ) , EEPROM_SECTOR_SETTINGS , true , false ) )
{
tryes + + ;
}
if ( tryes > = EEPROM_REPEAT_TRYES )
{
sendToDebug_strln ( " [ERR] Write EEPROM Settings multiple errors " ) ;
sendToDebug_flush ( ) ;
EEPROM_Busy = false ;
return ;
}
EEPROM_Busy = false ;
EEPROM_PowerDown ( ) ;
sendToDebug_strln ( " [OK] EEPROM Settings Saved " ) ;
sendToDebug_flush ( ) ;
}
void SaveCalibration ( void )
{
if ( EEPROM_Busy )
return ;
EEPROM_PowerUp ( ) ;
EEPROM_Busy = true ;
CALIBRATE . csum = calculateCSUM_EEPROM ( ) ;
uint8_t tryes = 0 ;
while ( tryes < EEPROM_REPEAT_TRYES & & ! EEPROM_Sector_Erase ( EEPROM_SECTOR_CALIBRATION , false ) )
{
tryes + + ;
}
if ( tryes > = EEPROM_REPEAT_TRYES )
{
sendToDebug_strln ( " [ERR] Erase EEPROM calibrate multiple errors " ) ;
EEPROM_Busy = false ;
return ;
}
tryes = 0 ;
while ( tryes < EEPROM_REPEAT_TRYES & & ! EEPROM_Write_Data ( ( uint8_t * ) & CALIBRATE , sizeof ( CALIBRATE ) , EEPROM_SECTOR_CALIBRATION , true , false ) )
{
tryes + + ;
}
if ( tryes > = EEPROM_REPEAT_TRYES )
{
sendToDebug_strln ( " [ERR] Write EEPROM calibrate multiple errors " ) ;
EEPROM_Busy = false ;
return ;
}
EEPROM_Busy = false ;
EEPROM_PowerDown ( ) ;
sendToDebug_strln ( " [OK] EEPROM Calibrations Saved " ) ;
NeedSaveCalibration = false ;
}
static bool EEPROM_Sector_Erase ( uint8_t sector , bool force )
{
if ( ! force & & ! EEPROM_Enabled )
return true ;
if ( ! force & & SPI_process )
return false ;
else
SPI_process = true ;
uint32_t BigAddress = sector * W25Q16_SECTOR_SIZE ;
Address [ 2 ] = ( BigAddress > > 16 ) & 0xFF ;
Address [ 1 ] = ( BigAddress > > 8 ) & 0xFF ;
Address [ 0 ] = BigAddress & 0xFF ;
//disable write protect
//SPI_Transmit(&Write_Status, NULL, 1, W25Q16_CS_GPIO_Port, W25Q16_CS_Pin, true, SPI_EEPROM_PRESCALER); // WRITE STATUS REGISTER Command
//SPI_Transmit(&Write_Status_REG, NULL, 1, W25Q16_CS_GPIO_Port, W25Q16_CS_Pin, false, SPI_EEPROM_PRESCALER); // WRITE STATUS REGISTER argument
//EEPROM_WaitWrite();
SPI_Transmit ( & Write_Enable , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Write Enable Command
SPI_Transmit ( & Sector_Erase , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , true , SPI_EEPROM_PRESCALER ) ; // Erase Command
SPI_Transmit ( Address , NULL , 3 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Write Address ( The first address of flash module is 0x00000000 )
EEPROM_WaitWrite ( ) ;
SPI_process = false ;
return true ;
}
static bool EEPROM_Write_Data ( uint8_t * Buffer , uint16_t size , uint8_t sector , bool verify , bool force )
{
if ( ! force & & ! EEPROM_Enabled )
return true ;
if ( ! force & & SPI_process )
return false ;
else
SPI_process = true ;
if ( size > sizeof ( write_clone ) )
{
sendToDebug_strln ( " EEPROM buffer error " ) ;
return false ;
}
memcpy ( write_clone , Buffer , size ) ;
const uint16_t page_size = 256 ;
for ( uint16_t page = 0 ; page < = ( size / page_size ) ; page + + )
{
uint32_t BigAddress = page * page_size + ( sector * W25Q16_SECTOR_SIZE ) ;
Address [ 2 ] = ( BigAddress > > 16 ) & 0xFF ;
Address [ 1 ] = ( BigAddress > > 8 ) & 0xFF ;
Address [ 0 ] = BigAddress & 0xFF ;
uint16_t bsize = size - page_size * page ;
if ( bsize > page_size )
bsize = page_size ;
SPI_Transmit ( & Write_Enable , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Write Enable Command
SPI_Transmit ( & Page_Program , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , true , SPI_EEPROM_PRESCALER ) ; // Write Command
SPI_Transmit ( Address , NULL , 3 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , true , SPI_EEPROM_PRESCALER ) ; // Write Address ( The first address of flash module is 0x00000000 )
SPI_Transmit ( ( uint8_t * ) ( write_clone + page_size * page ) , NULL , bsize , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Write Data
EEPROM_WaitWrite ( ) ;
}
//verify
if ( verify )
{
EEPROM_Read_Data ( verify_clone , size , sector , false , true ) ;
for ( uint16_t i = 0 ; i < size ; i + + )
if ( verify_clone [ i ] ! = write_clone [ i ] )
{
EEPROM_Sector_Erase ( sector , true ) ;
SPI_process = false ;
return false ;
}
}
SPI_process = false ;
return true ;
}
static bool EEPROM_Read_Data ( uint8_t * Buffer , uint16_t size , uint8_t sector , bool verify , bool force )
{
if ( ! force & & ! EEPROM_Enabled )
return true ;
if ( ! force & & SPI_process )
return false ;
else
SPI_process = true ;
uint32_t BigAddress = sector * W25Q16_SECTOR_SIZE ;
Address [ 2 ] = ( BigAddress > > 16 ) & 0xFF ;
Address [ 1 ] = ( BigAddress > > 8 ) & 0xFF ;
Address [ 0 ] = BigAddress & 0xFF ;
bool res = SPI_Transmit ( & Read_Data , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , true , SPI_EEPROM_PRESCALER ) ; // Read Command
if ( ! res )
{
EEPROM_Enabled = false ;
sendToDebug_strln ( " [ERR] EEPROM not found... " ) ;
LCD_showError ( " EEPROM init error " , true ) ;
SPI_process = false ;
return true ;
}
SPI_Transmit ( Address , NULL , 3 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , true , SPI_EEPROM_PRESCALER ) ; // Write Address
SPI_Transmit ( NULL , ( uint8_t * ) ( Buffer ) , size , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Read
//verify
if ( verify )
{
EEPROM_Read_Data ( read_clone , size , sector , false , true ) ;
for ( uint16_t i = 0 ; i < size ; i + + )
if ( read_clone [ i ] ! = Buffer [ i ] )
{
sendToDebug_uint8 ( read_clone [ i ] , false ) ;
SPI_process = false ;
return false ;
}
}
SPI_process = false ;
return true ;
}
static void EEPROM_WaitWrite ( void )
{
if ( ! EEPROM_Enabled )
return ;
uint8_t status = 0 ;
uint8_t tryes = 0 ;
do
{
tryes + + ;
SPI_Transmit ( & Get_Status , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , true , SPI_EEPROM_PRESCALER ) ; // Get Status command
SPI_Transmit ( NULL , & status , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Read data
if ( ( status & 0x01 ) = = 0x01 )
HAL_Delay ( 1 ) ;
}
while ( ( status & 0x01 ) = = 0x01 & & ( tryes < 200 ) ) ;
if ( tryes = = 200 )
sendToDebug_strln ( " [ERR]EEPROM Lock wait error " ) ;
}
static void EEPROM_PowerDown ( void )
{
if ( ! EEPROM_Enabled )
return ;
SPI_Transmit ( & Power_Down , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Power_Down Command
}
static void EEPROM_PowerUp ( void )
{
if ( ! EEPROM_Enabled )
return ;
SPI_Transmit ( & Power_Up , NULL , 1 , W25Q16_CS_GPIO_Port , W25Q16_CS_Pin , false , SPI_EEPROM_PRESCALER ) ; // Power_Up Command
EEPROM_WaitWrite ( ) ;
}
void BKPSRAM_Enable ( void )
{
RCC - > APB1ENR | = RCC_APB1ENR_PWREN ;
RCC - > AHB1ENR | = RCC_AHB1ENR_BKPSRAMEN ;
HAL_PWREx_EnableBkUpReg ( ) ;
HAL_PWR_EnableBkUpAccess ( ) ;
* ( __IO uint32_t * ) CSR_BRE_BB = ( uint32_t ) ENABLE ;
while ( ! ( PWR - > CSR & ( PWR_FLAG_BRR ) ) ) ;
}
void BKPSRAM_Disable ( void )
{
HAL_PWR_DisableBkUpAccess ( ) ;
}
static uint8_t calculateCSUM ( void )
{
uint8_t csum_old = TRX . csum ;
uint8_t csum_new = 0 ;
TRX . csum = 0 ;
uint8_t * TRX_addr = ( uint8_t * ) & TRX ;
for ( uint16_t i = 0 ; i < sizeof ( TRX ) ; i + + )
csum_new + = * ( TRX_addr + i ) ;
TRX . csum = csum_old ;
return csum_new ;
}
static uint8_t calculateCSUM_EEPROM ( void )
{
uint8_t csum_old = CALIBRATE . csum ;
uint8_t csum_new =
CALIBRATE . csum = 0 ;
uint8_t * CALIBRATE_addr = ( uint8_t * ) & CALIBRATE ;
for ( uint16_t i = 0 ; i < sizeof ( CALIBRATE ) ; i + + )
csum_new + = * ( CALIBRATE_addr + i ) ;
CALIBRATE . csum = csum_old ;
return csum_new ;
}