From 6cbb01db4114b82bcfb9a3d4e02d3effef211cac Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 22 Nov 2022 18:26:16 +1100 Subject: [PATCH] References --- source/Core/Drivers/Buttons.cpp | 1 + source/Core/Inc/settingsGUI.hpp | 1 - source/Core/Threads/GUIThread.cpp | 954 +----------------- .../Core/Threads/OperatingModes/Soldering.cpp | 5 +- .../utils/checkUndervoltage.cpp | 5 +- .../utils/drawPowerSourceIcon.cpp | 2 +- 6 files changed, 16 insertions(+), 952 deletions(-) diff --git a/source/Core/Drivers/Buttons.cpp b/source/Core/Drivers/Buttons.cpp index 18d4cc6f..4ab8718f 100644 --- a/source/Core/Drivers/Buttons.cpp +++ b/source/Core/Drivers/Buttons.cpp @@ -5,6 +5,7 @@ * Author: Ralim */ #include "FreeRTOS.h" +#include "OperatingModeUtilities.h" #include "settingsGUI.hpp" #include "task.h" #include diff --git a/source/Core/Inc/settingsGUI.hpp b/source/Core/Inc/settingsGUI.hpp index b64e14ea..f0c25297 100644 --- a/source/Core/Inc/settingsGUI.hpp +++ b/source/Core/Inc/settingsGUI.hpp @@ -35,7 +35,6 @@ typedef struct { } menuitem; void enterSettingsMenu(); -void GUIDelay(); void warnUser(const char *warning, const int timeout); extern const menuitem rootSettingsMenu[]; diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index a22b3e78..9f193833 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -13,6 +13,8 @@ extern "C" { #include "LIS2DH12.hpp" #include "MMA8652FC.hpp" #include "OLED.hpp" +#include "OperatingModeUtilities.h" +#include "OperatingModes.h" #include "Settings.h" #include "TipThermoModel.h" #include "Translation.h" @@ -30,956 +32,10 @@ extern "C" { #endif // File local variables -extern TickType_t lastMovementTime; -extern bool heaterThermalRunaway; -extern osThreadId GUITaskHandle; -extern osThreadId MOVTaskHandle; -extern osThreadId PIDTaskHandle; -static bool shouldBeSleeping(bool inAutoStart = false); -static bool shouldShutdown(); -void showWarnings(); +extern bool heaterThermalRunaway; + #define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ) #define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ) -static TickType_t lastHallEffectSleepStart = 0; -static uint16_t min(uint16_t a, uint16_t b) { - if (a > b) - return b; - else - return a; -} - -void warnUser(const char *warning, const int timeout) { - OLED::clearScreen(); - OLED::printWholeScreen(warning); - OLED::refresh(); - waitForButtonPressOrTimeout(timeout); -} - -void printVoltage() { - uint32_t volt = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); - OLED::printNumber(volt / 10, 2, FontStyle::SMALL); - OLED::print(SymbolDot, FontStyle::SMALL); - OLED::printNumber(volt % 10, 1, FontStyle::SMALL); -} -void GUIDelay() { - // Called in all UI looping tasks, - // This limits the re-draw rate to the LCD and also lets the DMA run - // As the gui task can very easily fill this bus with transactions, which will - // prevent the movement detection from running - vTaskDelay(5 * TICKS_10MS); -} -void gui_drawTipTemp(bool symbol, const FontStyle font) { - // Draw tip temp handling unit conversion & tolerance near setpoint - uint32_t Temp = 0; - if (getSettingValue(SettingsOptions::TemperatureInF)) { - Temp = TipThermoModel::getTipInF(); - } else { - Temp = TipThermoModel::getTipInC(); - } - - OLED::printNumber(Temp, 3, font); // Draw the tip temp out - if (symbol) { - if (font == FontStyle::LARGE) { - // Big font, can draw nice symbols - if (getSettingValue(SettingsOptions::TemperatureInF)) - OLED::drawSymbol(0); - else - OLED::drawSymbol(1); - } else { - // Otherwise fall back to chars - if (getSettingValue(SettingsOptions::TemperatureInF)) - OLED::print(SymbolDegF, FontStyle::SMALL); - else - OLED::print(SymbolDegC, FontStyle::SMALL); - } - } -} -void performCJCC() { - // Calibrate Cold Junction Compensation directly at boot, before internal components get warm. - OLED::refresh(); - osDelay(50); - if (!isTipDisconnected() && (TipThermoModel::getTipInC() - getHandleTemperature(0) / 10) < 10) { - uint16_t setoffset = 0; - // If the thermo-couple at the end of the tip, and the handle are at - // equilibrium, then the output should be zero, as there is no temperature - // differential. - while (setoffset == 0) { - uint32_t offset = 0; - for (uint8_t i = 0; i < 16; i++) { - offset += getTipRawTemp(1); - // cycle through the filter a fair bit to ensure we're stable. - OLED::clearScreen(); - OLED::setCursor(0, 0); - OLED::print(SymbolDot, FontStyle::LARGE); - for (uint8_t x = 0; x < (i / 4); x++) - OLED::print(SymbolDot, FontStyle::LARGE); - OLED::refresh(); - osDelay(100); - } - setoffset = TipThermoModel::convertTipRawADCTouV(offset / 16, true); - } - setSettingValue(SettingsOptions::CalibrationOffset, setoffset); - OLED::clearScreen(); - OLED::setCursor(0, 0); - OLED::drawCheckbox(true); - OLED::printNumber(setoffset, 5, FontStyle::LARGE); - OLED::refresh(); - osDelay(1200); - // Preventing to repeat calibration at boot automatically (only one shot). - setSettingValue(SettingsOptions::CalibrateCJC, 0); - saveSettings(); - } -} - -#ifdef POW_DC -// returns true if undervoltage has occured -static bool checkVoltageForExit() { - if (!getIsPoweredByDCIN()) { - return false; - } - uint16_t v = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); - - // Dont check for first 2 seconds while the ADC stabilizes and the DMA fills - // the buffer - if (xTaskGetTickCount() > (TICKS_SECOND * 2)) { - if ((v < lookupVoltageLevel())) { - currentTempTargetDegC = 0; - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (getSettingValue(SettingsOptions::DetailedSoldering)) { - OLED::print(translatedString(Tr->UndervoltageString), FontStyle::SMALL); - OLED::setCursor(0, 8); - OLED::print(translatedString(Tr->InputVoltageString), FontStyle::SMALL); - printVoltage(); - OLED::print(SymbolVolts, FontStyle::SMALL); - } else { - OLED::print(translatedString(Tr->UVLOWarningString), FontStyle::LARGE); - } - - OLED::refresh(); - GUIDelay(); - waitForButtonPress(); - return true; - } - } - return false; -} -#endif -static void gui_drawBatteryIcon() { -#if defined(POW_PD) || defined(POW_QC) - if (!getIsPoweredByDCIN()) { - // On non-DC inputs we replace this symbol with the voltage we are operating on - // If <9V then show single digit, if not show dual small ones vertically stacked - uint16_t V = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); - if (V % 10 >= 5) - V = (V / 10) + 1; // round up - else - V = V / 10; - if (V > 9) { - int16_t xPos = OLED::getCursorX(); - OLED::printNumber(V / 10, 1, FontStyle::SMALL); - OLED::setCursor(xPos, 8); - OLED::printNumber(V % 10, 1, FontStyle::SMALL); - OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char - } else { - OLED::printNumber(V, 1, FontStyle::LARGE); - } - return; - } -#endif -#ifdef POW_DC - if (getSettingValue(SettingsOptions::MinDCVoltageCells)) { - // User is on a lithium battery - // we need to calculate which of the 10 levels they are on - uint8_t cellCount = getSettingValue(SettingsOptions::MinDCVoltageCells) + 2; - uint32_t cellV = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0) / cellCount; - // Should give us approx cell voltage X10 - // Range is 42 -> Minimum voltage setting (systemSettings.minVoltageCells) = 9 steps therefore we will use battery 0-9 - if (cellV < getSettingValue(SettingsOptions::MinVoltageCells)) - cellV = getSettingValue(SettingsOptions::MinVoltageCells); - cellV -= getSettingValue(SettingsOptions::MinVoltageCells); // Should leave us a number of 0-9 - if (cellV > 9) - cellV = 9; - OLED::drawBattery(cellV + 1); - } else { - OLED::drawSymbol(15); // Draw the DC Logo - } -#endif -} -static void gui_solderingTempAdjust() { - TickType_t lastChange = xTaskGetTickCount(); - currentTempTargetDegC = 0; // Turn off heater while adjusting temp - TickType_t autoRepeatTimer = 0; - uint8_t autoRepeatAcceleration = 0; - bool waitForRelease = false; - ButtonState buttons = getButtonState(); - if (buttons != BUTTON_NONE) { - // Temp adjust entered by long-pressing F button. - waitForRelease = true; - } - for (;;) { - OLED::setCursor(0, 0); - OLED::clearScreen(); - buttons = getButtonState(); - if (buttons) { - if (waitForRelease) { - buttons = BUTTON_NONE; - } - lastChange = xTaskGetTickCount(); - } else { - waitForRelease = false; - } - int16_t delta = 0; - switch (buttons) { - case BUTTON_NONE: - // stay - autoRepeatAcceleration = 0; - break; - case BUTTON_BOTH: - // exit - return; - break; - case BUTTON_B_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - delta = -getSettingValue(SettingsOptions::TempChangeLongStep); - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_B_SHORT: - delta = -getSettingValue(SettingsOptions::TempChangeShortStep); - break; - case BUTTON_F_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - delta = getSettingValue(SettingsOptions::TempChangeLongStep); - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_F_SHORT: - delta = getSettingValue(SettingsOptions::TempChangeShortStep); - break; - default: - break; - } - if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) { - autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; - } - // If buttons are flipped; flip the delta - if (getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled)) { - delta = -delta; - } - if (delta != 0) { - // constrain between the set temp limits, i.e. 10-450 C - int16_t newTemp = getSettingValue(SettingsOptions::SolderingTemp); - newTemp += delta; - // Round to nearest increment of delta - delta = abs(delta); - newTemp = (newTemp / delta) * delta; - - if (getSettingValue(SettingsOptions::TemperatureInF)) { - if (newTemp > MAX_TEMP_F) - newTemp = MAX_TEMP_F; - if (newTemp < MIN_TEMP_F) - newTemp = MIN_TEMP_F; - } else { - if (newTemp > MAX_TEMP_C) - newTemp = MAX_TEMP_C; - if (newTemp < MIN_TEMP_C) - newTemp = MIN_TEMP_C; - } - setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp); - } - if (xTaskGetTickCount() - lastChange > (TICKS_SECOND * 2)) - return; // exit if user just doesn't press anything for a bit - - if (OLED::getRotation()) { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? SymbolPlus : SymbolMinus, FontStyle::LARGE); - } else { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? SymbolMinus : SymbolPlus, FontStyle::LARGE); - } - - OLED::print(SymbolSpace, FontStyle::LARGE); - OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE); - if (getSettingValue(SettingsOptions::TemperatureInF)) - OLED::drawSymbol(0); - else { - OLED::drawSymbol(1); - } - OLED::print(SymbolSpace, FontStyle::LARGE); - if (OLED::getRotation()) { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? SymbolMinus : SymbolPlus, FontStyle::LARGE); - } else { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? SymbolPlus : SymbolMinus, FontStyle::LARGE); - } - OLED::refresh(); - GUIDelay(); - } -} -static bool shouldShutdown() { - if (getSettingValue(SettingsOptions::ShutdownTime)) { // only allow shutdown exit if time > 0 - if (lastMovementTime) { - if (((TickType_t)(xTaskGetTickCount() - lastMovementTime)) > (TickType_t)(getSettingValue(SettingsOptions::ShutdownTime) * TICKS_MIN)) { - return true; - } - } - if (lastHallEffectSleepStart) { - if (((TickType_t)(xTaskGetTickCount() - lastHallEffectSleepStart)) > (TickType_t)(getSettingValue(SettingsOptions::ShutdownTime) * TICKS_MIN)) { - return true; - } - } - } - if (getButtonState() == BUTTON_B_LONG) { // allow also if back button is pressed long - return true; - } - return false; -} -static int gui_SolderingSleepingMode(bool stayOff, bool autoStarted) { - // Drop to sleep temperature and display until movement or button press - - for (;;) { - // user moved or pressed a button, go back to soldering - // If in the first two seconds we disable this to let accelerometer warm up - -#ifdef POW_DC - if (checkVoltageForExit()) - return 1; // return non-zero on error -#endif - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp))); - } else { - currentTempTargetDegC = stayOff ? 0 : min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp)); - } - // draw the lcd - uint16_t tipTemp; - if (getSettingValue(SettingsOptions::TemperatureInF)) - tipTemp = TipThermoModel::getTipInF(); - else { - tipTemp = TipThermoModel::getTipInC(); - } - - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (getSettingValue(SettingsOptions::DetailedSoldering)) { - OLED::print(translatedString(Tr->SleepingAdvancedString), FontStyle::SMALL); - OLED::setCursor(0, 8); - OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL); - OLED::printNumber(tipTemp, 3, FontStyle::SMALL); - if (getSettingValue(SettingsOptions::TemperatureInF)) - OLED::print(SymbolDegF, FontStyle::SMALL); - else { - OLED::print(SymbolDegC, FontStyle::SMALL); - } - - OLED::print(SymbolSpace, FontStyle::SMALL); - printVoltage(); - OLED::print(SymbolVolts, FontStyle::SMALL); - } else { - OLED::print(translatedString(Tr->SleepingSimpleString), FontStyle::LARGE); - OLED::printNumber(tipTemp, 3, FontStyle::LARGE); - if (getSettingValue(SettingsOptions::TemperatureInF)) - OLED::drawSymbol(0); - else { - OLED::drawSymbol(1); - } - } - - OLED::refresh(); - GUIDelay(); - - if (!shouldBeSleeping(autoStarted)) { - return 0; - } - - if (shouldShutdown()) { - // shutdown - currentTempTargetDegC = 0; - return 1; // we want to exit soldering mode - } - } - return 0; -} -#ifndef NO_SLEEP_MODE - -static void display_countdown(int sleepThres) { - /* - * Print seconds or minutes (if > 99 seconds) until sleep - * mode is triggered. - */ - TickType_t lastEventTime = lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime; - TickType_t downCount = sleepThres - xTaskGetTickCount() + lastEventTime; - if (downCount > (99 * TICKS_SECOND)) { - OLED::printNumber(downCount / 60000 + 1, 2, FontStyle::SMALL); - OLED::print(SymbolMinutes, FontStyle::SMALL); - } else { - OLED::printNumber(downCount / 1000 + 1, 2, FontStyle::SMALL); - OLED::print(SymbolSeconds, FontStyle::SMALL); - } -} -static uint32_t getSleepTimeout() { - - if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) { - - uint32_t sleepThres = 0; - if (getSettingValue(SettingsOptions::SleepTime) < 6) - sleepThres = getSettingValue(SettingsOptions::SleepTime) * 10 * 1000; - else - sleepThres = (getSettingValue(SettingsOptions::SleepTime) - 5) * 60 * 1000; - return sleepThres; - } - return 0; -} -#endif -static bool shouldBeSleeping(bool inAutoStart) { -#ifndef NO_SLEEP_MODE - // Return true if the iron should be in sleep mode - if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) { - if (inAutoStart) { - // In auto start we are asleep until movement - if (lastMovementTime == 0 && lastButtonTime == 0) { - return true; - } - } - if (lastMovementTime > 0 || lastButtonTime > 0) { - if (((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout()) && ((xTaskGetTickCount() - lastButtonTime) > getSleepTimeout())) { - return true; - } - } - } - -#ifdef HALL_SENSOR - // If the hall effect sensor is enabled in the build, check if its over - // threshold, and if so then we force sleep - if (getHallSensorFitted() && lookupHallEffectThreshold()) { - int16_t hallEffectStrength = getRawHallEffect(); - if (hallEffectStrength < 0) - hallEffectStrength = -hallEffectStrength; - // Have absolute value of measure of magnetic field strength - if (hallEffectStrength > lookupHallEffectThreshold()) { - if (lastHallEffectSleepStart == 0) { - lastHallEffectSleepStart = xTaskGetTickCount(); - } - if ((xTaskGetTickCount() - lastHallEffectSleepStart) > TICKS_SECOND) { - return true; - } - } else { - lastHallEffectSleepStart = 0; - } - } -#endif -#endif - return false; -} -static void gui_solderingMode(uint8_t jumpToSleep) { - /* - * * Soldering (gui_solderingMode) - * -> Main loop where we draw temp, and animations - * --> User presses buttons and they goto the temperature adjust screen - * ---> Display the current setpoint temperature - * ---> Use buttons to change forward and back on temperature - * ---> Both buttons or timeout for exiting - * --> Long hold front button to enter boost mode - * ---> Just temporarily sets the system into the alternate temperature for - * PID control - * --> Long hold back button to exit - * --> Double button to exit - * --> Long hold double button to toggle key lock - */ - bool boostModeOn = false; - bool buttonsLocked = false; - - if (jumpToSleep) { - if (gui_SolderingSleepingMode(jumpToSleep == 2, true) == 1) { - lastButtonTime = xTaskGetTickCount(); - return; // If the function returns non-0 then exit - } - } - for (;;) { - ButtonState buttons = getButtonState(); - if (buttonsLocked && (getSettingValue(SettingsOptions::LockingMode) != 0)) { // If buttons locked - switch (buttons) { - case BUTTON_NONE: - boostModeOn = false; - break; - case BUTTON_BOTH_LONG: - // Unlock buttons - buttonsLocked = false; - warnUser(translatedString(Tr->UnlockingKeysString), TICKS_SECOND); - break; - case BUTTON_F_LONG: - // if boost mode is enabled turn it on - if (getSettingValue(SettingsOptions::BoostTemp) && (getSettingValue(SettingsOptions::LockingMode) == 1)) { - boostModeOn = true; - } - break; - // fall through - case BUTTON_BOTH: - case BUTTON_B_LONG: - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: - // Do nothing and display a lock warning - warnUser(translatedString(Tr->WarningKeysLockedString), TICKS_SECOND / 2); - break; - default: - break; - } - } else { // Button not locked - switch (buttons) { - case BUTTON_NONE: - // stay - boostModeOn = false; - break; - case BUTTON_BOTH: - case BUTTON_B_LONG: - return; // exit on back long hold - case BUTTON_F_LONG: - // if boost mode is enabled turn it on - if (getSettingValue(SettingsOptions::BoostTemp)) - boostModeOn = true; - break; - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: { - uint16_t oldTemp = getSettingValue(SettingsOptions::SolderingTemp); - gui_solderingTempAdjust(); // goto adjust temp mode - if (oldTemp != getSettingValue(SettingsOptions::SolderingTemp)) { - saveSettings(); // only save on change - } - } break; - case BUTTON_BOTH_LONG: - if (getSettingValue(SettingsOptions::LockingMode) != 0) { - // Lock buttons - buttonsLocked = true; - warnUser(translatedString(Tr->LockingKeysString), TICKS_SECOND); - } - break; - default: - break; - } - } - // else we update the screen information - - OLED::clearScreen(); - - // Draw in the screen details - if (getSettingValue(SettingsOptions::DetailedSoldering)) { - if (OLED::getRotation()) { - OLED::setCursor(50, 0); - } else { - OLED::setCursor(-1, 0); - } - gui_drawTipTemp(true, FontStyle::LARGE); - -#ifndef NO_SLEEP_MODE - if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) { - if (OLED::getRotation()) { - OLED::setCursor(32, 0); - } else { - OLED::setCursor(47, 0); - } - display_countdown(getSleepTimeout()); - } -#endif - - if (boostModeOn) { - if (OLED::getRotation()) { - OLED::setCursor(38, 8); - } else { - OLED::setCursor(55, 8); - } - OLED::print(SymbolPlus, FontStyle::SMALL); - } - - if (OLED::getRotation()) { - OLED::setCursor(0, 0); - } else { - OLED::setCursor(67, 0); - } - OLED::printNumber(x10WattHistory.average() / 10, 2, FontStyle::SMALL); - OLED::print(SymbolDot, FontStyle::SMALL); - OLED::printNumber(x10WattHistory.average() % 10, 1, FontStyle::SMALL); - OLED::print(SymbolWatts, FontStyle::SMALL); - - if (OLED::getRotation()) { - OLED::setCursor(0, 8); - } else { - OLED::setCursor(67, 8); - } - printVoltage(); - OLED::print(SymbolVolts, FontStyle::SMALL); - } else { - OLED::setCursor(0, 0); - // We switch the layout direction depending on the orientation of the oled - if (OLED::getRotation()) { - // battery - gui_drawBatteryIcon(); - OLED::print(SymbolSpace, FontStyle::LARGE); // Space out gap between battery <-> temp - gui_drawTipTemp(true, FontStyle::LARGE); // Draw current tip temp - - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace, FontStyle::LARGE); - - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - } else { - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace, FontStyle::LARGE); - gui_drawTipTemp(true, FontStyle::LARGE); // Draw current tip temp - - OLED::print(SymbolSpace, FontStyle::LARGE); // Space out gap between battery <-> temp - - gui_drawBatteryIcon(); - } - } - OLED::refresh(); - // Update the setpoints for the temperature - if (boostModeOn) { - if (getSettingValue(SettingsOptions::TemperatureInF)) - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp)); - else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); - } - } else { - if (getSettingValue(SettingsOptions::TemperatureInF)) - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp)); - else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp)); - } - } - -#ifdef POW_DC - // Undervoltage test - if (checkVoltageForExit()) { - lastButtonTime = xTaskGetTickCount(); - return; - } -#endif - -#ifdef ACCEL_EXITS_ON_MOVEMENT - // If the accel works in reverse where movement will cause exiting the soldering mode - if (getSettingValue(SettingsOptions::Sensitivity)) { - if (lastMovementTime) { - if (lastMovementTime > TICKS_SECOND * 10) { - // If we have moved recently; in the last second - // Then exit soldering mode - - if (((TickType_t)(xTaskGetTickCount() - lastMovementTime)) < (TickType_t)(TICKS_SECOND)) { - currentTempTargetDegC = 0; - return; - } - } - } - } -#endif -#ifdef NO_SLEEP_MODE - // No sleep mode, but still want shutdown timeout - - if (shouldShutdown()) { - // shutdown - currentTempTargetDegC = 0; - return; // we want to exit soldering mode - } -#endif - if (shouldBeSleeping()) { - if (gui_SolderingSleepingMode(false, false)) { - return; // If the function returns non-0 then exit - } - } - // Update LED status - int error = currentTempTargetDegC - TipThermoModel::getTipInC(); - if (error >= -10 && error <= 10) { - // converged - setStatusLED(LED_HOT); - } else { - setStatusLED(LED_HEATING); - } - // If we have tripped thermal runaway, turn off heater and show warning - if (heaterThermalRunaway) { - currentTempTargetDegC = 0; // heater control off - warnUser(translatedString(Tr->WarningThermalRunaway), 10 * TICKS_SECOND); - heaterThermalRunaway = false; - return; - } - // slow down ui update rate - GUIDelay(); - } -} - -void showDebugMenu(void) { - uint8_t screen = 0; - ButtonState b; - for (;;) { - OLED::clearScreen(); // Ensure the buffer starts clean - OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) - OLED::print(SymbolVersionNumber, FontStyle::SMALL); // Print version number - OLED::setCursor(0, 8); // second line - OLED::print(DebugMenu[screen], FontStyle::SMALL); - switch (screen) { - case 0: // Build Date - break; - case 1: // Device ID - { - uint64_t id = getDeviceID(); -#ifdef DEVICE_HAS_VALIDATION_CODE - // If device has validation code; then we want to take over both lines of the screen - OLED::clearScreen(); // Ensure the buffer starts clean - OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) - OLED::print(DebugMenu[screen], FontStyle::SMALL); - OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8); - OLED::setCursor(0, 8); // second line -#endif - OLED::drawHex((uint32_t)(id >> 32), FontStyle::SMALL, 8); - OLED::drawHex((uint32_t)(id & 0xFFFFFFFF), FontStyle::SMALL, 8); - } - break; - case 2: // ACC Type - OLED::print(AccelTypeNames[(int)DetectedAccelerometerVersion], FontStyle::SMALL); - break; - case 3: // Power Negotiation Status - { - int sourceNumber = 0; - if (getIsPoweredByDCIN()) { - sourceNumber = 0; - } else { - // We are not powered via DC, so want to display the appropriate state for PD or QC - bool poweredbyPD = false; - bool pdHasVBUSConnected = false; -#if POW_PD - if (USBPowerDelivery::fusbPresent()) { - // We are PD capable - if (USBPowerDelivery::negotiationComplete()) { - // We are powered via PD - poweredbyPD = true; -#ifdef VBUS_MOD_TEST - pdHasVBUSConnected = USBPowerDelivery::isVBUSConnected(); -#endif - } - } -#endif - if (poweredbyPD) { - - if (pdHasVBUSConnected) { - sourceNumber = 2; - } else { - sourceNumber = 3; - } - } else { - sourceNumber = 1; - } - } - OLED::print(PowerSourceNames[sourceNumber], FontStyle::SMALL); - } - break; - case 4: // Input Voltage - printVoltage(); - break; - case 5: // Temp in °C - OLED::printNumber(TipThermoModel::getTipInC(), 6, FontStyle::SMALL); - break; - case 6: // Handle Temp in °C - OLED::printNumber(getHandleTemperature(0) / 10, 6, FontStyle::SMALL); - OLED::print(SymbolDot, FontStyle::SMALL); - OLED::printNumber(getHandleTemperature(0) % 10, 1, FontStyle::SMALL); - break; - case 7: // Max Temp Limit in °C - OLED::printNumber(TipThermoModel::getTipMaxInC(), 6, FontStyle::SMALL); - break; - case 8: // System Uptime - OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 8, FontStyle::SMALL); - break; - case 9: // Movement Timestamp - OLED::printNumber(lastMovementTime / TICKS_100MS, 8, FontStyle::SMALL); - break; - case 10: // Tip Resistance in Ω - OLED::printNumber(getTipResistanceX10() / 10, 6, FontStyle::SMALL); // large to pad over so that we cover ID left overs - OLED::print(SymbolDot, FontStyle::SMALL); - OLED::printNumber(getTipResistanceX10() % 10, 1, FontStyle::SMALL); - break; - case 11: // Raw Tip in µV - OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), 8, FontStyle::SMALL); - break; - case 12: // Tip Cold Junction Compensation Offset in µV - OLED::printNumber(getSettingValue(SettingsOptions::CalibrationOffset), 8, FontStyle::SMALL); - break; - case 13: // High Water Mark for GUI - OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 8, FontStyle::SMALL); - break; - case 14: // High Water Mark for Movement Task - OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 8, FontStyle::SMALL); - break; - case 15: // High Water Mark for PID Task - OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 8, FontStyle::SMALL); - break; - break; -#ifdef HALL_SENSOR - case 16: // Raw Hall Effect Value - { - int16_t hallEffectStrength = getRawHallEffect(); - if (hallEffectStrength < 0) - hallEffectStrength = -hallEffectStrength; - OLED::printNumber(hallEffectStrength, 6, FontStyle::SMALL); - } - break; -#endif - - default: - break; - } - - OLED::refresh(); - b = getButtonState(); - if (b == BUTTON_B_SHORT) - return; - else if (b == BUTTON_F_SHORT) { - screen++; -#ifdef HALL_SENSOR - screen = screen % 17; -#else - screen = screen % 16; -#endif - } - GUIDelay(); - } -} - -#if POW_PD -#ifdef HAS_POWER_DEBUG_MENU -static void showPDDebug(void) { - // Print out the USB-PD state - // Basically this is like the Debug menu, but instead we want to print out the PD status - uint8_t screen = 0; - ButtonState b; - for (;;) { - OLED::clearScreen(); // Ensure the buffer starts clean - OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) - OLED::print(SymbolPDDebug, FontStyle::SMALL); // Print Title - OLED::setCursor(0, 8); // second line - if (screen == 0) { - // Print the PD state machine - OLED::print(SymbolState, FontStyle::SMALL); - OLED::print(SymbolSpace, FontStyle::SMALL); - OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true); - OLED::print(SymbolSpace, FontStyle::SMALL); - // Also print vbus mod status - if (USBPowerDelivery::fusbPresent()) { - if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) { - if (!USBPowerDelivery::isVBUSConnected()) { - OLED::print(SymbolNoVBus, FontStyle::SMALL); - } else { - OLED::print(SymbolVBus, FontStyle::SMALL); - } - } - } - } else { - // Print out the Proposed power options one by one - auto lastCaps = USBPowerDelivery::getLastSeenCapabilities(); - if ((screen - 1) < 11) { - int voltage_mv = 0; - int min_voltage = 0; - int current_a_x100 = 0; - int wattage = 0; - - if ((lastCaps[screen - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { - voltage_mv = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(lastCaps[screen - 1])); // voltage in mV units - current_a_x100 = PD_PDO_SRC_FIXED_CURRENT_GET(lastCaps[screen - 1]); // current in 10mA units - } else if ((lastCaps[screen - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED) { - voltage_mv = PD_PAV2MV(PD_APDO_AVS_MAX_VOLTAGE_GET(lastCaps[screen - 1])); - min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCaps[screen - 1])); - // Last value is wattage - wattage = PD_APDO_AVS_MAX_POWER_GET(lastCaps[screen - 1]); - } else { - voltage_mv = PD_PAV2MV(PD_APDO_PPS_MAX_VOLTAGE_GET(lastCaps[screen - 1])); - min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCaps[screen - 1])); - current_a_x100 = PD_PAI2CA(PD_APDO_PPS_CURRENT_GET(lastCaps[screen - 1])); // max current in 10mA units - } - // Skip not used entries - if (voltage_mv == 0) { - screen++; - } else { - // print out this entry of the proposal - OLED::printNumber(screen, 2, FontStyle::SMALL, true); // print the entry number - OLED::print(SymbolSpace, FontStyle::SMALL); - if (min_voltage > 0) { - OLED::printNumber(min_voltage / 1000, 2, FontStyle::SMALL, true); // print the voltage - OLED::print(SymbolMinus, FontStyle::SMALL); - } - OLED::printNumber(voltage_mv / 1000, 2, FontStyle::SMALL, true); // print the voltage - OLED::print(SymbolVolts, FontStyle::SMALL); - OLED::print(SymbolSpace, FontStyle::SMALL); - if (wattage) { - OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res - OLED::print(SymbolWatts, FontStyle::SMALL); - } else { - OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res - OLED::print(SymbolDot, FontStyle::SMALL); - OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res - OLED::print(SymbolAmps, FontStyle::SMALL); - } - } - } else { - screen = 0; - } - } - - OLED::refresh(); - b = getButtonState(); - if (b == BUTTON_B_SHORT) - return; - else if (b == BUTTON_F_SHORT) { - screen++; - } - GUIDelay(); - } -} -#endif -#endif -void showWarnings() { - // Display alert if settings were reset - if (settingsWereReset) { - warnUser(translatedString(Tr->SettingsResetMessage), 10 * TICKS_SECOND); - } -#ifdef DEVICE_HAS_VALIDATION_SUPPORT - if (getDeviceValidationStatus()) { - // Warn user this device might be counterfeit - warnUser(translatedString(Tr->DeviceFailedValidationWarning), 10 * TICKS_SECOND); - } -#endif -#ifndef NO_WARN_MISSING - // We also want to alert if accel or pd is not detected / not responding - // In this case though, we dont want to nag the user _too_ much - // So only show first 2 times - while (DetectedAccelerometerVersion == AccelType::Scanning) { - osDelay(5); - } - // Display alert if accelerometer is not detected - if (DetectedAccelerometerVersion == AccelType::None) { - if (getSettingValue(SettingsOptions::AccelMissingWarningCounter) < 2) { - nextSettingValue(SettingsOptions::AccelMissingWarningCounter); - saveSettings(); - warnUser(translatedString(Tr->NoAccelerometerMessage), 10 * TICKS_SECOND); - } - } -#if POW_PD - // We expect pd to be present - if (!USBPowerDelivery::fusbPresent()) { - if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { - nextSettingValue(SettingsOptions::PDMissingWarningCounter); - saveSettings(); - warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND); - } - } -#endif -#endif -} uint8_t buttonAF[sizeof(buttonA)]; uint8_t buttonBF[sizeof(buttonB)]; @@ -1116,6 +172,8 @@ void startGUITask(void const *argument) { && (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { OLED::setDisplayState(OLED::DisplayState::OFF); setStatusLED(LED_OFF); + } else { + OLED::setDisplayState(OLED::DisplayState::ON); } // Clear the lcd buffer OLED::clearScreen(); diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index 16746f58..41473869 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -1,5 +1,8 @@ #include "OperatingModes.h" + +extern bool heaterThermalRunaway; + void gui_solderingMode(uint8_t jumpToSleep) { /* * * Soldering (gui_solderingMode) @@ -219,7 +222,7 @@ void gui_solderingMode(uint8_t jumpToSleep) { return; // we want to exit soldering mode } #endif - if (shouldBeSleeping()) { + if (shouldBeSleeping(false)) { if (gui_SolderingSleepingMode(false, false)) { return; // If the function returns non-0 then exit } diff --git a/source/Core/Threads/OperatingModes/utils/checkUndervoltage.cpp b/source/Core/Threads/OperatingModes/utils/checkUndervoltage.cpp index b95359f6..d2eabc24 100644 --- a/source/Core/Threads/OperatingModes/utils/checkUndervoltage.cpp +++ b/source/Core/Threads/OperatingModes/utils/checkUndervoltage.cpp @@ -1,5 +1,8 @@ - +#include "Buttons.hpp" +#include "OperatingModeUtilities.h" +#include "configuration.h" #ifdef POW_DC +extern volatile uint32_t currentTempTargetDegC; // returns true if undervoltage has occured bool checkForUnderVoltage(void) { if (!getIsPoweredByDCIN()) { diff --git a/source/Core/Threads/OperatingModes/utils/drawPowerSourceIcon.cpp b/source/Core/Threads/OperatingModes/utils/drawPowerSourceIcon.cpp index 4eb01000..f30687e4 100644 --- a/source/Core/Threads/OperatingModes/utils/drawPowerSourceIcon.cpp +++ b/source/Core/Threads/OperatingModes/utils/drawPowerSourceIcon.cpp @@ -1,6 +1,6 @@ #include "OperatingModeUtilities.h" -static void gui_drawBatteryIcon() { +void gui_drawBatteryIcon(void) { #if defined(POW_PD) || defined(POW_QC) if (!getIsPoweredByDCIN()) { // On non-DC inputs we replace this symbol with the voltage we are operating on