Big overhaul of the UI framework (#1749)
* Starting GUI render refactor to be more immediate mode Update TemperatureAdjust.cpp . Cleanup Soldering Sleep SolderingProfiles Soldering Rework Rough pass GUI Temp Adjust Cleanup old OperatingMode Debug Menu * Update TemperatureAdjust.cpp * Roughing some transition work * Fixup! Hook in the init starter helper * Better home screen button handler * FIXUP! Fix typo's . * Update SettingsMenu.cpp * More settings rework * More settings rendering * Fixup * Transitions Update SolderingProfile.cpp Hook in transistions * Update TemperatureAdjust.cpp * Update push.yml * Add auto-repeat to settings menu * Miniware: Use IT for I2C writes * Update USBPDDebug_HUSB238.cpp * Force write screen on side animation cancel . * Refactor moving down the settings list * Update settingsGUI.cpp * Update I2C_Wrapper.cpp * Update OLED.cpp * Rework button handling * Fix PD debug at boot * Fixup not showing right menu options * silence some warnings * Style cleanup * Fkit use bit-bang I2C for Miniware * Update GUIRendering.md * Fixup transition on enter soldering mode * Save Settings * Fixes for some animations not running Dont bail on animations if keypress is still held * Fixup settings acceleration * OLED Up animation * Link up/down on debug meny * Make all accelerometers I2C bus aware Update accelerometers_common.h * Make I2C mag optional * Miniware -> Only Bit-Bang I2C * Fixup for scrollbar FIXUP! Debug menu returns to home screen FIXUP! Up oled animation Fix temp exit * Settings menu -> Both buttons return a menu layer * Merge fixup * Update BMA223.cpp * Re-Enable OLED sleep * Save Setting on temp adjust exit * WiP on startup mode * Some autostart working * Add hibernation mode & more autostart fixes * If cant CJC; go to startup * Hibernate in sleep * Cleanup scroll indicator * FIXUP! Ensure startup warnings are linked in * FIXUP! Ensure we render out temp change before timing out * Ensure 100ms delay between CJC samples * Fix not re-calculating menu length on entering menu * Implement NegotiationinProgress for USB-PD * Mask heating until PD finishes negotiation * Fixup staying in hibernate correctly * Warning timeout * Show reset settings warning * Correctly compensate help text start time * Update GUIThread.cpp * Update USBPD.cpp * . * Fixup sleep time * Update printSleepCountdown.cpp * replacing countdown with big plus while in boost mode * bringing back the + 1 since it was missing when not in boost mode * Bail on USB-PD check after 3 seconds incase of DC source * Fix hibernate * Update PIDThread.cpp * did center plus symbol (boost mode) * Big refactor to not make settings increment handler handle the "is last item" return * Fixup boot logo * Fix flashing * Fixup recalculate the menu length on long hold * Fixup missing menu entries * Fix junk left on screen after user confirmation * Re-order button handler to use custom, then default order to allow setting associated setting * Attach setting for settings using custom handler * Fix swap +/- keys * Fix boost temp * Implement last menu option for Language selector * Wait for init before CJC runs * Check last setting via increment value * Update BSP.cpp * removed = from >= Otherwise incrementing would stop and the scroll bar would already flash at the second to last value. * (Hacky) Fix for Settings reset --------- Co-authored-by: discip <53649486+discip@users.noreply.github.com>
This commit is contained in:
@@ -32,8 +32,179 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// File local variables
|
||||
#define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
#define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
|
||||
extern bool heaterThermalRunaway;
|
||||
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 (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;
|
||||
}
|
||||
// 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) {
|
||||
@@ -47,42 +218,22 @@ void startGUITask(void const *argument) {
|
||||
bool buttonLockout = false;
|
||||
renderHomeScreenAssets();
|
||||
getTipRawTemp(1); // reset filter
|
||||
memset(&context, 0, sizeof(context));
|
||||
|
||||
OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1);
|
||||
// If the front button is held down, on supported devices, show PD debugging metrics
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
#ifdef DEBUG_POWER_MENU_BUTTON_B
|
||||
if (getButtonB()) {
|
||||
#else
|
||||
|
||||
// Read boot button state
|
||||
if (getButtonA()) {
|
||||
#endif
|
||||
showPDDebug();
|
||||
buttonsAtDeviceBoot = BUTTON_F_LONG;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
|
||||
performCJCC();
|
||||
if (getButtonB()) {
|
||||
buttonsAtDeviceBoot = BUTTON_B_LONG;
|
||||
}
|
||||
|
||||
uint16_t logoMode = getSettingValue(SettingsOptions::LOGOTime);
|
||||
uint16_t startMode = getSettingValue(SettingsOptions::AutoStartMode);
|
||||
// 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 (logoMode && logoMode < logoMode_t::ONETIME && startMode && startMode < autoStartMode_t::ZERO) {
|
||||
uint16_t sleepTempDegC = getSettingValue(SettingsOptions::SleepTemp);
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
sleepTempDegC = TipThermoModel::convertFtoC(sleepTempDegC);
|
||||
}
|
||||
// Only heat to sleep temperature (but no higher than 75°C for safety)
|
||||
currentTempTargetDegC = min(sleepTempDegC, 75);
|
||||
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
|
||||
}
|
||||
|
||||
showBootLogo();
|
||||
showWarnings();
|
||||
if (getSettingValue(SettingsOptions::AutoStartMode)) {
|
||||
// jump directly to the autostart mode
|
||||
gui_solderingMode(getSettingValue(SettingsOptions::AutoStartMode) - 1);
|
||||
buttonLockout = true;
|
||||
}
|
||||
|
||||
drawHomeScreen(buttonLockout);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user