/* * GUIThread.cpp * * Created on: 19 Aug 2019 * Author: ralim */ extern "C" { #include "FreeRTOSConfig.h" } #include "BootLogo.h" #include "Buttons.hpp" #include "I2CBB.hpp" #include "LIS2DH12.hpp" #include "MMA8652FC.hpp" #include "OLED.hpp" #include "OperatingModeUtilities.h" #include "OperatingModes.h" #include "Settings.h" #include "TipThermoModel.h" #include "Translation.h" #include "cmsis_os.h" #include "configuration.h" #include "history.hpp" #include "main.hpp" #include "power.hpp" #include "settingsGUI.hpp" #include "stdlib.h" #include "string.h" #if POW_PD #include "USBPD.h" #include "pd.h" #endif // File local variables extern bool heaterThermalRunaway; #define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ) #define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ) uint8_t buttonAF[sizeof(buttonA)]; uint8_t buttonBF[sizeof(buttonB)]; uint8_t disconnectedTipF[sizeof(disconnectedTip)]; /* StartGUITask function */ void startGUITask(void const *argument) { (void)argument; prepareTranslations(); OLED::initialize(); // start up the LCD OLED::setBrightness(getSettingValue(SettingsOptions::OLEDBrightness)); OLED::setInverseDisplay(getSettingValue(SettingsOptions::OLEDInversion)); uint8_t tempWarningState = 0; bool buttonLockout = false; bool tempOnDisplay = false; bool tipDisconnectedDisplay = false; bool showExitMenuTransition = false; { // Generate the flipped screen into ram for later use // flipped is generated by flipping each row for (int row = 0; row < 2; row++) { for (int x = 0; x < 42; x++) { buttonAF[(row * 42) + x] = buttonA[(row * 42) + (41 - x)]; buttonBF[(row * 42) + x] = buttonB[(row * 42) + (41 - x)]; disconnectedTipF[(row * 42) + x] = disconnectedTip[(row * 42) + (41 - x)]; } } } getTipRawTemp(1); // reset filter OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1); // If the front button is held down, on supported devices, show PD debugging metrics #if POW_PD #ifdef HAS_POWER_DEBUG_MENU if (getButtonA()) { showPDDebug(); } #endif #endif if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) { performCJCC(); } // If the boot logo is enabled (but it times out) and the autostart mode is enabled (but not set to sleep w/o heat), start heating during boot logo if (getSettingValue(SettingsOptions::LOGOTime) > 0 && getSettingValue(SettingsOptions::LOGOTime) < 5 && getSettingValue(SettingsOptions::AutoStartMode) > 0 && getSettingValue(SettingsOptions::AutoStartMode) < 3) { uint16_t sleepTempDegC; if (getSettingValue(SettingsOptions::TemperatureInF)) { sleepTempDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SleepTemp)); } else { sleepTempDegC = getSettingValue(SettingsOptions::SleepTemp); } // Only heat to sleep temperature (but no higher than 75°C for safety) currentTempTargetDegC = min(sleepTempDegC, 75); } BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); showWarnings(); if (getSettingValue(SettingsOptions::AutoStartMode)) { // jump directly to the autostart mode gui_solderingMode(getSettingValue(SettingsOptions::AutoStartMode) - 1); buttonLockout = true; } for (;;) { ButtonState buttons = getButtonState(); if (buttons != BUTTON_NONE) { OLED::setDisplayState(OLED::DisplayState::ON); } if (tempWarningState == 2) buttons = BUTTON_F_SHORT; if (buttons != BUTTON_NONE && buttonLockout) buttons = BUTTON_NONE; else buttonLockout = false; switch (buttons) { case BUTTON_NONE: // Do nothing break; case BUTTON_BOTH: // Not used yet // In multi-language this might be used to reset language on a long hold // or some such break; case BUTTON_B_LONG: // Show the version information showDebugMenu(); break; case BUTTON_F_LONG: gui_solderingTempAdjust(); saveSettings(); break; case BUTTON_F_SHORT: if (!isTipDisconnected()) { gui_solderingMode(0); // enter soldering mode buttonLockout = true; } break; case BUTTON_B_SHORT: enterSettingsMenu(); // enter the settings menu { OLED::useSecondaryFramebuffer(true); showExitMenuTransition = true; } buttonLockout = true; break; default: break; } currentTempTargetDegC = 0; // ensure tip is off getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); uint32_t tipTemp = TipThermoModel::getTipInC(); if (tipTemp > 55) { setStatusLED(LED_COOLING_STILL_HOT); } else { setStatusLED(LED_STANDBY); } // Preemptively turn the display on. Turn it off if and only if // the tip temperature is below 50 degrees C *and* motion sleep // detection is enabled *and* there has been no activity (movement or // button presses) in a while. // This is zero cost really as state is only changed on display updates OLED::setDisplayState(OLED::DisplayState::ON); if ((tipTemp < 50) && getSettingValue(SettingsOptions::Sensitivity) && (((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(); if (OLED::getRotation()) { OLED::setCursor(50, 0); } else { OLED::setCursor(-1, 0); } if (getSettingValue(SettingsOptions::DetailedIDLE)) { if (isTipDisconnected()) { if (OLED::getRotation()) { // in right handed mode we want to draw over the first part OLED::drawArea(54, 0, 42, 16, disconnectedTipF); } else { OLED::drawArea(0, 0, 42, 16, disconnectedTip); } if (OLED::getRotation()) { OLED::setCursor(-1, 0); } else { OLED::setCursor(42, 0); } uint32_t Vlt = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); OLED::printNumber(Vlt / 10, 2, FontStyle::LARGE); OLED::print(SymbolDot, FontStyle::LARGE); OLED::printNumber(Vlt % 10, 1, FontStyle::LARGE); if (OLED::getRotation()) { OLED::setCursor(48, 8); } else { OLED::setCursor(91, 8); } OLED::print(SymbolVolts, FontStyle::SMALL); } else { if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (tipTemp > 55) && (xTaskGetTickCount() % 1000 < 300))) // Blink temp if setting enable and temp < 55° // 1000 tick/sec // OFF 300ms ON 700ms gui_drawTipTemp(true, FontStyle::LARGE); // draw in the temp if (OLED::getRotation()) { OLED::setCursor(6, 0); } else { OLED::setCursor(73, 0); // top right } OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::SMALL); // draw set temp if (getSettingValue(SettingsOptions::TemperatureInF)) OLED::print(SymbolDegF, FontStyle::SMALL); else OLED::print(SymbolDegC, FontStyle::SMALL); if (OLED::getRotation()) { OLED::setCursor(0, 8); } else { OLED::setCursor(67, 8); // bottom right } printVoltage(); // draw voltage then symbol (v) OLED::print(SymbolVolts, FontStyle::SMALL); } } else { if (OLED::getRotation()) { OLED::drawArea(54, 0, 42, 16, buttonAF); OLED::drawArea(12, 0, 42, 16, buttonBF); OLED::setCursor(0, 0); gui_drawBatteryIcon(); } else { OLED::drawArea(0, 0, 42, 16, buttonA); // Needs to be flipped so button ends up OLED::drawArea(42, 0, 42, 16, buttonB); // on right side of screen OLED::setCursor(84, 0); gui_drawBatteryIcon(); } tipDisconnectedDisplay = false; if (tipTemp > 55) tempOnDisplay = true; else if (tipTemp < 45) tempOnDisplay = false; if (isTipDisconnected()) { tempOnDisplay = false; tipDisconnectedDisplay = true; } if (tempOnDisplay || tipDisconnectedDisplay) { // draw temp over the start soldering button // Location changes on screen rotation if (OLED::getRotation()) { // in right handed mode we want to draw over the first part OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp OLED::setCursor(56, 0); } else { OLED::fillArea(0, 0, 41, 16, 0); // clear the area OLED::setCursor(0, 0); } // If we have a tip connected draw the temp, if not we leave it blank if (!tipDisconnectedDisplay) { // draw in the temp if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (xTaskGetTickCount() % 260 < 160))) gui_drawTipTemp(false, FontStyle::LARGE); // draw in the temp } else { // Draw in missing tip symbol if (OLED::getRotation()) { // in right handed mode we want to draw over the first part OLED::drawArea(54, 0, 42, 16, disconnectedTipF); } else { OLED::drawArea(0, 0, 42, 16, disconnectedTip); } } } } if (showExitMenuTransition) { OLED::useSecondaryFramebuffer(false); OLED::transitionSecondaryFramebuffer(false); showExitMenuTransition = false; } else { OLED::refresh(); GUIDelay(); } } }