1
0
forked from me/IronOS
Files
IronOS/source/Core/Threads/GUIThread.cpp
Ben V. Brown 6002cc3270 FIXUP! Fix typo's
.
2023-10-24 08:27:04 +11:00

215 lines
7.2 KiB
C++

/*
* GUIThread.cpp
*
* Created on: 19 Aug 2019
* Author: ralim
*/
extern "C" {
#include "FreeRTOSConfig.h"
}
#include "BootLogo.h"
#include "Buttons.hpp"
#include "I2CBB2.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"
#ifdef POW_PD
#include "USBPD.h"
#include "pd.h"
#endif
// File local variables
#define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
#define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
ButtonState buttonsAtDeviceBoot; // We record button state at startup, incase of jumping to debug modes
OperatingMode currentOperatingMode = OperatingMode::InitialisationDone; // Current mode we are rendering
guiContext context; // Context passed to functions to aid in state during render passes
OperatingMode handle_post_init_state();
void guiRenderLoop(void) {
OLED::clearScreen(); // Clear ready for render pass
// Read button state
ButtonState buttons = getButtonState();
// Enforce screen on if buttons pressed, movement, hot tip etc
if (buttons != BUTTON_NONE) {
OLED::setDisplayState(OLED::DisplayState::ON);
} else {
// Buttons are none; check if we can sleep display
uint32_t tipTemp = TipThermoModel::getTipInC();
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);
if (tipTemp > 55) {
setStatusLED(LED_COOLING_STILL_HOT);
} else {
setStatusLED(LED_STANDBY);
}
}
}
// Dispatch button state to gui mode
OperatingMode newMode = currentOperatingMode;
switch (currentOperatingMode) {
case OperatingMode::StartupWarnings:
newMode = showWarnings(buttons, &context);
break;
case OperatingMode::UsbPDDebug:
#ifdef HAS_POWER_DEBUG_MENU
showPDDebug(buttons, &context);
break;
#else
/*fallthrough*/
#endif
case OperatingMode::StartupLogo:
BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); // TODO needs refactor
newMode = OperatingMode::StartupWarnings;
break;
default:
/* Fallthrough */
case OperatingMode::HomeScreen:
newMode = drawHomeScreen(buttons, &context);
break;
case OperatingMode::Soldering:
newMode = gui_solderingMode(buttons, &context);
break;
case OperatingMode::SolderingProfile:
newMode = gui_solderingProfileMode(buttons, &context);
break;
case OperatingMode::Sleeping:
newMode = gui_SolderingSleepingMode(buttons, &context);
break;
case OperatingMode::TemperatureAdjust:
newMode = gui_solderingTempAdjust(buttons, &context);
break;
case OperatingMode::DebugMenuReadout:
newMode = showDebugMenu(buttons, &context);
break;
case OperatingMode::CJCCalibration:
newMode = performCJCC(buttons, &context);
break;
case OperatingMode::SettingsMenu:
newMode = gui_SettingsMenu(buttons, &context);
break;
case OperatingMode::InitialisationDone:
newMode = handle_post_init_state();
break;
case OperatingMode::Hibernating:
break;
case OperatingMode::ThermalRunaway:
break;
};
// Update state holders
if (newMode != currentOperatingMode) {
context.viewEnterTime = xTaskGetTickCount();
context.previousMode = currentOperatingMode;
memset(&context.scratch_state, 0, sizeof(context.scratch_state));
currentOperatingMode = newMode;
// If the transition marker is set, we need to make the next draw occur to the secondary buffer so we have something to transition to
if (context.transitionMode != TransitionAnimation::None) {
OLED::refresh();
OLED::useSecondaryFramebuffer(true);
return; // Exit early to avoid refresh with new framebuffer
}
} else if (context.transitionMode != TransitionAnimation::None) {
// We haven't changed mode but transition is set, so we are at the other side of a transition
// We now want to transition from old contents (main buffer) to new contents (secondary buffer)
switch (context.transitionMode) {
case TransitionAnimation::Down:
break;
case TransitionAnimation::Left:
break;
case TransitionAnimation::Right:
break;
case TransitionAnimation::None:
default:
break; // Do nothing on unknown
}
OLED::useSecondaryFramebuffer(false);
context.transitionMode = TransitionAnimation::None; // Clear transition flag
}
// Render done, draw it out
OLED::refresh();
}
OperatingMode handle_post_init_state() {
#ifdef HAS_POWER_DEBUG_MENU
#ifdef DEBUG_POWER_MENU_BUTTON_B
if (buttonsAtDeviceBoot == BUTTON_B_LONG || buttonsAtDeviceBoot == BUTTON_B_SHORT) {
#else
if (buttonsAtDeviceBoot == BUTTON_F_LONG || buttonsAtDeviceBoot == BUTTON_F_SHORT) {
#endif
return OperatingMode::UsbPDDebug;
}
#endif
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
return OperatingMode::CJCCalibration;
}
if (getSettingValue(SettingsOptions::AutoStartMode) == 1) {
// jump directly to the autostart mode
return OperatingMode::Sleeping;
}
if (getSettingValue(SettingsOptions::AutoStartMode) == 2) {
return OperatingMode::Hibernating;
}
return OperatingMode::HomeScreen;
}
/* 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));
bool buttonLockout = false;
renderHomeScreenAssets();
getTipRawTemp(1); // reset filter
memset(&context, 0, sizeof(context));
OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1);
buttonsAtDeviceBoot = getButtonState();
// // If the boot logo is enabled with timeout 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);
// }
// TODO
TickType_t startRender = xTaskGetTickCount();
for (;;) {
guiRenderLoop();
resetWatchdog();
vTaskDelayUntil(&startRender, TICKS_100MS / 2); // Try and maintain 20fps ish update rate, way to fast but if we can its nice
}
}