#include "settings.h" #include "stm32f4xx_hal.h" #include #include #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; TRX.BANDS_SAVED_SETTINGS[i].IF_Gain = TRX.IF_Gain; // TRX.BANDS_SAVED_SETTINGS[i].AutoGain_Stage = 6; } 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; TRX.FFT_Automatic = true; //Automatic FFT Scale TRX.FFT_Sensitivity = 8; //Threshold of FFT autocalibrate TRX.ShiftEnabled = false; // activate the SHIFT mode TRX.SHIFT_INTERVAL = 1000; // Detune range with the SHIFT knob (5000 = -5000hz / + 5000hz) 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 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 TRX.AGC_GAIN_TARGET = -25; // Maximum (target) AGC gain TRX.RX_AGC_Max_gain = 25; //Maximum AGC gain TRX.TX_Compressor_speed_SSB = 3; // TX скорость компрессора SSB TRX.TX_Compressor_maxgain_SSB = 10; // TX максимальное усиление SSB TRX.TX_Compressor_speed_AMFM = 3; // TX скорость компрессора AM/FM TRX.TX_Compressor_maxgain_AMFM = 10; // TX максимальное усиление AM/FM TRX.TX_func_mode = 0; // 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 CALIBRATE.ENCODER2_DEBOUNCE = 30; // time to eliminate contact bounce at the additional encoder, ms CALIBRATE.ENCODER_SLOW_RATE = 25; // slow down the encoder for high resolutions CALIBRATE.ENCODER2_SLOW_RATE = 2; // slow down the encoder for high resolutions 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; }