/* * settings.c * * Created on: Jan 12, 2021 * Author: David Original work by Jose (PTDreamer), 2017 */ #include "settings.h" #include "pid.h" #include "iron.h" #include "gui.h" #include "ssd1306.h" #include "tempsensors.h" systemSettings_t systemSettings; flashSettings_t* flashSettings = (flashSettings_t*)FLASH_ADDR; void settingsChkErr(void); void ProfileChkErr(void); void Flash_error(void); void Button_reset(void); void Diag_init(void); void ErrCountDown(uint8_t Start,uint8_t xpos, uint8_t ypos); // Check for changes in system settings. void checkSettings(void){ static uint32_t prevSysChecksum=0, newSysChecksum=0, prevTipChecksum=0, newTipChecksum=0, checksumtime=0; uint32_t CurrentTime = HAL_GetTick(); // Don't check if in: Calibration mode, Setup mode, Save delay==0, failure error active if( (systemSettings.setupMode==setup_On) || (Iron.calibrating==calibration_On) || (systemSettings.settings.saveSettingsDelay==0) || (Iron.Error.failState!=noError) || (CurrentTime-checksumtime<999)){ return; } checksumtime=CurrentTime; // Store current time newSysChecksum=ChecksumSettings(&systemSettings.settings); // Calculate system checksum newTipChecksum=ChecksumProfile(&systemSettings.Profile); // Calculate tip profile checksum if((systemSettings.settingsChecksum!=newSysChecksum)||(systemSettings.ProfileChecksum!=newTipChecksum)){ // If anything was changed (Checksum mismatch) if((prevSysChecksum!=newSysChecksum)||(prevTipChecksum!=newTipChecksum)){ // If different from the previous calculated checksum (settings are being changed quickly, don't save every time). prevSysChecksum=newSysChecksum; // Store last computed checksum prevTipChecksum=newTipChecksum; Iron.LastSysChangeTime=CurrentTime; // Reset timer (we don't save anything until we pass a certain time without changes) } else if((CurrentTime-Iron.LastSysChangeTime)>((uint32_t)systemSettings.settings.saveSettingsDelay*1000)){ // If different from the previous calculated checksum, and timer expired (No changes for enough time) saveSettings(saveKeepingProfiles); // Data was saved (so any pending interrupt knows this) } } } void saveSettings(bool wipeAllProfileData) { uint32_t error=0; //Read stored data, as everything will be erased and we don't store data for all iron tips in ram (only the current tip type) flashSettings_t flashBuffer=*flashSettings; // Check init flags if( (systemSettings.settings.NotInitialized!=initialized) || (systemSettings.Profile.NotInitialized!=initialized) ){ Error_Handler(); } // Compute checksum of current system settings systemSettings.settingsChecksum = ChecksumSettings(&systemSettings.settings); // Transfer system settings to flash buffer flashBuffer.settingsChecksum=systemSettings.settingsChecksum; flashBuffer.settings=systemSettings.settings; if(!wipeAllProfileData){ // If wipe all tips is not set if(systemSettings.settings.currentProfile!=profile_None){ // If current tip is initialized if((systemSettings.settings.currentProfile<=profile_C210) && // Check valid Profile (systemSettings.Profile.ID == systemSettings.settings.currentProfile )){ // Ensure profile ID is correct systemSettings.ProfileChecksum = ChecksumProfile(&systemSettings.Profile); // Compute checksum flashBuffer.ProfileChecksum[systemSettings.settings.currentProfile]=systemSettings.ProfileChecksum; memcpy(&flashBuffer.Profile[systemSettings.settings.currentProfile],&systemSettings.Profile,sizeof(profile_t)); // Transfer system profile to flash buffer } else{ Error_Handler(); // Invalid tip (uncontrolled state) } } } else{ // Wipe all tip data for(uint8_t x=0;xProfile[systemSettings.settings.currentProfile]); uint32_t ProfileRam = ChecksumProfile(&systemSettings.Profile); // Check flash and system tip profile have same checksum and profile type if((ProfileFlash != ProfileRam) || (flashSettings->settings.currentProfile != systemSettings.settings.currentProfile)){ Flash_error(); // Error if data mismatchº } } // Check flash and system settings have same checksum uint32_t SettingsFlash = ChecksumSettings(&flashSettings->settings); uint32_t SettingsRam = ChecksumSettings(&systemSettings.settings); if(SettingsFlash != SettingsRam){ // Check flash and system settings have same checksum Flash_error(); // Error if data mismatch } } void restoreSettings() { #ifdef NOSAVESETTINGS // Stop erasing the flash every time while in debug mode resetSystemSettings(); // TODO not tested with the new profile system setupPID(systemSettings.Profile.tip[systemSettings.settings.currentTip[systemSettings.settings.currentProfile]].PID); return; #endif if(flashSettings->settings.NotInitialized!=initialized){ // If flash not initialized (Erased flash is always read "1") resetSystemSettings(); saveSettings(saveWipingProfiles); } else{ Button_reset(); // Check for button reset } systemSettings.settings=flashSettings->settings; // Load system settings from flash systemSettings.settingsChecksum=flashSettings->settingsChecksum; // Load stored checksum loadProfile(systemSettings.settings.currentProfile); // Load current tip data into system memory // Compare loaded checksum with calculated checksum if( (systemSettings.settings.version != SETTINGS_VERSION) || (ChecksumSettings(&systemSettings.settings)!=systemSettings.settingsChecksum) ){ settingsChkErr(); } setContrast(systemSettings.settings.contrast); } uint32_t ChecksumSettings(settings_t* settings){ uint32_t checksum; checksum = HAL_CRC_Calculate(&hcrc, (uint32_t*)settings, sizeof(settings_t)/sizeof(uint32_t) ); return checksum; } uint32_t ChecksumProfile(profile_t* profile){ uint32_t checksum; checksum = HAL_CRC_Calculate(&hcrc, (uint32_t*)profile, sizeof(profile_t)/sizeof(uint32_t)); return checksum; } void resetSystemSettings(void) { systemSettings.settings.version = SETTINGS_VERSION; systemSettings.settings.contrast = 255; systemSettings.settings.screenDimming = true; systemSettings.settings.OledOffset = 2; systemSettings.settings.errorDelay = 100; systemSettings.settings.guiUpdateDelay = 200; systemSettings.settings.tempUnit = mode_Celsius; systemSettings.settings.tempStep = 10; // 10º steps systemSettings.settings.activeDetection = true; systemSettings.settings.saveSettingsDelay = 5; // 5s systemSettings.settings.lvp = 110; // 11.0V Low voltage systemSettings.settings.currentProfile = profile_None; systemSettings.settings.initMode = mode_run; systemSettings.settings.buzzerMode = buzzer_Off; systemSettings.settings.wakeOnButton = wakeButton_On; systemSettings.settings.wakeOnShake = wakeShake_On; systemSettings.settings.WakeInputMode = wakeInputmode_shake; systemSettings.settings.StandMode = mode_sleep; systemSettings.settings.EncoderMode = RE_Mode_One; systemSettings.settings.NotInitialized = initialized; } void resetCurrentProfile(void){ #ifdef NOSAVESETTINGS systemSettings.settings.currentProfile=profile_T12; /// Force T12 when debugging. TODO this is not tested with the profiles update! #endif char str[TipCharSize]; for(uint8_t x=0;xProfile[profile]; // Load stored tip data systemSettings.ProfileChecksum = flashSettings->ProfileChecksum[profile]; // Load stored checksum if(systemSettings.Profile.NotInitialized!=initialized){ // Check if initialized resetCurrentProfile(); // Load defaults if not systemSettings.ProfileChecksum = ChecksumProfile(&systemSettings.Profile); // Compute checksum } // Calculate data checksum and compare with stored checksum, also ensure the stored ID is the same as the requested profile if( (profile!=systemSettings.Profile.ID) || (systemSettings.ProfileChecksum != ChecksumProfile(&systemSettings.Profile)) ){ ProfileChkErr(); // Checksum mismatch, reset current tip data } setUserTemperature(systemSettings.Profile.UserSetTemperature); // Load user set temperature setCurrentTip(systemSettings.Profile.currentTip); // Load TIP data Iron.updatePwm=needs_update; // Apply profile PWM settings } else if(profile==profile_None){ return; // Profiles not initialized, load nothing } else{ // Unknown profile Error_Handler(); } if(systemSettings.settings.tempUnit != systemSettings.Profile.tempUnit){ // If stored temps are in different units setSystemTempUnit(systemSettings.settings.tempUnit); // Convert temperatures systemSettings.Profile.tempUnit = systemSettings.settings.tempUnit; // Store unit in profile } } void Diag_init(void){ setContrast(255); FillBuffer(BLACK,fill_soft); u8g2_SetFont(&u8g2,default_font ); u8g2_SetDrawColor(&u8g2, WHITE); } void Flash_error(void){ __disable_irq(); HAL_FLASH_Lock(); __enable_irq(); Diag_init(); putStrAligned("FLASH ERROR!", 16, align_center); putStrAligned("HALTING SYSTEM", 32, align_center); update_display(); while(1){ HAL_IWDG_Refresh(&hiwdg); } } void settingsChkErr(void){ Diag_init(); systemSettings.settings.OledOffset = 2; // Set default value putStrAligned("SETTING ERR!", 10, align_center); putStrAligned("RESTORING", 26, align_center); putStrAligned("DEFAULTS...", 42, align_center); update_display(); ErrCountDown(3,117,50); if(systemSettings.settings.currentProfile<=profile_C210){ // If current tip type is valid if(systemSettings.ProfileChecksum==ChecksumProfile(&systemSettings.Profile)){ // If current profile checksum is correct uint8_t tip = systemSettings.settings.currentProfile; // save current tip resetSystemSettings(); // reset settings systemSettings.settings.currentProfile=tip; // Restore tip type saveSettings(saveKeepingProfiles); // Save settings preserving tip data } else{ // If checksum wrong resetSystemSettings(); // reset settings saveSettings(saveWipingProfiles); // Save settings erasing tip data } } else{ // If current tip not valid resetSystemSettings(); // Assume something went wrong, reset settings saveSettings(saveKeepingProfiles); // Save keeping tip data } } void ProfileChkErr(void){ Diag_init(); putStrAligned("PROFILE ERR!", 10, align_center); putStrAligned("RESTORING", 26, align_center); putStrAligned("DEFAULTS...", 42, align_center); update_display(); ErrCountDown(3,117,50); resetCurrentProfile(); // Reset current tip type data only } void Button_reset(void){ uint16_t ResetTimer= HAL_GetTick(); if(!BUTTON_input()){ Diag_init(); putStrAligned("HOLD BUTTON", 10, align_center); putStrAligned("TO RESTORE", 26, align_center); putStrAligned("DEFAULTS", 42, align_center); update_display(); while(!BUTTON_input()){ HAL_IWDG_Refresh(&hiwdg); if((HAL_GetTick()-ResetTimer)>5000){ FillBuffer(BLACK,fill_dma); putStrAligned("RELEASE", 16, align_center); putStrAligned("BUTTON NOW", 32, align_center); update_display(); while(!BUTTON_input()){ HAL_IWDG_Refresh(&hiwdg); } resetSystemSettings(); saveSettings(saveWipingProfiles); } } } } //Max 99 seconds countdown. void ErrCountDown(uint8_t Start,uint8_t xpos, uint8_t ypos){ uint32_t timErr = 0; char str[4]; uint8_t length; if(Start>99){Start=99;} if(Start>9){ length=2; } else{ length=1; } HAL_IWDG_Refresh(&hiwdg); while(oled.status!=oled_idle); // Wait for the screen to be idle (few mS at most). Hanging here will cause a watchdog reset. while(Start){ timErr=HAL_GetTick(); u8g2_SetDrawColor(&u8g2, BLACK); u8g2_DrawBox(&u8g2,xpos,ypos,u8g2_GetStrWidth(&u8g2,str),u8g2_GetMaxCharHeight(&u8g2)); u8g2_SetDrawColor(&u8g2, WHITE); sprintf(&str[0],"%*u",length-1,Start--); u8g2_DrawStr(&u8g2,xpos,ypos,str); update_display(); while( (HAL_GetTick()-timErr)<999 ){ HAL_IWDG_Refresh(&hiwdg); // Clear watchdog } } }