mirror of
https://github.com/Ralim/IronOS.git
synced 2025-07-23 12:23:06 +02:00
252 lines
8.8 KiB
C++
252 lines
8.8 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"
|
|
#include "ui_drawing.hpp"
|
|
#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();
|
|
OperatingMode guiHandleDraw(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 (currentOperatingMode != OperatingMode::Soldering && currentOperatingMode != OperatingMode::SolderingProfile) {
|
|
// Not in soldering mode, so set this based on temp
|
|
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
|
|
newMode = showPDDebug(buttons, &context);
|
|
break;
|
|
#else
|
|
newMode = OperatingMode::InitialisationDone;
|
|
#endif
|
|
case OperatingMode::StartupLogo:
|
|
showBootLogo();
|
|
|
|
if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SLEEP) {
|
|
lastMovementTime = lastButtonTime = 0; // We mask the values so that sleep goes until user moves again or presses a button
|
|
newMode = OperatingMode::Sleeping;
|
|
} else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SOLDER) {
|
|
lastMovementTime = lastButtonTime = xTaskGetTickCount(); // Move forward so we dont go to sleep
|
|
newMode = OperatingMode::Soldering;
|
|
} else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::ZERO) {
|
|
lastMovementTime = lastButtonTime = 0; // We mask the values so that sleep goes until user moves again or presses a button
|
|
newMode = OperatingMode::Hibernating;
|
|
} else {
|
|
newMode = OperatingMode::HomeScreen;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
/* Fallthrough */
|
|
case OperatingMode::HomeScreen:
|
|
newMode = drawHomeScreen(buttons, &context);
|
|
break;
|
|
case OperatingMode::Soldering:
|
|
context.scratch_state.state4 = 0;
|
|
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:
|
|
context.scratch_state.state4 = 1;
|
|
gui_SolderingSleepingMode(buttons, &context);
|
|
if (lastButtonTime > 0 || lastMovementTime > 0) {
|
|
newMode = OperatingMode::Soldering;
|
|
}
|
|
break;
|
|
case OperatingMode::ThermalRunaway:
|
|
/*TODO*/
|
|
newMode = OperatingMode::HomeScreen;
|
|
break;
|
|
};
|
|
return newMode;
|
|
}
|
|
void guiRenderLoop(void) {
|
|
OperatingMode newMode = guiHandleDraw(); // This does the screen drawing
|
|
|
|
// Post draw we handle any state transitions
|
|
|
|
if (newMode != currentOperatingMode) {
|
|
context.viewEnterTime = xTaskGetTickCount();
|
|
context.previousMode = currentOperatingMode;
|
|
// If the previous mode is the startup logo; we dont want to return to it, but instead dispatch out to either home or soldering
|
|
if (currentOperatingMode == OperatingMode::StartupLogo) {
|
|
if (getSettingValue(SettingsOptions::AutoStartMode)) {
|
|
context.previousMode = OperatingMode::Soldering;
|
|
} else {
|
|
newMode = OperatingMode::HomeScreen;
|
|
}
|
|
}
|
|
memset(&context.scratch_state, 0, sizeof(context.scratch_state));
|
|
currentOperatingMode = newMode;
|
|
}
|
|
|
|
bool detailedView = getSettingValue(SettingsOptions::DetailedIDLE) && getSettingValue(SettingsOptions::DetailedSoldering);
|
|
if (detailedView &&
|
|
((newMode == OperatingMode::HomeScreen && context.previousMode == OperatingMode::Soldering) || (newMode == OperatingMode::Soldering && context.previousMode == OperatingMode::HomeScreen))) {
|
|
// Exclude side-slide-scroll animation if we do transition between soldering/home back and forth while detailed view setting for both modes is set
|
|
return OLED::refresh();
|
|
}
|
|
|
|
// 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::useSecondaryFramebuffer(true);
|
|
// Now we need to fill the secondary buffer with the _next_ frame to transistion to
|
|
guiHandleDraw();
|
|
OLED::useSecondaryFramebuffer(false);
|
|
// Now dispatch the transition
|
|
switch (context.transitionMode) {
|
|
case TransitionAnimation::Down:
|
|
OLED::transitionScrollDown(context.viewEnterTime);
|
|
break;
|
|
case TransitionAnimation::Left:
|
|
OLED::transitionSecondaryFramebuffer(false, context.viewEnterTime);
|
|
break;
|
|
case TransitionAnimation::Right:
|
|
OLED::transitionSecondaryFramebuffer(true, context.viewEnterTime);
|
|
break;
|
|
case TransitionAnimation::Up:
|
|
OLED::transitionScrollUp(context.viewEnterTime);
|
|
|
|
case TransitionAnimation::None:
|
|
default:
|
|
break; // Do nothing on unknown
|
|
}
|
|
|
|
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
|
|
buttonsAtDeviceBoot = BUTTON_NONE;
|
|
return OperatingMode::UsbPDDebug;
|
|
}
|
|
#endif
|
|
|
|
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
|
|
return OperatingMode::CJCCalibration;
|
|
}
|
|
|
|
return OperatingMode::StartupWarnings;
|
|
}
|
|
|
|
/* 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;
|
|
ui_pre_render_assets();
|
|
getTipRawTemp(1); // reset filter
|
|
memset(&context, 0, sizeof(context));
|
|
|
|
OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1);
|
|
|
|
// Read boot button state
|
|
if (getButtonA()) {
|
|
buttonsAtDeviceBoot = BUTTON_F_LONG;
|
|
}
|
|
if (getButtonB()) {
|
|
buttonsAtDeviceBoot = BUTTON_B_LONG;
|
|
}
|
|
|
|
TickType_t startRender = xTaskGetTickCount();
|
|
for (;;) {
|
|
guiRenderLoop();
|
|
resetWatchdog();
|
|
vTaskDelayUntil(&startRender, TICKS_100MS * 4 / 10); // Try and maintain 20-25fps ish update rate, way to fast but if we can its nice
|
|
}
|
|
}
|