From cd51e2a5b0a6289bebbfbe0497d559b2351a0e32 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 11 Jul 2023 08:36:32 +1000 Subject: [PATCH 01/86] 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 --- source/Core/Inc/settingsGUI.hpp | 3 +- source/Core/Src/settingsGUI.cpp | 2 +- source/Core/Threads/GUIRendering.md | 18 + source/Core/Threads/GUIThread.cpp | 170 +++++++-- source/Core/Threads/OperatingModes/CJC.cpp | 53 ++- .../Core/Threads/OperatingModes/DebugMenu.cpp | 185 +++++----- .../Threads/OperatingModes/HomeScreen.cpp | 110 ++---- .../Threads/OperatingModes/OperatingModes.cpp | 3 - .../Threads/OperatingModes/OperatingModes.h | 64 +++- .../OperatingModes/ShowStartupWarnings.cpp | 108 +++--- source/Core/Threads/OperatingModes/Sleep.cpp | 95 +++-- .../Core/Threads/OperatingModes/Soldering.cpp | 283 +++++++------- .../OperatingModes/SolderingProfile.cpp | 347 +++++++++--------- .../OperatingModes/TemperatureAdjust.cpp | 193 +++++----- .../OperatingModes/USBPDDebug_FUSB.cpp | 138 ++++--- .../OperatingModes/USBPDDebug_HUSB238.cpp | 2 +- .../utils/OperatingModeUtilities.h | 25 +- .../OperatingModes/utils/ShowWarning.cpp | 7 +- .../OperatingModes/utils/SolderingCommon.cpp | 22 -- .../utils/shouldDeviceSleep.cpp | 10 +- 20 files changed, 933 insertions(+), 905 deletions(-) create mode 100644 source/Core/Threads/GUIRendering.md diff --git a/source/Core/Inc/settingsGUI.hpp b/source/Core/Inc/settingsGUI.hpp index f1d9085253..3f89ad0fe9 100644 --- a/source/Core/Inc/settingsGUI.hpp +++ b/source/Core/Inc/settingsGUI.hpp @@ -9,6 +9,7 @@ #define GUI_HPP_ #include "BSP.h" #include "FreeRTOS.h" +#include "Buttons.hpp" #include "Settings.h" #include "Translation.h" @@ -37,7 +38,7 @@ typedef struct { } menuitem; void enterSettingsMenu(); -void warnUser(const char *warning, const TickType_t timeout); +bool warnUser(const char *warning, const ButtonState buttons); extern const menuitem rootSettingsMenu[]; #endif /* GUI_HPP_ */ diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index cc6910accc..ae948df6ed 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -949,7 +949,7 @@ static void displayPowerPulseDuration(void) { OLED::printNumber(getSettingValue( static bool setResetSettings(void) { if (userConfirmation(translatedString(Tr->SettingsResetWarning))) { resetSettings(); - warnUser(translatedString(Tr->ResetOKMessage), 3 * TICKS_SECOND); + // warnUser(translatedString(Tr->ResetOKMessage), buttons); //TODO reboot(); } return false; diff --git a/source/Core/Threads/GUIRendering.md b/source/Core/Threads/GUIRendering.md new file mode 100644 index 0000000000..ec65038e08 --- /dev/null +++ b/source/Core/Threads/GUIRendering.md @@ -0,0 +1,18 @@ +# GUI Rendering + +The GUI aims to be somewhat similar to immediate mode rendering, where the screen is re-rendered each sweep. +This is due to a few aims: + +1. Functions should try and contain their state to the context struct (helps keep state usage flatter) +2. Allows external events to change the state +3. Means state can be read/write over BLE or other external control interfaces + +## TODO notes + +On settings menu exit: + +``` + OLED::useSecondaryFramebuffer(true); + showExitMenuTransition = true; + +``` diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index a068408701..ff6a78bb9a 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -32,57 +32,157 @@ 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 -/* StartGUITask function */ -void startGUITask(void const *argument) { - (void)argument; - prepareTranslations(); +OperatingMode currentOperatingMode; // Current mode we are rendering +guiContext context; // Context passed to functions to aid in state during render passes - OLED::initialize(); // start up the LCD - OLED::setBrightness(getSettingValue(SettingsOptions::OLEDBrightness)); - OLED::setInverseDisplay(getSettingValue(SettingsOptions::OLEDInversion)); +void guiRenderLoop(void) { + OLED::clearScreen(); // Clear ready for render pass + // Read button state + ButtonState buttons = getButtonState(); + // Enforce screen on if buttons pressed + 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); + } + } + } - bool buttonLockout = false; - renderHomeScreenAssets(); - getTipRawTemp(1); // reset filter + // 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: + break; + case OperatingMode::InitialisationDone: + break; + case OperatingMode::Hibernating: + break; + case OperatingMode::ThermalRunaway: + break; + }; + // Render done, draw it out + OLED::refresh(); + // Update state holders + if (newMode != currentOperatingMode) { + context.viewEnterTime = xTaskGetTickCount(); + context.previousMode = currentOperatingMode; + memset(&context.scratch_state, 0, sizeof(context.scratch_state)); + currentOperatingMode = newMode; + } +} - OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1); - // If the front button is held down, on supported devices, show PD debugging metrics +OperatingMode handle_post_init_state() { #ifdef HAS_POWER_DEBUG_MENU #ifdef DEBUG_POWER_MENU_BUTTON_B - if (getButtonB()) { + if (buttonsAtDeviceBoot == BUTTON_B_LONG || buttonsAtDeviceBoot == BUTTON_B_SHORT) { #else - if (getButtonA()) { + if (buttonsAtDeviceBoot == BUTTON_F_LONG || buttonsAtDeviceBoot == BUTTON_F_SHORT) { #endif - showPDDebug(); + return OperatingMode::UsbPDDebug; } #endif if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) { - performCJCC(); - } - - 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); + return OperatingMode::CJCCalibration; } - showBootLogo(); - showWarnings(); - if (getSettingValue(SettingsOptions::AutoStartMode)) { + if (getSettingValue(SettingsOptions::AutoStartMode) == 1) { // jump directly to the autostart mode - gui_solderingMode(getSettingValue(SettingsOptions::AutoStartMode) - 1); - buttonLockout = true; + return OperatingMode::Sleeping; + } + if (getSettingValue(SettingsOptions::AutoStartMode) == 2) { + return OperatingMode::Hibernating; } - drawHomeScreen(buttonLockout); + 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 + + 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); + } } diff --git a/source/Core/Threads/OperatingModes/CJC.cpp b/source/Core/Threads/OperatingModes/CJC.cpp index 4da688f96e..2359aad166 100644 --- a/source/Core/Threads/OperatingModes/CJC.cpp +++ b/source/Core/Threads/OperatingModes/CJC.cpp @@ -1,39 +1,36 @@ #include "OperatingModes.h" -void performCJCC(void) { +OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { // Calibrate Cold Junction Compensation directly at boot, before internal components get warm. - OLED::refresh(); - osDelay(50); if (!isTipDisconnected() && abs(int(TipThermoModel::getTipInC() - getHandleTemperature(0) / 10)) < 10) { - uint16_t setoffset = 0; + // Take 16 samples + if (cxt->scratch_state.state1 < 16) { + cxt->scratch_state.state3 += getTipRawTemp(1); + OLED::setCursor(0, 0); + OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL); + OLED::setCursor(0, 8); + OLED::print(SmallSymbolDot, FontStyle::SMALL); + for (uint8_t x = 0; x < (cxt->scratch_state.state1 / 4); x++) + OLED::print(SmallSymbolDot, FontStyle::SMALL); + cxt->scratch_state.state1++; + return OperatingMode::CJCCalibration; + } + // 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(translatedString(Tr->CJCCalibrating), FontStyle::SMALL); - OLED::setCursor(0, 8); - OLED::print(SmallSymbolDot, FontStyle::SMALL); - for (uint8_t x = 0; x < (i / 4); x++) { - OLED::print(SmallSymbolDot, FontStyle::SMALL); - } - OLED::refresh(); - osDelay(100); - } - setoffset = TipThermoModel::convertTipRawADCTouV(offset / 16, true); + + uint16_t setOffset = TipThermoModel::convertTipRawADCTouV(cxt->scratch_state.state3 / 16, true); + setSettingValue(SettingsOptions::CalibrationOffset, setOffset); + if (warnUser(translatedString(Tr->CJCCalibrationDone), buttons)) { + // Preventing to repeat calibration at boot automatically (only one shot). + setSettingValue(SettingsOptions::CalibrateCJC, 0); + saveSettings(); + return OperatingMode::InitialisationDone; } - setSettingValue(SettingsOptions::CalibrationOffset, setoffset); - OLED::clearScreen(); - warnUser(translatedString(Tr->CalibrationDone), 3 * TICKS_SECOND); - OLED::refresh(); - // Preventing to repeat calibration at boot automatically (only one shot). - setSettingValue(SettingsOptions::CalibrateCJC, 0); - saveSettings(); + return OperatingMode::CJCCalibration; } + // Cant run calibration without the tip and for temps to be close + return OperatingMode::InitialisationDone; } diff --git a/source/Core/Threads/OperatingModes/DebugMenu.cpp b/source/Core/Threads/OperatingModes/DebugMenu.cpp index adf03ddde1..27695b6d90 100644 --- a/source/Core/Threads/OperatingModes/DebugMenu.cpp +++ b/source/Core/Threads/OperatingModes/DebugMenu.cpp @@ -1,111 +1,100 @@ #include "OperatingModes.h" -extern osThreadId GUITaskHandle; -extern osThreadId MOVTaskHandle; -extern osThreadId PIDTaskHandle; -extern OperatingMode currentMode; +extern osThreadId GUITaskHandle; +extern osThreadId MOVTaskHandle; +extern osThreadId PIDTaskHandle; -void showDebugMenu(void) { - currentMode = OperatingMode::debug; - 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(SmallSymbolVersionNumber, 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(); +OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) { + OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) + OLED::print(SmallSymbolVersionNumber, FontStyle::SMALL); // Print version number + OLED::setCursor(0, 8); // second line + OLED::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL); + switch (cxt->scratch_state.state1) { + 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 + // 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 - OLED::print(PowerSourceNames[getPowerSourceNumber()], 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(SmallSymbolDot, 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 Ω large to pad over so that we cover ID left overs - OLED::printNumber(getTipResistanceX10() / 10, 6, FontStyle::SMALL); - OLED::print(SmallSymbolDot, 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; + 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 + OLED::print(PowerSourceNames[getPowerSourceNumber()], 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(SmallSymbolDot, 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(SmallSymbolDot, 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; + 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; - } + default: + break; + } - OLED::refresh(); - b = getButtonState(); - if (b == BUTTON_B_SHORT) { - return; - } else if (b == BUTTON_F_SHORT) { - screen++; + if (buttons == BUTTON_B_SHORT) + return OperatingMode::InitialisationDone; + else if (buttons == BUTTON_F_SHORT) { + cxt->scratch_state.state1++; #ifdef HALL_SENSOR - screen = screen % 17; + cxt->scratch_state.state1 = cxt->scratch_state.state1 % 17; #else - screen = screen % 16; + cxt->scratch_state.state1 = cxt->scratch_state.state1 % 16; #endif - } - - GUIDelay(); } + return OperatingMode::DebugMenuReadout; // Stay in debug menu } diff --git a/source/Core/Threads/OperatingModes/HomeScreen.cpp b/source/Core/Threads/OperatingModes/HomeScreen.cpp index fa2511e8ac..502fe1d259 100644 --- a/source/Core/Threads/OperatingModes/HomeScreen.cpp +++ b/source/Core/Threads/OperatingModes/HomeScreen.cpp @@ -2,14 +2,10 @@ #include "Buttons.hpp" #include "OperatingModes.h" -#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)]; -extern OperatingMode currentMode; -bool showExitMenuTransition = false; +uint8_t buttonAF[sizeof(buttonA)]; +uint8_t buttonBF[sizeof(buttonB)]; +uint8_t disconnectedTipF[sizeof(disconnectedTip)]; +bool showExitMenuTransition = false; void renderHomeScreenAssets(void) { @@ -24,55 +20,42 @@ void renderHomeScreenAssets(void) { } } -void handleButtons(bool *buttonLockout) { - ButtonState buttons = getButtonState(); +OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { if (buttons != BUTTON_NONE) { OLED::setDisplayState(OLED::DisplayState::ON); } - if (buttons != BUTTON_NONE && *buttonLockout) { - buttons = BUTTON_NONE; + if (buttons != BUTTON_NONE && cxt->scratch_state.state1 == 0) { + return OperatingMode::HomeScreen; // Ignore button press } else { - *buttonLockout = false; + cxt->scratch_state.state1 == 1; } 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(); + return OperatingMode::DebugMenuReadout; break; case BUTTON_F_LONG: #ifdef PROFILE_SUPPORT if (!isTipDisconnected()) { - gui_solderingProfileMode(); // enter profile mode - *buttonLockout = true; + return OperatingMode::SolderingProfile; } #else - gui_solderingTempAdjust(); + return OperatingMode::TemperatureAdjust; saveSettings(); #endif break; case BUTTON_F_SHORT: if (!isTipDisconnected()) { - gui_solderingMode(0); // enter soldering mode - *buttonLockout = true; + return OperatingMode::Soldering; } break; case BUTTON_B_SHORT: - currentMode = OperatingMode::settings; - enterSettingsMenu(); // enter the settings menu - { - OLED::useSecondaryFramebuffer(true); - showExitMenuTransition = true; - } - *buttonLockout = true; + return OperatingMode::SettingsMenu; break; default: break; @@ -181,55 +164,28 @@ void drawSimplifiedHomeScreen(uint32_t tipTemp) { } } } -void drawHomeScreen(bool buttonLockout) { - - for (;;) { - currentMode = OperatingMode::idle; - handleButtons(&buttonLockout); +OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt) { - currentTempTargetDegC = 0; // ensure tip is off - getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); - uint32_t tipTemp = TipThermoModel::getTipInC(); - // 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); + OperatingMode newMode = handleHomeButtons(buttons, cxt); + if (newMode != OperatingMode::HomeScreen) { + return newMode; + } - 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); - } - } + currentTempTargetDegC = 0; // ensure tip is off + getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); + uint32_t tipTemp = TipThermoModel::getTipInC(); - // Clear the lcd buffer - OLED::clearScreen(); - if (OLED::getRotation()) { - OLED::setCursor(50, 0); - } else { - OLED::setCursor(-1, 0); - } - if (getSettingValue(SettingsOptions::DetailedIDLE)) { - drawDetailedHomeScreen(tipTemp); - } else { - drawSimplifiedHomeScreen(tipTemp); - } - - if (showExitMenuTransition) { - OLED::useSecondaryFramebuffer(false); - OLED::transitionSecondaryFramebuffer(false); - showExitMenuTransition = false; - } else { - OLED::refresh(); - GUIDelay(); - } + // Setup LCD Cursor location + if (OLED::getRotation()) { + OLED::setCursor(50, 0); + } else { + OLED::setCursor(-1, 0); } + if (getSettingValue(SettingsOptions::DetailedIDLE)) { + drawDetailedHomeScreen(tipTemp); + } else { + drawSimplifiedHomeScreen(tipTemp); + } + + return OperatingMode::HomeScreen; } diff --git a/source/Core/Threads/OperatingModes/OperatingModes.cpp b/source/Core/Threads/OperatingModes/OperatingModes.cpp index c09e71d0a1..d334d13b4e 100644 --- a/source/Core/Threads/OperatingModes/OperatingModes.cpp +++ b/source/Core/Threads/OperatingModes/OperatingModes.cpp @@ -3,6 +3,3 @@ // #include "OperatingModes.h" - -// Global variables -OperatingMode currentMode = OperatingMode::idle; \ No newline at end of file diff --git a/source/Core/Threads/OperatingModes/OperatingModes.h b/source/Core/Threads/OperatingModes/OperatingModes.h index c552e327c2..fb42251f6f 100644 --- a/source/Core/Threads/OperatingModes/OperatingModes.h +++ b/source/Core/Threads/OperatingModes/OperatingModes.h @@ -24,29 +24,53 @@ extern "C" { #include "pd.h" #endif -// Exposed modes -enum OperatingMode { - idle = 0, - soldering = 1, - boost = 2, - sleeping = 3, - settings = 4, - debug = 5 +enum class OperatingMode { + StartupLogo = 0, // Showing the startup logo + CJCCalibration, // Cold Junction Calibration + StartupWarnings, // Startup checks and warnings + InitialisationDone, // Special state we use just before we to home screen at first startup. Allows jumping to extra startup states + HomeScreen, // Home/Idle screen that is the main launchpad to other modes + Soldering, // Main soldering operating mode + SolderingProfile, // Soldering by following a profile, used for reflow for example + Sleeping, // Sleep state holds iron at lower sleep temp + Hibernating, // Like sleeping but keeps heater fully off until woken + SettingsMenu, // Settings Menu + DebugMenuReadout, // Debug metrics + TemperatureAdjust, // Set point temperature adjustment + UsbPDDebug, // USB PD debugging information + ThermalRunaway, // Thermal Runaway warning state. +}; + +// Generic context struct used for gui functions to be able to retain state +struct guiContext { + TickType_t viewEnterTime; // Set to ticks when this view state was first entered + OperatingMode previousMode; + struct scratch { + uint16_t state1; // 16 bit state scratch + uint16_t state2; // 16 bit state scratch + uint32_t state3; // 32 bit state scratch + uint32_t state4; // 32 bit state scratch + uint16_t state5; // 16 bit state scratch + uint16_t state6; // 16 bit state scratch + + } scratch_state; }; // Main functions -void performCJCC(void); // Used to calibrate the Cold Junction offset -void gui_solderingTempAdjust(void); // For adjusting the setpoint temperature of the iron -int gui_SolderingSleepingMode(bool stayOff, bool autoStarted); // Sleep mode -void gui_solderingMode(uint8_t jumpToSleep); // Main mode for hot pointy tool -void gui_solderingProfileMode(); // Profile mode for hot likely-not-so-pointy tool -void showDebugMenu(void); // Debugging values -void showPDDebug(void); // Debugging menu that shows PD adaptor info -void showWarnings(void); // Shows user warnings if required -void drawHomeScreen(bool buttonLockout) __attribute__((noreturn)); // IDLE / Home screen -void renderHomeScreenAssets(void); // Called to act as start delay and used to render out flipped images for home screen graphics +OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt); // Sleep mode +OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt); // Main mode for hot pointy tool +OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt); // For adjusting the setpoint temperature of the iron +OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt); // IDLE / Home screen + +OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt); // Profile mode for hot likely-not-so-pointy tool +OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt); // Used to calibrate the Cold Junction offset +OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt); // Debugging values +OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt); // Debugging menu that shows PD adaptor info +OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt); // Shows user warnings if required // Common helpers -int8_t getPowerSourceNumber(void); // Returns number ID of power source -TemperatureType_t getTipTemp(void); // Returns temperature of the tip in *C/*F (based on user settings) +int8_t getPowerSourceNumber(void); // Returns number ID of power source +void renderHomeScreenAssets(void); // Called to act as start delay and used to render out flipped images for home screen graphics + +extern bool heaterThermalRunaway; #endif diff --git a/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp b/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp index 62ed5d0e8b..3598e9b186 100644 --- a/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp +++ b/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp @@ -1,56 +1,78 @@ #include "HUB238.hpp" #include "OperatingModes.h" -void showWarnings(void) { +OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) { // Display alert if settings were reset - if (settingsWereReset) { - warnUser(translatedString(Tr->SettingsResetMessage), 10 * TICKS_SECOND); - } + + switch (cxt->scratch_state.state1) { + case 0: // Settings reset warning + if (settingsWereReset) { + if (warnUser(translatedString(Tr->SettingsResetMessage), buttons)) { + settingsWereReset = false; + cxt->scratch_state.state1 = 1; + } + } + break; + case 1: // Device validations #ifdef DEVICE_HAS_VALIDATION_SUPPORT - if (getDeviceValidationStatus()) { - // Warn user this device might be counterfeit - warnUser(translatedString(Tr->DeviceFailedValidationWarning), 10 * TICKS_SECOND); - } + if (getDeviceValidationStatus()) { + // Warn user this device might be counterfeit + if (warnUser(translatedString(Tr->DeviceFailedValidationWarning), buttons)) { + cxt->scratch_state.state1 = 2; + } + } +#else + cxt->scratch_state.state1 = 2; #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); - resetWatchdog(); - } - // 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); + break; + case 2: // Accelerometer detection + if (DetectedAccelerometerVersion == AccelType::Scanning) { + break; } - } + // Display alert if accelerometer is not detected + if (DetectedAccelerometerVersion == AccelType::None) { + if (getSettingValue(SettingsOptions::AccelMissingWarningCounter) < 2) { + nextSettingValue(SettingsOptions::AccelMissingWarningCounter); + saveSettings(); + if (warnUser(translatedString(Tr->NoAccelerometerMessage), buttons)) { + cxt->scratch_state.state1 = 3; + } + } + } + break; + case 3: + #ifdef POW_PD - // We expect pd to be present - resetWatchdog(); - if (!USBPowerDelivery::fusbPresent()) { - if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { - nextSettingValue(SettingsOptions::PDMissingWarningCounter); - saveSettings(); - warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND); + // We expect pd to be present + if (!USBPowerDelivery::fusbPresent()) { + if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { + nextSettingValue(SettingsOptions::PDMissingWarningCounter); + saveSettings(); + if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) { + cxt->scratch_state.state1 = 4; + } + } } - } -#endif /*POW_PD*/ +#else #if POW_PD_EXT == 1 - if (!hub238_probe()) { - if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { - nextSettingValue(SettingsOptions::PDMissingWarningCounter); - saveSettings(); - warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND); + if (!hub238_probe()) { + if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { + nextSettingValue(SettingsOptions::PDMissingWarningCounter); + saveSettings(); + if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) { + cxt->scratch_state.state1 = 4; + } + } } - } +#else + cxt->scratch_state.state1 = 4; #endif /*POW_PD_EXT==1*/ - // If tip looks to be shorted, yell at user and dont auto dismiss - if (isTipShorted()) { - warnUser(translatedString(Tr->WarningTipShorted), portMAX_DELAY); +#endif /*POW_PD*/ + + break; + default: + // We are off the end, warnings done + return OperatingMode::InitialisationDone; } -#endif /*NO_WARN_MISSING*/ + + return OperatingMode::StartupWarnings; // Stay in warnings } diff --git a/source/Core/Threads/OperatingModes/Sleep.cpp b/source/Core/Threads/OperatingModes/Sleep.cpp index 5c3c47e763..bdfa76c498 100644 --- a/source/Core/Threads/OperatingModes/Sleep.cpp +++ b/source/Core/Threads/OperatingModes/Sleep.cpp @@ -1,64 +1,59 @@ #include "OperatingModes.h" -extern OperatingMode currentMode; - -int gui_SolderingSleepingMode(bool stayOff, bool autoStarted) { -#ifndef NO_SLEEP_MODE +OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt) { +#ifdef NO_SLEEP_MODE + return OperatingMode::SolderingMode; +#endif // Drop to sleep temperature and display until movement or button press - currentMode = OperatingMode::sleeping; - 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 + // 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 (checkForUnderVoltage()) { - // return non-zero on error - return 1; - } + if (checkForUnderVoltage()) + return OperatingMode::HomeScreen; // 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 - TemperatureType_t tipTemp = getTipTemp(); - - 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); - OLED::printSymbolDeg(FontStyle::SMALL); - OLED::print(SmallSymbolSpace, FontStyle::SMALL); - printVoltage(); - OLED::print(SmallSymbolVolts, FontStyle::SMALL); - } else { - OLED::print(translatedString(Tr->SleepingSimpleString), FontStyle::LARGE); - OLED::printNumber(tipTemp, 3, FontStyle::LARGE); - OLED::printSymbolDeg(FontStyle::EXTRAS); + if (getSettingValue(SettingsOptions::TemperatureInF)) { + currentTempTargetDegC = TipThermoModel::convertFtoC(min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp))); + } else { + currentTempTargetDegC = min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp)); + } + // draw the lcd + uint16_t tipTemp = getSettingValue(SettingsOptions::TemperatureInF) ? TipThermoModel::getTipInF() : 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(SmallSymbolDegF, FontStyle::SMALL); + else { + OLED::print(SmallSymbolDegC, FontStyle::SMALL); } - OLED::refresh(); - GUIDelay(); + OLED::print(SmallSymbolSpace, FontStyle::SMALL); + printVoltage(); + OLED::print(SmallSymbolVolts, FontStyle::SMALL); + } else { + OLED::print(translatedString(Tr->SleepingSimpleString), FontStyle::LARGE); + OLED::printNumber(tipTemp, 3, FontStyle::LARGE); + OLED::printSymbolDeg(FontStyle::EXTRAS); + } - if (!shouldBeSleeping(autoStarted)) { - return 0; - } + OLED::refresh(); + GUIDelay(); - if (shouldShutdown()) { - // shutdown - currentTempTargetDegC = 0; - // we want to exit soldering mode - return 1; - } + if (!shouldBeSleeping()) { + return cxt->previousMode; } -#endif - return 0; + if (shouldShutdown()) { + // shutdown + currentTempTargetDegC = 0; + return OperatingMode::HomeScreen; + } + return OperatingMode::Sleeping; } diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index d923871ea9..5604af6c78 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -1,10 +1,61 @@ #include "OperatingModes.h" #include "SolderingCommon.h" +// State 1 = button locking +// State 2 = boost mode +// State 3 = buzzer timer -extern OperatingMode currentMode; +OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) { + if (cxt->scratch_state.state1 == 1) { + // Buttons are currently locked + if (buttons == BUTTON_F_LONG) { + if (getSettingValue(SettingsOptions::BoostTemp) && (getSettingValue(SettingsOptions::LockingMode) == 1)) { + cxt->scratch_state.state2 = 1; + } + } else if (buttons == BUTTON_BOTH_LONG) { + // Unlocking + if (warnUser(translatedString(Tr->UnlockingKeysString), buttons)) { + cxt->scratch_state.state1 = 0; + } + } else if (buttons != BUTTON_NONE) { + // Do nothing and display a lock warning + warnUser(translatedString(Tr->WarningKeysLockedString), buttons); + } + return OperatingMode::Soldering; + } + // otherwise we are unlocked + switch (buttons) { + case BUTTON_NONE: + cxt->scratch_state.state2 = 0; + break; + case BUTTON_BOTH: + case BUTTON_B_LONG: + return OperatingMode::HomeScreen; + case BUTTON_F_LONG: + // if boost mode is enabled turn it on + if (getSettingValue(SettingsOptions::BoostTemp)) { + cxt->scratch_state.state2 = 1; + } + break; + case BUTTON_F_SHORT: + case BUTTON_B_SHORT: { + return OperatingMode::TemperatureAdjust; + case BUTTON_BOTH_LONG: + if (getSettingValue(SettingsOptions::LockingMode) != 0) { + // Lock buttons -void gui_solderingMode(uint8_t jumpToSleep) { + if (warnUser(translatedString(Tr->LockingKeysString), buttons)) { + cxt->scratch_state.state1 = 1; + } + } + break; + default: + break; + } + } + return OperatingMode::Soldering; +} +OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { /* * * Soldering (gui_solderingMode) * -> Main loop where we draw temp, and animations @@ -19,171 +70,109 @@ void gui_solderingMode(uint8_t jumpToSleep) { * --> Double button to exit * --> Long hold double button to toggle key lock */ - bool boostModeOn = false; - bool buttonsLocked = false; - bool converged = false; - currentMode = OperatingMode::soldering; - TickType_t buzzerEnd = 0; + // First check for button locking & dispatch buttons - if (jumpToSleep) { - if (gui_SolderingSleepingMode(jumpToSleep == 2, true) == 1) { - lastButtonTime = xTaskGetTickCount(); - return; // If the function returns non-0 then exit + OperatingMode newMode = handleSolderingButtons(buttons, cxt); + if (newMode != OperatingMode::Soldering) { + return newMode; + } + // Check if we should bail due to undervoltage for example + if (checkExitSoldering()) { + setBuzzer(false); + return OperatingMode::HomeScreen; + } +#ifdef NO_SLEEP_MODE + + if (shouldShutdown()) { + // shutdown + currentTempTargetDegC = 0; + return OperatingMode::HomeScreen; + } +#endif + if (shouldBeSleeping()) { + return OperatingMode::Sleeping; + } + + if (heaterThermalRunaway) { + currentTempTargetDegC = 0; // heater control off + heaterThermalRunaway = false; + return OperatingMode::ThermalRunaway; + } + + // Update the setpoints for the temperature + if (cxt->scratch_state.state2) { + 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)); } } - 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; - currentMode = OperatingMode::boost; - } - 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; - currentMode = OperatingMode::soldering; - 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; - currentMode = OperatingMode::boost; - } - 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; - } + + // Update status + int error = currentTempTargetDegC - TipThermoModel::getTipInC(); + if (error >= -10 && error <= 10) { + // converged + if (!cxt->scratch_state.state5) { + setBuzzer(true); + cxt->scratch_state.state3 = xTaskGetTickCount() + TICKS_SECOND / 3; + cxt->scratch_state.state5 = true; } - // else we update the screen information + setStatusLED(LED_HOT); + } else { + setStatusLED(LED_HEATING); + cxt->scratch_state.state5 = false; + } + if (cxt->scratch_state.state3 != 0 && xTaskGetTickCount() >= cxt->scratch_state.state3) { + setBuzzer(false); + } - OLED::clearScreen(); - // Draw in the screen details - if (getSettingValue(SettingsOptions::DetailedSoldering)) { - if (OLED::getRotation()) { - OLED::setCursor(50, 0); - } else { - OLED::setCursor(-1, 0); - } + // 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); + 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); - } - printCountdownUntilSleep(getSleepTimeout()); - } -#endif - - if (boostModeOn) { - if (OLED::getRotation()) { - OLED::setCursor(38, 8); - } else { - OLED::setCursor(55, 8); - } - OLED::print(SmallSymbolPlus, FontStyle::SMALL); + if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) { + if (OLED::getRotation()) { + OLED::setCursor(32, 0); } else { - if (OLED::getRotation()) { - OLED::setCursor(32, 8); - } else { - OLED::setCursor(47, 8); - } - OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2); + OLED::setCursor(47, 0); } - - detailedPowerStatus(); - - } else { - basicSolderingStatus(boostModeOn); + printCountdownUntilSleep(getSleepTimeout()); } +#endif - OLED::refresh(); - // Update the setpoints for the temperature - if (boostModeOn) { - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp)); + if (cxt->scratch_state.state2) { // Boost mode is on + if (OLED::getRotation()) { + OLED::setCursor(38, 8); } else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); + OLED::setCursor(55, 8); } + OLED::print(SmallSymbolPlus, FontStyle::SMALL); } else { - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp)); + if (OLED::getRotation()) { + OLED::setCursor(32, 8); } else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp)); + OLED::setCursor(47, 8); } + OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2); } - if (checkExitSoldering()) { - setBuzzer(false); - return; - } - - // Update status - int error = currentTempTargetDegC - TipThermoModel::getTipInC(); - if (error >= -10 && error <= 10) { - // converged - if (!converged) { - setBuzzer(true); - buzzerEnd = xTaskGetTickCount() + TICKS_SECOND / 3; - converged = true; - } - setStatusLED(LED_HOT); - } else { - setStatusLED(LED_HEATING); - converged = false; - } - if (buzzerEnd != 0 && xTaskGetTickCount() >= buzzerEnd) { - setBuzzer(false); - } + detailedPowerStatus(); - // slow down ui update rate - GUIDelay(); + } else { + basicSolderingStatus(cxt->scratch_state.state2); } } diff --git a/source/Core/Threads/OperatingModes/SolderingProfile.cpp b/source/Core/Threads/OperatingModes/SolderingProfile.cpp index df6b580569..83cc065d6e 100644 --- a/source/Core/Threads/OperatingModes/SolderingProfile.cpp +++ b/source/Core/Threads/OperatingModes/SolderingProfile.cpp @@ -2,222 +2,209 @@ #include "OperatingModes.h" #include "SolderingCommon.h" -extern OperatingMode currentMode; - -void gui_solderingProfileMode() { +OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt) { /* - * * Soldering (gui_solderingMode) + * * Soldering * -> Main loop where we draw temp, and animations - * PID control * --> Long hold back button to exit * --> Double button to exit */ - currentMode = OperatingMode::soldering; - - TickType_t buzzerEnd = 0; - bool waitForRelease = true; - TickType_t phaseStartTime = xTaskGetTickCount(); + uint16_t tipTemp = 0; - uint16_t tipTemp = 0; - uint8_t profilePhase = 0; - - uint16_t phaseElapsedSeconds = 0; - uint16_t phaseTotalSeconds = 0; - uint16_t phaseStartTemp = 0; - uint16_t phaseEndTemp = getSettingValue(SettingsOptions::ProfilePreheatTemp); + // If this is during init, start at preheat + if (cxt->scratch_state.state1 == 0) { + cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePreheatTemp); + } uint16_t phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfilePreheatSpeed); uint16_t profileCurrentTargetTemp = 0; - for (;;) { - ButtonState buttons = getButtonState(); - if (buttons) { - if (waitForRelease) { - buttons = BUTTON_NONE; - } - } else { - waitForRelease = false; - } - - switch (buttons) { - case BUTTON_NONE: - break; - case BUTTON_BOTH: - case BUTTON_B_LONG: - return; // exit on back long hold - case BUTTON_F_LONG: - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: - // Not used yet - break; - default: - break; - } + switch (buttons) { + case BUTTON_BOTH: + case BUTTON_B_LONG: + return OperatingMode::HomeScreen; // exit on back long hold + case BUTTON_F_LONG: + case BUTTON_F_SHORT: + case BUTTON_B_SHORT: + case BUTTON_NONE: + // Not used yet + break; + default: + break; + } - tipTemp = getTipTemp(); + if (getSettingValue(SettingsOptions::TemperatureInF)) { + tipTemp = TipThermoModel::getTipInF(); + } else { + tipTemp = TipThermoModel::getTipInC(); + } + // If time of entering is unknown; then we start now + if (cxt->scratch_state.state3 == 0) { + cxt->scratch_state.state3 = xTaskGetTickCount(); + } - // if start temp is unknown (preheat), we're setting it now - if (phaseStartTemp == 0) { - phaseStartTemp = tipTemp; - // if this is hotter than the preheat temperature, we should fail - if (phaseStartTemp >= 55) { - warnUser(translatedString(Tr->TooHotToStartProfileWarning), 10 * TICKS_SECOND); - return; - } + // if start temp is unknown (preheat), we're setting it now + if (cxt->scratch_state.state6 == 0) { + cxt->scratch_state.state6 = tipTemp; + // if this is hotter than the preheat temperature, we should fail + if (cxt->scratch_state.state6 >= 55) { + warnUser(translatedString(Tr->TooHotToStartProfileWarning), buttons); + return OperatingMode::HomeScreen; } - - phaseElapsedSeconds = (xTaskGetTickCount() - phaseStartTime) / TICKS_SECOND; - - // have we finished this phase? - if (phaseElapsedSeconds >= phaseTotalSeconds && tipTemp == phaseEndTemp) { - profilePhase++; - - phaseStartTemp = phaseEndTemp; - phaseStartTime = xTaskGetTickCount(); - phaseElapsedSeconds = 0; - - if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) { - // done with all phases, lets go to cooldown - phaseTotalSeconds = 0; - phaseEndTemp = 0; - phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfileCooldownSpeed); + } + uint16_t phaseElapsedSeconds = (xTaskGetTickCount() - cxt->scratch_state.state3) / TICKS_SECOND; + + // have we finished this phase? + if (phaseElapsedSeconds >= cxt->scratch_state.state2 && tipTemp == cxt->scratch_state.state5) { + cxt->scratch_state.state1++; + cxt->scratch_state.state6 = cxt->scratch_state.state5; + cxt->scratch_state.state3 = xTaskGetTickCount(); + phaseElapsedSeconds = 0; + if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) { + // done with all phases, lets go to cooldown + cxt->scratch_state.state2 = 0; + cxt->scratch_state.state5 = 0; + phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfileCooldownSpeed); + } else { + // set up next phase + switch (cxt->scratch_state.state1) { + case 1: + cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase1Duration); + cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase1Temp); + break; + case 2: + cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase2Duration); + cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase2Temp); + break; + case 3: + cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase3Duration); + cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase3Temp); + break; + case 4: + cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase4Duration); + cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase4Temp); + break; + case 5: + cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase5Duration); + cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase5Temp); + break; + default: + break; + } + if (cxt->scratch_state.state6 < cxt->scratch_state.state5) { + phaseTicksPerDegree = (cxt->scratch_state.state2 * TICKS_SECOND) / (cxt->scratch_state.state5 - cxt->scratch_state.state6); } else { - // set up next phase - switch (profilePhase) { - case 1: - phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase1Duration); - phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase1Temp); - break; - case 2: - phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase2Duration); - phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase2Temp); - break; - case 3: - phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase3Duration); - phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase3Temp); - break; - case 4: - phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase4Duration); - phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase4Temp); - break; - case 5: - phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase5Duration); - phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase5Temp); - break; - default: - break; - } - if (phaseStartTemp < phaseEndTemp) { - phaseTicksPerDegree = (phaseTotalSeconds * TICKS_SECOND) / (phaseEndTemp - phaseStartTemp); - } else { - phaseTicksPerDegree = (phaseTotalSeconds * TICKS_SECOND) / (phaseStartTemp - phaseEndTemp); - } + phaseTicksPerDegree = (cxt->scratch_state.state2 * TICKS_SECOND) / (cxt->scratch_state.state6 - cxt->scratch_state.state5); } } + } - // cooldown phase done? - if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) { - if (TipThermoModel::getTipInC() < 55) { - // we're done, let the buzzer beep too - setStatusLED(LED_STANDBY); - if (buzzerEnd == 0) { - setBuzzer(true); - buzzerEnd = xTaskGetTickCount() + TICKS_SECOND / 3; - } + // cooldown phase done? + if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) { + if (TipThermoModel::getTipInC() < 55) { + // we're done, let the buzzer beep too + setStatusLED(LED_STANDBY); + if (cxt->scratch_state.state4 == 0) { + setBuzzer(true); + cxt->scratch_state.state4 = xTaskGetTickCount() + TICKS_SECOND / 3; } } + } - // determine current target temp - if (phaseStartTemp < phaseEndTemp) { - if (profileCurrentTargetTemp < phaseEndTemp) { - profileCurrentTargetTemp = phaseStartTemp + ((xTaskGetTickCount() - phaseStartTime) / phaseTicksPerDegree); - } + // determine current target temp + if (cxt->scratch_state.state6 < cxt->scratch_state.state5) { + if (profileCurrentTargetTemp < cxt->scratch_state.state5) { + profileCurrentTargetTemp = cxt->scratch_state.state6 + ((xTaskGetTickCount() - cxt->viewEnterTime) / phaseTicksPerDegree); + } + } else { + if (profileCurrentTargetTemp > cxt->scratch_state.state5) { + profileCurrentTargetTemp = cxt->scratch_state.state6 - ((xTaskGetTickCount() - cxt->viewEnterTime) / phaseTicksPerDegree); + } + } + + // Draw in the screen details + if (getSettingValue(SettingsOptions::DetailedSoldering)) { + // print temperature + if (OLED::getRotation()) { + OLED::setCursor(48, 0); } else { - if (profileCurrentTargetTemp > phaseEndTemp) { - profileCurrentTargetTemp = phaseStartTemp - ((xTaskGetTickCount() - phaseStartTime) / phaseTicksPerDegree); - } + OLED::setCursor(0, 0); } - OLED::clearScreen(); - // Draw in the screen details - if (getSettingValue(SettingsOptions::DetailedSoldering)) { - // print temperature - if (OLED::getRotation()) { - OLED::setCursor(48, 0); - } else { - OLED::setCursor(0, 0); - } + OLED::printNumber(tipTemp, 3, FontStyle::SMALL); + OLED::print(SmallSymbolSlash, FontStyle::SMALL); + OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL); - OLED::printNumber(tipTemp, 3, FontStyle::SMALL); - OLED::print(SmallSymbolSlash, FontStyle::SMALL); - OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL); - OLED::printSymbolDeg(FontStyle::SMALL); - - // print phase - if (profilePhase > 0 && profilePhase <= getSettingValue(SettingsOptions::ProfilePhases)) { - if (OLED::getRotation()) { - OLED::setCursor(36, 0); - } else { - OLED::setCursor(55, 0); - } - OLED::printNumber(profilePhase, 1, FontStyle::SMALL); - } + if (getSettingValue(SettingsOptions::TemperatureInF)) + OLED::print(SmallSymbolDegF, FontStyle::SMALL); + else + OLED::print(SmallSymbolDegC, FontStyle::SMALL); - // print time progress / preheat / cooldown + // print phase + if (cxt->scratch_state.state1 > 0 && cxt->scratch_state.state1 <= getSettingValue(SettingsOptions::ProfilePhases)) { if (OLED::getRotation()) { - OLED::setCursor(42, 8); - } else { - OLED::setCursor(0, 8); - } - - if (profilePhase == 0) { - OLED::print(translatedString(Tr->ProfilePreheatString), FontStyle::SMALL); - } else if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) { - OLED::print(translatedString(Tr->ProfileCooldownString), FontStyle::SMALL); + OLED::setCursor(36, 0); } else { - OLED::printNumber(phaseElapsedSeconds / 60, 1, FontStyle::SMALL); - OLED::print(SmallSymbolColon, FontStyle::SMALL); - OLED::printNumber(phaseElapsedSeconds % 60, 2, FontStyle::SMALL, false); - - OLED::print(SmallSymbolSlash, FontStyle::SMALL); - - // blink if we can't keep up with the time goal - if (phaseElapsedSeconds < phaseTotalSeconds + 2 || (xTaskGetTickCount() / TICKS_SECOND) % 2 == 0) { - OLED::printNumber(phaseTotalSeconds / 60, 1, FontStyle::SMALL); - OLED::print(SmallSymbolColon, FontStyle::SMALL); - OLED::printNumber(phaseTotalSeconds % 60, 2, FontStyle::SMALL, false); - } + OLED::setCursor(55, 0); } + OLED::printNumber(cxt->scratch_state.state1, 1, FontStyle::SMALL); + } - detailedPowerStatus(); - + // print time progress / preheat / cooldown + if (OLED::getRotation()) { + OLED::setCursor(42, 8); } else { - basicSolderingStatus(false); + OLED::setCursor(0, 8); } - OLED::refresh(); - // Update the setpoints for the temperature - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(profileCurrentTargetTemp); + if (cxt->scratch_state.state1 == 0) { + OLED::print(translatedString(Tr->ProfilePreheatString), FontStyle::SMALL); + } else if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) { + OLED::print(translatedString(Tr->ProfileCooldownString), FontStyle::SMALL); } else { - currentTempTargetDegC = profileCurrentTargetTemp; - } + OLED::printNumber(phaseElapsedSeconds / 60, 1, FontStyle::SMALL); + OLED::print(SmallSymbolColon, FontStyle::SMALL); + OLED::printNumber(phaseElapsedSeconds % 60, 2, FontStyle::SMALL, false); - if (checkExitSoldering() || (buzzerEnd != 0 && xTaskGetTickCount() >= buzzerEnd)) { - setBuzzer(false); - return; - } + OLED::print(SmallSymbolSlash, FontStyle::SMALL); - // Update LED status - if (profilePhase == 0) { - setStatusLED(LED_HEATING); - } else if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) { - setStatusLED(LED_COOLING_STILL_HOT); - } else { - setStatusLED(LED_HOT); + // blink if we can't keep up with the time goal + if (phaseElapsedSeconds < cxt->scratch_state.state2 + 2 || (xTaskGetTickCount() / TICKS_SECOND) % 2 == 0) { + OLED::printNumber(cxt->scratch_state.state2 / 60, 1, FontStyle::SMALL); + OLED::print(SmallSymbolColon, FontStyle::SMALL); + OLED::printNumber(cxt->scratch_state.state2 % 60, 2, FontStyle::SMALL, false); + } } - // slow down ui update rate - GUIDelay(); + detailedPowerStatus(); + + } else { + basicSolderingStatus(false); + } + + // Update the setpoints for the temperature + if (getSettingValue(SettingsOptions::TemperatureInF)) { + currentTempTargetDegC = TipThermoModel::convertFtoC(profileCurrentTargetTemp); + } else { + currentTempTargetDegC = profileCurrentTargetTemp; + } + + if (checkExitSoldering() || (cxt->scratch_state.state4 != 0 && xTaskGetTickCount() >= cxt->scratch_state.state4)) { + setBuzzer(false); + return OperatingMode::HomeScreen; + } + if (heaterThermalRunaway) { + currentTempTargetDegC = 0; // heater control off + heaterThermalRunaway = false; + return OperatingMode::ThermalRunaway; + } + + // Update LED status + if (cxt->scratch_state.state1 == 0) { + setStatusLED(LED_HEATING); + } else if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) { + setStatusLED(LED_COOLING_STILL_HOT); + } else { + setStatusLED(LED_HOT); } } diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index ce06e83bad..3f750d3165 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -1,120 +1,99 @@ #include "OperatingModes.h" -void gui_solderingTempAdjust(void) { - TickType_t lastChange = xTaskGetTickCount(); - currentTempTargetDegC = 0; // Turn off heater while adjusting temp - TickType_t autoRepeatTimer = 0; - uint8_t autoRepeatAcceleration = 0; -#ifndef PROFILE_SUPPORT - bool waitForRelease = false; - ButtonState buttons = getButtonState(); +OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt) { - if (buttons != BUTTON_NONE) { - // Temp adjust entered by long-pressing F button. - waitForRelease = true; - } -#else - ButtonState buttons; -#endif + currentTempTargetDegC = 0; // Turn off heater while adjusting temp + uint16_t *buttonLockout = &(cxt->scratch_state.state1); + uint32_t *lastButtonTime = &(cxt->scratch_state.state3); + uint16_t *buttonAccel = &(cxt->scratch_state.state2); - for (;;) { - OLED::setCursor(0, 0); - OLED::clearScreen(); - buttons = getButtonState(); - if (buttons) { - lastChange = xTaskGetTickCount(); -#ifndef PROFILE_SUPPORT - if (waitForRelease) { - buttons = BUTTON_NONE; - } - } else { - waitForRelease = false; -#endif - } - 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 (*buttonLockout == 0) { + // When we first enter we wait for the user to release buttons before enabling changes + if (buttons != BUTTON_NONE) { + return OperatingMode::TemperatureAdjust; } - // 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; + (*buttonLockout)++; + } - 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); + OLED::setCursor(0, 0); + + int16_t delta = 0; + switch (buttons) { + case BUTTON_NONE: + // stay + (*buttonAccel) = 0; + break; + case BUTTON_BOTH: + // exit + return cxt->previousMode; + case BUTTON_B_LONG: + if (xTaskGetTickCount() - (*lastButtonTime) + (*buttonAccel) > PRESS_ACCEL_INTERVAL_MAX) { + delta = -getSettingValue(SettingsOptions::TempChangeLongStep); + (*lastButtonTime) = xTaskGetTickCount(); + (*buttonAccel) += PRESS_ACCEL_STEP; } - if (xTaskGetTickCount() - lastChange > (TICKS_SECOND * 2)) { - return; // exit if user just doesn't press anything for a bit + break; + case BUTTON_B_SHORT: + delta = -getSettingValue(SettingsOptions::TempChangeShortStep); + break; + case BUTTON_F_LONG: + if (xTaskGetTickCount() - (*lastButtonTime) + (*buttonAccel) > PRESS_ACCEL_INTERVAL_MAX) { + delta = getSettingValue(SettingsOptions::TempChangeLongStep); + (*lastButtonTime) = xTaskGetTickCount(); + (*buttonAccel) += PRESS_ACCEL_STEP; } + break; + case BUTTON_F_SHORT: + delta = getSettingValue(SettingsOptions::TempChangeShortStep); + break; + default: + break; + } + if ((PRESS_ACCEL_INTERVAL_MAX - (*buttonAccel)) < PRESS_ACCEL_INTERVAL_MIN) { + (*buttonAccel) = 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 (OLED::getRotation()) { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE); + if (getSettingValue(SettingsOptions::TemperatureInF)) { + if (newTemp > MAX_TEMP_F) + newTemp = MAX_TEMP_F; + if (newTemp < MIN_TEMP_F) + newTemp = MIN_TEMP_F; } else { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE); + 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() - cxt->viewEnterTime > (TICKS_SECOND * 2)) { + return cxt->previousMode; // exit if user just doesn't press anything for a bit + } + if (OLED::getRotation()) { + OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE); + } else { + OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE); + } - OLED::print(LargeSymbolSpace, FontStyle::LARGE); - OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE); - OLED::printSymbolDeg(FontStyle::EXTRAS); - OLED::print(LargeSymbolSpace, FontStyle::LARGE); - if (OLED::getRotation()) { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE); - } else { - OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE); - } - OLED::refresh(); - GUIDelay(); + OLED::print(LargeSymbolSpace, FontStyle::LARGE); + OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE); + OLED::printSymbolDeg(FontStyle::EXTRAS); + OLED::print(LargeSymbolSpace, FontStyle::LARGE); + if (OLED::getRotation()) { + OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE); + } else { + OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE); } + + return OperatingMode::TemperatureAdjust; // Stay in temp adjust } diff --git a/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp b/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp index 65776970ff..9be7b7e2f7 100644 --- a/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp +++ b/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp @@ -2,93 +2,89 @@ #ifdef POW_PD #ifdef HAS_POWER_DEBUG_MENU -void showPDDebug(void) { +OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) { // 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(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title - OLED::setCursor(0, 8); // second line - if (screen == 0) { - // Print the PD state machine - OLED::print(SmallSymbolState, FontStyle::SMALL); - OLED::print(SmallSymbolSpace, FontStyle::SMALL); - OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true); - OLED::print(SmallSymbolSpace, FontStyle::SMALL); - // Also print vbus mod status - if (USBPowerDelivery::fusbPresent()) { - if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) { - if (!USBPowerDelivery::isVBUSConnected()) { - OLED::print(SmallSymbolNoVBus, FontStyle::SMALL); - } else { - OLED::print(SmallSymbolVBus, FontStyle::SMALL); - } + uint16_t *screen = &(cxt->scratch_state.state1); + OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) + OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title + OLED::setCursor(0, 8); // second line + if ((*screen) == 0) { + // Print the PD state machine + OLED::print(SmallSymbolState, FontStyle::SMALL); + OLED::print(SmallSymbolSpace, FontStyle::SMALL); + OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true); + OLED::print(SmallSymbolSpace, FontStyle::SMALL); + // Also print vbus mod status + if (USBPowerDelivery::fusbPresent()) { + if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) { + if (!USBPowerDelivery::isVBUSConnected()) { + OLED::print(SmallSymbolNoVBus, FontStyle::SMALL); + } else { + OLED::print(SmallSymbolVBus, 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; + } + } 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) && ((lastCaps[screen - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_AVS)) { - 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 if (((lastCaps[screen - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED) && ((lastCaps[screen - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS)) { - 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 + 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) && ((lastCaps[(*screen) - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_AVS)) { + 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 if (((lastCaps[(*screen) - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED) && ((lastCaps[(*screen) - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS)) { + 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(SmallSymbolSpace, FontStyle::SMALL); + if (min_voltage > 0) { + OLED::printNumber(min_voltage / 1000, 2, FontStyle::SMALL, true); // print the voltage + OLED::print(SmallSymbolMinus, FontStyle::SMALL); } - // Skip not used entries - if (voltage_mv == 0) { - screen++; + OLED::printNumber(voltage_mv / 1000, 2, FontStyle::SMALL, true); // print the voltage + OLED::print(SmallSymbolVolts, FontStyle::SMALL); + OLED::print(SmallSymbolSpace, FontStyle::SMALL); + if (wattage) { + OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res + OLED::print(SmallSymbolWatts, FontStyle::SMALL); } else { - // print out this entry of the proposal - OLED::printNumber(screen, 2, FontStyle::SMALL, true); // print the entry number - OLED::print(SmallSymbolSpace, FontStyle::SMALL); - if (min_voltage > 0) { - OLED::printNumber(min_voltage / 1000, 2, FontStyle::SMALL, true); // print the voltage - OLED::print(SmallSymbolMinus, FontStyle::SMALL); - } - OLED::printNumber(voltage_mv / 1000, 2, FontStyle::SMALL, true); // print the voltage - OLED::print(SmallSymbolVolts, FontStyle::SMALL); - OLED::print(SmallSymbolSpace, FontStyle::SMALL); - if (wattage) { - OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res - OLED::print(SmallSymbolWatts, FontStyle::SMALL); - } else { - OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res - OLED::print(SmallSymbolDot, FontStyle::SMALL); - OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, false); // print the current in 0.1A res - OLED::print(SmallSymbolAmps, FontStyle::SMALL); - } + OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res + OLED::print(SmallSymbolDot, FontStyle::SMALL); + OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, false); // print the current in 0.1A res + OLED::print(SmallSymbolAmps, FontStyle::SMALL); } - } else { - screen = 0; } + } else { + *screen = 0; } OLED::refresh(); - b = getButtonState(); - if (b == BUTTON_B_SHORT) { - return; - } else if (b == BUTTON_F_SHORT) { - screen++; + if (buttons == BUTTON_B_SHORT) + return OperatingMode::InitialisationDone; + else if (buttons == BUTTON_F_SHORT) { + *screen++; } GUIDelay(); } + return OperatingMode::UsbPDDebug; } #endif #endif diff --git a/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp b/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp index 5841e47ce5..db9c7ff62c 100644 --- a/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp +++ b/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp @@ -2,7 +2,7 @@ #include "OperatingModes.h" #if POW_PD_EXT == 1 #ifdef HAS_POWER_DEBUG_MENU -void showPDDebug(void) { +OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) { // 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; diff --git a/source/Core/Threads/OperatingModes/utils/OperatingModeUtilities.h b/source/Core/Threads/OperatingModes/utils/OperatingModeUtilities.h index ab3f36f993..e204adf369 100644 --- a/source/Core/Threads/OperatingModes/utils/OperatingModeUtilities.h +++ b/source/Core/Threads/OperatingModes/utils/OperatingModeUtilities.h @@ -1,18 +1,19 @@ #ifndef OPERATING_MODE_UTILITIES_H_ #define OPERATING_MODE_UTILITIES_H_ +#include "Buttons.hpp" #include "OLED.hpp" #include -void GUIDelay(); // -bool checkForUnderVoltage(void); // -uint32_t getSleepTimeout(void); // -bool shouldBeSleeping(bool inAutoStart); // -bool shouldShutdown(void); // -void gui_drawTipTemp(bool symbol, const FontStyle font); // -void printVoltage(void); // -void warnUser(const char *warning, const TickType_t timeout); // -void gui_drawBatteryIcon(void); // -bool checkForUnderVoltage(void); // -uint16_t min(uint16_t a, uint16_t b); // -void printCountdownUntilSleep(int sleepThres); // +void GUIDelay(); // +bool checkForUnderVoltage(void); // +uint32_t getSleepTimeout(void); // +bool shouldBeSleeping(); // +bool shouldShutdown(void); // +void gui_drawTipTemp(bool symbol, const FontStyle font); // +void printVoltage(void); // +bool warnUser(const char *warning, const ButtonState buttons); // +void gui_drawBatteryIcon(void); // +bool checkForUnderVoltage(void); // +uint16_t min(uint16_t a, uint16_t b); // +void printCountdownUntilSleep(int sleepThres); // #endif \ No newline at end of file diff --git a/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp b/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp index fcd2972e28..80bfa2df4b 100644 --- a/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp +++ b/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp @@ -1,8 +1,9 @@ #include "Buttons.hpp" #include "OperatingModeUtilities.h" -void warnUser(const char *warning, const TickType_t timeout) { +#include "OperatingModes.h" +bool warnUser(const char *warning, const ButtonState buttons) { OLED::clearScreen(); OLED::printWholeScreen(warning); - OLED::refresh(); - waitForButtonPressOrTimeout(timeout); + // TODO also timeout + return buttons != BUTTON_NONE; } diff --git a/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp b/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp index 0f1bbd2a3c..5975a1b86c 100644 --- a/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp +++ b/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp @@ -106,30 +106,8 @@ bool checkExitSoldering(void) { } } #endif -#ifdef NO_SLEEP_MODE - // No sleep mode, but still want shutdown timeout - - if (shouldShutdown()) { - // shutdown - currentTempTargetDegC = 0; - lastMovementTime = xTaskGetTickCount(); // We manually move the movement time to now such that shutdown timer is reset - - return true; // we want to exit soldering mode - } -#endif - if (shouldBeSleeping(false)) { - if (gui_SolderingSleepingMode(false, false)) { - return true; // If the function returns non-0 then exit - } - } // 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 true; - } return false; } diff --git a/source/Core/Threads/OperatingModes/utils/shouldDeviceSleep.cpp b/source/Core/Threads/OperatingModes/utils/shouldDeviceSleep.cpp index 92a99fc9d4..9e27f2ebd0 100644 --- a/source/Core/Threads/OperatingModes/utils/shouldDeviceSleep.cpp +++ b/source/Core/Threads/OperatingModes/utils/shouldDeviceSleep.cpp @@ -4,15 +4,13 @@ TickType_t lastHallEffectSleepStart = 0; extern TickType_t lastMovementTime; -bool shouldBeSleeping(bool inAutoStart) { +bool shouldBeSleeping() { #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; - } + // 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())) { From cc081402c47f9f96e8e1c7ba49096921e2bd97a2 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 11 Jul 2023 23:59:54 +1000 Subject: [PATCH 02/86] Update TemperatureAdjust.cpp --- .../OperatingModes/TemperatureAdjust.cpp | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index 3f750d3165..25b60f46f4 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -1,17 +1,17 @@ #include "OperatingModes.h" OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt) { - currentTempTargetDegC = 0; // Turn off heater while adjusting temp - uint16_t *buttonLockout = &(cxt->scratch_state.state1); - uint32_t *lastButtonTime = &(cxt->scratch_state.state3); - uint16_t *buttonAccel = &(cxt->scratch_state.state2); + currentTempTargetDegC = 0; // Turn off heater while adjusting temp + uint16_t *waitForRelease = &(cxt->scratch_state.state1); + uint32_t *autoRepeatTimer = &(cxt->scratch_state.state3); + uint16_t *autoRepeatAcceleration = &(cxt->scratch_state.state2); - if (*buttonLockout == 0) { + if (*waitForRelease == 0) { // When we first enter we wait for the user to release buttons before enabling changes if (buttons != BUTTON_NONE) { return OperatingMode::TemperatureAdjust; } - (*buttonLockout)++; + (*waitForRelease)++; } OLED::setCursor(0, 0); @@ -20,26 +20,26 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt switch (buttons) { case BUTTON_NONE: // stay - (*buttonAccel) = 0; + (*autoRepeatAcceleration) = 0; break; case BUTTON_BOTH: // exit return cxt->previousMode; case BUTTON_B_LONG: - if (xTaskGetTickCount() - (*lastButtonTime) + (*buttonAccel) > PRESS_ACCEL_INTERVAL_MAX) { - delta = -getSettingValue(SettingsOptions::TempChangeLongStep); - (*lastButtonTime) = xTaskGetTickCount(); - (*buttonAccel) += PRESS_ACCEL_STEP; + 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() - (*lastButtonTime) + (*buttonAccel) > PRESS_ACCEL_INTERVAL_MAX) { - delta = getSettingValue(SettingsOptions::TempChangeLongStep); - (*lastButtonTime) = xTaskGetTickCount(); - (*buttonAccel) += PRESS_ACCEL_STEP; + if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) { + delta = getSettingValue(SettingsOptions::TempChangeLongStep); + (*autoRepeatTimer) = xTaskGetTickCount(); + (*autoRepeatAcceleration) += PRESS_ACCEL_STEP; } break; case BUTTON_F_SHORT: @@ -48,8 +48,8 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt default: break; } - if ((PRESS_ACCEL_INTERVAL_MAX - (*buttonAccel)) < PRESS_ACCEL_INTERVAL_MIN) { - (*buttonAccel) = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; + 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)) { From e329b09a7d0370f324430ee9b38d22c361a70481 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Jul 2023 07:48:02 +1000 Subject: [PATCH 03/86] Roughing some transition work --- source/Core/Threads/GUIRendering.md | 11 ++++++++ source/Core/Threads/GUIThread.cpp | 25 ++++++++++++++++--- .../Threads/OperatingModes/OperatingModes.h | 9 +++++-- .../Threads/OperatingModes/SettingsMenu.cpp | 8 ++++++ 4 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 source/Core/Threads/OperatingModes/SettingsMenu.cpp diff --git a/source/Core/Threads/GUIRendering.md b/source/Core/Threads/GUIRendering.md index ec65038e08..cd67187cbe 100644 --- a/source/Core/Threads/GUIRendering.md +++ b/source/Core/Threads/GUIRendering.md @@ -7,6 +7,17 @@ This is due to a few aims: 2. Allows external events to change the state 3. Means state can be read/write over BLE or other external control interfaces +## Transitions + +When changing the view to a new view it can be preferable to transition using an animation. +The tooling provides for left, right and down animations at this point. +The use of these gives a notion of "direction" when navigating the menu. + +``` + + +``` + ## TODO notes On settings menu exit: diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index ff6a78bb9a..a55043607c 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -44,7 +44,7 @@ void guiRenderLoop(void) { OLED::clearScreen(); // Clear ready for render pass // Read button state ButtonState buttons = getButtonState(); - // Enforce screen on if buttons pressed + // Enforce screen on if buttons pressed, movement, hot tip etc if (buttons != BUTTON_NONE) { OLED::setDisplayState(OLED::DisplayState::ON); } else { @@ -113,15 +113,34 @@ void guiRenderLoop(void) { case OperatingMode::ThermalRunaway: break; }; - // Render done, draw it out - OLED::refresh(); // 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; + } + OLED::useSecondaryFramebuffer(false); + context.transitionMode = TransitionAnimation::None; // Clear transition flag } + // Render done, draw it out + OLED::refresh(); } OperatingMode handle_post_init_state() { diff --git a/source/Core/Threads/OperatingModes/OperatingModes.h b/source/Core/Threads/OperatingModes/OperatingModes.h index fb42251f6f..736be8667e 100644 --- a/source/Core/Threads/OperatingModes/OperatingModes.h +++ b/source/Core/Threads/OperatingModes/OperatingModes.h @@ -41,10 +41,14 @@ enum class OperatingMode { ThermalRunaway, // Thermal Runaway warning state. }; +enum class TransitionAnimation { None = 0, Right, Left, Down }; + // Generic context struct used for gui functions to be able to retain state struct guiContext { - TickType_t viewEnterTime; // Set to ticks when this view state was first entered - OperatingMode previousMode; + TickType_t viewEnterTime; // Set to ticks when this view state was first entered + OperatingMode previousMode; + TransitionAnimation transitionMode; + // Below is scratch state, this is retained over re-draws but blown away on state change struct scratch { uint16_t state1; // 16 bit state scratch uint16_t state2; // 16 bit state scratch @@ -61,6 +65,7 @@ OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *c OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt); // Main mode for hot pointy tool OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt); // For adjusting the setpoint temperature of the iron OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt); // IDLE / Home screen +OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt); // OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt); // Profile mode for hot likely-not-so-pointy tool OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt); // Used to calibrate the Cold Junction offset diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp new file mode 100644 index 0000000000..0513bd9073 --- /dev/null +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -0,0 +1,8 @@ +#include "OperatingModes.h" +OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { + // Render out the current settings menu + // State 1 -> Root menu + // State 2 -> Sub entry + + return OperatingMode::SettingsMenu; +} \ No newline at end of file From a89bccce308d83de1d81e002552eec7454852246 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Jul 2023 07:56:58 +1000 Subject: [PATCH 04/86] Fixup! Hook in the init starter helper --- source/Core/Threads/GUIThread.cpp | 13 ++++++++++--- source/Core/Threads/OperatingModes/HomeScreen.cpp | 1 + source/Core/Threads/OperatingModes/Sleep.cpp | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index a55043607c..310720115f 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -35,10 +35,11 @@ extern "C" { #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 +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 currentOperatingMode; // 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 @@ -107,6 +108,7 @@ void guiRenderLoop(void) { case OperatingMode::SettingsMenu: break; case OperatingMode::InitialisationDone: + newMode = handle_post_init_state(); break; case OperatingMode::Hibernating: break; @@ -135,6 +137,9 @@ void guiRenderLoop(void) { break; case TransitionAnimation::Right: break; + case TransitionAnimation::None: + default: + break; // Do nothing on unknown } OLED::useSecondaryFramebuffer(false); context.transitionMode = TransitionAnimation::None; // Clear transition flag @@ -181,6 +186,7 @@ void startGUITask(void const *argument) { bool buttonLockout = false; renderHomeScreenAssets(); getTipRawTemp(1); // reset filter + memset(&context, 0, sizeof(context)); OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1); buttonsAtDeviceBoot = getButtonState(); @@ -198,6 +204,7 @@ void startGUITask(void const *argument) { // currentTempTargetDegC = min(sleepTempDegC, 75); // } // TODO + TickType_t startRender = xTaskGetTickCount(); for (;;) { guiRenderLoop(); diff --git a/source/Core/Threads/OperatingModes/HomeScreen.cpp b/source/Core/Threads/OperatingModes/HomeScreen.cpp index 502fe1d259..7c9321c6f7 100644 --- a/source/Core/Threads/OperatingModes/HomeScreen.cpp +++ b/source/Core/Threads/OperatingModes/HomeScreen.cpp @@ -60,6 +60,7 @@ OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { default: break; } + return OperatingMode::HomeScreen; } void drawDetailedHomeScreen(uint32_t tipTemp) { diff --git a/source/Core/Threads/OperatingModes/Sleep.cpp b/source/Core/Threads/OperatingModes/Sleep.cpp index bdfa76c498..60f3fc31a8 100644 --- a/source/Core/Threads/OperatingModes/Sleep.cpp +++ b/source/Core/Threads/OperatingModes/Sleep.cpp @@ -2,7 +2,7 @@ OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt) { #ifdef NO_SLEEP_MODE - return OperatingMode::SolderingMode; + return OperatingMode::Soldering; #endif // Drop to sleep temperature and display until movement or button press From 9650a1a59699d4829f8cd30734ffd61df0e25b29 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Jul 2023 08:06:12 +1000 Subject: [PATCH 05/86] Better home screen button handler --- source/Core/Threads/GUIRendering.md | 3 +++ source/Core/Threads/GUIThread.cpp | 2 +- source/Core/Threads/OperatingModes/HomeScreen.cpp | 8 +------- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/source/Core/Threads/GUIRendering.md b/source/Core/Threads/GUIRendering.md index cd67187cbe..c39a6d4381 100644 --- a/source/Core/Threads/GUIRendering.md +++ b/source/Core/Threads/GUIRendering.md @@ -18,6 +18,9 @@ The use of these gives a notion of "direction" when navigating the menu. ``` +The downside of supporting transitions is that for these to work, the code should render the screen _first_ then return the new state. +This ensures there is a good working copy in the buffer before the transition changes the view. + ## TODO notes On settings menu exit: diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 310720115f..51b6726123 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -209,6 +209,6 @@ void startGUITask(void const *argument) { for (;;) { guiRenderLoop(); resetWatchdog(); - vTaskDelayUntil(&startRender, TICKS_100MS / 2); + vTaskDelayUntil(&startRender, TICKS_100MS / 2); // Try and maintain 20fps ish update rate, way to fast but if we can its nice } } diff --git a/source/Core/Threads/OperatingModes/HomeScreen.cpp b/source/Core/Threads/OperatingModes/HomeScreen.cpp index 7c9321c6f7..6f9b4c2b19 100644 --- a/source/Core/Threads/OperatingModes/HomeScreen.cpp +++ b/source/Core/Threads/OperatingModes/HomeScreen.cpp @@ -167,11 +167,6 @@ void drawSimplifiedHomeScreen(uint32_t tipTemp) { } OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt) { - OperatingMode newMode = handleHomeButtons(buttons, cxt); - if (newMode != OperatingMode::HomeScreen) { - return newMode; - } - currentTempTargetDegC = 0; // ensure tip is off getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); uint32_t tipTemp = TipThermoModel::getTipInC(); @@ -187,6 +182,5 @@ OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt) { } else { drawSimplifiedHomeScreen(tipTemp); } - - return OperatingMode::HomeScreen; + return handleHomeButtons(buttons, cxt); } diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 0513bd9073..5a620a8a58 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -4,5 +4,5 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // State 1 -> Root menu // State 2 -> Sub entry - return OperatingMode::SettingsMenu; + return OperatingMode::HomeScreen; } \ No newline at end of file From 28bfca2a5008c63c5059bfd9499043407fcd5915 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Jul 2023 20:04:04 +1000 Subject: [PATCH 06/86] FIXUP! Fix typo's . --- source/Core/BSP/Pinecilv2/ble_handlers.cpp | 6 +++--- source/Core/Threads/GUIThread.cpp | 1 + source/Core/Threads/OperatingModes/DebugMenu.cpp | 2 +- source/Core/Threads/OperatingModes/HomeScreen.cpp | 6 +----- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 2 ++ 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/source/Core/BSP/Pinecilv2/ble_handlers.cpp b/source/Core/BSP/Pinecilv2/ble_handlers.cpp index b231981919..98a795b7d9 100644 --- a/source/Core/BSP/Pinecilv2/ble_handlers.cpp +++ b/source/Core/BSP/Pinecilv2/ble_handlers.cpp @@ -34,7 +34,7 @@ #endif extern TickType_t lastMovementTime; -extern OperatingMode currentMode; +extern OperatingMode currentOperatingMode; int ble_char_read_status_callback(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset) { if (attr == NULL || attr->uuid == NULL) { @@ -123,7 +123,7 @@ int ble_char_read_status_callback(struct bt_conn *conn, const struct bt_gatt_att break; case 13: // Operating mode - temp = currentMode; + temp = (uint32_t)currentOperatingMode; memcpy(buf, &temp, sizeof(temp)); return sizeof(temp); break; @@ -162,7 +162,7 @@ int ble_char_read_bulk_value_callback(struct bt_conn *conn, const struct bt_gatt TipThermoModel::getTipMaxInC(), // 9 - max temp TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), // 10 - Raw tip in μV abs(getRawHallEffect()), // 11 - hall sensor - currentMode, // 12 - Operating mode + (uint32_t)currentOperatingMode, // 12 - Operating mode x10WattHistory.average(), // 13 - Estimated Wattage *10 }; int lenToCopy = sizeof(bulkData) - offset; diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 51b6726123..53a6b302d1 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -106,6 +106,7 @@ void guiRenderLoop(void) { newMode = performCJCC(buttons, &context); break; case OperatingMode::SettingsMenu: + newMode = gui_SettingsMenu(buttons, &context); break; case OperatingMode::InitialisationDone: newMode = handle_post_init_state(); diff --git a/source/Core/Threads/OperatingModes/DebugMenu.cpp b/source/Core/Threads/OperatingModes/DebugMenu.cpp index 27695b6d90..79ef9d7807 100644 --- a/source/Core/Threads/OperatingModes/DebugMenu.cpp +++ b/source/Core/Threads/OperatingModes/DebugMenu.cpp @@ -18,7 +18,7 @@ OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) { // 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::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL); OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8); OLED::setCursor(0, 8); // second line #endif diff --git a/source/Core/Threads/OperatingModes/HomeScreen.cpp b/source/Core/Threads/OperatingModes/HomeScreen.cpp index 6f9b4c2b19..47ee5009e7 100644 --- a/source/Core/Threads/OperatingModes/HomeScreen.cpp +++ b/source/Core/Threads/OperatingModes/HomeScreen.cpp @@ -21,13 +21,10 @@ void renderHomeScreenAssets(void) { } OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { - if (buttons != BUTTON_NONE) { - OLED::setDisplayState(OLED::DisplayState::ON); - } if (buttons != BUTTON_NONE && cxt->scratch_state.state1 == 0) { return OperatingMode::HomeScreen; // Ignore button press } else { - cxt->scratch_state.state1 == 1; + cxt->scratch_state.state1 = 1; } switch (buttons) { case BUTTON_NONE: @@ -46,7 +43,6 @@ OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { } #else return OperatingMode::TemperatureAdjust; - saveSettings(); #endif break; case BUTTON_F_SHORT: diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 5a620a8a58..67a2674218 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -3,6 +3,8 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Render out the current settings menu // State 1 -> Root menu // State 2 -> Sub entry + uint16_t *mainEntry = &(cxt->scratch_state.state1); + uint16_t *subEntry = &(cxt->scratch_state.state2); return OperatingMode::HomeScreen; } \ No newline at end of file From f5246189f4ff290f9bb6d9053801728156c76f0e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Jul 2023 20:38:36 +1000 Subject: [PATCH 07/86] Update SettingsMenu.cpp --- .../Threads/OperatingModes/SettingsMenu.cpp | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 67a2674218..042587be16 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -1,4 +1,39 @@ #include "OperatingModes.h" + +OperatingMode handleSettingsButtons(const ButtonState buttons, guiContext *cxt) { + switch (buttons) { + case BUTTON_NONE: + // Do nothing + break; + case BUTTON_BOTH: + break; + + case BUTTON_B_LONG: + return OperatingMode::DebugMenuReadout; + break; + case BUTTON_F_LONG: +#ifdef PROFILE_SUPPORT + if (!isTipDisconnected()) { + return OperatingMode::SolderingProfile; + } +#else + return OperatingMode::TemperatureAdjust; +#endif + break; + case BUTTON_F_SHORT: + if (!isTipDisconnected()) { + return OperatingMode::Soldering; + } + break; + case BUTTON_B_SHORT: + return OperatingMode::SettingsMenu; + break; + default: + break; + } + return OperatingMode::HomeScreen; +} + OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Render out the current settings menu // State 1 -> Root menu @@ -6,5 +41,5 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { uint16_t *mainEntry = &(cxt->scratch_state.state1); uint16_t *subEntry = &(cxt->scratch_state.state2); - return OperatingMode::HomeScreen; + return handleSettingsButtons(buttons, cxt); } \ No newline at end of file From d1b5aaf33958ab248780cb564d6be7de01734987 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 19 Jul 2023 23:13:13 +1000 Subject: [PATCH 08/86] More settings rework --- source/Core/Inc/ScrollMessage.hpp | 57 ++------ source/Core/Inc/settingsGUI.hpp | 8 +- source/Core/Src/ScrollMessage.cpp | 31 ++--- source/Core/Src/settingsGUI.cpp | 17 ++- source/Core/Threads/GUIThread.cpp | 4 +- .../Threads/OperatingModes/SettingsMenu.cpp | 124 ++++++++++++++---- 6 files changed, 142 insertions(+), 99 deletions(-) diff --git a/source/Core/Inc/ScrollMessage.hpp b/source/Core/Inc/ScrollMessage.hpp index 3f97fdb996..9352ad4e5f 100644 --- a/source/Core/Inc/ScrollMessage.hpp +++ b/source/Core/Inc/ScrollMessage.hpp @@ -4,50 +4,21 @@ #include "portmacro.h" #include /** - * A helper class for showing a full-screen scrolling message. + * A helper for showing a full-screen scrolling message. */ -class ScrollMessage { - TickType_t messageStart = 0; - int16_t lastOffset = -1; - /** - * Calcualte the width in pixels of the message string, in the large - * font and taking into account multi-byte chars. - * - * @param message The null-terminated message string. - */ - static uint16_t messageWidth(const char *message); - -public: - ScrollMessage() {} - - /** - * Resets this `ScrollMessage` instance to its initial state. - */ - void reset() { - messageStart = 0; - lastOffset = -1; - } - - /** - * Gets whether this `ScrollMessage` instance is in its initial state. - */ - bool isReset() const { return messageStart == 0; } - - /** - * Draw and update the scroll message if needed. - * - * This function does not call `OLED::refresh()`. If this function - * returns `true`, the caller shall call `OLED::refresh()` to draw the - * modified framebuffer to the OLED screen. - * - * @param message The null-terminated message string. This must be the - * same string as the previous call, unless this `ScrollMessage` instance - * is in its initial state or `reset()` has been called. - * @param currentTick The current tick as returned by `xTaskGetTickCount()`. - * @return Whether the OLED framebuffer has been modified. - */ - bool drawUpdate(const char *message, TickType_t currentTick); -}; +/** + * Draw and update the scroll message if needed. + * + * This function does not call `OLED::refresh()`. If this function + * returns `true`, the caller shall call `OLED::refresh()` to draw the + * modified framebuffer to the OLED screen. + * + * @param message The null-terminated message string. This must be the + * same string as the previous call, unless this `ScrollMessage` instance + * is in its initial state or `reset()` has been called. + * @param currentTick The current tick as returned by `xTaskGetTickCount()` offset to 0 at start of scrolling. + */ +void drawScrollingText(const char *message, TickType_t currentTickOffset); #endif /* SCROLL_MESSAGE_HPP_ */ diff --git a/source/Core/Inc/settingsGUI.hpp b/source/Core/Inc/settingsGUI.hpp index 3f89ad0fe9..07695f41a5 100644 --- a/source/Core/Inc/settingsGUI.hpp +++ b/source/Core/Inc/settingsGUI.hpp @@ -13,7 +13,6 @@ #include "Settings.h" #include "Translation.h" - #define PRESS_ACCEL_STEP (TICKS_100MS / 3) #define PRESS_ACCEL_INTERVAL_MIN TICKS_100MS #define PRESS_ACCEL_INTERVAL_MAX (TICKS_100MS * 3) @@ -37,8 +36,9 @@ typedef struct { uint8_t shortDescriptionSize; } menuitem; -void enterSettingsMenu(); -bool warnUser(const char *warning, const ButtonState buttons); -extern const menuitem rootSettingsMenu[]; +void enterSettingsMenu(); +bool warnUser(const char *warning, const ButtonState buttons); +extern const menuitem rootSettingsMenu[]; +extern const menuitem *subSettingsMenus[]; #endif /* GUI_HPP_ */ diff --git a/source/Core/Src/ScrollMessage.cpp b/source/Core/Src/ScrollMessage.cpp index d63cede373..a99521a6c2 100644 --- a/source/Core/Src/ScrollMessage.cpp +++ b/source/Core/Src/ScrollMessage.cpp @@ -28,19 +28,20 @@ static uint16_t str_display_len(const char *const str) { return count; } -uint16_t ScrollMessage::messageWidth(const char *message) { return FONT_12_WIDTH * str_display_len(message); } +/** + * Calculate the width in pixels of the message string, in the large + * font and taking into account multi-byte chars. + * + * @param message The null-terminated message string. + */ +uint16_t messageWidth(const char *message) { return FONT_12_WIDTH * str_display_len(message); } -bool ScrollMessage::drawUpdate(const char *message, TickType_t currentTick) { - bool lcdRefresh = false; +void drawScrollingText(const char *message, TickType_t currentTickOffset) { - if (messageStart == 0) { - messageStart = currentTick; - lcdRefresh = true; - } int16_t messageOffset; uint16_t msgWidth = messageWidth(message); if (msgWidth > OLED_WIDTH) { - messageOffset = ((currentTick - messageStart) / (getSettingValue(SettingsOptions::DescriptionScrollSpeed) == 1 ? TICKS_100MS / 10 : (TICKS_100MS / 5))); + messageOffset = (currentTickOffset / (getSettingValue(SettingsOptions::DescriptionScrollSpeed) == 1 ? TICKS_100MS / 10 : (TICKS_100MS / 5))); messageOffset %= msgWidth + OLED_WIDTH; // Roll around at the end if (messageOffset < OLED_WIDTH) { // Snap the message to the left edge. @@ -54,15 +55,7 @@ bool ScrollMessage::drawUpdate(const char *message, TickType_t currentTick) { messageOffset = (OLED_WIDTH - msgWidth) / 2 + msgWidth; } - if (lastOffset != messageOffset) { - OLED::clearScreen(); - - //^ Rolling offset based on time - OLED::setCursor((OLED_WIDTH - messageOffset), 0); - OLED::print(message, FontStyle::LARGE); - lastOffset = messageOffset; - lcdRefresh = true; - } - - return lcdRefresh; + //^ Rolling offset based on time + OLED::setCursor((OLED_WIDTH - messageOffset), 0); + OLED::print(message, FontStyle::LARGE); } diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index ae948df6ed..410aaa1d12 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -440,6 +440,12 @@ const menuitem advancedMenu[] = { /* clang-format on */ +extern const menuitem *subSettingsMenus[] { +#if defined(POW_DC) || defined(POW_QC) || defined(POW_PD) + powerMenu, +#endif + solderingMenu, PowerSavingMenu, UIMenu, advancedMenu, +}; /* ^^^ !!!ENABLE CLANG-FORMAT back!!! ^^^ */ /** @@ -460,10 +466,9 @@ static void printShortDescription(SettingsItemIndex settingsItemIndex, uint16_t } static int userConfirmation(const char *message) { - ScrollMessage scrollMessage; - + TickType_t tickStart = xTaskGetTickCount(); for (;;) { - bool lcdRefresh = scrollMessage.drawUpdate(message, xTaskGetTickCount()); + drawScrollingText(message, xTaskGetTickCount() - tickStart); ButtonState buttons = getButtonState(); switch (buttons) { @@ -481,10 +486,8 @@ static int userConfirmation(const char *message) { return 0; } - if (lcdRefresh) { - OLED::refresh(); - osDelay(40); - } + OLED::refresh(); + osDelay(40); } return 0; } diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 53a6b302d1..04876451e4 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -18,6 +18,7 @@ extern "C" { #include "Settings.h" #include "TipThermoModel.h" #include "Translation.h" +#include "bflb_platform.h" #include "cmsis_os.h" #include "configuration.h" #include "history.hpp" @@ -64,7 +65,7 @@ void guiRenderLoop(void) { } } } - + MSG("Run GUI %d - %d\r\n", (int)currentOperatingMode, (int)buttons); // Dispatch button state to gui mode OperatingMode newMode = currentOperatingMode; switch (currentOperatingMode) { @@ -145,6 +146,7 @@ void guiRenderLoop(void) { OLED::useSecondaryFramebuffer(false); context.transitionMode = TransitionAnimation::None; // Clear transition flag } + MSG("Post GUI %d - %d\r\n", (int)currentOperatingMode, (int)buttons); // Render done, draw it out OLED::refresh(); } diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 042587be16..410047a16b 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -1,45 +1,119 @@ #include "OperatingModes.h" +#include "ScrollMessage.hpp" + +#define HELP_TEXT_TIMEOUT_TICKS (TICKS_SECOND * 3) +/* + * The settings menu is the most complex bit of GUI code we have + * The menu consists of a two tier menu + * Main menu -> Categories + * Secondary menu -> Settings + * + * For each entry in the menu + */ + +/** + * Prints two small lines (or one line for CJK) of short description for + * setting items and prepares cursor after it. + * @param settingsItemIndex Index of the setting item. + * @param cursorCharPosition Custom cursor char position to set after printing + * description. + */ +static void printShortDescription(SettingsItemIndex settingsItemIndex, uint16_t cursorCharPosition) { + // print short description (default single line, explicit double line) + uint8_t shortDescIndex = static_cast(settingsItemIndex); + OLED::printWholeScreen(translatedString(Tr->SettingsShortNames[shortDescIndex])); + + // prepare cursor for value + // make room for scroll indicator + OLED::setCursor(cursorCharPosition * FONT_12_WIDTH - 2, 0); +} + +// Render a menu, based on the position given +// This will either draw the menu item, or the help text depending on how long its been since button press +void render_menu(const menuitem *item, guiContext *cxt) { + + // If recent interaction or not help text draw the entry + if ((xTaskGetTickCount() - lastButtonTime < HELP_TEXT_TIMEOUT_TICKS) || item->description == 0) { + + if (item->shortDescriptionSize > 0) { + printShortDescription(item->shortDescriptionIndex, item->shortDescriptionSize); + } + item->draw(); + } else { + // Draw description + const char *description = translatedString(Tr->SettingsDescriptions[item->description - 1]); + drawScrollingText(description, xTaskGetTickCount() - lastButtonTime); + } +} + +uint16_t getMenuLength(const menuitem *menu) { + // walk this menu to find the length + for (uint16_t pos = 0; pos < 64; pos++) { + if (menu[pos].draw == NULL) { + return pos + 1; + } + } + return 0; // Cant find length, be safe +} + +OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { + // Render out the current settings menu + // State 1 -> Root menu + // State 2 -> Sub entry + // Draw main entry if sub-entry is 0, otherwise draw sub-entry + + uint16_t *mainEntry = &(cxt->scratch_state.state1); + uint16_t *subEntry = &(cxt->scratch_state.state2); + uint16_t *currentMenuLength = &(cxt->scratch_state.state5); + + const menuitem *currentMenu; + // Draw the currently on screen item + uint16_t currentScreen; + if (*subEntry == 0) { + // Drawing main menu + currentMenu = rootSettingsMenu; + currentScreen = *mainEntry; + } else { + // Drawing sub menu + currentMenu = subSettingsMenus[*mainEntry]; + currentScreen = *subEntry; + } + render_menu(&(currentMenu[currentScreen]), cxt); + + // Update the cached menu length if unknown + if (*currentMenuLength == 0) { + // We walk the current menu to find the length + *currentMenuLength = getMenuLength(currentMenu); + } + // Draw scroll + uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength; + uint8_t position = (OLED_HEIGHT * currentScreen) / *currentMenuLength; + // Draw if not last item + if ((*currentMenuLength != currentScreen) || xTaskGetTickCount() % 1000 < 500) { + OLED::drawScrollIndicator(position, indicatorHeight); + } + + // Now handle user button input -OperatingMode handleSettingsButtons(const ButtonState buttons, guiContext *cxt) { switch (buttons) { case BUTTON_NONE: - // Do nothing break; case BUTTON_BOTH: + return OperatingMode::HomeScreen; break; case BUTTON_B_LONG: - return OperatingMode::DebugMenuReadout; break; case BUTTON_F_LONG: -#ifdef PROFILE_SUPPORT - if (!isTipDisconnected()) { - return OperatingMode::SolderingProfile; - } -#else - return OperatingMode::TemperatureAdjust; -#endif + break; case BUTTON_F_SHORT: - if (!isTipDisconnected()) { - return OperatingMode::Soldering; - } break; case BUTTON_B_SHORT: - return OperatingMode::SettingsMenu; break; default: break; } - return OperatingMode::HomeScreen; -} - -OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { - // Render out the current settings menu - // State 1 -> Root menu - // State 2 -> Sub entry - uint16_t *mainEntry = &(cxt->scratch_state.state1); - uint16_t *subEntry = &(cxt->scratch_state.state2); - - return handleSettingsButtons(buttons, cxt); + // Otherwise we stay put for next render iteration + return OperatingMode::SettingsMenu; } \ No newline at end of file From 7ea36b2bf63340ae7010d08f768203b527ac06b2 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 20 Jul 2023 20:31:01 +1000 Subject: [PATCH 09/86] More settings rendering --- source/Core/Src/settingsGUI.cpp | 228 +----------------- .../Threads/OperatingModes/SettingsMenu.cpp | 65 ++++- 2 files changed, 68 insertions(+), 225 deletions(-) diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index 410aaa1d12..85ab90c53d 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -120,17 +120,12 @@ static bool showHallEffect(void); #if defined(POW_DC) || defined(POW_QC) static void displayPowerMenu(void); -static bool enterPowerMenu(void); #endif /* POW_DC or POW_QC */ static void displaySolderingMenu(void); -static bool enterSolderingMenu(void); static void displayPowerSavingMenu(void); -static bool enterPowerSavingMenu(void); static void displayUIMenu(void); -static bool enterUIMenu(void); static void displayAdvancedMenu(void); -static bool enterAdvancedMenu(void); /* * Root Settings Menu @@ -216,16 +211,16 @@ const menuitem rootSettingsMenu[] { */ #if defined(POW_DC) || defined(POW_QC) /* Power */ - {0, enterPowerMenu, displayPowerMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, + {0, nullptr, displayPowerMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, #endif /* Soldering */ - {0, enterSolderingMenu, displaySolderingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, + {0, nullptr, displaySolderingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, /* Sleep Options Menu */ - {0, enterPowerSavingMenu, displayPowerSavingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, + {0, nullptr, displayPowerSavingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, /* UI Menu */ - {0, enterUIMenu, displayUIMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, + {0, nullptr, displayUIMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, /* Advanced Menu */ - {0, enterAdvancedMenu, displayAdvancedMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, + {0, nullptr, displayAdvancedMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, /* Language Switch */ {0, settings_setLanguageSwitch, settings_displayLanguageSwitch, settings_showLanguageSwitch, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, /* vvvv end of menu marker. DO NOT REMOVE vvvv */ @@ -440,7 +435,7 @@ const menuitem advancedMenu[] = { /* clang-format on */ -extern const menuitem *subSettingsMenus[] { +const menuitem *subSettingsMenus[] { #if defined(POW_DC) || defined(POW_QC) || defined(POW_PD) powerMenu, #endif @@ -1036,214 +1031,3 @@ static bool enterAdvancedMenu(void) { gui_Menu(advancedMenu); return false; } - -uint8_t gui_getMenuLength(const menuitem *menu) { - uint8_t scrollContentSize = 0; - for (uint8_t i = 0; menu[i].draw != nullptr; i++) { - if (menu[i].isVisible == nullptr) { - scrollContentSize += 1; // Always visible - } else if (menu[i].isVisible()) { - scrollContentSize += 1; // Selectively visible and chosen to show - } - } - return scrollContentSize; -} - -void gui_Menu(const menuitem *menu) { - // Draw the settings menu and provide iteration support etc - - // This is used to detect whether a menu-exit transition should be played. - static bool wasInGuiMenu; - wasInGuiMenu = true; - - enum class NavState { - Idle, - Entering, - ScrollingDown, - Exiting, - }; - - uint8_t currentScreen = 0; // Current screen index in the menu struct - uint8_t screensSkipped = 0; // Number of screens skipped due to being disabled - TickType_t autoRepeatTimer = 0; - TickType_t autoRepeatAcceleration = 0; - bool earlyExit = false; - bool lcdRefresh = true; - - ButtonState lastButtonState = BUTTON_NONE; - uint8_t scrollContentSize = gui_getMenuLength(menu); - - bool scrollBlink = false; - bool lastValue = false; - NavState navState = NavState::Entering; - - ScrollMessage scrollMessage; - - while ((menu[currentScreen].draw != nullptr) && earlyExit == false) { - bool valueChanged = false; - // Handle menu transition: - if (navState != NavState::Idle) { - // Check if this menu item shall be skipped. If it shall be skipped, - // `draw()` returns true. Draw on the secondary framebuffer as we want - // to keep the primary framebuffer intact for the upcoming transition - // animation. - OLED::useSecondaryFramebuffer(true); - if (menu[currentScreen].isVisible != nullptr) { - if (!menu[currentScreen].isVisible()) { - currentScreen++; - screensSkipped++; - OLED::useSecondaryFramebuffer(false); - continue; - } - } - - animOpenState = true; - // The menu entering/exiting transition uses the secondary framebuffer, - // but the scroll down transition does not. - OLED::setCursor(0, 0); - OLED::clearScreen(); - if (menu[currentScreen].shortDescriptionSize > 0) { - printShortDescription(menu[currentScreen].shortDescriptionIndex, menu[currentScreen].shortDescriptionSize); - } - menu[currentScreen].draw(); - if (navState == NavState::ScrollingDown) { - // Play the scroll down animation. - OLED::maskScrollIndicatorOnOLED(); - OLED::transitionScrollDown(); - OLED::useSecondaryFramebuffer(false); - } else { - // The menu was drawn in a secondary framebuffer. - // Now we play a transition from the pre-drawn primary - // framebuffer to the new buffer. - // The extra buffer is discarded at the end of the transition. - OLED::useSecondaryFramebuffer(false); - OLED::transitionSecondaryFramebuffer(navState == NavState::Entering); - } - animOpenState = false; - navState = NavState::Idle; - } - - // If the user has hesitated for >=3 seconds, show the long text - // Otherwise "draw" the option - if ((xTaskGetTickCount() - lastButtonTime < (TICKS_SECOND * 3)) || menu[currentScreen].description == 0) { - lcdRefresh = true; - OLED::setCursor(0, 0); - OLED::clearScreen(); - if (menu[currentScreen].shortDescriptionSize > 0) { - printShortDescription(menu[currentScreen].shortDescriptionIndex, menu[currentScreen].shortDescriptionSize); - } - menu[currentScreen].draw(); - uint8_t indicatorHeight = OLED_HEIGHT / scrollContentSize; - uint8_t position = OLED_HEIGHT * (currentScreen - screensSkipped) / scrollContentSize; - if (lastValue) { - scrollBlink = !scrollBlink; - } - if (!lastValue || !scrollBlink) { - OLED::drawScrollIndicator(position, indicatorHeight); - } - } else { - // Draw description - const char *description = translatedString(Tr->SettingsDescriptions[menu[currentScreen].description - 1]); - lcdRefresh |= scrollMessage.drawUpdate(description, xTaskGetTickCount()); - } - - if (lcdRefresh) { - OLED::refresh(); // update the LCD - osDelay(40); - lcdRefresh = false; - } - - ButtonState buttons = getButtonState(); - - if (buttons != lastButtonState) { - autoRepeatAcceleration = 0; - lastButtonState = buttons; - } - - auto callIncrementHandler = [&]() { - wasInGuiMenu = false; - valueChanged = true; - bool res = false; - if ((int)menu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { - res = nextSettingValue(menu[currentScreen].autoSettingOption); - } else if (menu[currentScreen].incrementHandler != nullptr) { - res = menu[currentScreen].incrementHandler(); - } else { - earlyExit = true; - } - if (wasInGuiMenu) { - navState = NavState::Exiting; - } - wasInGuiMenu = true; - return res; - }; - - switch (buttons) { - case BUTTON_BOTH: - earlyExit = true; // will make us exit next loop - scrollMessage.reset(); - break; - case BUTTON_F_SHORT: - // increment - if (scrollMessage.isReset()) { - lastValue = callIncrementHandler(); - } else { - scrollMessage.reset(); - } - break; - case BUTTON_B_SHORT: - if (scrollMessage.isReset()) { - currentScreen++; - navState = NavState::ScrollingDown; - lastValue = false; - } else { - scrollMessage.reset(); - } - break; - case BUTTON_F_LONG: - if (xTaskGetTickCount() + autoRepeatAcceleration > autoRepeatTimer + PRESS_ACCEL_INTERVAL_MAX) { - if ((lastValue = callIncrementHandler())) { - autoRepeatTimer = 1000; - } else { - autoRepeatTimer = 0; - } - autoRepeatTimer += xTaskGetTickCount(); - scrollMessage.reset(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_B_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - currentScreen++; - navState = NavState::ScrollingDown; - autoRepeatTimer = xTaskGetTickCount(); - scrollMessage.reset(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_NONE: - default: - break; - } - - if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) { - autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; - } - - if ((xTaskGetTickCount() - lastButtonTime) > (TICKS_SECOND * 2 * 60)) { - // If user has not pressed any buttons in 30 seconds, exit back a menu layer - // This will trickle the user back to the main screen eventually - earlyExit = true; - scrollMessage.reset(); - } - if (valueChanged) { - // If user changed value, update the scroll content size - scrollContentSize = gui_getMenuLength(menu); - } - } -} - -void enterSettingsMenu() { - gui_Menu(rootSettingsMenu); // Call the root menu - saveSettings(); -} diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 410047a16b..6ac5dc0160 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -1,5 +1,6 @@ #include "OperatingModes.h" #include "ScrollMessage.hpp" +#include "bflb_platform.h" #define HELP_TEXT_TIMEOUT_TICKS (TICKS_SECOND * 3) /* @@ -40,6 +41,9 @@ void render_menu(const menuitem *item, guiContext *cxt) { } item->draw(); } else { + + uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); + *wasRenderingHelp = 1; // Draw description const char *description = translatedString(Tr->SettingsDescriptions[item->description - 1]); drawScrollingText(description, xTaskGetTickCount() - lastButtonTime); @@ -48,9 +52,13 @@ void render_menu(const menuitem *item, guiContext *cxt) { uint16_t getMenuLength(const menuitem *menu) { // walk this menu to find the length + uint16_t counter = 0; for (uint16_t pos = 0; pos < 64; pos++) { - if (menu[pos].draw == NULL) { - return pos + 1; + if (menu[pos].draw == nullptr) { + return counter; + } + if (menu[pos].isVisible == nullptr || menu[pos].isVisible()) { + counter++; } } return 0; // Cant find length, be safe @@ -65,6 +73,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { uint16_t *mainEntry = &(cxt->scratch_state.state1); uint16_t *subEntry = &(cxt->scratch_state.state2); uint16_t *currentMenuLength = &(cxt->scratch_state.state5); + uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); const menuitem *currentMenu; // Draw the currently on screen item @@ -76,7 +85,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { } else { // Drawing sub menu currentMenu = subSettingsMenus[*mainEntry]; - currentScreen = *subEntry; + currentScreen = (*subEntry) - 1; } render_menu(&(currentMenu[currentScreen]), cxt); @@ -95,6 +104,16 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Now handle user button input + auto callIncrementHandler = [&]() { + if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { + nextSettingValue(currentMenu[currentScreen].autoSettingOption); + } else if (currentMenu[currentScreen].incrementHandler != nullptr) { + currentMenu[currentScreen].incrementHandler(); + } + }; + + // + switch (buttons) { case BUTTON_NONE: break; @@ -103,17 +122,57 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { break; case BUTTON_B_LONG: + break; case BUTTON_F_LONG: break; case BUTTON_F_SHORT: + // Increment setting + if (*wasRenderingHelp) { + *wasRenderingHelp = 0; + } else { + if (*subEntry == 0) { + // In a root menu, if its null handler we enter the menu + if (currentMenu[currentScreen].incrementHandler != nullptr) { + currentMenu[currentScreen].incrementHandler(); + } else { + (*subEntry) += 1; + } + } else { + callIncrementHandler(); + } + } break; case BUTTON_B_SHORT: + // Increment menu item + if (*wasRenderingHelp) { + *wasRenderingHelp = 0; + } else { + // Scroll down + if (currentScreen < (*currentMenuLength) - 1) { + // We can increment freely + if (*subEntry == 0) { + (*mainEntry) += 1; + } else { + (*subEntry) += 1; + } + } else { + // We are at an end somewhere, increment as appropriate + if (*subEntry == 0) { + // This is end of the list + return OperatingMode::HomeScreen; + } else { + (*subEntry) = 0; + (*mainEntry) += 1; + } + } + } break; default: break; } + // Otherwise we stay put for next render iteration return OperatingMode::SettingsMenu; } \ No newline at end of file From 385f816f1cb4d048c8b40ba7ea70ebdc10616d8d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 20 Jul 2023 20:31:06 +1000 Subject: [PATCH 10/86] Fixup --- .../OperatingModes/utils/DrawTipTemperature.cpp | 1 + .../Threads/OperatingModes/utils/SolderingCommon.h | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/source/Core/Threads/OperatingModes/utils/DrawTipTemperature.cpp b/source/Core/Threads/OperatingModes/utils/DrawTipTemperature.cpp index 7e5cff175d..8e3d749834 100644 --- a/source/Core/Threads/OperatingModes/utils/DrawTipTemperature.cpp +++ b/source/Core/Threads/OperatingModes/utils/DrawTipTemperature.cpp @@ -1,5 +1,6 @@ #include "OperatingModeUtilities.h" #include "OperatingModes.h" +#include "SolderingCommon.h" #include "TipThermoModel.h" void gui_drawTipTemp(bool symbol, const FontStyle font) { diff --git a/source/Core/Threads/OperatingModes/utils/SolderingCommon.h b/source/Core/Threads/OperatingModes/utils/SolderingCommon.h index 13443e6cce..79ba06d162 100644 --- a/source/Core/Threads/OperatingModes/utils/SolderingCommon.h +++ b/source/Core/Threads/OperatingModes/utils/SolderingCommon.h @@ -1,8 +1,10 @@ #ifndef SOLDERING_COMMON_H #define SOLDERING_COMMON_H +#include -void detailedPowerStatus(); -void basicSolderingStatus(bool boostModeOn); -bool checkExitSoldering(); +void detailedPowerStatus(); +void basicSolderingStatus(bool boostModeOn); +bool checkExitSoldering(); +uint16_t getTipTemp(void); -#endif //SOLDERING_COMMON_H +#endif // SOLDERING_COMMON_H From 12b79578b358acde26bf2f9d60e81dcba124343e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 20 Jul 2023 21:19:39 +1000 Subject: [PATCH 11/86] Transitions Update SolderingProfile.cpp Hook in transistions --- source/Core/Threads/GUIThread.cpp | 74 ++++++++++--------- .../Core/Threads/OperatingModes/DebugMenu.cpp | 5 +- .../Threads/OperatingModes/HomeScreen.cpp | 4 + .../Threads/OperatingModes/OperatingModes.h | 8 +- .../Threads/OperatingModes/SettingsMenu.cpp | 6 +- .../Core/Threads/OperatingModes/Soldering.cpp | 4 + .../OperatingModes/SolderingProfile.cpp | 2 + .../OperatingModes/TemperatureAdjust.cpp | 1 + 8 files changed, 65 insertions(+), 39 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 04876451e4..46e3d2219f 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -18,7 +18,6 @@ extern "C" { #include "Settings.h" #include "TipThermoModel.h" #include "Translation.h" -#include "bflb_platform.h" #include "cmsis_os.h" #include "configuration.h" #include "history.hpp" @@ -41,31 +40,29 @@ OperatingMode currentOperatingMode = OperatingMode::InitialisationDone; // Curre guiContext context; // Context passed to functions to aid in state during render passes OperatingMode handle_post_init_state(); - -void guiRenderLoop(void) { +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); - } - } - } - MSG("Run GUI %d - %d\r\n", (int)currentOperatingMode, (int)buttons); + // 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) { @@ -117,36 +114,43 @@ void guiRenderLoop(void) { case OperatingMode::ThermalRunaway: break; }; - // Update state holders + 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; 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) + } + // 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(); break; case TransitionAnimation::Left: + OLED::transitionSecondaryFramebuffer(false); break; case TransitionAnimation::Right: + OLED::transitionSecondaryFramebuffer(true); break; case TransitionAnimation::None: default: break; // Do nothing on unknown } - OLED::useSecondaryFramebuffer(false); + context.transitionMode = TransitionAnimation::None; // Clear transition flag } - MSG("Post GUI %d - %d\r\n", (int)currentOperatingMode, (int)buttons); // Render done, draw it out OLED::refresh(); } @@ -212,6 +216,6 @@ void startGUITask(void const *argument) { for (;;) { guiRenderLoop(); resetWatchdog(); - vTaskDelayUntil(&startRender, TICKS_100MS / 2); // Try and maintain 20fps ish update rate, way to fast but if we can its nice + vTaskDelayUntil(&startRender, TICKS_100MS * 4 / 10); // Try and maintain 20-25fps ish update rate, way to fast but if we can its nice } } diff --git a/source/Core/Threads/OperatingModes/DebugMenu.cpp b/source/Core/Threads/OperatingModes/DebugMenu.cpp index 79ef9d7807..54db74de6a 100644 --- a/source/Core/Threads/OperatingModes/DebugMenu.cpp +++ b/source/Core/Threads/OperatingModes/DebugMenu.cpp @@ -86,9 +86,10 @@ OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) { break; } - if (buttons == BUTTON_B_SHORT) + if (buttons == BUTTON_B_SHORT) { + cxt->transitionMode = TransitionAnimation::Up; return OperatingMode::InitialisationDone; - else if (buttons == BUTTON_F_SHORT) { + } else if (buttons == BUTTON_F_SHORT) { cxt->scratch_state.state1++; #ifdef HALL_SENSOR cxt->scratch_state.state1 = cxt->scratch_state.state1 % 17; diff --git a/source/Core/Threads/OperatingModes/HomeScreen.cpp b/source/Core/Threads/OperatingModes/HomeScreen.cpp index 47ee5009e7..f34f02ebcb 100644 --- a/source/Core/Threads/OperatingModes/HomeScreen.cpp +++ b/source/Core/Threads/OperatingModes/HomeScreen.cpp @@ -34,9 +34,11 @@ OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { break; case BUTTON_B_LONG: + cxt->transitionMode = TransitionAnimation::Down; return OperatingMode::DebugMenuReadout; break; case BUTTON_F_LONG: + cxt->transitionMode = TransitionAnimation::Left; #ifdef PROFILE_SUPPORT if (!isTipDisconnected()) { return OperatingMode::SolderingProfile; @@ -46,11 +48,13 @@ OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { #endif break; case BUTTON_F_SHORT: + cxt->transitionMode = TransitionAnimation::Left; if (!isTipDisconnected()) { return OperatingMode::Soldering; } break; case BUTTON_B_SHORT: + cxt->transitionMode = TransitionAnimation::Right; return OperatingMode::SettingsMenu; break; default: diff --git a/source/Core/Threads/OperatingModes/OperatingModes.h b/source/Core/Threads/OperatingModes/OperatingModes.h index 736be8667e..f499b0cccb 100644 --- a/source/Core/Threads/OperatingModes/OperatingModes.h +++ b/source/Core/Threads/OperatingModes/OperatingModes.h @@ -41,7 +41,13 @@ enum class OperatingMode { ThermalRunaway, // Thermal Runaway warning state. }; -enum class TransitionAnimation { None = 0, Right, Left, Down }; +enum class TransitionAnimation { + None = 0, + Right = 1, + Left = 2, + Down = 3, + Up = 4, +}; // Generic context struct used for gui functions to be able to retain state struct guiContext { diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 6ac5dc0160..610885e0b1 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -1,6 +1,5 @@ #include "OperatingModes.h" #include "ScrollMessage.hpp" -#include "bflb_platform.h" #define HELP_TEXT_TIMEOUT_TICKS (TICKS_SECOND * 3) /* @@ -138,6 +137,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { currentMenu[currentScreen].incrementHandler(); } else { (*subEntry) += 1; + cxt->transitionMode = TransitionAnimation::Right; } } else { callIncrementHandler(); @@ -152,6 +152,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Scroll down if (currentScreen < (*currentMenuLength) - 1) { // We can increment freely + cxt->transitionMode = TransitionAnimation::Down; if (*subEntry == 0) { (*mainEntry) += 1; } else { @@ -161,11 +162,14 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // We are at an end somewhere, increment as appropriate if (*subEntry == 0) { // This is end of the list + cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::HomeScreen; } else { (*subEntry) = 0; (*mainEntry) += 1; } + // When we exit a list we want to animate to the left + cxt->transitionMode = TransitionAnimation::Left; } } break; diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index 5604af6c78..b38b058535 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -30,6 +30,7 @@ OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) break; case BUTTON_BOTH: case BUTTON_B_LONG: + cxt->transitionMode = TransitionAnimation::Right; return OperatingMode::HomeScreen; case BUTTON_F_LONG: // if boost mode is enabled turn it on @@ -39,6 +40,7 @@ OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) break; case BUTTON_F_SHORT: case BUTTON_B_SHORT: { + cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::TemperatureAdjust; case BUTTON_BOTH_LONG: if (getSettingValue(SettingsOptions::LockingMode) != 0) { @@ -80,6 +82,7 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { // Check if we should bail due to undervoltage for example if (checkExitSoldering()) { setBuzzer(false); + cxt->transitionMode = TransitionAnimation::Right; return OperatingMode::HomeScreen; } #ifdef NO_SLEEP_MODE @@ -175,4 +178,5 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { } else { basicSolderingStatus(cxt->scratch_state.state2); } + return OperatingMode::Soldering; // Stay put } diff --git a/source/Core/Threads/OperatingModes/SolderingProfile.cpp b/source/Core/Threads/OperatingModes/SolderingProfile.cpp index 83cc065d6e..d18dc21d62 100644 --- a/source/Core/Threads/OperatingModes/SolderingProfile.cpp +++ b/source/Core/Threads/OperatingModes/SolderingProfile.cpp @@ -22,6 +22,7 @@ OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cx switch (buttons) { case BUTTON_BOTH: case BUTTON_B_LONG: + cxt->transitionMode = TransitionAnimation::Right; return OperatingMode::HomeScreen; // exit on back long hold case BUTTON_F_LONG: case BUTTON_F_SHORT: @@ -207,4 +208,5 @@ OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cx } else { setStatusLED(LED_HOT); } + return OperatingMode::SolderingProfile; } diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index 25b60f46f4..4a8961d702 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -77,6 +77,7 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp); } if (xTaskGetTickCount() - cxt->viewEnterTime > (TICKS_SECOND * 2)) { + cxt->transitionMode = TransitionAnimation::Right; return cxt->previousMode; // exit if user just doesn't press anything for a bit } if (OLED::getRotation()) { From d78162fce85498be654fb83ceb672fb2c1bb1d57 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 20 Jul 2023 21:59:55 +1000 Subject: [PATCH 12/86] Update TemperatureAdjust.cpp --- .../OperatingModes/TemperatureAdjust.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index 4a8961d702..15b6ccc8a1 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -1,17 +1,18 @@ #include "OperatingModes.h" -OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt) { - - currentTempTargetDegC = 0; // Turn off heater while adjusting temp - uint16_t *waitForRelease = &(cxt->scratch_state.state1); - uint32_t *autoRepeatTimer = &(cxt->scratch_state.state3); - uint16_t *autoRepeatAcceleration = &(cxt->scratch_state.state2); +OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cxt) { + currentTempTargetDegC = 0; // Turn off heater while adjusting temp + uint16_t *waitForRelease = &(cxt->scratch_state.state1); + uint32_t *autoRepeatTimer = &(cxt->scratch_state.state3); + uint16_t *autoRepeatAcceleration = &(cxt->scratch_state.state2); + ButtonState buttons = buttonIn; if (*waitForRelease == 0) { // When we first enter we wait for the user to release buttons before enabling changes if (buttons != BUTTON_NONE) { - return OperatingMode::TemperatureAdjust; + buttons = BUTTON_NONE; + } else { + (*waitForRelease)++; } - (*waitForRelease)++; } OLED::setCursor(0, 0); @@ -76,7 +77,7 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt } setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp); } - if (xTaskGetTickCount() - cxt->viewEnterTime > (TICKS_SECOND * 2)) { + if (xTaskGetTickCount() - lastButtonTime > (TICKS_SECOND * 3)) { cxt->transitionMode = TransitionAnimation::Right; return cxt->previousMode; // exit if user just doesn't press anything for a bit } From 3e2a4381aba51217641deaa3052d72a2b22ca9c3 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 20 Jul 2023 22:01:30 +1000 Subject: [PATCH 13/86] Update push.yml --- .github/workflows/push.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 42d20b7f8b..cb64cb5c54 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,6 +1,16 @@ name: CI -on: [push, pull_request] +on: + push: + branches: + - master + - dev + - main + pull_request: + branches: + - master + - dev + - main jobs: build: From ea38061aa894aaa05ea421d483c38f09109e0d9e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 20 Jul 2023 22:30:50 +1000 Subject: [PATCH 14/86] Add auto-repeat to settings menu --- .../Threads/OperatingModes/SettingsMenu.cpp | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 610885e0b1..f2c8ff4438 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -69,10 +69,12 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // State 2 -> Sub entry // Draw main entry if sub-entry is 0, otherwise draw sub-entry - uint16_t *mainEntry = &(cxt->scratch_state.state1); - uint16_t *subEntry = &(cxt->scratch_state.state2); - uint16_t *currentMenuLength = &(cxt->scratch_state.state5); - uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); + uint16_t *mainEntry = &(cxt->scratch_state.state1); + uint16_t *subEntry = &(cxt->scratch_state.state2); + uint16_t *currentMenuLength = &(cxt->scratch_state.state5); + uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); + uint32_t *autoRepeatAcceleration = &(cxt->scratch_state.state3); + uint32_t *autoRepeatTimer = &(cxt->scratch_state.state4); const menuitem *currentMenu; // Draw the currently on screen item @@ -105,26 +107,34 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { auto callIncrementHandler = [&]() { if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { - nextSettingValue(currentMenu[currentScreen].autoSettingOption); + return nextSettingValue(currentMenu[currentScreen].autoSettingOption); } else if (currentMenu[currentScreen].incrementHandler != nullptr) { - currentMenu[currentScreen].incrementHandler(); + return currentMenu[currentScreen].incrementHandler(); } + return false; }; // switch (buttons) { case BUTTON_NONE: + (*autoRepeatAcceleration) = 0; // reset acceleration + (*autoRepeatTimer) = 0; // reset acceleration break; case BUTTON_BOTH: return OperatingMode::HomeScreen; break; - case BUTTON_B_LONG: - - break; case BUTTON_F_LONG: - + if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) { + if (callIncrementHandler()) { + (*autoRepeatTimer) = 1000; + } else { + (*autoRepeatTimer) = 0; + } + (*autoRepeatTimer) += xTaskGetTickCount(); + (*autoRepeatAcceleration) += PRESS_ACCEL_STEP; + } break; case BUTTON_F_SHORT: // Increment setting @@ -144,6 +154,14 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { } } break; + case BUTTON_B_LONG: + if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) { + (*autoRepeatTimer) = xTaskGetTickCount(); + (*autoRepeatAcceleration) += PRESS_ACCEL_STEP; + } else { + break; + } + /* Fall through*/ case BUTTON_B_SHORT: // Increment menu item if (*wasRenderingHelp) { @@ -173,6 +191,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { } } break; + default: break; } From e2f893c265e839a4af0b6faea2cacb3fd30afc92 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 17:40:11 +1000 Subject: [PATCH 15/86] Miniware: Use IT for I2C writes --- source/Core/BSP/Miniware/I2C_Wrapper.cpp | 89 ++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 source/Core/BSP/Miniware/I2C_Wrapper.cpp diff --git a/source/Core/BSP/Miniware/I2C_Wrapper.cpp b/source/Core/BSP/Miniware/I2C_Wrapper.cpp new file mode 100644 index 0000000000..b173c374c8 --- /dev/null +++ b/source/Core/BSP/Miniware/I2C_Wrapper.cpp @@ -0,0 +1,89 @@ +/* + * FRToSI2C.cpp + * + * Created on: 14Apr.,2018 + * Author: Ralim + */ +#include "BSP.h" +#include "Setup.h" +#include +SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; +StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; + +void FRToSI2C::CpltCallback() { + hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) + if (I2CSemaphore) { + xSemaphoreGiveFromISR(I2CSemaphore, NULL); + } +} + +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { + + if (!lock()) + return false; + if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { + + I2C_Unstick(); + unlock(); + return false; + } + + unlock(); + return true; +} +bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); } + +uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { + uint8_t tx_data[1]; + Mem_Read(add, reg, tx_data, 1); + return tx_data[0]; +} +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { + + if (!lock()) + return false; + if (HAL_I2C_Mem_Write_IT(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size) != HAL_OK) { + + I2C_Unstick(); + unlock(); + return false; + } + return true; +} + +bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { + if (!lock()) + return false; + if (HAL_I2C_Master_Transmit_IT(&hi2c1, DevAddress, pData, Size) != HAL_OK) { + I2C_Unstick(); + unlock(); + return false; + } + return true; +} + +bool FRToSI2C::probe(uint16_t DevAddress) { + if (!lock()) + return false; + uint8_t buffer[1]; + bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; + unlock(); + return worked; +} + +void FRToSI2C::I2C_Unstick() { unstick_I2C(); } + +void FRToSI2C::unlock() { xSemaphoreGive(I2CSemaphore); } + +bool FRToSI2C::lock() { return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; } + +bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { + return false; + } + if (registers[index].pause_ms) + delay_ms(registers[index].pause_ms); + } + return true; +} From 8c5fe1128e67b8aca76ca5a8e8382270edef6b30 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 17:49:56 +1000 Subject: [PATCH 16/86] Update USBPDDebug_HUSB238.cpp --- source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp b/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp index db9c7ff62c..173f7ea0e0 100644 --- a/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp +++ b/source/Core/Threads/OperatingModes/USBPDDebug_HUSB238.cpp @@ -44,13 +44,14 @@ OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) { OLED::refresh(); b = getButtonState(); if (b == BUTTON_B_SHORT) { - return; + return OperatingMode::InitialisationDone; } else if (b == BUTTON_F_SHORT) { screen++; } GUIDelay(); } + return OperatingMode::UsbPDDebug; } #endif #endif From 7cec1dc68cddb4f70b08e7abe6a1308704742cd1 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 18:13:00 +1000 Subject: [PATCH 17/86] Force write screen on side animation cancel . --- source/Core/Drivers/OLED.cpp | 3 +++ source/Core/Threads/OperatingModes/CJC.cpp | 4 +++- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/Core/Drivers/OLED.cpp b/source/Core/Drivers/OLED.cpp index 03668e624a..9188a9730d 100644 --- a/source/Core/Drivers/OLED.cpp +++ b/source/Core/Drivers/OLED.cpp @@ -318,9 +318,12 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { refresh(); // Now refresh to write out the contents to the new page vTaskDelayUntil(&startDraw, TICKS_100MS / 7); if (getButtonState() != BUTTON_NONE) { + memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START); + refresh(); // Now refresh to write out the contents to the new page return; } } + refresh(); // } void OLED::useSecondaryFramebuffer(bool useSecondary) { diff --git a/source/Core/Threads/OperatingModes/CJC.cpp b/source/Core/Threads/OperatingModes/CJC.cpp index 2359aad166..44b1206cee 100644 --- a/source/Core/Threads/OperatingModes/CJC.cpp +++ b/source/Core/Threads/OperatingModes/CJC.cpp @@ -11,8 +11,10 @@ OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL); OLED::setCursor(0, 8); OLED::print(SmallSymbolDot, FontStyle::SMALL); - for (uint8_t x = 0; x < (cxt->scratch_state.state1 / 4); x++) + for (uint8_t x = 0; x < (cxt->scratch_state.state1 / 4); x++) { OLED::print(SmallSymbolDot, FontStyle::SMALL); + } + cxt->scratch_state.state1++; return OperatingMode::CJCCalibration; } diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index f2c8ff4438..0b12e5e339 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -183,8 +183,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::HomeScreen; } else { - (*subEntry) = 0; - (*mainEntry) += 1; + (*subEntry) = 0; // Reset back to the main menu } // When we exit a list we want to animate to the left cxt->transitionMode = TransitionAnimation::Left; From 37011c0f3d8ff03983ab976121a0360ac1f2f6c9 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 18:40:48 +1000 Subject: [PATCH 18/86] Refactor moving down the settings list --- .../Threads/OperatingModes/SettingsMenu.cpp | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 0b12e5e339..1412265d5f 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -62,6 +62,39 @@ uint16_t getMenuLength(const menuitem *menu) { } return 0; // Cant find length, be safe } +OperatingMode moveToNextEntry(guiContext *cxt) { + uint16_t *mainEntry = &(cxt->scratch_state.state1); + uint16_t *subEntry = &(cxt->scratch_state.state2); + uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); + if (*wasRenderingHelp) { + *wasRenderingHelp = 0; + } else { + // Scroll down + // We can increment freely _once_ + cxt->transitionMode = TransitionAnimation::Down; + if (*subEntry == 0) { + (*mainEntry) += 1; + if (rootSettingsMenu[*mainEntry].draw == nullptr) { + // We are off the end of the menu now + cxt->transitionMode = TransitionAnimation::Left; + return OperatingMode::HomeScreen; + } + } else { + (*subEntry) += 1; + // If the new entry is null, we need to exit + if (subSettingsMenus[*mainEntry][*subEntry].draw == nullptr) { + (*subEntry) = 0; // Reset back to the main menu + cxt->transitionMode = TransitionAnimation::Left; + } + // Check if visible + if (subSettingsMenus[*mainEntry][*subEntry].isVisible != nullptr && !subSettingsMenus[*mainEntry][*subEntry].isVisible()) { + // We need to move on as this one isnt visible + return moveToNextEntry(cxt); + } + } + } + return OperatingMode::SettingsMenu; +} OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Render out the current settings menu @@ -115,7 +148,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { }; // - + OperatingMode newMode = OperatingMode::SettingsMenu; switch (buttons) { case BUTTON_NONE: (*autoRepeatAcceleration) = 0; // reset acceleration @@ -164,31 +197,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { /* Fall through*/ case BUTTON_B_SHORT: // Increment menu item - if (*wasRenderingHelp) { - *wasRenderingHelp = 0; - } else { - // Scroll down - if (currentScreen < (*currentMenuLength) - 1) { - // We can increment freely - cxt->transitionMode = TransitionAnimation::Down; - if (*subEntry == 0) { - (*mainEntry) += 1; - } else { - (*subEntry) += 1; - } - } else { - // We are at an end somewhere, increment as appropriate - if (*subEntry == 0) { - // This is end of the list - cxt->transitionMode = TransitionAnimation::Left; - return OperatingMode::HomeScreen; - } else { - (*subEntry) = 0; // Reset back to the main menu - } - // When we exit a list we want to animate to the left - cxt->transitionMode = TransitionAnimation::Left; - } - } + newMode = moveToNextEntry(cxt); break; default: @@ -196,5 +205,5 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { } // Otherwise we stay put for next render iteration - return OperatingMode::SettingsMenu; + return newMode; } \ No newline at end of file From 5e79a48733e2020a3b484deae87b1d6d5e53666c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 18:44:48 +1000 Subject: [PATCH 19/86] Update settingsGUI.cpp --- source/Core/Src/settingsGUI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index 85ab90c53d..812b4f3007 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -824,13 +824,13 @@ static void displayAnimationLoop(void) { OLED::drawCheckbox(getSettingValue(Sett static void displayBrightnessLevel(void) { OLED::printNumber((getSettingValue(SettingsOptions::OLEDBrightness) / BRIGHTNESS_STEP + 1), 1, FontStyle::LARGE); - // While not optimal to apply this here, it is _very_ convienient + // While not optimal to apply this here, it is _very_ convenient OLED::setBrightness(getSettingValue(SettingsOptions::OLEDBrightness)); } static void displayInvertColor(void) { OLED::drawCheckbox(getSettingValue(SettingsOptions::OLEDInversion)); - // While not optimal to apply this here, it is _very_ convienient + // While not optimal to apply this here, it is _very_ convenient OLED::setInverseDisplay(getSettingValue(SettingsOptions::OLEDInversion)); } From b4a257576c9bc70831b93c5258ee69b68aabdfe4 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 19:02:08 +1000 Subject: [PATCH 20/86] Update I2C_Wrapper.cpp --- source/Core/BSP/Miniware/I2C_Wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/BSP/Miniware/I2C_Wrapper.cpp b/source/Core/BSP/Miniware/I2C_Wrapper.cpp index b173c374c8..1ccbdfe54d 100644 --- a/source/Core/BSP/Miniware/I2C_Wrapper.cpp +++ b/source/Core/BSP/Miniware/I2C_Wrapper.cpp @@ -75,7 +75,7 @@ void FRToSI2C::I2C_Unstick() { unstick_I2C(); } void FRToSI2C::unlock() { xSemaphoreGive(I2CSemaphore); } -bool FRToSI2C::lock() { return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; } +bool FRToSI2C::lock() { return xSemaphoreTake(I2CSemaphore, (TickType_t)(TICKS_100MS * 2)) == pdTRUE; } bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { for (int index = 0; index < registersLength; index++) { From 9e5943e19cfe0ab2c9ed5abd08ee1bf07a978e67 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 19:02:14 +1000 Subject: [PATCH 21/86] Update OLED.cpp --- source/Core/Drivers/OLED.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/Core/Drivers/OLED.cpp b/source/Core/Drivers/OLED.cpp index 9188a9730d..cfe992ff08 100644 --- a/source/Core/Drivers/OLED.cpp +++ b/source/Core/Drivers/OLED.cpp @@ -431,14 +431,18 @@ void OLED::setRotation(bool leftHanded) { } void OLED::setBrightness(uint8_t contrast) { - OLED_Setup_Array[15].val = contrast; - I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, &OLED_Setup_Array[14], 2); + if (OLED_Setup_Array[15].val != contrast) { + OLED_Setup_Array[15].val = contrast; + I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, &OLED_Setup_Array[14], 2); + } } void OLED::setInverseDisplay(bool inverse) { uint8_t normalInverseCmd = inverse ? 0xA7 : 0xA6; - OLED_Setup_Array[21].val = normalInverseCmd; - I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, normalInverseCmd); + if (OLED_Setup_Array[21].val != normalInverseCmd) { + OLED_Setup_Array[21].val = normalInverseCmd; + I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, normalInverseCmd); + } } // print a string to the current cursor location, len chars MAX From 1acc6fa3467a05f3091367009d66cacb377f635f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 19:19:22 +1000 Subject: [PATCH 22/86] Rework button handling --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 1412265d5f..f3ce065292 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -79,6 +79,11 @@ OperatingMode moveToNextEntry(guiContext *cxt) { cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::HomeScreen; } + // Check if visible + if (rootSettingsMenu[*mainEntry].isVisible != nullptr && !rootSettingsMenu[*mainEntry].isVisible()) { + // We need to move on as this one isn't visible + return moveToNextEntry(cxt); + } } else { (*subEntry) += 1; // If the new entry is null, we need to exit @@ -88,7 +93,7 @@ OperatingMode moveToNextEntry(guiContext *cxt) { } // Check if visible if (subSettingsMenus[*mainEntry][*subEntry].isVisible != nullptr && !subSettingsMenus[*mainEntry][*subEntry].isVisible()) { - // We need to move on as this one isnt visible + // We need to move on as this one isn't visible return moveToNextEntry(cxt); } } @@ -188,7 +193,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { } break; case BUTTON_B_LONG: - if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) { + if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) { (*autoRepeatTimer) = xTaskGetTickCount(); (*autoRepeatAcceleration) += PRESS_ACCEL_STEP; } else { From d9efc79ef08294944ec441a835e30258358cbbda Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 20:14:25 +1000 Subject: [PATCH 23/86] Fix PD debug at boot --- source/Core/Threads/GUIThread.cpp | 33 +++++++++++-------- .../OperatingModes/USBPDDebug_FUSB.cpp | 18 ++++------ 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 46e3d2219f..e191ba986f 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -71,14 +71,21 @@ OperatingMode guiHandleDraw(void) { break; case OperatingMode::UsbPDDebug: #ifdef HAS_POWER_DEBUG_MENU - showPDDebug(buttons, &context); + newMode = showPDDebug(buttons, &context); break; #else - /*fallthrough*/ + newMode = OperatingMode::InitialisationDone; #endif case OperatingMode::StartupLogo: BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); // TODO needs refactor - newMode = OperatingMode::StartupWarnings; + if (getSettingValue(SettingsOptions::AutoStartMode) == 1) { + // jump directly to the autostart mode + newMode = OperatingMode::Sleeping; + } else if (getSettingValue(SettingsOptions::AutoStartMode) == 2) { + newMode = OperatingMode::Hibernating; + } else { + newMode = OperatingMode::HomeScreen; + } break; default: /* Fallthrough */ @@ -162,6 +169,7 @@ OperatingMode handle_post_init_state() { #else if (buttonsAtDeviceBoot == BUTTON_F_LONG || buttonsAtDeviceBoot == BUTTON_F_SHORT) { #endif + buttonsAtDeviceBoot = BUTTON_NONE; return OperatingMode::UsbPDDebug; } #endif @@ -170,15 +178,7 @@ OperatingMode handle_post_init_state() { 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; + return OperatingMode::StartupLogo; } /* StartGUITask function */ @@ -196,7 +196,6 @@ void startGUITask(void const *argument) { 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 @@ -210,7 +209,13 @@ void startGUITask(void const *argument) { // // Only heat to sleep temperature (but no higher than 75°C for safety) // currentTempTargetDegC = min(sleepTempDegC, 75); // } - // TODO + // Read boot button state + if (getButtonA()) { + buttonsAtDeviceBoot = BUTTON_F_LONG; + } + if (getButtonB()) { + buttonsAtDeviceBoot = BUTTON_B_LONG; + } TickType_t startRender = xTaskGetTickCount(); for (;;) { diff --git a/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp b/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp index 9be7b7e2f7..c22bc673dc 100644 --- a/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp +++ b/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp @@ -49,7 +49,7 @@ OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) { } // Skip not used entries if (voltage_mv == 0) { - *screen++; + (*screen) += 1; } else { // print out this entry of the proposal OLED::printNumber(*screen, 2, FontStyle::SMALL, true); // print the entry number @@ -72,17 +72,13 @@ OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) { } } } else { - *screen = 0; + (*screen) = 0; } - - OLED::refresh(); - if (buttons == BUTTON_B_SHORT) - return OperatingMode::InitialisationDone; - else if (buttons == BUTTON_F_SHORT) { - *screen++; - } - - GUIDelay(); + } + if (buttons == BUTTON_B_SHORT) + return OperatingMode::InitialisationDone; + else if (buttons == BUTTON_F_SHORT) { + (*screen) += 1; } return OperatingMode::UsbPDDebug; } From 3bbeb93f9b785a3cf32557fed8fe1f135ee7c369 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 20:22:31 +1000 Subject: [PATCH 24/86] Fixup not showing right menu options --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index f3ce065292..ed3eca1a1c 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -86,13 +86,16 @@ OperatingMode moveToNextEntry(guiContext *cxt) { } } else { (*subEntry) += 1; + // If the new entry is null, we need to exit - if (subSettingsMenus[*mainEntry][*subEntry].draw == nullptr) { + if (subSettingsMenus[*mainEntry][(*subEntry) - 1].draw == nullptr) { (*subEntry) = 0; // Reset back to the main menu cxt->transitionMode = TransitionAnimation::Left; + // Have to break early to avoid the below check underflowing + return OperatingMode::SettingsMenu; } // Check if visible - if (subSettingsMenus[*mainEntry][*subEntry].isVisible != nullptr && !subSettingsMenus[*mainEntry][*subEntry].isVisible()) { + if (subSettingsMenus[*mainEntry][(*subEntry) - 1].isVisible != nullptr && !subSettingsMenus[*mainEntry][(*subEntry) - 1].isVisible()) { // We need to move on as this one isn't visible return moveToNextEntry(cxt); } From 6cac8fa4142b1b26ca285c471ecd8111bbe13efa Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 20:33:14 +1000 Subject: [PATCH 25/86] silence some warnings --- .../Vendor/NMSIS/Core/Include/core_feature_base.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/Core/BSP/Pinecil/Vendor/NMSIS/Core/Include/core_feature_base.h b/source/Core/BSP/Pinecil/Vendor/NMSIS/Core/Include/core_feature_base.h index 0c0e9c3b62..bbae08c7d1 100644 --- a/source/Core/BSP/Pinecil/Vendor/NMSIS/Core/Include/core_feature_base.h +++ b/source/Core/BSP/Pinecil/Vendor/NMSIS/Core/Include/core_feature_base.h @@ -282,7 +282,7 @@ typedef union { */ #define __RV_CSR_SWAP(csr, val) \ ({ \ - register rv_csr_t __v = (unsigned long)(val); \ + volatile rv_csr_t __v = (unsigned long)(val); \ __ASM volatile("csrrw %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \ __v; \ }) @@ -297,7 +297,7 @@ typedef union { */ #define __RV_CSR_READ(csr) \ ({ \ - register rv_csr_t __v; \ + volatile rv_csr_t __v; \ __ASM volatile("csrr %0, " STRINGIFY(csr) : "=r"(__v) : : "memory"); \ __v; \ }) @@ -312,7 +312,7 @@ typedef union { */ #define __RV_CSR_WRITE(csr, val) \ ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ + volatile rv_csr_t __v = (rv_csr_t)(val); \ __ASM volatile("csrw " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \ }) @@ -328,7 +328,7 @@ typedef union { */ #define __RV_CSR_READ_SET(csr, val) \ ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ + volatile rv_csr_t __v = (rv_csr_t)(val); \ __ASM volatile("csrrs %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \ __v; \ }) @@ -343,7 +343,7 @@ typedef union { */ #define __RV_CSR_SET(csr, val) \ ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ + volatile rv_csr_t __v = (rv_csr_t)(val); \ __ASM volatile("csrs " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \ }) @@ -359,7 +359,7 @@ typedef union { */ #define __RV_CSR_READ_CLEAR(csr, val) \ ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ + volatile rv_csr_t __v = (rv_csr_t)(val); \ __ASM volatile("csrrc %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \ __v; \ }) @@ -374,7 +374,7 @@ typedef union { */ #define __RV_CSR_CLEAR(csr, val) \ ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ + volatile rv_csr_t __v = (rv_csr_t)(val); \ __ASM volatile("csrc " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \ }) #endif /* __ASSEMBLY__ */ From b33f57c082bd0e1badf9f383eb78e001d4e5b693 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 20:45:29 +1000 Subject: [PATCH 26/86] Style cleanup --- source/Core/Threads/OperatingModes/DebugMenu.cpp | 3 ++- source/Core/Threads/OperatingModes/Sleep.cpp | 7 ++++--- source/Core/Threads/OperatingModes/Soldering.cpp | 8 ++++---- .../Core/Threads/OperatingModes/SolderingProfile.cpp | 5 +++-- .../Core/Threads/OperatingModes/TemperatureAdjust.cpp | 10 ++++++---- source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp | 4 ++-- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/source/Core/Threads/OperatingModes/DebugMenu.cpp b/source/Core/Threads/OperatingModes/DebugMenu.cpp index 54db74de6a..e48399b6c9 100644 --- a/source/Core/Threads/OperatingModes/DebugMenu.cpp +++ b/source/Core/Threads/OperatingModes/DebugMenu.cpp @@ -76,8 +76,9 @@ OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) { case 16: // Raw Hall Effect Value { int16_t hallEffectStrength = getRawHallEffect(); - if (hallEffectStrength < 0) + if (hallEffectStrength < 0) { hallEffectStrength = -hallEffectStrength; + } OLED::printNumber(hallEffectStrength, 6, FontStyle::SMALL); } break; #endif diff --git a/source/Core/Threads/OperatingModes/Sleep.cpp b/source/Core/Threads/OperatingModes/Sleep.cpp index 60f3fc31a8..94123eef6c 100644 --- a/source/Core/Threads/OperatingModes/Sleep.cpp +++ b/source/Core/Threads/OperatingModes/Sleep.cpp @@ -10,8 +10,9 @@ OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *c // If in the first two seconds we disable this to let accelerometer warm up #ifdef POW_DC - if (checkForUnderVoltage()) + if (checkForUnderVoltage()) { return OperatingMode::HomeScreen; // return non-zero on error + } #endif if (getSettingValue(SettingsOptions::TemperatureInF)) { currentTempTargetDegC = TipThermoModel::convertFtoC(min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp))); @@ -28,9 +29,9 @@ OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *c OLED::setCursor(0, 8); OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL); OLED::printNumber(tipTemp, 3, FontStyle::SMALL); - if (getSettingValue(SettingsOptions::TemperatureInF)) + if (getSettingValue(SettingsOptions::TemperatureInF)) { OLED::print(SmallSymbolDegF, FontStyle::SMALL); - else { + } else { OLED::print(SmallSymbolDegC, FontStyle::SMALL); } diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index b38b058535..a1b46173a4 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -105,15 +105,15 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { // Update the setpoints for the temperature if (cxt->scratch_state.state2) { - if (getSettingValue(SettingsOptions::TemperatureInF)) + if (getSettingValue(SettingsOptions::TemperatureInF)) { currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp)); - else { + } else { currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); } } else { - if (getSettingValue(SettingsOptions::TemperatureInF)) + if (getSettingValue(SettingsOptions::TemperatureInF)) { currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp)); - else { + } else { currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp)); } } diff --git a/source/Core/Threads/OperatingModes/SolderingProfile.cpp b/source/Core/Threads/OperatingModes/SolderingProfile.cpp index d18dc21d62..1bbc133f7b 100644 --- a/source/Core/Threads/OperatingModes/SolderingProfile.cpp +++ b/source/Core/Threads/OperatingModes/SolderingProfile.cpp @@ -136,10 +136,11 @@ OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cx OLED::print(SmallSymbolSlash, FontStyle::SMALL); OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL); - if (getSettingValue(SettingsOptions::TemperatureInF)) + if (getSettingValue(SettingsOptions::TemperatureInF)) { OLED::print(SmallSymbolDegF, FontStyle::SMALL); - else + } else { OLED::print(SmallSymbolDegC, FontStyle::SMALL); + } // print phase if (cxt->scratch_state.state1 > 0 && cxt->scratch_state.state1 <= getSettingValue(SettingsOptions::ProfilePhases)) { diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index 15b6ccc8a1..73b5b8d69e 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -65,15 +65,17 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx newTemp = (newTemp / delta) * delta; if (getSettingValue(SettingsOptions::TemperatureInF)) { - if (newTemp > MAX_TEMP_F) + if (newTemp > MAX_TEMP_F) { newTemp = MAX_TEMP_F; - if (newTemp < MIN_TEMP_F) + } else if (newTemp < MIN_TEMP_F) { newTemp = MIN_TEMP_F; + } } else { - if (newTemp > MAX_TEMP_C) + if (newTemp > MAX_TEMP_C) { newTemp = MAX_TEMP_C; - if (newTemp < MIN_TEMP_C) + } else if (newTemp < MIN_TEMP_C) { newTemp = MIN_TEMP_C; + } } setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp); } diff --git a/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp b/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp index c22bc673dc..50637259cf 100644 --- a/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp +++ b/source/Core/Threads/OperatingModes/USBPDDebug_FUSB.cpp @@ -75,9 +75,9 @@ OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) { (*screen) = 0; } } - if (buttons == BUTTON_B_SHORT) + if (buttons == BUTTON_B_SHORT) { return OperatingMode::InitialisationDone; - else if (buttons == BUTTON_F_SHORT) { + } else if (buttons == BUTTON_F_SHORT) { (*screen) += 1; } return OperatingMode::UsbPDDebug; From b45f90b66bf4348b53a913df64d9fd6c5e8a8cfb Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 21:09:13 +1000 Subject: [PATCH 27/86] Fkit use bit-bang I2C for Miniware --- source/Core/BSP/Miniware/configuration.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Core/BSP/Miniware/configuration.h b/source/Core/BSP/Miniware/configuration.h index 6fed0d5341..e864bb2913 100644 --- a/source/Core/BSP/Miniware/configuration.h +++ b/source/Core/BSP/Miniware/configuration.h @@ -257,6 +257,9 @@ #define USB_PD_EPR_WATTAGE 0 /*No EPR*/ #define POW_QC 1 #define TEMP_NTC +#define I2C_SOFT_BUS_2 1 +#define I2C_SOFT_BUS_1 1 +#define OLED_I2CBB1 1 #define SC7_ORI_FLIP #endif /* TS80P */ From 4ed4d3410e296565d498a250668a879dd5732bec Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 21 Jul 2023 21:25:04 +1000 Subject: [PATCH 28/86] Update GUIRendering.md --- source/Core/Threads/GUIRendering.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/source/Core/Threads/GUIRendering.md b/source/Core/Threads/GUIRendering.md index c39a6d4381..3e7940498d 100644 --- a/source/Core/Threads/GUIRendering.md +++ b/source/Core/Threads/GUIRendering.md @@ -14,19 +14,21 @@ The tooling provides for left, right and down animations at this point. The use of these gives a notion of "direction" when navigating the menu. ``` - - + ┌───────────┐ + │ Debug Menu│ + └─────┬─────┘ + │ + │ + │ +┌──────────────┐ ┌────┴─────┐ ┌──────────────────┐ ┌─────────────────┐ +│Soldering Mode│ │ │ │ │ │ │ +│ OR ├───────────┤Home Menu ├───────────┤Settings Main Menu├───────────┤Settings sub menu│ +│Reflow Mode│ │ │ │ │ │ │ +└──────────────┘ └──────────┘ └──────────────────┘ └─────────────────┘ ``` The downside of supporting transitions is that for these to work, the code should render the screen _first_ then return the new state. This ensures there is a good working copy in the buffer before the transition changes the view. -## TODO notes - -On settings menu exit: - -``` - OLED::useSecondaryFramebuffer(true); - showExitMenuTransition = true; - -``` +The code that handles the dispatch will run a new render pass again to get the new buffer contents and then transition between the two for you. +At the moment scrolling "Up" isn't implemented but the enumeration is there so that its implementation can follow. From 9c394543cfe8fd04362b9d6c1c14165c759143f8 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 16:43:54 +1000 Subject: [PATCH 29/86] Fixup transition on enter soldering mode --- source/Core/Threads/OperatingModes/HomeScreen.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/OperatingModes/HomeScreen.cpp b/source/Core/Threads/OperatingModes/HomeScreen.cpp index f34f02ebcb..d8cc5d1137 100644 --- a/source/Core/Threads/OperatingModes/HomeScreen.cpp +++ b/source/Core/Threads/OperatingModes/HomeScreen.cpp @@ -38,18 +38,21 @@ OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { return OperatingMode::DebugMenuReadout; break; case BUTTON_F_LONG: - cxt->transitionMode = TransitionAnimation::Left; #ifdef PROFILE_SUPPORT if (!isTipDisconnected()) { + cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::SolderingProfile; + } else { + return OperatingMode::HomeScreen; } #else + cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::TemperatureAdjust; #endif break; case BUTTON_F_SHORT: - cxt->transitionMode = TransitionAnimation::Left; if (!isTipDisconnected()) { + cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::Soldering; } break; From e802373569f5941d919dcce966b84f678284d72c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 17:01:16 +1000 Subject: [PATCH 30/86] Save Settings --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index ed3eca1a1c..9b33c7ecbb 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -76,6 +76,7 @@ OperatingMode moveToNextEntry(guiContext *cxt) { (*mainEntry) += 1; if (rootSettingsMenu[*mainEntry].draw == nullptr) { // We are off the end of the menu now + saveSettings(); cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::HomeScreen; } From 7bf02cc86189a9cee317fb262a9e671f4b20e9d6 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 17:01:28 +1000 Subject: [PATCH 31/86] Fixes for some animations not running Dont bail on animations if keypress is still held --- source/Core/Drivers/OLED.cpp | 14 +++-- source/Core/Drivers/OLED.hpp | 4 +- source/Core/Threads/GUIThread.cpp | 8 ++- .../Core/Threads/OperatingModes/Soldering.cpp | 62 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/source/Core/Drivers/OLED.cpp b/source/Core/Drivers/OLED.cpp index cfe992ff08..187ee9f61e 100644 --- a/source/Core/Drivers/OLED.cpp +++ b/source/Core/Drivers/OLED.cpp @@ -262,7 +262,8 @@ void OLED::maskScrollIndicatorOnOLED() { * If forward is true, this displays a forward navigation to the second framebuffer contents. * Otherwise a rewinding navigation animation is shown to the second framebuffer contents. */ -void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { +void OLED::transitionSecondaryFramebuffer(const bool forwardNavigation, const TickType_t viewEnterTime) { + bool buttonsReleased = getButtonState() == BUTTON_NONE; uint8_t *stripBackPointers[4]; stripBackPointers[0] = &secondFrameBuffer[FRAMEBUFFER_START + 0]; stripBackPointers[1] = &secondFrameBuffer[FRAMEBUFFER_START + OLED_WIDTH]; @@ -317,7 +318,8 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { refresh(); // Now refresh to write out the contents to the new page vTaskDelayUntil(&startDraw, TICKS_100MS / 7); - if (getButtonState() != BUTTON_NONE) { + buttonsReleased |= getButtonState() == BUTTON_NONE; + if (getButtonState() != BUTTON_NONE && buttonsReleased) { memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START); refresh(); // Now refresh to write out the contents to the new page return; @@ -340,8 +342,9 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) { * * **This function blocks until the transition has completed or user presses button** */ -void OLED::transitionScrollDown() { - TickType_t startDraw = xTaskGetTickCount(); +void OLED::transitionScrollDown(const TickType_t viewEnterTime) { + TickType_t startDraw = xTaskGetTickCount(); + bool buttonsReleased = getButtonState() == BUTTON_NONE; for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) { // For each line, we shuffle all bits up a row @@ -378,7 +381,8 @@ void OLED::transitionScrollDown() { secondFrameBuffer[secondStripPos] >>= 1; #endif /* OLED_128x32 */ } - if (getButtonState() != BUTTON_NONE) { + buttonsReleased |= getButtonState() == BUTTON_NONE; + if (getButtonState() != BUTTON_NONE && buttonsReleased) { // Exit early, but have to transition whole buffer memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START); refresh(); // Now refresh to write out the contents to the new page diff --git a/source/Core/Drivers/OLED.hpp b/source/Core/Drivers/OLED.hpp index 04ce62e491..32a27f6d46 100644 --- a/source/Core/Drivers/OLED.hpp +++ b/source/Core/Drivers/OLED.hpp @@ -149,9 +149,9 @@ class OLED { static void drawHeatSymbol(uint8_t state); static void drawScrollIndicator(uint8_t p, uint8_t h); // Draws a scrolling position indicator static void maskScrollIndicatorOnOLED(); - static void transitionSecondaryFramebuffer(bool forwardNavigation); + static void transitionSecondaryFramebuffer(const bool forwardNavigation, const TickType_t viewEnterTime); static void useSecondaryFramebuffer(bool useSecondary); - static void transitionScrollDown(); + static void transitionScrollDown(const TickType_t viewEnterTime); private: static bool checkDisplayBufferChecksum() { diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index e191ba986f..78a0a56ae2 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -117,8 +117,10 @@ OperatingMode guiHandleDraw(void) { newMode = handle_post_init_state(); break; case OperatingMode::Hibernating: + newMode = OperatingMode::HomeScreen; break; case OperatingMode::ThermalRunaway: + newMode = OperatingMode::HomeScreen; break; }; return newMode; @@ -143,13 +145,13 @@ void guiRenderLoop(void) { // Now dispatch the transition switch (context.transitionMode) { case TransitionAnimation::Down: - OLED::transitionScrollDown(); + OLED::transitionScrollDown(context.viewEnterTime); break; case TransitionAnimation::Left: - OLED::transitionSecondaryFramebuffer(false); + OLED::transitionSecondaryFramebuffer(false, context.viewEnterTime); break; case TransitionAnimation::Right: - OLED::transitionSecondaryFramebuffer(true); + OLED::transitionSecondaryFramebuffer(true, context.viewEnterTime); break; case TransitionAnimation::None: default: diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index a1b46173a4..52d4650c7c 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -29,6 +29,7 @@ OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) cxt->scratch_state.state2 = 0; break; case BUTTON_BOTH: + /*Fall through*/ case BUTTON_B_LONG: cxt->transitionMode = TransitionAnimation::Right; return OperatingMode::HomeScreen; @@ -39,13 +40,12 @@ OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) } break; case BUTTON_F_SHORT: - case BUTTON_B_SHORT: { + case BUTTON_B_SHORT: cxt->transitionMode = TransitionAnimation::Left; return OperatingMode::TemperatureAdjust; case BUTTON_BOTH_LONG: if (getSettingValue(SettingsOptions::LockingMode) != 0) { // Lock buttons - if (warnUser(translatedString(Tr->LockingKeysString), buttons)) { cxt->scratch_state.state1 = 1; } @@ -54,7 +54,6 @@ OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) default: break; } - } return OperatingMode::Soldering; } OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { @@ -73,36 +72,6 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { * --> Long hold double button to toggle key lock */ - // First check for button locking & dispatch buttons - - OperatingMode newMode = handleSolderingButtons(buttons, cxt); - if (newMode != OperatingMode::Soldering) { - return newMode; - } - // Check if we should bail due to undervoltage for example - if (checkExitSoldering()) { - setBuzzer(false); - cxt->transitionMode = TransitionAnimation::Right; - return OperatingMode::HomeScreen; - } -#ifdef NO_SLEEP_MODE - - if (shouldShutdown()) { - // shutdown - currentTempTargetDegC = 0; - return OperatingMode::HomeScreen; - } -#endif - if (shouldBeSleeping()) { - return OperatingMode::Sleeping; - } - - if (heaterThermalRunaway) { - currentTempTargetDegC = 0; // heater control off - heaterThermalRunaway = false; - return OperatingMode::ThermalRunaway; - } - // Update the setpoints for the temperature if (cxt->scratch_state.state2) { if (getSettingValue(SettingsOptions::TemperatureInF)) { @@ -178,5 +147,30 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { } else { basicSolderingStatus(cxt->scratch_state.state2); } - return OperatingMode::Soldering; // Stay put + // Check if we should bail due to undervoltage for example + if (checkExitSoldering()) { + setBuzzer(false); + cxt->transitionMode = TransitionAnimation::Right; + return OperatingMode::HomeScreen; + } +#ifdef NO_SLEEP_MODE + + if (shouldShutdown()) { + // shutdown + currentTempTargetDegC = 0; + cxt->transitionMode = TransitionAnimation::Right; + return OperatingMode::HomeScreen; + } +#endif + if (shouldBeSleeping()) { + return OperatingMode::Sleeping; + } + + if (heaterThermalRunaway) { + currentTempTargetDegC = 0; // heater control off + heaterThermalRunaway = false; + cxt->transitionMode = TransitionAnimation::Right; + return OperatingMode::ThermalRunaway; + } + return handleSolderingButtons(buttons, cxt); } From 0abb9581e962c3d4db81f14cd85bf0035e3f0d15 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 17:25:27 +1000 Subject: [PATCH 32/86] Fixup settings acceleration --- source/Core/Threads/GUIRendering.md | 8 +++++++- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/GUIRendering.md b/source/Core/Threads/GUIRendering.md index 3e7940498d..8f6fcee18e 100644 --- a/source/Core/Threads/GUIRendering.md +++ b/source/Core/Threads/GUIRendering.md @@ -24,7 +24,13 @@ The use of these gives a notion of "direction" when navigating the menu. │Soldering Mode│ │ │ │ │ │ │ │ OR ├───────────┤Home Menu ├───────────┤Settings Main Menu├───────────┤Settings sub menu│ │Reflow Mode│ │ │ │ │ │ │ -└──────────────┘ └──────────┘ └──────────────────┘ └─────────────────┘ +└──────────────┘ └──────────┘ └──────────────────┘ └─────────┬───────┘ + │ + ┌─────────┴───────┐ + │ │ + │Settings sub menu│ + │ │ + └─────────────────┘ ``` The downside of supporting transitions is that for these to work, the code should render the screen _first_ then return the new state. diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 9b33c7ecbb..fcb7447bd9 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -170,7 +170,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { case BUTTON_F_LONG: if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) { if (callIncrementHandler()) { - (*autoRepeatTimer) = 1000; + (*autoRepeatTimer) = TICKS_SECOND * 2; } else { (*autoRepeatTimer) = 0; } @@ -212,6 +212,9 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { default: break; } + if ((PRESS_ACCEL_INTERVAL_MAX - (*autoRepeatAcceleration)) < PRESS_ACCEL_INTERVAL_MIN) { + (*autoRepeatAcceleration) = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; + } // Otherwise we stay put for next render iteration return newMode; From c14742220b1f5d7ffdda4612a0291365aa5d7f7f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 17:55:07 +1000 Subject: [PATCH 33/86] OLED Up animation --- source/Core/Drivers/OLED.cpp | 59 ++++++++++++++++++++++++++++++++++-- source/Core/Drivers/OLED.hpp | 1 + 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/source/Core/Drivers/OLED.cpp b/source/Core/Drivers/OLED.cpp index 187ee9f61e..c0a8b06a37 100644 --- a/source/Core/Drivers/OLED.cpp +++ b/source/Core/Drivers/OLED.cpp @@ -335,6 +335,7 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) { setFramebuffer(screenBuffer); } } + /** * This assumes that the current display output buffer has the current on screen contents * Then the secondary buffer has the "new" contents to be slid up onto the screen @@ -371,9 +372,9 @@ void OLED::transitionScrollDown(const TickType_t viewEnterTime) { // Finally on the bottom row; we shuffle it up ready secondFrameBuffer[fourthStripPos] >>= 1; #else - // Move the MSB off the first strip, and pop MSB from second strip onto the first strip + // Move the LSB off the first strip, and pop MSB from second strip onto the first strip screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] >> 1) | ((screenBuffer[secondStripPos] & 0x01) << 7); - // Now shuffle off the second strip MSB, and replace it with the MSB of the secondary buffer + // Now shuffle off the second strip MSB, and replace it with the LSB of the secondary buffer screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] >> 1) | ((secondFrameBuffer[firstStripPos] & 0x01) << 7); // Finally, do the shuffle on the second frame buffer secondFrameBuffer[firstStripPos] = (secondFrameBuffer[firstStripPos] >> 1) | ((secondFrameBuffer[secondStripPos] & 0x01) << 7); @@ -392,6 +393,60 @@ void OLED::transitionScrollDown(const TickType_t viewEnterTime) { vTaskDelayUntil(&startDraw, TICKS_100MS / 7); } } +/** + * This assumes that the current display output buffer has the current on screen contents + * Then the secondary buffer has the "new" contents to be slid down onto the screen + * Sadly we cant use the hardware scroll as some devices with the 128x32 screens dont have the GRAM for holding both screens at once + * + * **This function blocks until the transition has completed or user presses button** + */ +void OLED::transitionScrollUp(const TickType_t viewEnterTime) { + TickType_t startDraw = xTaskGetTickCount(); + bool buttonsReleased = getButtonState() == BUTTON_NONE; + + for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) { + // For each line, we shuffle all bits down a row + for (uint8_t xPos = 0; xPos < OLED_WIDTH; xPos++) { + const uint16_t firstStripPos = FRAMEBUFFER_START + xPos; + const uint16_t secondStripPos = firstStripPos + OLED_WIDTH; +#ifdef OLED_128x32 + // For 32 pixel high OLED's we have four strips to tailchain + const uint16_t thirdStripPos = secondStripPos + OLED_WIDTH; + const uint16_t fourthStripPos = thirdStripPos + OLED_WIDTH; + // We are shffling LSB's off the end and pushing bits down + screenBuffer[fourthStripPos] = (screenBuffer[fourthStripPos] << 1) | ((screenBuffer[thirdStripPos] & 0x80) >> 7); + screenBuffer[thirdStripPos] = (screenBuffer[thirdStripPos] << 1) | ((screenBuffer[secondStripPos] & 0x80) >> 7); + screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] << 1) | ((screenBuffer[firstStripPos] & 0x80) >> 7); + screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] << 1) | ((secondFrameBuffer[fourthStripPos] & 0x80) >> 7); + + secondFrameBuffer[fourthStripPos] = (secondFrameBuffer[fourthStripPos] << 1) | ((secondFrameBuffer[thirdStripPos] & 0x80) >> 7); + secondFrameBuffer[thirdStripPos] = (secondFrameBuffer[thirdStripPos] << 1) | ((secondFrameBuffer[secondStripPos] & 0x80) >> 7); + secondFrameBuffer[secondStripPos] = (secondFrameBuffer[secondStripPos] << 1) | ((secondFrameBuffer[firstStripPos] & 0x80) >> 7); + // Finally on the bottom row; we shuffle it up ready + secondFrameBuffer[firstStripPos] <<= 1; +#else + // We pop the LSB off the bottom row, and replace the MSB in that byte with the LSB of the row above + screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] << 1) | ((screenBuffer[firstStripPos] & 0x80) >> 7); + // Move the LSB off the first strip, and pop MSB from second strip onto the first strip + screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] << 1) | ((secondFrameBuffer[secondStripPos] & 0x80) >> 7); + + // Finally, do the shuffle on the second frame buffer + secondFrameBuffer[secondStripPos] = (secondFrameBuffer[firstStripPos] << 1) | ((secondFrameBuffer[secondStripPos] & 0x80) >> 7); + // Finally on the bottom row; we shuffle it up ready + secondFrameBuffer[firstStripPos] <<= 1; +#endif /* OLED_128x32 */ + } + buttonsReleased |= getButtonState() == BUTTON_NONE; + if (getButtonState() != BUTTON_NONE && buttonsReleased) { + // Exit early, but have to transition whole buffer + memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START); + refresh(); // Now refresh to write out the contents to the new page + return; + } + refresh(); // Now refresh to write out the contents to the new page + vTaskDelayUntil(&startDraw, TICKS_100MS / 7); + } +} void OLED::setRotation(bool leftHanded) { #ifdef OLED_FLIP diff --git a/source/Core/Drivers/OLED.hpp b/source/Core/Drivers/OLED.hpp index 32a27f6d46..408119488c 100644 --- a/source/Core/Drivers/OLED.hpp +++ b/source/Core/Drivers/OLED.hpp @@ -152,6 +152,7 @@ class OLED { static void transitionSecondaryFramebuffer(const bool forwardNavigation, const TickType_t viewEnterTime); static void useSecondaryFramebuffer(bool useSecondary); static void transitionScrollDown(const TickType_t viewEnterTime); + static void transitionScrollUp(const TickType_t viewEnterTime); private: static bool checkDisplayBufferChecksum() { From 300e19eb8b1464a35e48eac818a5d35f2864e710 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 17:55:15 +1000 Subject: [PATCH 34/86] Link up/down on debug meny --- source/Core/Threads/GUIThread.cpp | 3 +++ source/Core/Threads/OperatingModes/DebugMenu.cpp | 2 +- source/Core/Threads/OperatingModes/HomeScreen.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 78a0a56ae2..2a30527cb7 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -153,6 +153,9 @@ void guiRenderLoop(void) { 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 diff --git a/source/Core/Threads/OperatingModes/DebugMenu.cpp b/source/Core/Threads/OperatingModes/DebugMenu.cpp index e48399b6c9..c7ef139be7 100644 --- a/source/Core/Threads/OperatingModes/DebugMenu.cpp +++ b/source/Core/Threads/OperatingModes/DebugMenu.cpp @@ -88,7 +88,7 @@ OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) { } if (buttons == BUTTON_B_SHORT) { - cxt->transitionMode = TransitionAnimation::Up; + cxt->transitionMode = TransitionAnimation::Down; return OperatingMode::InitialisationDone; } else if (buttons == BUTTON_F_SHORT) { cxt->scratch_state.state1++; diff --git a/source/Core/Threads/OperatingModes/HomeScreen.cpp b/source/Core/Threads/OperatingModes/HomeScreen.cpp index d8cc5d1137..5672b38da8 100644 --- a/source/Core/Threads/OperatingModes/HomeScreen.cpp +++ b/source/Core/Threads/OperatingModes/HomeScreen.cpp @@ -34,7 +34,7 @@ OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) { break; case BUTTON_B_LONG: - cxt->transitionMode = TransitionAnimation::Down; + cxt->transitionMode = TransitionAnimation::Up; return OperatingMode::DebugMenuReadout; break; case BUTTON_F_LONG: From 9b9d50b6a3dff3969b2e8de4833251bc83268537 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 18:18:07 +1000 Subject: [PATCH 35/86] Make all accelerometers I2C bus aware Update accelerometers_common.h --- source/Core/Drivers/BMA223.cpp | 15 ++++++++------- source/Core/Drivers/BMA223.hpp | 1 + source/Core/Drivers/MMA8652FC.cpp | 30 +++++++++++++++++------------- source/Core/Drivers/MSA301.cpp | 10 +++++----- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/source/Core/Drivers/BMA223.cpp b/source/Core/Drivers/BMA223.cpp index ab7757e589..bf91b7c053 100644 --- a/source/Core/Drivers/BMA223.cpp +++ b/source/Core/Drivers/BMA223.cpp @@ -9,6 +9,7 @@ #include #include + bool BMA223::detect() { if (ACCEL_I2C_CLASS::probe(BMA223_ADDRESS)) { // Read chip id to ensure its not an address collision @@ -22,13 +23,13 @@ bool BMA223::detect() { } static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = { - // - // - { BMA223_PMU_RANGE, 0b00000011, 0}, // 2G range - { BMA223_PMU_BW, 0b00001101, 0}, // 250Hz filter - { BMA223_PMU_LPW, 0b00000000, 0}, // Full power - { BMA223_ACCD_HBW, 0b00000000, 0}, // filtered data out - { BMA223_INT_OUT_CTRL, 0b00001010, 0}, // interrupt active low and OD to get it hi-z + // + // + {BMA223_PMU_RANGE, 0b00000011, 0}, // 2G range + {BMA223_PMU_BW, 0b00001101, 0}, // 250Hz filter + {BMA223_PMU_LPW, 0b00000000, 0}, // Full power + {BMA223_ACCD_HBW, 0b00000000, 0}, // filtered data out + {BMA223_INT_OUT_CTRL, 0b00001010, 0}, // interrupt active low and OD to get it hi-z {BMA223_INT_RST_LATCH, 0b10000000, 0}, // interrupt active low and OD to get it hi-z { BMA223_INT_EN_0, 0b01000000, 0}, // Enable orientation { BMA223_INT_A, 0b00100111, 0}, // Setup orientation detection diff --git a/source/Core/Drivers/BMA223.hpp b/source/Core/Drivers/BMA223.hpp index 34fff54364..54c0db517c 100644 --- a/source/Core/Drivers/BMA223.hpp +++ b/source/Core/Drivers/BMA223.hpp @@ -9,6 +9,7 @@ #define CORE_DRIVERS_BMA223_HPP_ #include "BMA223_defines.h" #include "BSP.h" +#include "accelerometers_common.h" #include "I2C_Wrapper.hpp" #include "accelerometers_common.h" diff --git a/source/Core/Drivers/MMA8652FC.cpp b/source/Core/Drivers/MMA8652FC.cpp index ac489d525d..81b1c104bf 100644 --- a/source/Core/Drivers/MMA8652FC.cpp +++ b/source/Core/Drivers/MMA8652FC.cpp @@ -10,20 +10,24 @@ #include "cmsis_os.h" #include +#include "MMA8652FC.hpp" +#include "accelerometers_common.h" +#include "cmsis_os.h" + static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = { - { CTRL_REG2, 0, 0}, // Normal mode - { CTRL_REG2, 0x40, 2}, // Reset all registers to POR values - { FF_MT_CFG_REG, 0x78, 0}, // Enable motion detection for X, Y, Z axis, latch disabled - { PL_CFG_REG, 0x40, 0}, // Enable the orientation detection - { PL_COUNT_REG, 200, 0}, // 200 count debounce - { PL_BF_ZCOMP_REG, 0b01000111, 0}, // Set the threshold to 42 degrees - { P_L_THS_REG, 0b10011100, 0}, // Up the trip angles - { CTRL_REG4, 0x01 | (1 << 4), 0}, // Enable dataready interrupt & orientation interrupt - { CTRL_REG5, 0x01, 0}, // Route data ready interrupts to INT1 ->PB5 ->EXTI5, leaving orientation routed to INT2 - { CTRL_REG2, 0x12, 0}, // Set maximum resolution oversampling - { XYZ_DATA_CFG_REG, (1 << 4), 0}, // select high pass filtered data - {HP_FILTER_CUTOFF_REG, 0x03, 0}, // select high pass filtered data - { CTRL_REG1, 0x19, 0} // ODR=12 Hz, Active mode + {CTRL_REG2, 0, 0}, // Normal mode + {CTRL_REG2, 0x40, 2}, // Reset all registers to POR values + {FF_MT_CFG_REG, 0x78, 0}, // Enable motion detection for X, Y, Z axis, latch disabled + {PL_CFG_REG, 0x40, 0}, // Enable the orientation detection + {PL_COUNT_REG, 200, 0}, // 200 count debounce + {PL_BF_ZCOMP_REG, 0b01000111, 0}, // Set the threshold to 42 degrees + {P_L_THS_REG, 0b10011100, 0}, // Up the trip angles + {CTRL_REG4, 0x01 | (1 << 4), 0}, // Enable dataready interrupt & orientation interrupt + {CTRL_REG5, 0x01, 0}, // Route data ready interrupts to INT1 ->PB5 ->EXTI5, leaving orientation routed to INT2 + {CTRL_REG2, 0x12, 0}, // Set maximum resolution oversampling + {XYZ_DATA_CFG_REG, (1 << 4), 0}, // select high pass filtered data + {HP_FILTER_CUTOFF_REG, 0x03, 0}, // select high pass filtered data + {CTRL_REG1, 0x19, 0} // ODR=12 Hz, Active mode }; bool MMA8652FC::initalize() { return ACCEL_I2C_CLASS::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } diff --git a/source/Core/Drivers/MSA301.cpp b/source/Core/Drivers/MSA301.cpp index d732076963..7b3d2091aa 100644 --- a/source/Core/Drivers/MSA301.cpp +++ b/source/Core/Drivers/MSA301.cpp @@ -13,11 +13,11 @@ bool MSA301::detect() { return ACCEL_I2C_CLASS::probe(MSA301_I2C_ADDRESS); } static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = { - // - // - { MSA301_REG_ODR, 0b00001000, 1}, // X/Y/Z enabled @ 250Hz - {MSA301_REG_POWERMODE, 0b0001001, 1}, // Normal mode - { MSA301_REG_RESRANGE, 0b00000001, 0}, // 14bit resolution @ 4G range + // + // + {MSA301_REG_ODR, 0b00001000, 1}, // X/Y/Z enabled @ 250Hz + {MSA301_REG_POWERMODE, 0b0001001, 1}, // Normal mode + {MSA301_REG_RESRANGE, 0b00000001, 0}, // 14bit resolution @ 4G range {MSA301_REG_ORIENT_HY, 0b01000000, 0}, // 4*62.5mg hyst, no blocking, symmetrical { MSA301_REG_INTSET0, 1 << 6, 0}, // Turn on orientation detection (by enabling its interrupt) }; From 07fa6716e8509bd8a89a0af26e6d6efd0235ac69 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 18:18:29 +1000 Subject: [PATCH 36/86] Make I2C mag optional --- source/Core/BSP/Pinecil/configuration.h | 11 ++++++----- source/Core/BSP/Pinecilv2/configuration.h | 1 + source/Core/Drivers/Si7210.cpp | 4 +++- source/Core/Drivers/Si7210.h | 5 ++++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/source/Core/BSP/Pinecil/configuration.h b/source/Core/BSP/Pinecil/configuration.h index bced820735..7eaf902777 100644 --- a/source/Core/BSP/Pinecil/configuration.h +++ b/source/Core/BSP/Pinecil/configuration.h @@ -147,11 +147,12 @@ #define POW_PD 1 #define USB_PD_EPR_WATTAGE 0 /*No EPR (Yet?) */ -#define POW_PD_EXT 0 -#define POW_QC 1 -#define POW_DC 1 -#define POW_QC_20V 1 -#define ENABLE_QC2 1 +#define POW_PD_EXT 0 +#define POW_QC 1 +#define POW_DC 1 +#define POW_QC_20V 1 +#define ENABLE_QC2 1 +#define MAG_SLEEP_SUPPORT 1 #define TEMP_TMP36 #define ACCEL_BMA #define ACCEL_SC7 diff --git a/source/Core/BSP/Pinecilv2/configuration.h b/source/Core/BSP/Pinecilv2/configuration.h index 84425f0e1a..094727195c 100644 --- a/source/Core/BSP/Pinecilv2/configuration.h +++ b/source/Core/BSP/Pinecilv2/configuration.h @@ -153,6 +153,7 @@ #define POW_QC_20V 1 // Supported features #define POW_EPR 1 #define ENABLE_QC2 1 +#define MAG_SLEEP_SUPPORT 1 #define DEVICE_HAS_VALIDATION_SUPPORT #define TEMP_NTC #define ACCEL_BMA diff --git a/source/Core/Drivers/Si7210.cpp b/source/Core/Drivers/Si7210.cpp index 0bffb671a4..8683672f01 100644 --- a/source/Core/Drivers/Si7210.cpp +++ b/source/Core/Drivers/Si7210.cpp @@ -13,7 +13,8 @@ #include "Si7210_defines.h" #include "accelerometers_common.h" #include -bool Si7210::detect() { return ACCEL_I2C_CLASS::wakePart(SI7210_ADDRESS); } +#ifdef MAG_SLEEP_SUPPORT +bool Si7210::detect() { return FRToSI2C::wakePart(SI7210_ADDRESS); } bool Si7210::init() { // Turn on auto increment and sanity check ID @@ -185,3 +186,4 @@ bool Si7210::set_high_range() { worked &= write_reg(SI7210_A5, 0, val); return worked; } +#endif // MAG_SLEEP_SUPPORT \ No newline at end of file diff --git a/source/Core/Drivers/Si7210.h b/source/Core/Drivers/Si7210.h index 305c91ea0a..2bbc46bea6 100644 --- a/source/Core/Drivers/Si7210.h +++ b/source/Core/Drivers/Si7210.h @@ -7,7 +7,10 @@ #ifndef CORE_DRIVERS_SI7210_H_ #define CORE_DRIVERS_SI7210_H_ +#include "configuration.h" #include + +#ifdef MAG_SLEEP_SUPPORT class Si7210 { public: // Return true if present @@ -23,5 +26,5 @@ class Si7210 { static bool get_field_strength(int16_t *field); static bool set_high_range(); }; - +#endif // MAG_SLEEP_SUPPORT #endif /* CORE_DRIVERS_SI7210_H_ */ From c71b69430c6866be17b1a42b3b839fa8ac15c209 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 22 Jul 2023 18:18:44 +1000 Subject: [PATCH 37/86] Miniware -> Only Bit-Bang I2C --- source/Core/BSP/Miniware/I2C_Wrapper.cpp | 89 - .../Inc/stm32f1xx_hal_i2c.h | 634 --- .../Src/stm32f1xx_hal_i2c.c | 4569 ----------------- source/Core/BSP/Miniware/configuration.h | 7 + 4 files changed, 7 insertions(+), 5292 deletions(-) delete mode 100644 source/Core/BSP/Miniware/I2C_Wrapper.cpp delete mode 100644 source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c diff --git a/source/Core/BSP/Miniware/I2C_Wrapper.cpp b/source/Core/BSP/Miniware/I2C_Wrapper.cpp deleted file mode 100644 index 1ccbdfe54d..0000000000 --- a/source/Core/BSP/Miniware/I2C_Wrapper.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * FRToSI2C.cpp - * - * Created on: 14Apr.,2018 - * Author: Ralim - */ -#include "BSP.h" -#include "Setup.h" -#include -SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; -StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; - -void FRToSI2C::CpltCallback() { - hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) - if (I2CSemaphore) { - xSemaphoreGiveFromISR(I2CSemaphore, NULL); - } -} - -bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { - - if (!lock()) - return false; - if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { - - I2C_Unstick(); - unlock(); - return false; - } - - unlock(); - return true; -} -bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); } - -uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { - uint8_t tx_data[1]; - Mem_Read(add, reg, tx_data, 1); - return tx_data[0]; -} -bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { - - if (!lock()) - return false; - if (HAL_I2C_Mem_Write_IT(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size) != HAL_OK) { - - I2C_Unstick(); - unlock(); - return false; - } - return true; -} - -bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - if (HAL_I2C_Master_Transmit_IT(&hi2c1, DevAddress, pData, Size) != HAL_OK) { - I2C_Unstick(); - unlock(); - return false; - } - return true; -} - -bool FRToSI2C::probe(uint16_t DevAddress) { - if (!lock()) - return false; - uint8_t buffer[1]; - bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; - unlock(); - return worked; -} - -void FRToSI2C::I2C_Unstick() { unstick_I2C(); } - -void FRToSI2C::unlock() { xSemaphoreGive(I2CSemaphore); } - -bool FRToSI2C::lock() { return xSemaphoreTake(I2CSemaphore, (TickType_t)(TICKS_100MS * 2)) == pdTRUE; } - -bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { - for (int index = 0; index < registersLength; index++) { - if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { - return false; - } - if (registers[index].pause_ms) - delay_ms(registers[index].pause_ms); - } - return true; -} diff --git a/source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_i2c.h b/source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_i2c.h index 817f86e98c..a9c8a22765 100644 --- a/source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_i2c.h +++ b/source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_i2c.h @@ -1,639 +1,5 @@ -/** - ****************************************************************************** - * @file stm32f1xx_hal_i2c.h - * @author MCD Application Team - * @brief Header file of I2C HAL module. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ -/* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32F1xx_HAL_I2C_H #define __STM32F1xx_HAL_I2C_H -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f1xx_hal_def.h" - -/** @addtogroup STM32F1xx_HAL_Driver - * @{ - */ - -/** @addtogroup I2C - * @{ - */ - -/* Exported types ------------------------------------------------------------*/ -/** @defgroup I2C_Exported_Types I2C Exported Types - * @{ - */ - -/** - * @brief I2C Configuration Structure definition - */ -typedef struct { - uint32_t ClockSpeed; /*!< Specifies the clock frequency. - This parameter must be set to a value lower than 400kHz */ - - uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle. - This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ - - uint32_t OwnAddress1; /*!< Specifies the first device own address. - This parameter can be a 7-bit or 10-bit address. */ - - uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. - This parameter can be a value of @ref I2C_addressing_mode */ - - uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. - This parameter can be a value of @ref I2C_dual_addressing_mode */ - - uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected - This parameter can be a 7-bit address. */ - - uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. - This parameter can be a value of @ref I2C_general_call_addressing_mode */ - - uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. - This parameter can be a value of @ref I2C_nostretch_mode */ - -} I2C_InitTypeDef; - -/** - * @brief HAL State structure definition - * @note HAL I2C State value coding follow below described bitmap : - * b7-b6 Error information - * 00 : No Error - * 01 : Abort (Abort user request on going) - * 10 : Timeout - * 11 : Error - * b5 IP initilisation status - * 0 : Reset (IP not initialized) - * 1 : Init done (IP initialized and ready to use. HAL I2C Init function called) - * b4 (not used) - * x : Should be set to 0 - * b3 - * 0 : Ready or Busy (No Listen mode ongoing) - * 1 : Listen (IP in Address Listen Mode) - * b2 Intrinsic process state - * 0 : Ready - * 1 : Busy (IP busy with some configuration or internal operations) - * b1 Rx state - * 0 : Ready (no Rx operation ongoing) - * 1 : Busy (Rx operation ongoing) - * b0 Tx state - * 0 : Ready (no Tx operation ongoing) - * 1 : Busy (Tx operation ongoing) - */ -typedef enum { - HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ - HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ - HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ - HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ - HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ - HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ - HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission - process is ongoing */ - HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception - process is ongoing */ - HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ - HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ - HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ - -} HAL_I2C_StateTypeDef; - -/** - * @brief HAL Mode structure definition - * @note HAL I2C Mode value coding follow below described bitmap : - * b7 (not used) - * x : Should be set to 0 - * b6 - * 0 : None - * 1 : Memory (HAL I2C communication is in Memory Mode) - * b5 - * 0 : None - * 1 : Slave (HAL I2C communication is in Slave Mode) - * b4 - * 0 : None - * 1 : Master (HAL I2C communication is in Master Mode) - * b3-b2-b1-b0 (not used) - * xxxx : Should be set to 0000 - */ -typedef enum { - HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */ - HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ - HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ - HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ - -} HAL_I2C_ModeTypeDef; - -/** - * @brief I2C handle Structure definition - */ -typedef struct { - I2C_TypeDef *Instance; /*!< I2C registers base address */ - - I2C_InitTypeDef Init; /*!< I2C communication parameters */ - - uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */ - - uint16_t XferSize; /*!< I2C transfer size */ - - __IO uint16_t XferCount; /*!< I2C transfer counter */ - - __IO uint32_t XferOptions; /*!< I2C transfer options */ - - __IO uint32_t PreviousState; /*!< I2C communication Previous state and mode - context for internal usage */ - - DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */ - - DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */ - - HAL_LockTypeDef Lock; /*!< I2C locking object */ - - __IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */ - - __IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */ - - __IO uint32_t ErrorCode; /*!< I2C Error code */ - - __IO uint32_t Devaddress; /*!< I2C Target device address */ - - __IO uint32_t Memaddress; /*!< I2C Target memory address */ - - __IO uint32_t MemaddSize; /*!< I2C Target memory address size */ - - __IO uint32_t EventCount; /*!< I2C Event counter */ - -} I2C_HandleTypeDef; - -/** - * @} - */ - -/* Exported constants --------------------------------------------------------*/ -/** @defgroup I2C_Exported_Constants I2C Exported Constants - * @{ - */ - -/** @defgroup I2C_Error_Code I2C Error Code - * @brief I2C Error Code - * @{ - */ -#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */ -#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */ -#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */ -#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */ -#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */ -#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */ -#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */ -/** - * @} - */ - -/** @defgroup I2C_duty_cycle_in_fast_mode I2C duty cycle in fast mode - * @{ - */ -#define I2C_DUTYCYCLE_2 0x00000000U -#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY -/** - * @} - */ - -/** @defgroup I2C_addressing_mode I2C addressing mode - * @{ - */ -#define I2C_ADDRESSINGMODE_7BIT 0x00004000U -// #define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U) -/** - * @} - */ - -/** @defgroup I2C_dual_addressing_mode I2C dual addressing mode - * @{ - */ -#define I2C_DUALADDRESS_DISABLE 0x00000000U -#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL -/** - * @} - */ - -/** @defgroup I2C_general_call_addressing_mode I2C general call addressing mode - * @{ - */ -#define I2C_GENERALCALL_DISABLE 0x00000000U -#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC -/** - * @} - */ - -/** @defgroup I2C_nostretch_mode I2C nostretch mode - * @{ - */ -#define I2C_NOSTRETCH_DISABLE 0x00000000U -#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH -/** - * @} - */ - -/** @defgroup I2C_Memory_Address_Size I2C Memory Address Size - * @{ - */ -#define I2C_MEMADD_SIZE_8BIT 0x00000001U -#define I2C_MEMADD_SIZE_16BIT 0x00000010U -/** - * @} - */ - -/** @defgroup I2C_XferDirection_definition I2C XferDirection definition - * @{ - */ -#define I2C_DIRECTION_RECEIVE 0x00000000U -#define I2C_DIRECTION_TRANSMIT 0x00000001U -/** - * @} - */ - -/** @defgroup I2C_XferOptions_definition I2C XferOptions definition - * @{ - */ -#define I2C_FIRST_FRAME 0x00000001U -#define I2C_NEXT_FRAME 0x00000002U -#define I2C_FIRST_AND_LAST_FRAME 0x00000004U -#define I2C_LAST_FRAME 0x00000008U -/** - * @} - */ - -/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition - * @{ - */ -#define I2C_IT_BUF I2C_CR2_ITBUFEN -#define I2C_IT_EVT I2C_CR2_ITEVTEN -#define I2C_IT_ERR I2C_CR2_ITERREN -/** - * @} - */ - -/** @defgroup I2C_Flag_definition I2C Flag definition - * @{ - */ -#define I2C_FLAG_SMBALERT 0x00018000U -#define I2C_FLAG_TIMEOUT 0x00014000U -#define I2C_FLAG_PECERR 0x00011000U -#define I2C_FLAG_OVR 0x00010800U -#define I2C_FLAG_AF 0x00010400U -#define I2C_FLAG_ARLO 0x00010200U -#define I2C_FLAG_BERR 0x00010100U -#define I2C_FLAG_TXE 0x00010080U -#define I2C_FLAG_RXNE 0x00010040U -#define I2C_FLAG_STOPF 0x00010010U -// #define I2C_FLAG_ADD10 0x00010008U -#define I2C_FLAG_BTF 0x00010004U -#define I2C_FLAG_ADDR 0x00010002U -#define I2C_FLAG_SB 0x00010001U -#define I2C_FLAG_DUALF 0x00100080U -#define I2C_FLAG_SMBHOST 0x00100040U -#define I2C_FLAG_SMBDEFAULT 0x00100020U -#define I2C_FLAG_GENCALL 0x00100010U -#define I2C_FLAG_TRA 0x00100004U -#define I2C_FLAG_BUSY 0x00100002U -#define I2C_FLAG_MSL 0x00100001U -/** - * @} - */ - -/** - * @} - */ - -/* Exported macro ------------------------------------------------------------*/ -/** @defgroup I2C_Exported_Macros I2C Exported Macros - * @{ - */ - -/** @brief Reset I2C handle state - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. - * @retval None - */ -#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET) - -/** @brief Enable or disable the specified I2C interrupts. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. - * @param __INTERRUPT__: specifies the interrupt source to enable or disable. - * This parameter can be one of the following values: - * @arg I2C_IT_BUF: Buffer interrupt enable - * @arg I2C_IT_EVT: Event interrupt enable - * @arg I2C_IT_ERR: Error interrupt enable - * @retval None - */ -#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 |= (__INTERRUPT__)) -#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 &= (~(__INTERRUPT__))) - -/** @brief Checks if the specified I2C interrupt source is enabled or disabled. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. - * @param __INTERRUPT__: specifies the I2C interrupt source to check. - * This parameter can be one of the following values: - * @arg I2C_IT_BUF: Buffer interrupt enable - * @arg I2C_IT_EVT: Event interrupt enable - * @arg I2C_IT_ERR: Error interrupt enable - * @retval The new state of __INTERRUPT__ (TRUE or FALSE). - */ -#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) - -/** @brief Checks whether the specified I2C flag is set or not. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. - * @param __FLAG__: specifies the flag to check. - * This parameter can be one of the following values: - * @arg I2C_FLAG_SMBALERT: SMBus Alert flag - * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag - * @arg I2C_FLAG_PECERR: PEC error in reception flag - * @arg I2C_FLAG_OVR: Overrun/Underrun flag - * @arg I2C_FLAG_AF: Acknowledge failure flag - * @arg I2C_FLAG_ARLO: Arbitration lost flag - * @arg I2C_FLAG_BERR: Bus error flag - * @arg I2C_FLAG_TXE: Data register empty flag - * @arg I2C_FLAG_RXNE: Data register not empty flag - * @arg I2C_FLAG_STOPF: Stop detection flag - * @arg I2C_FLAG_ADD10: 10-bit header sent flag - * @arg I2C_FLAG_BTF: Byte transfer finished flag - * @arg I2C_FLAG_ADDR: Address sent flag - * Address matched flag - * @arg I2C_FLAG_SB: Start bit flag - * @arg I2C_FLAG_DUALF: Dual flag - * @arg I2C_FLAG_SMBHOST: SMBus host header - * @arg I2C_FLAG_SMBDEFAULT: SMBus default header - * @arg I2C_FLAG_GENCALL: General call header flag - * @arg I2C_FLAG_TRA: Transmitter/Receiver flag - * @arg I2C_FLAG_BUSY: Bus busy flag - * @arg I2C_FLAG_MSL: Master/Slave flag - * @retval The new state of __FLAG__ (TRUE or FALSE). - */ -#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) \ - ((((uint8_t)((__FLAG__) >> 16U)) == 0x01U) ? ((((__HANDLE__)->Instance->SR1) & ((__FLAG__)&I2C_FLAG_MASK)) == ((__FLAG__)&I2C_FLAG_MASK)) \ - : ((((__HANDLE__)->Instance->SR2) & ((__FLAG__)&I2C_FLAG_MASK)) == ((__FLAG__)&I2C_FLAG_MASK))) - -/** @brief Clears the I2C pending flags which are cleared by writing 0 in a specific bit. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. - * @param __FLAG__: specifies the flag to clear. - * This parameter can be any combination of the following values: - * @arg I2C_FLAG_SMBALERT: SMBus Alert flag - * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag - * @arg I2C_FLAG_PECERR: PEC error in reception flag - * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode) - * @arg I2C_FLAG_AF: Acknowledge failure flag - * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode) - * @arg I2C_FLAG_BERR: Bus error flag - * @retval None - */ -#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = ~((__FLAG__)&I2C_FLAG_MASK)) - -/** @brief Clears the I2C ADDR pending flag. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. - * @retval None - */ -#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ - do { \ - __IO uint32_t tmpreg = 0x00U; \ - tmpreg = (__HANDLE__)->Instance->SR1; \ - tmpreg = (__HANDLE__)->Instance->SR2; \ - UNUSED(tmpreg); \ - } while (0U) - -/** @brief Clears the I2C STOPF pending flag. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. - * @retval None - */ -#define __HAL_I2C_CLEAR_STOPFLAG(__HANDLE__) \ - do { \ - __IO uint32_t tmpreg = 0x00U; \ - tmpreg = (__HANDLE__)->Instance->SR1; \ - (__HANDLE__)->Instance->CR1 |= I2C_CR1_PE; \ - UNUSED(tmpreg); \ - } while (0U) - -/** @brief Enable the I2C peripheral. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral. - * @retval None - */ -#define __HAL_I2C_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= I2C_CR1_PE) - -/** @brief Disable the I2C peripheral. - * @param __HANDLE__: specifies the I2C Handle. - * This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral. - * @retval None - */ -#define __HAL_I2C_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~I2C_CR1_PE) - -/** - * @} - */ - -/* Exported functions --------------------------------------------------------*/ -/** @addtogroup I2C_Exported_Functions - * @{ - */ - -/** @addtogroup I2C_Exported_Functions_Group1 - * @{ - */ -/* Initialization/de-initialization functions **********************************/ -HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); -HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c); -void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c); -void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c); -/** - * @} - */ - -/** @addtogroup I2C_Exported_Functions_Group2 - * @{ - */ -/* I/O operation functions *****************************************************/ -/******* Blocking mode: Polling */ -HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); -HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); -HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); -HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); -HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); -HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); -HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout); - -/******* Non-Blocking mode: Interrupt */ -HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); - -HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress); -HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c); -HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c); - -/******* Non-Blocking mode: DMA */ -HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); -HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); - -/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ -void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c); -void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c); -void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); -void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c); -void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c); -/** - * @} - */ - -/** @addtogroup I2C_Exported_Functions_Group3 - * @{ - */ -/* Peripheral State, Mode and Errors functions *********************************/ -HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c); -HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c); -uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c); - -/** - * @} - */ - -/** - * @} - */ -/* Private types -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Private constants ---------------------------------------------------------*/ -/** @defgroup I2C_Private_Constants I2C Private Constants - * @{ - */ -#define I2C_FLAG_MASK 0x0000FFFFU -#define I2C_MIN_PCLK_FREQ_STANDARD 2000000U /*!< 2 MHz */ -#define I2C_MIN_PCLK_FREQ_FAST 4000000U /*!< 4 MHz */ -/** - * @} - */ - -/* Private macros ------------------------------------------------------------*/ -/** @defgroup I2C_Private_Macros I2C Private Macros - * @{ - */ - -#define I2C_MIN_PCLK_FREQ(__PCLK__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD) : ((__PCLK__) < I2C_MIN_PCLK_FREQ_FAST)) -#define I2C_CCR_CALCULATION(__PCLK__, __SPEED__, __COEFF__) (((((__PCLK__)-1U) / ((__SPEED__) * (__COEFF__))) + 1U) & I2C_CCR_CCR) -#define I2C_FREQRANGE(__PCLK__) ((__PCLK__) / 1000000U) -#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__)*300U) / 1000U) + 1U)) -#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) ((I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U) < 4U) ? 4U : I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U)) -#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) \ - (((__DUTYCYCLE__) == I2C_DUTYCYCLE_2) ? I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 3U) : (I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 25U) | I2C_DUTYCYCLE_16_9)) -#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) \ - (((__SPEED__) <= 100000U) ? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) \ - : ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U) ? 1U \ - : ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS)) - -#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (~I2C_OAR1_ADD0))) -#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0)) - -#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FFU)))) -#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0x0300U))) >> 7U) | (uint16_t)(0x00F0U)))) -#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0x0300U))) >> 7U) | (uint16_t)(0x00F1U)))) - -#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0xFF00U))) >> 8U))) -#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FFU)))) - -/** @defgroup I2C_IS_RTC_Definitions I2C Private macros to check input parameters - * @{ - */ -#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DUTYCYCLE_2) || ((CYCLE) == I2C_DUTYCYCLE_16_9)) -#define IS_I2C_ADDRESSING_MODE(ADDRESS) (((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || ((ADDRESS) == I2C_ADDRESSINGMODE_10BIT)) -#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || ((ADDRESS) == I2C_DUALADDRESS_ENABLE)) -#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || ((CALL) == I2C_GENERALCALL_ENABLE)) -#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || ((STRETCH) == I2C_NOSTRETCH_ENABLE)) -#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || ((SIZE) == I2C_MEMADD_SIZE_16BIT)) -#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) > 0) && ((SPEED) <= 400000U)) -#define IS_I2C_OWN_ADDRESS1(ADDRESS1) (((ADDRESS1) & (uint32_t)(0xFFFFFC00U)) == 0U) -#define IS_I2C_OWN_ADDRESS2(ADDRESS2) (((ADDRESS2) & (uint32_t)(0xFFFFFF01U)) == 0U) -#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || ((REQUEST) == I2C_NEXT_FRAME) || ((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || ((REQUEST) == I2C_LAST_FRAME)) -/** - * @} - */ - -/** - * @} - */ - -/* Private functions ---------------------------------------------------------*/ -/** @defgroup I2C_Private_Functions I2C Private Functions - * @{ - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - #endif /* __STM32F1xx_HAL_I2C_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c b/source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c deleted file mode 100644 index 2c38ddb99f..0000000000 --- a/source/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c +++ /dev/null @@ -1,4569 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f1xx_hal_i2c.c - * @author MCD Application Team - * @brief I2C HAL module driver. - * This file provides firmware functions to manage the following - * functionalities of the Inter Integrated Circuit (I2C) peripheral: - * + Initialization and de-initialization functions - * + IO operation functions - * + Peripheral State, Mode and Error functions - * - @verbatim - ============================================================================== - ##### How to use this driver ##### - ============================================================================== - [..] - The I2C HAL driver can be used as follows: - - (#) Declare a I2C_HandleTypeDef handle structure, for example: - I2C_HandleTypeDef hi2c; - - (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API: - (##) Enable the I2Cx interface clock - (##) I2C pins configuration - (+++) Enable the clock for the I2C GPIOs - (+++) Configure I2C pins as alternate function open-drain - (##) NVIC configuration if you need to use interrupt process - (+++) Configure the I2Cx interrupt priority - (+++) Enable the NVIC I2C IRQ Channel - (##) DMA Configuration if you need to use DMA process - (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive channel - (+++) Enable the DMAx interface clock using - (+++) Configure the DMA handle parameters - (+++) Configure the DMA Tx or Rx channel - (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle - (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on - the DMA Tx or Rx channel - - (#) Configure the Communication Speed, Duty cycle, Addressing mode, Own Address1, - Dual Addressing mode, Own Address2, General call and Nostretch mode in the hi2c Init structure. - - (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware - (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API. - - (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady() - - (#) For I2C IO and IO MEM operations, three operation modes are available within this driver : - - *** Polling mode IO operation *** - ================================= - [..] - (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit() - (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive() - (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit() - (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive() - - *** Polling mode IO MEM operation *** - ===================================== - [..] - (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write() - (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read() - - - *** Interrupt mode IO operation *** - =================================== - [..] - (+) Transmit in master mode an amount of data in non blocking mode using HAL_I2C_Master_Transmit_IT() - (+) At transmission end of transfer HAL_I2C_MasterTxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback - (+) Receive in master mode an amount of data in non blocking mode using HAL_I2C_Master_Receive_IT() - (+) At reception end of transfer HAL_I2C_MasterRxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback - (+) Transmit in slave mode an amount of data in non blocking mode using HAL_I2C_Slave_Transmit_IT() - (+) At transmission end of transfer HAL_I2C_SlaveTxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback - (+) Receive in slave mode an amount of data in non blocking mode using HAL_I2C_Slave_Receive_IT() - (+) At reception end of transfer HAL_I2C_SlaveRxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback - (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can - add his own code by customization of function pointer HAL_I2C_ErrorCallback - (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() - (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() - - *** Interrupt mode IO sequential operation *** - ============================================== - [..] - (@) These interfaces allow to manage a sequential transfer with a repeated start condition - when a direction change during transfer - [..] - (+) A specific option field manage the different steps of a sequential transfer - (+) Option field values are defined through @ref I2C_XFEROPTIONS and are listed below: - (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode - (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address - and data to transfer without a final stop condition - (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address - and with new data to transfer if the direction change or manage only the new data to transfer - if no direction change and without a final stop condition in both cases - (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address - and with new data to transfer if the direction change or manage only the new data to transfer - if no direction change and with a final stop condition in both cases - - (+) Differents sequential I2C interfaces are listed below: - (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Transmit_IT() - (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() - (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Receive_IT() - (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() - (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() - (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() - (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT() HAL_I2C_DisableListen_IT() - (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and user can - add his own code to check the Address Match Code and the transmission direction request by master (Write/Read). - (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_ListenCpltCallback() - (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Transmit_IT() - (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() - (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Receive_IT() - (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() - (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can - add his own code by customization of function pointer HAL_I2C_ErrorCallback() - - *** Interrupt mode IO MEM operation *** - ======================================= - [..] - (+) Write an amount of data in no-blocking mode with Interrupt to a specific memory address using - HAL_I2C_Mem_Write_IT() - (+) At MEM end of write transfer HAL_I2C_MemTxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback - (+) Read an amount of data in no-blocking mode with Interrupt from a specific memory address using - HAL_I2C_Mem_Read_IT() - (+) At MEM end of read transfer HAL_I2C_MemRxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback - (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can - add his own code by customization of function pointer HAL_I2C_ErrorCallback - - *** DMA mode IO operation *** - ============================== - [..] - (+) Transmit in master mode an amount of data in non blocking mode (DMA) using - HAL_I2C_Master_Transmit_DMA() - (+) At transmission end of transfer HAL_I2C_MasterTxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback - (+) Receive in master mode an amount of data in non blocking mode (DMA) using - HAL_I2C_Master_Receive_DMA() - (+) At reception end of transfer HAL_I2C_MasterRxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback - (+) Transmit in slave mode an amount of data in non blocking mode (DMA) using - HAL_I2C_Slave_Transmit_DMA() - (+) At transmission end of transfer HAL_I2C_SlaveTxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback - (+) Receive in slave mode an amount of data in non blocking mode (DMA) using - HAL_I2C_Slave_Receive_DMA() - (+) At reception end of transfer HAL_I2C_SlaveRxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback - (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can - add his own code by customization of function pointer HAL_I2C_ErrorCallback - (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() - (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can - add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() - - *** DMA mode IO MEM operation *** - ================================= - [..] - (+) Write an amount of data in no-blocking mode with DMA to a specific memory address using - HAL_I2C_Mem_Write_DMA() - (+) At MEM end of write transfer HAL_I2C_MemTxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback - (+) Read an amount of data in no-blocking mode with DMA from a specific memory address using - HAL_I2C_Mem_Read_DMA() - (+) At MEM end of read transfer HAL_I2C_MemRxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback - (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can - add his own code by customization of function pointer HAL_I2C_ErrorCallback - - - *** I2C HAL driver macros list *** - ================================== - [..] - Below the list of most used macros in I2C HAL driver. - - (+) __HAL_I2C_ENABLE: Enable the I2C peripheral - (+) __HAL_I2C_DISABLE: Disable the I2C peripheral - (+) __HAL_I2C_GET_FLAG : Checks whether the specified I2C flag is set or not - (+) __HAL_I2C_CLEAR_FLAG : Clear the specified I2C pending flag - (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt - (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt - - [..] - (@) You can refer to the I2C HAL driver header file for more useful macros - - *** I2C Workarounds linked to Silicon Limitation *** - ==================================================== - [..] - Below the list of all silicon limitations implemented for HAL on STM32F1xx product. - (@) See ErrataSheet to know full silicon limitation list of your product. - - (#) Workarounds Implemented inside I2C HAL Driver - (##) Wrong data read into data register (Polling and Interrupt mode) - (##) Start cannot be generated after a misplaced Stop - (##) Some software events must be managed before the current byte is being transferred: - Workaround: Use DMA in general, except when the Master is receiving a single byte. - For Interupt mode, I2C should have the highest priority in the application. - (##) Mismatch on the "Setup time for a repeated Start condition" timing parameter: - Workaround: Reduce the frequency down to 88 kHz or use the I2C Fast-mode if - supported by the slave. - (##) Data valid time (tVD;DAT) violated without the OVR flag being set: - Workaround: If the slave device allows it, use the clock stretching mechanism - by programming NoStretchMode = I2C_NOSTRETCH_DISABLE in HAL_I2C_Init. - - @endverbatim - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f1xx_hal.h" - -/** @addtogroup STM32F1xx_HAL_Driver - * @{ - */ - -/** @defgroup I2C I2C - * @brief I2C HAL module driver - * @{ - */ - -#ifdef HAL_I2C_MODULE_ENABLED - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/** @addtogroup I2C_Private_Define - * @{ - */ -#define I2C_TIMEOUT_FLAG 35U /*!< Timeout 35 ms */ -#define I2C_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */ -#define I2C_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */ - -/* Private define for @ref PreviousState usage */ -#define I2C_STATE_MSK ((uint32_t)((HAL_I2C_STATE_BUSY_TX | HAL_I2C_STATE_BUSY_RX) & (~(uint32_t)HAL_I2C_STATE_READY))) /*!< Mask State define, keep only RX and TX bits */ -#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */ -#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ -#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ -#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ -#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ - -/** - * @} - */ - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/** @addtogroup I2C_Private_Functions - * @{ - */ -/* Private functions to handle DMA transfer */ -static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma); -static void I2C_DMAError(DMA_HandleTypeDef *hdma); -static void I2C_DMAAbort(DMA_HandleTypeDef *hdma); - -static void I2C_ITError(I2C_HandleTypeDef *hi2c); - -static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c); - -/* Private functions for I2C transfer IRQ handler */ -static HAL_StatusTypeDef I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c); -static HAL_StatusTypeDef I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c); -static HAL_StatusTypeDef I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c); -static HAL_StatusTypeDef I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c); -static HAL_StatusTypeDef I2C_Master_SB(I2C_HandleTypeDef *hi2c); -static HAL_StatusTypeDef I2C_Master_ADDR(I2C_HandleTypeDef *hi2c); - -/** - * @} - */ - -/* Exported functions --------------------------------------------------------*/ -/** @defgroup I2C_Exported_Functions I2C Exported Functions - * @{ - */ - -/** @defgroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions - * @brief Initialization and Configuration functions - * -@verbatim - =============================================================================== - ##### Initialization and de-initialization functions ##### - =============================================================================== - [..] This subsection provides a set of functions allowing to initialize and - de-initialize the I2Cx peripheral: - - (+) User must Implement HAL_I2C_MspInit() function in which he configures - all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC). - - (+) Call the function HAL_I2C_Init() to configure the selected device with - the selected configuration: - (++) Communication Speed - (++) Duty cycle - (++) Addressing mode - (++) Own Address 1 - (++) Dual Addressing mode - (++) Own Address 2 - (++) General call mode - (++) Nostretch mode - - (+) Call the function HAL_I2C_DeInit() to restore the default configuration - of the selected I2Cx peripheral. - -@endverbatim - * @{ - */ - -/** - * @brief Initializes the I2C according to the specified parameters - * in the I2C_InitTypeDef and create the associated handle. - * @param hi2c: pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) { - uint32_t freqrange = 0U; - uint32_t pclk1 = 0U; - - /* Check the I2C handle allocation */ - if (hi2c == NULL) { - return HAL_ERROR; - } - - /* Check the parameters */ - assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); - assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed)); - assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle)); - assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); - assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); - assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); - assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); - assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); - assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); - - if (hi2c->State == HAL_I2C_STATE_RESET) { - /* Allocate lock resource and initialize it */ - hi2c->Lock = HAL_UNLOCKED; - /* Init the low level hardware : GPIO, CLOCK, NVIC */ - HAL_I2C_MspInit(hi2c); - } - - hi2c->State = HAL_I2C_STATE_BUSY; - - /* Disable the selected I2C peripheral */ - __HAL_I2C_DISABLE(hi2c); - - /* Get PCLK1 frequency */ - pclk1 = HAL_RCC_GetPCLK1Freq(); - - /* Check the minimum allowed PCLK1 frequency */ - if (I2C_MIN_PCLK_FREQ(pclk1, hi2c->Init.ClockSpeed) == 1U) { - return HAL_ERROR; - } - - /* Calculate frequency range */ - freqrange = I2C_FREQRANGE(pclk1); - - /*---------------------------- I2Cx CR2 Configuration ----------------------*/ - /* Configure I2Cx: Frequency range */ - hi2c->Instance->CR2 = freqrange; - - /*---------------------------- I2Cx TRISE Configuration --------------------*/ - /* Configure I2Cx: Rise Time */ - hi2c->Instance->TRISE = I2C_RISE_TIME(freqrange, hi2c->Init.ClockSpeed); - - /*---------------------------- I2Cx CCR Configuration ----------------------*/ - /* Configure I2Cx: Speed */ - hi2c->Instance->CCR = I2C_SPEED(pclk1, hi2c->Init.ClockSpeed, hi2c->Init.DutyCycle); - - /*---------------------------- I2Cx CR1 Configuration ----------------------*/ - /* Configure I2Cx: Generalcall and NoStretch mode */ - hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode); - - /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ - /* Configure I2Cx: Own Address1 and addressing mode */ - hi2c->Instance->OAR1 = (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1); - - /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ - /* Configure I2Cx: Dual mode and Own Address2 */ - hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2); - - /* Enable the selected I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - hi2c->State = HAL_I2C_STATE_READY; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->Mode = HAL_I2C_MODE_NONE; - - return HAL_OK; -} - -/** - * @brief DeInitializes the I2C peripheral. - * @param hi2c: pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) { - /* Check the I2C handle allocation */ - if (hi2c == NULL) { - return HAL_ERROR; - } - - /* Check the parameters */ - assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); - - hi2c->State = HAL_I2C_STATE_BUSY; - - /* Disable the I2C Peripheral Clock */ - __HAL_I2C_DISABLE(hi2c); - - /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ - HAL_I2C_MspDeInit(hi2c); - - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - hi2c->State = HAL_I2C_STATE_RESET; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Release Lock */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; -} - -/** - * @brief I2C MSP Init. - * @param hi2c: pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval None - */ -__weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - /* NOTE : This function Should not be modified, when the callback is needed, - the HAL_I2C_MspInit could be implemented in the user file - */ -} - -/** - * @brief I2C MSP DeInit - * @param hi2c: pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval None - */ -__weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - /* NOTE : This function Should not be modified, when the callback is needed, - the HAL_I2C_MspDeInit could be implemented in the user file - */ -} - -/** - * @} - */ - -/** @defgroup I2C_Exported_Functions_Group2 IO operation functions - * @brief Data transfers functions - * -@verbatim - =============================================================================== - ##### IO operation functions ##### - =============================================================================== - [..] - This subsection provides a set of functions allowing to manage the I2C data - transfers. - - (#) There are two modes of transfer: - (++) Blocking mode : The communication is performed in the polling mode. - The status of all data processing is returned by the same function - after finishing transfer. - (++) No-Blocking mode : The communication is performed using Interrupts - or DMA. These functions return the status of the transfer startup. - The end of the data processing will be indicated through the - dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when - using DMA mode. - - (#) Blocking mode functions are : - (++) HAL_I2C_Master_Transmit() - (++) HAL_I2C_Master_Receive() - (++) HAL_I2C_Slave_Transmit() - (++) HAL_I2C_Slave_Receive() - (++) HAL_I2C_Mem_Write() - (++) HAL_I2C_Mem_Read() - (++) HAL_I2C_IsDeviceReady() - - (#) No-Blocking mode functions with Interrupt are : - (++) HAL_I2C_Master_Transmit_IT() - (++) HAL_I2C_Master_Receive_IT() - (++) HAL_I2C_Slave_Transmit_IT() - (++) HAL_I2C_Slave_Receive_IT() - (++) HAL_I2C_Master_Sequential_Transmit_IT() - (++) HAL_I2C_Master_Sequential_Receive_IT() - (++) HAL_I2C_Slave_Sequential_Transmit_IT() - (++) HAL_I2C_Slave_Sequential_Receive_IT() - (++) HAL_I2C_Mem_Write_IT() - (++) HAL_I2C_Mem_Read_IT() - - (#) No-Blocking mode functions with DMA are : - (++) HAL_I2C_Master_Transmit_DMA() - (++) HAL_I2C_Master_Receive_DMA() - (++) HAL_I2C_Slave_Transmit_DMA() - (++) HAL_I2C_Slave_Receive_DMA() - (++) HAL_I2C_Mem_Write_DMA() - (++) HAL_I2C_Mem_Read_DMA() - - (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: - (++) HAL_I2C_MemTxCpltCallback() - (++) HAL_I2C_MemRxCpltCallback() - (++) HAL_I2C_MasterTxCpltCallback() - (++) HAL_I2C_MasterRxCpltCallback() - (++) HAL_I2C_SlaveTxCpltCallback() - (++) HAL_I2C_SlaveRxCpltCallback() - (++) HAL_I2C_ErrorCallback() - (++) HAL_I2C_AbortCpltCallback() - -@endverbatim - * @{ - */ - -/** - * @brief Transmits in master mode an amount of data in blocking mode. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param Timeout Timeout duration - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) { - uint32_t tickstart = 0x00U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) { - return HAL_BUSY; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Send Slave Address */ - if (I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_ERROR; - } else { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_TIMEOUT; - } - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - while (hi2c->XferSize > 0U) { - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferCount--; - hi2c->XferSize--; - - if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) { - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferCount--; - hi2c->XferSize--; - } - - /* Wait until BTF flag is set */ - if (I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - } - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Receives in master mode an amount of data in blocking mode. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param Timeout Timeout duration - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) { - uint32_t tickstart = 0x00U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) { - return HAL_BUSY; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Send Slave Address */ - if (I2C_MasterRequestRead(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_ERROR; - } else { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_TIMEOUT; - } - } - - if (hi2c->XferSize == 0U) { - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - } else if (hi2c->XferSize == 1U) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Re-enable IRQs */ - __enable_irq(); - } else if (hi2c->XferSize == 2U) { - /* Enable Pos */ - hi2c->Instance->CR1 |= I2C_CR1_POS; - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Re-enable IRQs */ - __enable_irq(); - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } - - while (hi2c->XferSize > 0U) { - if (hi2c->XferSize <= 3U) { - /* One byte */ - if (hi2c->XferSize == 1U) { - /* Wait until RXNE flag is set */ - if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) { - return HAL_TIMEOUT; - } else { - return HAL_ERROR; - } - } - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - /* Two bytes */ - else if (hi2c->XferSize == 2U) { - /* Wait until BTF flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - /* Re-enable IRQs */ - __enable_irq(); - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - /* 3 Last bytes */ - else { - /* Wait until BTF flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - /* Wait until BTF flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - /* Re-enable IRQs */ - __enable_irq(); - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - } else { - /* Wait until RXNE flag is set */ - if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) { - return HAL_TIMEOUT; - } else { - return HAL_ERROR; - } - } - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - } - } - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Transmits in slave mode an amount of data in blocking mode. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param Timeout Timeout duration - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) { - uint32_t tickstart = 0x00U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - if (hi2c->State == HAL_I2C_STATE_READY) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Enable Address Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Wait until ADDR flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - while (hi2c->XferSize > 0U) { - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - /* Disable Address Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferCount--; - hi2c->XferSize--; - - if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) { - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferCount--; - hi2c->XferSize--; - } - } - - /* Wait until AF flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_AF, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Clear AF flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); - - /* Disable Address Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Receive in slave mode an amount of data in blocking mode - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param Timeout Timeout duration - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) { - uint32_t tickstart = 0x00U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - if (hi2c->State == HAL_I2C_STATE_READY) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Enable Address Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Wait until ADDR flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - while (hi2c->XferSize > 0U) { - /* Wait until RXNE flag is set */ - if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - /* Disable Address Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - if (hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) { - return HAL_TIMEOUT; - } else { - return HAL_ERROR; - } - } - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - } - - /* Wait until STOP flag is set */ - if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - /* Disable Address Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Clear STOP flag */ - __HAL_I2C_CLEAR_STOPFLAG(hi2c); - - /* Disable Address Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - hi2c->Devaddress = DevAddress; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - hi2c->Devaddress = DevAddress; - - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Sequential transmit in master mode an amount of data in non-blocking mode with Interrupt - * @note This interface allow to manage repeated start condition when a direction change during transfer - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) { - __IO uint32_t Prev_State = 0x00U; - __IO uint32_t count = 0x00U; - - /* Check the parameters */ - assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Check Busy Flag only if FIRST call of Master interface */ - if ((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = XferOptions; - hi2c->XferSize = hi2c->XferCount; - hi2c->Devaddress = DevAddress; - - Prev_State = hi2c->PreviousState; - - /* Generate Start */ - if ((Prev_State == I2C_STATE_MASTER_BUSY_RX) || (Prev_State == I2C_STATE_NONE)) { - /* Generate Start condition if first transfer */ - if ((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) { - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } else { - /* Generate ReStart */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } - } - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Sequential receive in master mode an amount of data in non-blocking mode with Interrupt - * @note This interface allow to manage repeated start condition when a direction change during transfer - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) { - __IO uint32_t count = 0U; - - /* Check the parameters */ - assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Check Busy Flag only if FIRST call of Master interface */ - if ((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = XferOptions; - hi2c->XferSize = hi2c->XferCount; - hi2c->Devaddress = DevAddress; - - if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) || (hi2c->PreviousState == I2C_STATE_NONE)) { - /* Generate Start condition if first transfer */ - if ((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_NO_OPTION_FRAME)) { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate ReStart */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } - } - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Enable Address Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferSize = Size; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - - /* Enable Address Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Sequential transmit in slave mode an amount of data in no-blocking mode with Interrupt - * @note This interface allow to manage repeated start condition when a direction change during transfer - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) { - /* Check the parameters */ - assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); - - if (hi2c->State == HAL_I2C_STATE_LISTEN) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = XferOptions; - hi2c->XferSize = hi2c->XferCount; - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Sequential receive in slave mode an amount of data in non-blocking mode with Interrupt - * @note This interface allow to manage repeated start condition when a direction change during transfer - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) { - /* Check the parameters */ - assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); - - if (hi2c->State == HAL_I2C_STATE_LISTEN) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = XferOptions; - hi2c->XferSize = hi2c->XferCount; - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Enable the Address listen mode with Interrupt. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c) { - if (hi2c->State == HAL_I2C_STATE_READY) { - hi2c->State = HAL_I2C_STATE_LISTEN; - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Enable Address Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Enable EVT and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Disable the Address listen mode with Interrupt. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c) { - /* Declaration of tmp to prevent undefined behavior of volatile usage */ - uint32_t tmp; - - /* Disable Address listen mode only if a transfer is not ongoing */ - if (hi2c->State == HAL_I2C_STATE_LISTEN) { - tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK; - hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode); - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Disable Address Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Disable EVT and ERR interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Transmit in master mode an amount of data in non-blocking mode with DMA - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - hi2c->Devaddress = DevAddress; - - if (hi2c->XferSize > 0U) { - /* Set the I2C DMA transfer complete callback */ - hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; - - /* Set the DMA error callback */ - hi2c->hdmatx->XferErrorCallback = I2C_DMAError; - - /* Set the unused DMA callbacks to NULL */ - hi2c->hdmatx->XferHalfCpltCallback = NULL; - hi2c->hdmatx->XferAbortCallback = NULL; - - /* Enable the DMA channel */ - HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); - - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - - /* Enable DMA Request */ - hi2c->Instance->CR2 |= I2C_CR2_DMAEN; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - } - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Receive in master mode an amount of data in non-blocking mode with DMA - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_MASTER; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - hi2c->Devaddress = DevAddress; - - if (hi2c->XferSize > 0U) { - /* Set the I2C DMA transfer complete callback */ - hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; - - /* Set the DMA error callback */ - hi2c->hdmarx->XferErrorCallback = I2C_DMAError; - - /* Set the unused DMA callbacks to NULL */ - hi2c->hdmarx->XferHalfCpltCallback = NULL; - hi2c->hdmarx->XferAbortCallback = NULL; - - /* Enable the DMA channel */ - HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); - - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - - /* Enable DMA Request */ - hi2c->Instance->CR2 |= I2C_CR2_DMAEN; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - } - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Abort a master I2C process communication with Interrupt. - * @note This abort can be called only if state is ready - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(DevAddress); - - /* Abort Master transfer during Receive or Transmit process */ - if (hi2c->Mode == HAL_I2C_MODE_MASTER) { - /* Process Locked */ - __HAL_LOCK(hi2c); - - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_ABORT; - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - hi2c->XferCount = 0U; - - /* Disable EVT, BUF and ERR interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Call the corresponding callback to inform upper layer of End of Transfer */ - I2C_ITError(hi2c); - - return HAL_OK; - } else { - /* Wrong usage of abort function */ - /* This function should be used only in case of abort monitored by master device */ - return HAL_ERROR; - } -} - -/** - * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Set the I2C DMA transfer complete callback */ - hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; - - /* Set the DMA error callback */ - hi2c->hdmatx->XferErrorCallback = I2C_DMAError; - - /* Set the unused DMA callbacks to NULL */ - hi2c->hdmatx->XferHalfCpltCallback = NULL; - hi2c->hdmatx->XferAbortCallback = NULL; - - /* Enable the DMA channel */ - HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); - - /* Enable Address Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - /* Enable EVT and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - - /* Enable DMA Request */ - hi2c->Instance->CR2 |= I2C_CR2_DMAEN; - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Receive in slave mode an amount of data in non-blocking mode with DMA - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - if (hi2c->State == HAL_I2C_STATE_READY) { - if ((pData == NULL) || (Size == 0U)) { - return HAL_ERROR; - } - - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_SLAVE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Set the I2C DMA transfer complete callback */ - hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; - - /* Set the DMA error callback */ - hi2c->hdmarx->XferErrorCallback = I2C_DMAError; - - /* Set the unused DMA callbacks to NULL */ - hi2c->hdmarx->XferHalfCpltCallback = NULL; - hi2c->hdmarx->XferAbortCallback = NULL; - - /* Enable the DMA channel */ - HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); - - /* Enable Address Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - /* Enable EVT and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - - /* Enable DMA Request */ - hi2c->Instance->CR2 |= I2C_CR2_DMAEN; - - return HAL_OK; - } else { - return HAL_BUSY; - } -} -/** - * @brief Write an amount of data in blocking mode to a specific memory address - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param Timeout Timeout duration - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) { - uint32_t tickstart = 0x00U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) { - return HAL_BUSY; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_MEM; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Send Slave Address and Memory Address */ - if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_ERROR; - } else { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_TIMEOUT; - } - } - - while (hi2c->XferSize > 0U) { - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferSize--; - hi2c->XferCount--; - - if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) { - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferSize--; - hi2c->XferCount--; - } - } - - /* Wait until BTF flag is set */ - if (I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Read an amount of data in blocking mode from a specific memory address - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @param Timeout Timeout duration - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) { - uint32_t tickstart = 0x00U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) { - return HAL_BUSY; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_MEM; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - /* Send Slave Address and Memory Address */ - if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_ERROR; - } else { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_TIMEOUT; - } - } - - if (hi2c->XferSize == 0U) { - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - } else if (hi2c->XferSize == 1U) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Re-enable IRQs */ - __enable_irq(); - } else if (hi2c->XferSize == 2U) { - /* Enable Pos */ - hi2c->Instance->CR1 |= I2C_CR1_POS; - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Re-enable IRQs */ - __enable_irq(); - } else { - /* Enable Acknowledge */ - SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } - - while (hi2c->XferSize > 0U) { - if (hi2c->XferSize <= 3U) { - /* One byte */ - if (hi2c->XferSize == 1U) { - /* Wait until RXNE flag is set */ - if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) { - return HAL_TIMEOUT; - } else { - return HAL_ERROR; - } - } - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - /* Two bytes */ - else if (hi2c->XferSize == 2U) { - /* Wait until BTF flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - /* Re-enable IRQs */ - __enable_irq(); - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - /* 3 Last bytes */ - else { - /* Wait until BTF flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3 - software sequence must complete before the current byte end of transfer */ - __disable_irq(); - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - /* Wait until BTF flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - /* Re-enable IRQs */ - __enable_irq(); - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - } else { - /* Wait until RXNE flag is set */ - if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) { - return HAL_TIMEOUT; - } else { - return HAL_ERROR; - } - } - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferSize--; - hi2c->XferCount--; - } - } - } - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - /* Check the parameters */ - assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_MEM; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferSize = Size; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->Devaddress = DevAddress; - hi2c->Memaddress = MemAddress; - hi2c->MemaddSize = MemAddSize; - hi2c->EventCount = 0U; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - /* Check the parameters */ - assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_MEM; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferSize = Size; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->Devaddress = DevAddress; - hi2c->Memaddress = MemAddress; - hi2c->MemaddSize = MemAddSize; - hi2c->EventCount = 0U; - - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - if (hi2c->XferSize > 0U) { - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - - /* Enable EVT, BUF and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - } - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param pData Pointer to data buffer - * @param Size Amount of data to be sent - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) { - __IO uint32_t count = 0U; - - uint32_t tickstart = 0x00U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_MEM; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferSize = Size; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - - if (hi2c->XferSize > 0U) { - /* Set the I2C DMA transfer complete callback */ - hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; - - /* Set the DMA error callback */ - hi2c->hdmatx->XferErrorCallback = I2C_DMAError; - - /* Set the unused DMA callbacks to NULL */ - hi2c->hdmatx->XferHalfCpltCallback = NULL; - hi2c->hdmatx->XferAbortCallback = NULL; - - /* Enable the DMA channel */ - HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); - - /* Send Slave Address and Memory Address */ - if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_ERROR; - } else { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_TIMEOUT; - } - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - /* Enable ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); - - /* Enable DMA Request */ - hi2c->Instance->CR2 |= I2C_CR2_DMAEN; - } - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param pData Pointer to data buffer - * @param Size Amount of data to be read - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) { - uint32_t tickstart = 0x00U; - __IO uint32_t count = 0U; - - /* Init tickstart for timeout management*/ - tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); - do { - if (count-- == 0U) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY_RX; - hi2c->Mode = HAL_I2C_MODE_MEM; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Prepare transfer parameters */ - hi2c->pBuffPtr = pData; - hi2c->XferCount = Size; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->XferSize = hi2c->XferCount; - - if (hi2c->XferSize > 0U) { - /* Set the I2C DMA transfer complete callback */ - hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; - - /* Set the DMA error callback */ - hi2c->hdmarx->XferErrorCallback = I2C_DMAError; - - /* Set the unused DMA callbacks to NULL */ - hi2c->hdmarx->XferAbortCallback = NULL; - - /* Enable the DMA channel */ - HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); - - /* Send Slave Address and Memory Address */ - if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_ERROR; - } else { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_TIMEOUT; - } - } - - if (Size == 1U) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - } else { - /* Enable Last DMA bit */ - hi2c->Instance->CR2 |= I2C_CR2_LAST; - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - /* Note : The I2C interrupts must be enabled after unlocking current process - to avoid the risk of I2C interrupt handle execution before current - process unlock */ - /* Enable ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); - - /* Enable DMA Request */ - hi2c->Instance->CR2 |= I2C_CR2_DMAEN; - } else { - /* Send Slave Address and Memory Address */ - if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_ERROR; - } else { - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - return HAL_TIMEOUT; - } - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - } - - return HAL_OK; - } else { - return HAL_BUSY; - } -} - -/** - * @brief Checks if target device is ready for communication. - * @note This function is used with Memory devices - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param Trials Number of trials - * @param Timeout Timeout duration - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) { - uint32_t tickstart = 0U, tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, I2C_Trials = 1U; - - /* Get tick */ - tickstart = HAL_GetTick(); - - if (hi2c->State == HAL_I2C_STATE_READY) { - /* Wait until BUSY flag is reset */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) { - return HAL_BUSY; - } - - /* Process Locked */ - __HAL_LOCK(hi2c); - - /* Check if the I2C is already enabled */ - if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { - /* Enable I2C peripheral */ - __HAL_I2C_ENABLE(hi2c); - } - - /* Disable Pos */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - hi2c->State = HAL_I2C_STATE_BUSY; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - - do { - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Wait until SB flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Send slave address */ - hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); - - /* Wait until ADDR or AF flag are set */ - /* Get tick */ - tickstart = HAL_GetTick(); - - tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); - tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); - tmp3 = hi2c->State; - while ((tmp1 == RESET) && (tmp2 == RESET) && (tmp3 != HAL_I2C_STATE_TIMEOUT)) { - if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) { - hi2c->State = HAL_I2C_STATE_TIMEOUT; - } - tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); - tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); - tmp3 = hi2c->State; - } - - hi2c->State = HAL_I2C_STATE_READY; - - /* Check if the ADDR flag has been set */ - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == SET) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Clear ADDR Flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Wait until BUSY flag is reset */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_OK; - } else { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Clear AF Flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); - - /* Wait until BUSY flag is reset */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - } - } while (I2C_Trials++ < Trials); - - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_ERROR; - } else { - return HAL_BUSY; - } -} - -/** - * @brief This function handles I2C event interrupt request. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) { - uint32_t sr2itflags = READ_REG(hi2c->Instance->SR2); - uint32_t sr1itflags = READ_REG(hi2c->Instance->SR1); - uint32_t itsources = READ_REG(hi2c->Instance->CR2); - - uint32_t CurrentMode = hi2c->Mode; - - /* Master or Memory mode selected */ - if ((CurrentMode == HAL_I2C_MODE_MASTER) || (CurrentMode == HAL_I2C_MODE_MEM)) { - /* SB Set ----------------------------------------------------------------*/ - if (((sr1itflags & I2C_FLAG_SB) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) { - I2C_Master_SB(hi2c); - } - /* ADDR Set --------------------------------------------------------------*/ - else if (((sr1itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) { - I2C_Master_ADDR(hi2c); - } - - /* I2C in mode Transmitter -----------------------------------------------*/ - if ((sr2itflags & I2C_FLAG_TRA) != RESET) { - /* TXE set and BTF reset -----------------------------------------------*/ - if (((sr1itflags & I2C_FLAG_TXE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) { - I2C_MasterTransmit_TXE(hi2c); - } - /* BTF set -------------------------------------------------------------*/ - else if (((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) { - I2C_MasterTransmit_BTF(hi2c); - } - } - /* I2C in mode Receiver --------------------------------------------------*/ - else { - /* RXNE set and BTF reset -----------------------------------------------*/ - if (((sr1itflags & I2C_FLAG_RXNE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) { - I2C_MasterReceive_RXNE(hi2c); - } - /* BTF set -------------------------------------------------------------*/ - else if (((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) { - I2C_MasterReceive_BTF(hi2c); - } - } - } - /* Slave mode selected */ -#if 0 - else - { - /* ADDR set --------------------------------------------------------------*/ - if(((sr1itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) - { - I2C_Slave_ADDR(hi2c); - } - /* STOPF set --------------------------------------------------------------*/ - else if(((sr1itflags & I2C_FLAG_STOPF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) - { - I2C_Slave_STOPF(hi2c); - } - /* I2C in mode Transmitter -----------------------------------------------*/ - else if((sr2itflags & I2C_FLAG_TRA) != RESET) - { - /* TXE set and BTF reset -----------------------------------------------*/ - if(((sr1itflags & I2C_FLAG_TXE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) - { - I2C_SlaveTransmit_TXE(hi2c); - } - /* BTF set -------------------------------------------------------------*/ - else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) - { - I2C_SlaveTransmit_BTF(hi2c); - } - } - /* I2C in mode Receiver --------------------------------------------------*/ - else - { - /* RXNE set and BTF reset ----------------------------------------------*/ - if(((sr1itflags & I2C_FLAG_RXNE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) - { - I2C_SlaveReceive_RXNE(hi2c); - } - /* BTF set -------------------------------------------------------------*/ - else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) - { - I2C_SlaveReceive_BTF(hi2c); - } - } - } -#endif -} - -/** - * @brief This function handles I2C error interrupt request. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c) { - uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, tmp4 = 0U; - uint32_t sr1itflags = READ_REG(hi2c->Instance->SR1); - uint32_t itsources = READ_REG(hi2c->Instance->CR2); - - /* I2C Bus error interrupt occurred ----------------------------------------*/ - if (((sr1itflags & I2C_FLAG_BERR) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) { - hi2c->ErrorCode |= HAL_I2C_ERROR_BERR; - - /* Clear BERR flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); - - /* Workaround: Start cannot be generated after a misplaced Stop */ - SET_BIT(hi2c->Instance->CR1, I2C_CR1_SWRST); - } - - /* I2C Arbitration Loss error interrupt occurred ---------------------------*/ - if (((sr1itflags & I2C_FLAG_ARLO) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) { - hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO; - - /* Clear ARLO flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); - } - - /* I2C Acknowledge failure error interrupt occurred ------------------------*/ - if (((sr1itflags & I2C_FLAG_AF) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) { - tmp1 = hi2c->Mode; - tmp2 = hi2c->XferCount; - tmp3 = hi2c->State; - tmp4 = hi2c->PreviousState; - if ((tmp1 == HAL_I2C_MODE_SLAVE) && (tmp2 == 0U) && - ((tmp3 == HAL_I2C_STATE_BUSY_TX) || (tmp3 == HAL_I2C_STATE_BUSY_TX_LISTEN) || ((tmp3 == HAL_I2C_STATE_LISTEN) && (tmp4 == I2C_STATE_SLAVE_BUSY_TX)))) { - } else { - hi2c->ErrorCode |= HAL_I2C_ERROR_AF; - - /* Do not generate a STOP in case of Slave receive non acknowledge during transfer (mean not at the end of transfer) */ - if (hi2c->Mode == HAL_I2C_MODE_MASTER) { - /* Generate Stop */ - SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); - } - - /* Clear AF flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); - } - } - - /* I2C Over-Run/Under-Run interrupt occurred -------------------------------*/ - if (((sr1itflags & I2C_FLAG_OVR) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) { - hi2c->ErrorCode |= HAL_I2C_ERROR_OVR; - /* Clear OVR flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); - } - - /* Call the Error Callback in case of Error detected -----------------------*/ - if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) { - I2C_ITError(hi2c); - } -} - -/** - * @brief Master Tx Transfer completed callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_MasterTxCpltCallback can be implemented in the user file - */ -} - -/** - * @brief Master Rx Transfer completed callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_MasterRxCpltCallback can be implemented in the user file - */ -} - -/** @brief Slave Tx Transfer completed callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_SlaveTxCpltCallback can be implemented in the user file - */ -} - -/** - * @brief Slave Rx Transfer completed callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_SlaveRxCpltCallback can be implemented in the user file - */ -} - -/** - * @brief Slave Address Match callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XferOptions_definition - * @param AddrMatchCode Address Match Code - * @retval None - */ -__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - UNUSED(TransferDirection); - UNUSED(AddrMatchCode); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_AddrCallback can be implemented in the user file - */ -} - -/** - * @brief Listen Complete callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_ListenCpltCallback can be implemented in the user file - */ -} - -/** - * @brief Memory Tx Transfer completed callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_MemTxCpltCallback can be implemented in the user file - */ -} - -/** - * @brief Memory Rx Transfer completed callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_MemRxCpltCallback can be implemented in the user file - */ -} - -/** - * @brief I2C error callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_ErrorCallback can be implemented in the user file - */ -} - -/** - * @brief I2C abort callback. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval None - */ -__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hi2c); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_I2C_AbortCpltCallback could be implemented in the user file - */ -} - -/** - * @} - */ - -/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions - * @brief Peripheral State and Errors functions - * -@verbatim - =============================================================================== - ##### Peripheral State, Mode and Error functions ##### - =============================================================================== - [..] - This subsection permits to get in run-time the status of the peripheral - and the data flow. - -@endverbatim - * @{ - */ - -/** - * @brief Return the I2C handle state. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval HAL state - */ -HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c) { - /* Return I2C handle state */ - return hi2c->State; -} - -/** - * @brief Return the I2C Master, Slave, Memory or no mode. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL mode - */ -HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c) { return hi2c->Mode; } - -/** - * @brief Return the I2C error code - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval I2C Error Code - */ -uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) { return hi2c->ErrorCode; } - -/** - * @} - */ - -/** - * @brief Handle TXE flag for Master - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c) { - /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ - uint32_t CurrentState = hi2c->State; - uint32_t CurrentMode = hi2c->Mode; - uint32_t CurrentXferOptions = hi2c->XferOptions; - - if ((hi2c->XferSize == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX)) { - /* Call TxCpltCallback() directly if no stop mode is set */ - if ((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) { - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - HAL_I2C_MasterTxCpltCallback(hi2c); - } else /* Generate Stop condition then Call TxCpltCallback() */ - { - /* Disable EVT, BUF and ERR interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - if (hi2c->Mode == HAL_I2C_MODE_MEM) { - hi2c->Mode = HAL_I2C_MODE_NONE; - HAL_I2C_MemTxCpltCallback(hi2c); - } else { - hi2c->Mode = HAL_I2C_MODE_NONE; - HAL_I2C_MasterTxCpltCallback(hi2c); - } - } - } else if ((CurrentState == HAL_I2C_STATE_BUSY_TX) || ((CurrentMode == HAL_I2C_MODE_MEM) && (CurrentState == HAL_I2C_STATE_BUSY_RX))) { - if (hi2c->XferCount == 0U) { - /* Disable BUF interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); - } else { - if (hi2c->Mode == HAL_I2C_MODE_MEM) { - if (hi2c->EventCount == 0) { - /* If Memory address size is 8Bit */ - if (hi2c->MemaddSize == I2C_MEMADD_SIZE_8BIT) { - /* Send Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); - - hi2c->EventCount += 2; - } - /* If Memory address size is 16Bit */ - else { - /* Send MSB of Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_MSB(hi2c->Memaddress); - - hi2c->EventCount++; - } - } else if (hi2c->EventCount == 1) { - /* Send LSB of Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); - - hi2c->EventCount++; - } else if (hi2c->EventCount == 2) { - if (hi2c->State == HAL_I2C_STATE_BUSY_RX) { - /* Generate Restart */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } else if (hi2c->State == HAL_I2C_STATE_BUSY_TX) { - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferCount--; - } - } - } else { - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferCount--; - } - } - } - return HAL_OK; -} - -/** - * @brief Handle BTF flag for Master transmitter - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c) { - /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ - uint32_t CurrentXferOptions = hi2c->XferOptions; - - if (hi2c->State == HAL_I2C_STATE_BUSY_TX) { - if (hi2c->XferCount != 0U) { - /* Write data to DR */ - hi2c->Instance->DR = (*hi2c->pBuffPtr++); - hi2c->XferCount--; - } else { - /* Call TxCpltCallback() directly if no stop mode is set */ - if ((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) { - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; - hi2c->Mode = HAL_I2C_MODE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - HAL_I2C_MasterTxCpltCallback(hi2c); - } else /* Generate Stop condition then Call TxCpltCallback() */ - { - /* Disable EVT, BUF and ERR interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - if (hi2c->Mode == HAL_I2C_MODE_MEM) { - hi2c->Mode = HAL_I2C_MODE_NONE; - - HAL_I2C_MemTxCpltCallback(hi2c); - } else { - hi2c->Mode = HAL_I2C_MODE_NONE; - - HAL_I2C_MasterTxCpltCallback(hi2c); - } - } - } - } - return HAL_OK; -} - -/** - * @brief Handle RXNE flag for Master - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c) { - if (hi2c->State == HAL_I2C_STATE_BUSY_RX) { - uint32_t tmp = 0U; - - tmp = hi2c->XferCount; - if (tmp > 3U) { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferCount--; - } else if ((tmp == 2U) || (tmp == 3U)) { - if (hi2c->XferOptions != I2C_NEXT_FRAME) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Enable Pos */ - hi2c->Instance->CR1 |= I2C_CR1_POS; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - } - - /* Disable BUF interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); - } else { - if (hi2c->XferOptions != I2C_NEXT_FRAME) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - } - - /* Disable EVT, BUF and ERR interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferCount--; - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->PreviousState = I2C_STATE_NONE; - - if (hi2c->Mode == HAL_I2C_MODE_MEM) { - hi2c->Mode = HAL_I2C_MODE_NONE; - HAL_I2C_MemRxCpltCallback(hi2c); - } else { - hi2c->Mode = HAL_I2C_MODE_NONE; - HAL_I2C_MasterRxCpltCallback(hi2c); - } - } - } - return HAL_OK; -} - -/** - * @brief Handle BTF flag for Master receiver - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c) { - /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ - uint32_t CurrentXferOptions = hi2c->XferOptions; - - if (hi2c->XferCount == 3U) { - if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - } - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferCount--; - } else if (hi2c->XferCount == 2U) { - /* Prepare next transfer or stop current transfer */ - if ((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) { - if (CurrentXferOptions != I2C_NEXT_FRAME) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - } - - /* Disable EVT and ERR interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - } else { - /* Disable EVT and ERR interrupt */ - __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - } - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferCount--; - - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferCount--; - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->PreviousState = I2C_STATE_NONE; - - if (hi2c->Mode == HAL_I2C_MODE_MEM) { - hi2c->Mode = HAL_I2C_MODE_NONE; - - HAL_I2C_MemRxCpltCallback(hi2c); - } else { - hi2c->Mode = HAL_I2C_MODE_NONE; - - HAL_I2C_MasterRxCpltCallback(hi2c); - } - } else { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - hi2c->XferCount--; - } - return HAL_OK; -} - -/** - * @brief Handle SB flag for Master - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_Master_SB(I2C_HandleTypeDef *hi2c) { - if (hi2c->Mode == HAL_I2C_MODE_MEM) { - if (hi2c->EventCount == 0U) { - /* Send slave address */ - hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); - } else { - hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); - } - } else { - if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) { - /* Send slave 7 Bits address */ - if (hi2c->State == HAL_I2C_STATE_BUSY_TX) { - hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); - } else { - hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); - } - } else { - if (hi2c->EventCount == 0U) { - /* Send header of slave address */ - hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(hi2c->Devaddress); - } else if (hi2c->EventCount == 1U) { - /* Send header of slave address */ - hi2c->Instance->DR = I2C_10BIT_HEADER_READ(hi2c->Devaddress); - } - } - } - - return HAL_OK; -} - -/** - * @brief Handle ADDR flag for Master - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_Master_ADDR(I2C_HandleTypeDef *hi2c) { - /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ - uint32_t CurrentMode = hi2c->Mode; - uint32_t CurrentXferOptions = hi2c->XferOptions; - uint32_t Prev_State = hi2c->PreviousState; - - if (hi2c->State == HAL_I2C_STATE_BUSY_RX) { - if ((hi2c->EventCount == 0U) && (CurrentMode == HAL_I2C_MODE_MEM)) { - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } else { - if (hi2c->XferCount == 0U) { - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - } else if (hi2c->XferCount == 1U) { - if (CurrentXferOptions == I2C_NO_OPTION_FRAME) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } else { - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - } - } - /* Prepare next transfer or stop current transfer */ - else if ((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (Prev_State != I2C_STATE_MASTER_BUSY_RX)) { - if (hi2c->XferOptions != I2C_NEXT_FRAME) { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } else { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - } - } else if (hi2c->XferCount == 2U) { - if (hi2c->XferOptions != I2C_NEXT_FRAME) { - /* Enable Pos */ - hi2c->Instance->CR1 |= I2C_CR1_POS; - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } - - if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) { - /* Enable Last DMA bit */ - hi2c->Instance->CR2 |= I2C_CR2_LAST; - } - } else { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) { - /* Enable Last DMA bit */ - hi2c->Instance->CR2 |= I2C_CR2_LAST; - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } - - /* Reset Event counter */ - hi2c->EventCount = 0U; - } - } else { - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - } - - return HAL_OK; -} - -/** - * @brief I2C interrupts error process - * @param hi2c I2C handle. - * @retval None - */ -static void I2C_ITError(I2C_HandleTypeDef *hi2c) { - /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ - uint32_t CurrentState = hi2c->State; - - if ((CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN) || (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN)) { - /* keep HAL_I2C_STATE_LISTEN */ - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_LISTEN; - } else { - /* If state is an abort treatment on going, don't change state */ - /* This change will be do later */ - if ((hi2c->State != HAL_I2C_STATE_ABORT) && ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) != I2C_CR2_DMAEN)) { - hi2c->State = HAL_I2C_STATE_READY; - } - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->Mode = HAL_I2C_MODE_NONE; - } - - /* Disable Pos bit in I2C CR1 when error occurred in Master/Mem Receive IT Process */ - hi2c->Instance->CR1 &= ~I2C_CR1_POS; - - /* Abort DMA transfer */ - if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) { - hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; - - if (hi2c->hdmatx->State != HAL_DMA_STATE_READY) { - /* Set the DMA Abort callback : - will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ - hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; - - if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) { - /* Disable I2C peripheral to prevent dummy data in buffer */ - __HAL_I2C_DISABLE(hi2c); - - hi2c->State = HAL_I2C_STATE_READY; - - /* Call Directly XferAbortCallback function in case of error */ - hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); - } - } else { - /* Set the DMA Abort callback : - will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ - hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; - - if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) { - /* Store Last receive data if any */ - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - } - - /* Disable I2C peripheral to prevent dummy data in buffer */ - __HAL_I2C_DISABLE(hi2c); - - hi2c->State = HAL_I2C_STATE_READY; - - /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */ - hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); - } - } - } else if (hi2c->State == HAL_I2C_STATE_ABORT) { - hi2c->State = HAL_I2C_STATE_READY; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Store Last receive data if any */ - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - } - - /* Disable I2C peripheral to prevent dummy data in buffer */ - __HAL_I2C_DISABLE(hi2c); - - /* Call the corresponding callback to inform upper layer of End of Transfer */ - HAL_I2C_AbortCpltCallback(hi2c); - } else { - /* Store Last receive data if any */ - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) { - /* Read data from DR */ - (*hi2c->pBuffPtr++) = hi2c->Instance->DR; - } - - /* Call user error callback */ - HAL_I2C_ErrorCallback(hi2c); - } - /* STOP Flag is not set after a NACK reception */ - /* So may inform upper layer that listen phase is stopped */ - /* during NACK error treatment */ - if ((hi2c->State == HAL_I2C_STATE_LISTEN) && ((hi2c->ErrorCode & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF)) { - hi2c->XferOptions = I2C_NO_OPTION_FRAME; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ - HAL_I2C_ListenCpltCallback(hi2c); - } -} - -/** - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) { - /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ - uint32_t CurrentXferOptions = hi2c->XferOptions; - - /* Generate Start condition if first transfer */ - if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) { - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) { - /* Generate ReStart */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } - - /* Wait until SB flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) { - /* Send slave address */ - hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); - } - - /* Wait until ADDR flag is set */ - if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - return HAL_OK; -} - -/** - * @brief Master sends target device address for read request. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) { - /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ - uint32_t CurrentXferOptions = hi2c->XferOptions; - - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start condition if first transfer */ - if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) { - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) { - /* Generate ReStart */ - hi2c->Instance->CR1 |= I2C_CR1_START; - } - - /* Wait until SB flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) { - /* Send slave address */ - hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); - } - - /* Wait until ADDR flag is set */ - if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - return HAL_OK; -} - -/** - * @brief Master sends target device address followed by internal memory address for write request. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) { - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Wait until SB flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Send slave address */ - hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); - - /* Wait until ADDR flag is set */ - if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* If Memory address size is 8Bit */ - if (MemAddSize == I2C_MEMADD_SIZE_8BIT) { - /* Send Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); - } - /* If Memory address size is 16Bit */ - else { - /* Send MSB of Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); - - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Send LSB of Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); - } - - return HAL_OK; -} - -/** - * @brief Master sends target device address followed by internal memory address for read request. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @param DevAddress Target device address: The device 7 bits address value - * in datasheet must be shifted to the left before calling the interface - * @param MemAddress Internal memory address - * @param MemAddSize Size of internal memory address - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) { - /* Enable Acknowledge */ - hi2c->Instance->CR1 |= I2C_CR1_ACK; - - /* Generate Start */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Wait until SB flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Send slave address */ - hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); - - /* Wait until ADDR flag is set */ - if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Clear ADDR flag */ - __HAL_I2C_CLEAR_ADDRFLAG(hi2c); - - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* If Memory address size is 8Bit */ - if (MemAddSize == I2C_MEMADD_SIZE_8BIT) { - /* Send Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); - } - /* If Memory address size is 16Bit */ - else { - /* Send MSB of Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); - - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Send LSB of Memory Address */ - hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); - } - - /* Wait until TXE flag is set */ - if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - /* Generate Restart */ - hi2c->Instance->CR1 |= I2C_CR1_START; - - /* Wait until SB flag is set */ - if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) { - return HAL_TIMEOUT; - } - - /* Send slave address */ - hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); - - /* Wait until ADDR flag is set */ - if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) { - if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { - return HAL_ERROR; - } else { - return HAL_TIMEOUT; - } - } - - return HAL_OK; -} - -/** - * @brief DMA I2C process complete callback. - * @param hdma DMA handle - * @retval None - */ -static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma) { - I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; - - /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ - uint32_t CurrentState = hi2c->State; - uint32_t CurrentMode = hi2c->Mode; - - if ((CurrentState == HAL_I2C_STATE_BUSY_TX) || ((CurrentState == HAL_I2C_STATE_BUSY_RX) && (CurrentMode == HAL_I2C_MODE_SLAVE))) { - /* Disable DMA Request */ - hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; - - hi2c->XferCount = 0U; - - /* Enable EVT and ERR interrupt */ - __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); - } else { - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Disable Last DMA */ - hi2c->Instance->CR2 &= ~I2C_CR2_LAST; - - /* Disable DMA Request */ - hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; - - hi2c->XferCount = 0U; - - /* Check if Errors has been detected during transfer */ - if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) { - HAL_I2C_ErrorCallback(hi2c); - } else { - hi2c->State = HAL_I2C_STATE_READY; - - if (hi2c->Mode == HAL_I2C_MODE_MEM) { - hi2c->Mode = HAL_I2C_MODE_NONE; - - HAL_I2C_MemRxCpltCallback(hi2c); - } else { - hi2c->Mode = HAL_I2C_MODE_NONE; - - HAL_I2C_MasterRxCpltCallback(hi2c); - } - } - } -} - -/** - * @brief DMA I2C communication error callback. - * @param hdma DMA handle - * @retval None - */ -static void I2C_DMAError(DMA_HandleTypeDef *hdma) { - I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - hi2c->XferCount = 0U; - - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; - - HAL_I2C_ErrorCallback(hi2c); -} - -/** - * @brief DMA I2C communication abort callback - * (To be called at end of DMA Abort procedure). - * @param hdma: DMA handle. - * @retval None - */ -static void I2C_DMAAbort(DMA_HandleTypeDef *hdma) { - I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; - - /* Disable Acknowledge */ - hi2c->Instance->CR1 &= ~I2C_CR1_ACK; - - hi2c->XferCount = 0U; - - /* Reset XferAbortCallback */ - hi2c->hdmatx->XferAbortCallback = NULL; - hi2c->hdmarx->XferAbortCallback = NULL; - - /* Check if come from abort from user */ - if (hi2c->State == HAL_I2C_STATE_ABORT) { - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - - /* Disable I2C peripheral to prevent dummy data in buffer */ - __HAL_I2C_DISABLE(hi2c); - - /* Call the corresponding callback to inform upper layer of End of Transfer */ - HAL_I2C_AbortCpltCallback(hi2c); - } else { - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Disable I2C peripheral to prevent dummy data in buffer */ - __HAL_I2C_DISABLE(hi2c); - - /* Call the corresponding callback to inform upper layer of End of Transfer */ - HAL_I2C_ErrorCallback(hi2c); - } -} - -/** - * @brief This function handles I2C Communication Timeout. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @param Flag specifies the I2C flag to check. - * @param Status The new Flag status (SET or RESET). - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) { - /* Wait until flag is set */ - while ((__HAL_I2C_GET_FLAG(hi2c, Flag) ? SET : RESET) == Status) { - /* Check for the Timeout */ - if (Timeout != HAL_MAX_DELAY) { - if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - hi2c->Mode = HAL_I2C_MODE_NONE; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } - } - - return HAL_OK; -} - -/** - * @brief This function handles I2C Communication Timeout for Master addressing phase. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for I2C module - * @param Flag specifies the I2C flag to check. - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) { - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) { - /* Generate Stop */ - hi2c->Instance->CR1 |= I2C_CR1_STOP; - - /* Clear AF Flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); - - hi2c->ErrorCode = HAL_I2C_ERROR_AF; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_ERROR; - } - - /* Check for the Timeout */ - if (Timeout != HAL_MAX_DELAY) { - if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) { - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } - } - return HAL_OK; -} - -/** - * @brief This function handles I2C Communication Timeout for specific usage of TXE flag. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) { - /* Check if a NACK is detected */ - if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) { - return HAL_ERROR; - } - - /* Check for the Timeout */ - if (Timeout != HAL_MAX_DELAY) { - if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) { - hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } - } - return HAL_OK; -} - -/** - * @brief This function handles I2C Communication Timeout for specific usage of BTF flag. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) { - /* Check if a NACK is detected */ - if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) { - return HAL_ERROR; - } - - /* Check for the Timeout */ - if (Timeout != HAL_MAX_DELAY) { - if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) { - hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } - } - return HAL_OK; -} - -/** - * @brief This function handles I2C Communication Timeout for specific usage of STOP flag. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) { - /* Check if a NACK is detected */ - if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) { - return HAL_ERROR; - } - - /* Check for the Timeout */ - if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) { - hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } - return HAL_OK; -} - -/** - * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @param Timeout Timeout duration - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) { - /* Check if a STOPF is detected */ - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) { - /* Clear STOP Flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); - - hi2c->ErrorCode = HAL_I2C_ERROR_NONE; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_ERROR; - } - - /* Check for the Timeout */ - if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) { - hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_TIMEOUT; - } - } - return HAL_OK; -} - -/** - * @brief This function handles Acknowledge failed detection during an I2C Communication. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval HAL status - */ -static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) { - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) { - /* Clear NACKF Flag */ - __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); - - hi2c->ErrorCode = HAL_I2C_ERROR_AF; - hi2c->PreviousState = I2C_STATE_NONE; - hi2c->State = HAL_I2C_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2c); - - return HAL_ERROR; - } - return HAL_OK; -} -/** - * @} - */ - -#endif /* HAL_I2C_MODULE_ENABLED */ - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/source/Core/BSP/Miniware/configuration.h b/source/Core/BSP/Miniware/configuration.h index e864bb2913..91923dfa7e 100644 --- a/source/Core/BSP/Miniware/configuration.h +++ b/source/Core/BSP/Miniware/configuration.h @@ -177,6 +177,9 @@ #define TIP_RESISTANCE 75 // x10 ohms, 7.5 typical for ts100 tips #define POW_DC +#define I2C_SOFT_BUS_1 1 +#define OLED_I2CBB1 1 +#define ACCEL_I2CBB1 1 #define TEMP_TMP36 #endif /* TS100 */ @@ -241,6 +244,9 @@ #define POW_QC #define TEMP_TMP36 +#define I2C_SOFT_BUS_1 1 +#define OLED_I2CBB1 1 +#define ACCEL_I2CBB1 1 #endif /* TS80 */ #ifdef MODEL_TS80P @@ -260,6 +266,7 @@ #define I2C_SOFT_BUS_2 1 #define I2C_SOFT_BUS_1 1 #define OLED_I2CBB1 1 +#define ACCEL_I2CBB1 1 #define SC7_ORI_FLIP #endif /* TS80P */ From f329fea181454faa3071b50dfe284bd1522d4585 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 23 Jul 2023 20:35:06 +1000 Subject: [PATCH 38/86] Fixup for scrollbar FIXUP! Debug menu returns to home screen FIXUP! Up oled animation Fix temp exit --- source/Core/Drivers/OLED.cpp | 2 +- .../Core/Threads/OperatingModes/DebugMenu.cpp | 2 +- .../Threads/OperatingModes/SettingsMenu.cpp | 48 ++++++++++--------- .../OperatingModes/TemperatureAdjust.cpp | 1 + 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/source/Core/Drivers/OLED.cpp b/source/Core/Drivers/OLED.cpp index c0a8b06a37..d8f046d174 100644 --- a/source/Core/Drivers/OLED.cpp +++ b/source/Core/Drivers/OLED.cpp @@ -431,7 +431,7 @@ void OLED::transitionScrollUp(const TickType_t viewEnterTime) { screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] << 1) | ((secondFrameBuffer[secondStripPos] & 0x80) >> 7); // Finally, do the shuffle on the second frame buffer - secondFrameBuffer[secondStripPos] = (secondFrameBuffer[firstStripPos] << 1) | ((secondFrameBuffer[secondStripPos] & 0x80) >> 7); + secondFrameBuffer[secondStripPos] = (secondFrameBuffer[secondStripPos] << 1) | ((secondFrameBuffer[firstStripPos] & 0x80) >> 7); // Finally on the bottom row; we shuffle it up ready secondFrameBuffer[firstStripPos] <<= 1; #endif /* OLED_128x32 */ diff --git a/source/Core/Threads/OperatingModes/DebugMenu.cpp b/source/Core/Threads/OperatingModes/DebugMenu.cpp index c7ef139be7..a33e9ff8fb 100644 --- a/source/Core/Threads/OperatingModes/DebugMenu.cpp +++ b/source/Core/Threads/OperatingModes/DebugMenu.cpp @@ -89,7 +89,7 @@ OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) { if (buttons == BUTTON_B_SHORT) { cxt->transitionMode = TransitionAnimation::Down; - return OperatingMode::InitialisationDone; + return OperatingMode::HomeScreen; } else if (buttons == BUTTON_F_SHORT) { cxt->scratch_state.state1++; #ifdef HALL_SENSOR diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index fcb7447bd9..3f4e28bc9e 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -41,18 +41,18 @@ void render_menu(const menuitem *item, guiContext *cxt) { item->draw(); } else { - uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); - *wasRenderingHelp = 1; + uint16_t *isRenderingHelp = &(cxt->scratch_state.state6); + *isRenderingHelp = 1; // Draw description const char *description = translatedString(Tr->SettingsDescriptions[item->description - 1]); drawScrollingText(description, xTaskGetTickCount() - lastButtonTime); } } -uint16_t getMenuLength(const menuitem *menu) { +uint16_t getMenuLength(const menuitem *menu, const uint16_t stop) { // walk this menu to find the length uint16_t counter = 0; - for (uint16_t pos = 0; pos < 64; pos++) { + for (uint16_t pos = 0; pos < stop; pos++) { if (menu[pos].draw == nullptr) { return counter; } @@ -60,14 +60,15 @@ uint16_t getMenuLength(const menuitem *menu) { counter++; } } - return 0; // Cant find length, be safe + return counter; } + OperatingMode moveToNextEntry(guiContext *cxt) { - uint16_t *mainEntry = &(cxt->scratch_state.state1); - uint16_t *subEntry = &(cxt->scratch_state.state2); - uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); - if (*wasRenderingHelp) { - *wasRenderingHelp = 0; + uint16_t *mainEntry = &(cxt->scratch_state.state1); + uint16_t *subEntry = &(cxt->scratch_state.state2); + uint16_t *isRenderingHelp = &(cxt->scratch_state.state6); + if (*isRenderingHelp) { + *isRenderingHelp = 0; } else { // Scroll down // We can increment freely _once_ @@ -113,10 +114,10 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { uint16_t *mainEntry = &(cxt->scratch_state.state1); uint16_t *subEntry = &(cxt->scratch_state.state2); - uint16_t *currentMenuLength = &(cxt->scratch_state.state5); - uint16_t *wasRenderingHelp = &(cxt->scratch_state.state6); uint32_t *autoRepeatAcceleration = &(cxt->scratch_state.state3); uint32_t *autoRepeatTimer = &(cxt->scratch_state.state4); + uint16_t *currentMenuLength = &(cxt->scratch_state.state5); + uint16_t *isRenderingHelp = &(cxt->scratch_state.state6); const menuitem *currentMenu; // Draw the currently on screen item @@ -135,16 +136,19 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Update the cached menu length if unknown if (*currentMenuLength == 0) { // We walk the current menu to find the length - *currentMenuLength = getMenuLength(currentMenu); + *currentMenuLength = getMenuLength(currentMenu, 64); } - // Draw scroll - uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength; - uint8_t position = (OLED_HEIGHT * currentScreen) / *currentMenuLength; - // Draw if not last item - if ((*currentMenuLength != currentScreen) || xTaskGetTickCount() % 1000 < 500) { - OLED::drawScrollIndicator(position, indicatorHeight); + if (*isRenderingHelp == 0) { + // Draw scroll + uint16_t currentVirtualPosition = getMenuLength(currentMenu, currentScreen + 1) - 1; + + uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength; + uint8_t position = (OLED_HEIGHT * currentVirtualPosition) / *currentMenuLength; + // Draw if not last item + if ((*currentMenuLength != currentVirtualPosition) || xTaskGetTickCount() % 1000 < 500) { + OLED::drawScrollIndicator(position, indicatorHeight); + } } - // Now handle user button input auto callIncrementHandler = [&]() { @@ -180,8 +184,8 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { break; case BUTTON_F_SHORT: // Increment setting - if (*wasRenderingHelp) { - *wasRenderingHelp = 0; + if (*isRenderingHelp) { + *isRenderingHelp = 0; } else { if (*subEntry == 0) { // In a root menu, if its null handler we enter the menu diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index 73b5b8d69e..e82a505be1 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -25,6 +25,7 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx break; case BUTTON_BOTH: // exit + cxt->transitionMode = TransitionAnimation::Right; return cxt->previousMode; case BUTTON_B_LONG: if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) { From 1ce2ab4ab799dca042bdda05ba3b6e69a0381bee Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 23 Jul 2023 21:21:12 +1000 Subject: [PATCH 39/86] Settings menu -> Both buttons return a menu layer --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 3f4e28bc9e..0f9bb69f6e 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -168,7 +168,15 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { (*autoRepeatTimer) = 0; // reset acceleration break; case BUTTON_BOTH: - return OperatingMode::HomeScreen; + if (*subEntry == 0) { + saveSettings(); + cxt->transitionMode = TransitionAnimation::Left; + return OperatingMode::HomeScreen; + } else { + cxt->transitionMode = TransitionAnimation::Left; + *subEntry = 0; + return OperatingMode::SettingsMenu; + } break; case BUTTON_F_LONG: From f768a0259e5d4b0aa59b804be512063e1c688c38 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 23 Nov 2023 21:11:04 +1100 Subject: [PATCH 40/86] Merge fixup --- source/Core/Drivers/TipThermoModel.h | 4 ++-- source/Core/Inc/Types.h | 2 +- source/Core/Src/settingsGUI.cpp | 2 +- source/Core/Threads/OperatingModes/CJC.cpp | 2 +- .../OperatingModes/utils/SolderingCommon.cpp | 1 + .../OperatingModes/utils/SolderingCommon.h | 15 ++++++++------- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/source/Core/Drivers/TipThermoModel.h b/source/Core/Drivers/TipThermoModel.h index 03a10ff0f9..b437b02683 100644 --- a/source/Core/Drivers/TipThermoModel.h +++ b/source/Core/Drivers/TipThermoModel.h @@ -5,11 +5,11 @@ * Author: ralim */ -#ifndef SRC_TIPTHERMOMODEL_H_ -#define SRC_TIPTHERMOMODEL_H_ #include "BSP.h" #include "Types.h" #include "stdint.h" +#ifndef SRC_TIPTHERMOMODEL_H_ +#define SRC_TIPTHERMOMODEL_H_ class TipThermoModel { public: // These are the main two functions diff --git a/source/Core/Inc/Types.h b/source/Core/Inc/Types.h index 145cd6beb3..a5d3fe59ff 100644 --- a/source/Core/Inc/Types.h +++ b/source/Core/Inc/Types.h @@ -1,6 +1,6 @@ #ifndef TYPES_H_ #define TYPES_H_ -#include +#include // Used for temperature represented in C or x10C. // diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index 812b4f3007..b934dfb69d 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -911,7 +911,7 @@ static bool setCalibrateVIN(void) { saveSettings(); OLED::clearScreen(); OLED::setCursor(0, 0); - warnUser(translatedString(Tr->CalibrationDone), 3 * TICKS_SECOND); + warnUser(translatedString(Tr->CalibrationDone), getButtonState()); OLED::refresh(); waitForButtonPressOrTimeout(0.5 * TICKS_SECOND); return false; diff --git a/source/Core/Threads/OperatingModes/CJC.cpp b/source/Core/Threads/OperatingModes/CJC.cpp index 44b1206cee..8d504f6953 100644 --- a/source/Core/Threads/OperatingModes/CJC.cpp +++ b/source/Core/Threads/OperatingModes/CJC.cpp @@ -25,7 +25,7 @@ OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { uint16_t setOffset = TipThermoModel::convertTipRawADCTouV(cxt->scratch_state.state3 / 16, true); setSettingValue(SettingsOptions::CalibrationOffset, setOffset); - if (warnUser(translatedString(Tr->CJCCalibrationDone), buttons)) { + if (warnUser(translatedString(Tr->CalibrationDone), buttons)) { // Preventing to repeat calibration at boot automatically (only one shot). setSettingValue(SettingsOptions::CalibrateCJC, 0); saveSettings(); diff --git a/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp b/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp index 5975a1b86c..083716482c 100644 --- a/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp +++ b/source/Core/Threads/OperatingModes/utils/SolderingCommon.cpp @@ -4,6 +4,7 @@ #include "SolderingCommon.h" #include "OperatingModes.h" +#include "Types.h" #include "configuration.h" #include "history.hpp" diff --git a/source/Core/Threads/OperatingModes/utils/SolderingCommon.h b/source/Core/Threads/OperatingModes/utils/SolderingCommon.h index 79ba06d162..42f3765ebb 100644 --- a/source/Core/Threads/OperatingModes/utils/SolderingCommon.h +++ b/source/Core/Threads/OperatingModes/utils/SolderingCommon.h @@ -1,10 +1,11 @@ -#ifndef SOLDERING_COMMON_H -#define SOLDERING_COMMON_H +#include "Types.h" #include +#ifndef SOLDERING_COMMON_H_ +#define SOLDERING_COMMON_H_ -void detailedPowerStatus(); -void basicSolderingStatus(bool boostModeOn); -bool checkExitSoldering(); -uint16_t getTipTemp(void); +void detailedPowerStatus(); +void basicSolderingStatus(bool boostModeOn); +bool checkExitSoldering(); +TemperatureType_t getTipTemp(void); -#endif // SOLDERING_COMMON_H +#endif // SOLDERING_COMMON_H_ From 39dd9415bb519aaa6fc810c1ed6e495fb2f4d04f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 23 Nov 2023 21:15:51 +1100 Subject: [PATCH 41/86] Update BMA223.cpp --- source/Core/Drivers/BMA223.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Core/Drivers/BMA223.cpp b/source/Core/Drivers/BMA223.cpp index bf91b7c053..feab820e5b 100644 --- a/source/Core/Drivers/BMA223.cpp +++ b/source/Core/Drivers/BMA223.cpp @@ -9,7 +9,6 @@ #include #include - bool BMA223::detect() { if (ACCEL_I2C_CLASS::probe(BMA223_ADDRESS)) { // Read chip id to ensure its not an address collision From 3d0c981e0812c4fa7c5c01a0c1da4f4a2397f8c0 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 23 Nov 2023 21:46:54 +1100 Subject: [PATCH 42/86] Re-Enable OLED sleep --- source/Core/Threads/GUIThread.cpp | 36 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 2a30527cb7..4ae446481d 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -45,24 +45,24 @@ OperatingMode guiHandleDraw(void) { // 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); - // } - // } - // } + 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) { From 4efad50157dbffc1110e6065ef6d91020d417020 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 23 Nov 2023 22:00:24 +1100 Subject: [PATCH 43/86] Save Setting on temp adjust exit --- source/Core/Threads/OperatingModes/TemperatureAdjust.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index e82a505be1..acda096666 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -25,6 +25,7 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx break; case BUTTON_BOTH: // exit + saveSettings(); cxt->transitionMode = TransitionAnimation::Right; return cxt->previousMode; case BUTTON_B_LONG: @@ -81,6 +82,7 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp); } if (xTaskGetTickCount() - lastButtonTime > (TICKS_SECOND * 3)) { + saveSettings(); cxt->transitionMode = TransitionAnimation::Right; return cxt->previousMode; // exit if user just doesn't press anything for a bit } From 4cd74ae172d29b5b9c51d5cd87399da015a36d09 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 24 Nov 2023 18:11:39 +1100 Subject: [PATCH 44/86] WiP on startup mode --- source/Core/Threads/GUIThread.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 4ae446481d..0083dfe57a 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -117,9 +117,11 @@ OperatingMode guiHandleDraw(void) { newMode = handle_post_init_state(); break; case OperatingMode::Hibernating: + /*TODO*/ newMode = OperatingMode::HomeScreen; break; case OperatingMode::ThermalRunaway: + /*TODO*/ newMode = OperatingMode::HomeScreen; break; }; @@ -133,6 +135,13 @@ void guiRenderLoop(void) { 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; + } + newMode = OperatingMode::HomeScreen; + } memset(&context.scratch_state, 0, sizeof(context.scratch_state)); currentOperatingMode = newMode; } From ab42ace5066d567929b0326e1302015ebf229d7f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 24 Nov 2023 19:10:38 +1100 Subject: [PATCH 45/86] Some autostart working --- source/Core/Threads/GUIThread.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 0083dfe57a..bb4b616029 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -78,14 +78,21 @@ OperatingMode guiHandleDraw(void) { #endif case OperatingMode::StartupLogo: BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); // TODO needs refactor - if (getSettingValue(SettingsOptions::AutoStartMode) == 1) { + + if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SLEEP) { // jump directly to the autostart mode + 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) == 2) { + } else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SOLDER) { + // jump directly to the autostart mode + newMode = OperatingMode::Soldering; + } else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::ZERO) { newMode = OperatingMode::Hibernating; } else { newMode = OperatingMode::HomeScreen; } + break; default: /* Fallthrough */ @@ -118,7 +125,7 @@ OperatingMode guiHandleDraw(void) { break; case OperatingMode::Hibernating: /*TODO*/ - newMode = OperatingMode::HomeScreen; + newMode = OperatingMode::Soldering; break; case OperatingMode::ThermalRunaway: /*TODO*/ @@ -139,8 +146,9 @@ void guiRenderLoop(void) { if (currentOperatingMode == OperatingMode::StartupLogo) { if (getSettingValue(SettingsOptions::AutoStartMode)) { context.previousMode = OperatingMode::Soldering; + } else { + newMode = OperatingMode::HomeScreen; } - newMode = OperatingMode::HomeScreen; } memset(&context.scratch_state, 0, sizeof(context.scratch_state)); currentOperatingMode = newMode; From 010f6deba967b0043fd0cae6e095f04a65401f0c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 24 Nov 2023 21:45:06 +1100 Subject: [PATCH 46/86] Add hibernation mode & more autostart fixes --- source/Core/Threads/GUIThread.cpp | 21 +++++++++-------- .../Core/Threads/OperatingModes/Soldering.cpp | 23 +++++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index bb4b616029..e1c155961d 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -80,15 +80,14 @@ OperatingMode guiHandleDraw(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); // TODO needs refactor if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SLEEP) { - // jump directly to the autostart mode lastMovementTime = lastButtonTime = 0; // We mask the values so that sleep goes until user moves again or presses a button - - newMode = OperatingMode::Sleeping; + newMode = OperatingMode::Sleeping; } else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SOLDER) { - // jump directly to the autostart mode - newMode = OperatingMode::Soldering; + lastMovementTime = lastButtonTime = xTaskGetTickCount(); // Move forward so we dont go to sleep + newMode = OperatingMode::Soldering; } else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::ZERO) { - newMode = OperatingMode::Hibernating; + lastMovementTime = lastButtonTime = xTaskGetTickCount(); // Move forward so we dont go to sleep + newMode = OperatingMode::Hibernating; } else { newMode = OperatingMode::HomeScreen; } @@ -100,7 +99,8 @@ OperatingMode guiHandleDraw(void) { newMode = drawHomeScreen(buttons, &context); break; case OperatingMode::Soldering: - newMode = gui_solderingMode(buttons, &context); + context.scratch_state.state4 = 0; + newMode = gui_solderingMode(buttons, &context); break; case OperatingMode::SolderingProfile: newMode = gui_solderingProfileMode(buttons, &context); @@ -124,8 +124,11 @@ OperatingMode guiHandleDraw(void) { newMode = handle_post_init_state(); break; case OperatingMode::Hibernating: - /*TODO*/ - newMode = OperatingMode::Soldering; + context.scratch_state.state4 = 1; + gui_solderingMode(buttons, &context); + if (lastButtonTime > 0 || lastMovementTime > 0) { + newMode = OperatingMode::Soldering; + } break; case OperatingMode::ThermalRunaway: /*TODO*/ diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index 52d4650c7c..424e7bfba9 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -73,17 +73,22 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { */ // Update the setpoints for the temperature - if (cxt->scratch_state.state2) { - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp)); - } else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); - } + if (cxt->scratch_state.state4) { + // Hibernating mode + currentTempTargetDegC = 0; } else { - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp)); + if (cxt->scratch_state.state2) { + if (getSettingValue(SettingsOptions::TemperatureInF)) { + currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp)); + } else { + currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); + } } else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp)); + if (getSettingValue(SettingsOptions::TemperatureInF)) { + currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp)); + } else { + currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp)); + } } } From cb4fb3dbc75fcfd97bda583e93659dc6e8c374e8 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 24 Nov 2023 23:02:31 +1100 Subject: [PATCH 47/86] If cant CJC; go to startup --- source/Core/Threads/OperatingModes/CJC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/CJC.cpp b/source/Core/Threads/OperatingModes/CJC.cpp index 8d504f6953..536810ee58 100644 --- a/source/Core/Threads/OperatingModes/CJC.cpp +++ b/source/Core/Threads/OperatingModes/CJC.cpp @@ -34,5 +34,5 @@ OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { return OperatingMode::CJCCalibration; } // Cant run calibration without the tip and for temps to be close - return OperatingMode::InitialisationDone; + return OperatingMode::StartupLogo; } From 940e060142aeca4a6878db21c20287195f73fec9 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 25 Nov 2023 21:30:43 +1100 Subject: [PATCH 48/86] Hibernate in sleep --- source/Core/Threads/GUIThread.cpp | 2 +- source/Core/Threads/OperatingModes/Sleep.cpp | 12 +++++++--- .../Core/Threads/OperatingModes/Soldering.cpp | 23 ++++++++----------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index e1c155961d..d20628f587 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -125,7 +125,7 @@ OperatingMode guiHandleDraw(void) { break; case OperatingMode::Hibernating: context.scratch_state.state4 = 1; - gui_solderingMode(buttons, &context); + gui_SolderingSleepingMode(buttons, &context); if (lastButtonTime > 0 || lastMovementTime > 0) { newMode = OperatingMode::Soldering; } diff --git a/source/Core/Threads/OperatingModes/Sleep.cpp b/source/Core/Threads/OperatingModes/Sleep.cpp index 94123eef6c..75c10b6a8a 100644 --- a/source/Core/Threads/OperatingModes/Sleep.cpp +++ b/source/Core/Threads/OperatingModes/Sleep.cpp @@ -14,10 +14,16 @@ OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *c return OperatingMode::HomeScreen; // return non-zero on error } #endif - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp))); + + if (cxt->scratch_state.state4) { + // Hibernating mode + currentTempTargetDegC = 0; } else { - currentTempTargetDegC = min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp)); + if (getSettingValue(SettingsOptions::TemperatureInF)) { + currentTempTargetDegC = TipThermoModel::convertFtoC(min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp))); + } else { + currentTempTargetDegC = min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp)); + } } // draw the lcd uint16_t tipTemp = getSettingValue(SettingsOptions::TemperatureInF) ? TipThermoModel::getTipInF() : TipThermoModel::getTipInC(); diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index 424e7bfba9..52d4650c7c 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -73,22 +73,17 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { */ // Update the setpoints for the temperature - if (cxt->scratch_state.state4) { - // Hibernating mode - currentTempTargetDegC = 0; + if (cxt->scratch_state.state2) { + if (getSettingValue(SettingsOptions::TemperatureInF)) { + currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp)); + } else { + currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); + } } else { - if (cxt->scratch_state.state2) { - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp)); - } else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); - } + if (getSettingValue(SettingsOptions::TemperatureInF)) { + currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp)); } else { - if (getSettingValue(SettingsOptions::TemperatureInF)) { - currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp)); - } else { - currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp)); - } + currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp)); } } From afea604fbfc172df985e4db60f8c08a997429ebe Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 26 Nov 2023 13:26:25 +1100 Subject: [PATCH 49/86] Cleanup scroll indicator --- .../Threads/OperatingModes/SettingsMenu.cpp | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 0f9bb69f6e..14e35d6d8b 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -53,9 +53,11 @@ uint16_t getMenuLength(const menuitem *menu, const uint16_t stop) { // walk this menu to find the length uint16_t counter = 0; for (uint16_t pos = 0; pos < stop; pos++) { + // End of list if (menu[pos].draw == nullptr) { return counter; } + // Otherwise increment for each visible item (null == always, or if not check function) if (menu[pos].isVisible == nullptr || menu[pos].isVisible()) { counter++; } @@ -64,17 +66,21 @@ uint16_t getMenuLength(const menuitem *menu, const uint16_t stop) { } OperatingMode moveToNextEntry(guiContext *cxt) { - uint16_t *mainEntry = &(cxt->scratch_state.state1); - uint16_t *subEntry = &(cxt->scratch_state.state2); - uint16_t *isRenderingHelp = &(cxt->scratch_state.state6); + uint16_t *mainEntry = &(cxt->scratch_state.state1); + uint16_t *subEntry = &(cxt->scratch_state.state2); + uint16_t *currentMenuLength = &(cxt->scratch_state.state5); + uint16_t *isRenderingHelp = &(cxt->scratch_state.state6); + if (*isRenderingHelp) { *isRenderingHelp = 0; } else { + *currentMenuLength = 0; // Reset menu length // Scroll down // We can increment freely _once_ cxt->transitionMode = TransitionAnimation::Down; if (*subEntry == 0) { (*mainEntry) += 1; + if (rootSettingsMenu[*mainEntry].draw == nullptr) { // We are off the end of the menu now saveSettings(); @@ -136,17 +142,24 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Update the cached menu length if unknown if (*currentMenuLength == 0) { // We walk the current menu to find the length - *currentMenuLength = getMenuLength(currentMenu, 64); + *currentMenuLength = getMenuLength(currentMenu, 128 /* Max length of any menu*/); } if (*isRenderingHelp == 0) { // Draw scroll + + // Get virtual pos by counting entries from start to _here_ uint16_t currentVirtualPosition = getMenuLength(currentMenu, currentScreen + 1) - 1; + // The height of the indicator is screen res height / total menu entries uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength; - uint8_t position = (OLED_HEIGHT * currentVirtualPosition) / *currentMenuLength; - // Draw if not last item - if ((*currentMenuLength != currentVirtualPosition) || xTaskGetTickCount() % 1000 < 500) { - OLED::drawScrollIndicator(position, indicatorHeight); + if (indicatorHeight == 0) { + indicatorHeight = 1; // always at least 1 pixel + } + + uint16_t position = (OLED_HEIGHT * (uint16_t)currentVirtualPosition) / *currentMenuLength; + // Draw if not last item || flash if it is + if ((*currentMenuLength != currentVirtualPosition) || (xTaskGetTickCount() % 1000 < 500)) { + OLED::drawScrollIndicator((uint8_t)position, indicatorHeight); } } // Now handle user button input From d3fee24856a7d56d58890346d6ff95d576b5c956 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 26 Nov 2023 13:35:02 +1100 Subject: [PATCH 50/86] FIXUP! Ensure startup warnings are linked in --- source/Core/Threads/GUIThread.cpp | 2 +- source/Core/Threads/OperatingModes/CJC.cpp | 2 +- .../OperatingModes/ShowStartupWarnings.cpp | 31 ++++++++++++++----- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index d20628f587..f23a2e5827 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -203,7 +203,7 @@ OperatingMode handle_post_init_state() { return OperatingMode::CJCCalibration; } - return OperatingMode::StartupLogo; + return OperatingMode::StartupWarnings; } /* StartGUITask function */ diff --git a/source/Core/Threads/OperatingModes/CJC.cpp b/source/Core/Threads/OperatingModes/CJC.cpp index 536810ee58..a33fe5cc0c 100644 --- a/source/Core/Threads/OperatingModes/CJC.cpp +++ b/source/Core/Threads/OperatingModes/CJC.cpp @@ -34,5 +34,5 @@ OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { return OperatingMode::CJCCalibration; } // Cant run calibration without the tip and for temps to be close - return OperatingMode::StartupLogo; + return OperatingMode::StartupWarnings; } diff --git a/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp b/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp index 3598e9b186..4e4a3aa7f6 100644 --- a/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp +++ b/source/Core/Threads/OperatingModes/ShowStartupWarnings.cpp @@ -10,6 +10,8 @@ OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) { settingsWereReset = false; cxt->scratch_state.state1 = 1; } + } else { + cxt->scratch_state.state1 = 1; } break; case 1: // Device validations @@ -19,6 +21,8 @@ OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) { if (warnUser(translatedString(Tr->DeviceFailedValidationWarning), buttons)) { cxt->scratch_state.state1 = 2; } + } else { + cxt->scratch_state.state1 = 2; } #else cxt->scratch_state.state1 = 2; @@ -31,12 +35,17 @@ OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) { // Display alert if accelerometer is not detected if (DetectedAccelerometerVersion == AccelType::None) { if (getSettingValue(SettingsOptions::AccelMissingWarningCounter) < 2) { - nextSettingValue(SettingsOptions::AccelMissingWarningCounter); - saveSettings(); + if (warnUser(translatedString(Tr->NoAccelerometerMessage), buttons)) { cxt->scratch_state.state1 = 3; + nextSettingValue(SettingsOptions::AccelMissingWarningCounter); + saveSettings(); } + } else { + cxt->scratch_state.state1 = 3; } + } else { + cxt->scratch_state.state1 = 3; } break; case 3: @@ -45,23 +54,31 @@ OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) { // We expect pd to be present if (!USBPowerDelivery::fusbPresent()) { if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { - nextSettingValue(SettingsOptions::PDMissingWarningCounter); - saveSettings(); if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) { + nextSettingValue(SettingsOptions::PDMissingWarningCounter); + saveSettings(); cxt->scratch_state.state1 = 4; } + } else { + cxt->scratch_state.state1 = 4; } + } else { + cxt->scratch_state.state1 = 4; } #else #if POW_PD_EXT == 1 if (!hub238_probe()) { if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { - nextSettingValue(SettingsOptions::PDMissingWarningCounter); - saveSettings(); if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) { cxt->scratch_state.state1 = 4; + nextSettingValue(SettingsOptions::PDMissingWarningCounter); + saveSettings(); } + } else { + cxt->scratch_state.state1 = 4; } + } else { + cxt->scratch_state.state1 = 4; } #else cxt->scratch_state.state1 = 4; @@ -71,7 +88,7 @@ OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) { break; default: // We are off the end, warnings done - return OperatingMode::InitialisationDone; + return OperatingMode::StartupLogo; } return OperatingMode::StartupWarnings; // Stay in warnings From fd78fbfd56ee0bd432fc3f9dc804384c1dd8f22b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 26 Nov 2023 13:36:54 +1100 Subject: [PATCH 51/86] FIXUP! Ensure we render out temp change before timing out --- .../Core/Threads/OperatingModes/TemperatureAdjust.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp index acda096666..2a840d780b 100644 --- a/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp +++ b/source/Core/Threads/OperatingModes/TemperatureAdjust.cpp @@ -81,11 +81,6 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx } setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp); } - if (xTaskGetTickCount() - lastButtonTime > (TICKS_SECOND * 3)) { - saveSettings(); - cxt->transitionMode = TransitionAnimation::Right; - return cxt->previousMode; // exit if user just doesn't press anything for a bit - } if (OLED::getRotation()) { OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE); } else { @@ -102,5 +97,10 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE); } + if (xTaskGetTickCount() - lastButtonTime > (TICKS_SECOND * 3)) { + saveSettings(); + cxt->transitionMode = TransitionAnimation::Right; + return cxt->previousMode; // exit if user just doesn't press anything for a bit + } return OperatingMode::TemperatureAdjust; // Stay in temp adjust } From 7be2f48094d32c9db249fde7af3bed86c2c98841 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 17:25:40 +1100 Subject: [PATCH 52/86] Ensure 100ms delay between CJC samples --- source/Core/Threads/OperatingModes/CJC.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/Core/Threads/OperatingModes/CJC.cpp b/source/Core/Threads/OperatingModes/CJC.cpp index a33fe5cc0c..e2847c6b63 100644 --- a/source/Core/Threads/OperatingModes/CJC.cpp +++ b/source/Core/Threads/OperatingModes/CJC.cpp @@ -4,9 +4,13 @@ OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { // Calibrate Cold Junction Compensation directly at boot, before internal components get warm. if (!isTipDisconnected() && abs(int(TipThermoModel::getTipInC() - getHandleTemperature(0) / 10)) < 10) { - // Take 16 samples + // Take 16 samples, only sample if (cxt->scratch_state.state1 < 16) { - cxt->scratch_state.state3 += getTipRawTemp(1); + if ((xTaskGetTickCount() - cxt->scratch_state.state4) > TICKS_100MS) { + cxt->scratch_state.state3 += getTipRawTemp(1); + cxt->scratch_state.state1++; + cxt->scratch_state.state4 = xTaskGetTickCount(); + } OLED::setCursor(0, 0); OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL); OLED::setCursor(0, 8); @@ -15,7 +19,6 @@ OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { OLED::print(SmallSymbolDot, FontStyle::SMALL); } - cxt->scratch_state.state1++; return OperatingMode::CJCCalibration; } From fa6db20f1f98d9f5390fde0bc61193b67ea3ae7a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 17:47:09 +1100 Subject: [PATCH 53/86] Fix not re-calculating menu length on entering menu --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 14e35d6d8b..9d7da355ad 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -148,8 +148,10 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Draw scroll // Get virtual pos by counting entries from start to _here_ - uint16_t currentVirtualPosition = getMenuLength(currentMenu, currentScreen + 1) - 1; - + uint16_t currentVirtualPosition = getMenuLength(currentMenu, currentScreen + 1); + if (currentVirtualPosition > 0) { + currentVirtualPosition--; + } // The height of the indicator is screen res height / total menu entries uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength; if (indicatorHeight == 0) { @@ -208,6 +210,8 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { if (*isRenderingHelp) { *isRenderingHelp = 0; } else { + uint16_t *currentMenuLength = &(cxt->scratch_state.state5); + *currentMenuLength = 0; if (*subEntry == 0) { // In a root menu, if its null handler we enter the menu if (currentMenu[currentScreen].incrementHandler != nullptr) { From 9c713c0107a3d0ee32704890adf99ae5a8c7c417 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 18:48:43 +1100 Subject: [PATCH 54/86] Implement NegotiationinProgress for USB-PD --- source/Core/Drivers/USBPD.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/Core/Drivers/USBPD.cpp b/source/Core/Drivers/USBPD.cpp index 8ca000c504..427b313fa8 100644 --- a/source/Core/Drivers/USBPD.cpp +++ b/source/Core/Drivers/USBPD.cpp @@ -29,6 +29,7 @@ bool EPREvaluateCapabilityFunc(const epr_pd_msg *capabilities, pd_msg *r FUSB302 fusb((0x22 << 1), fusb_read_buf, fusb_write_buf, ms_delay); // Create FUSB driver PolicyEngine pe(fusb, get_ms_timestamp, ms_delay, pdbs_dpm_get_sink_capability, pdbs_dpm_evaluate_capability, EPREvaluateCapabilityFunc, USB_PD_EPR_WATTAGE); int USBPowerDelivery::detectionState = 0; +bool haveSeenCapabilityOffer = false; uint16_t requested_voltage_mv = 0; /* The current draw when the output is disabled */ @@ -51,6 +52,15 @@ void USBPowerDelivery::step() { } void USBPowerDelivery::PPSTimerCallback() { pe.TimersCallback(); } +bool USBPowerDelivery::negotiationInProgress() { + if (USBPowerDelivery::negotiationComplete()) { + return true; + } + if (haveSeenCapabilityOffer) { + return false; + } + return true; +} bool USBPowerDelivery::negotiationComplete() { if (!fusbPresent()) { return true; @@ -268,6 +278,7 @@ bool EPREvaluateCapabilityFunc(const epr_pd_msg *capabilities, pd_msg *request) bool pdbs_dpm_evaluate_capability(const pd_msg *capabilities, pd_msg *request) { memset(lastCapabilities, 0, sizeof(lastCapabilities)); memcpy(lastCapabilities, capabilities->obj, sizeof(uint32_t) * 7); + haveSeenCapabilityOffer = true; /* Get the number of PDOs */ uint8_t numobj = PD_NUMOBJ_GET(capabilities); From 4addc8044cb93c6a804b772faac23bab61d7bc8e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 18:49:01 +1100 Subject: [PATCH 55/86] Mask heating until PD finishes negotiation --- source/Core/Threads/PIDThread.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/source/Core/Threads/PIDThread.cpp b/source/Core/Threads/PIDThread.cpp index 2c23108f24..1d08740e8a 100644 --- a/source/Core/Threads/PIDThread.cpp +++ b/source/Core/Threads/PIDThread.cpp @@ -16,6 +16,12 @@ #include "power.hpp" #include "task.h" +#ifdef POW_PD +#if POW_PD == 1 +#include "USBPD.h" +#endif +#endif + static TickType_t powerPulseWaitUnit = 25 * TICKS_100MS; // 2.5 s static TickType_t powerPulseDurationUnit = (5 * TICKS_100MS) / 2; // 250 ms TaskHandle_t pidTaskNotification = NULL; @@ -38,7 +44,9 @@ void startPIDTask(void const *argument __unused) { currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will // be over-ridden rapidly - pidTaskNotification = xTaskGetCurrentTaskHandle(); + + pidTaskNotification = xTaskGetCurrentTaskHandle(); + TemperatureType_t PIDTempTarget = 0; // Pre-seed the adc filters for (int i = 0; i < 32; i++) { @@ -51,6 +59,16 @@ void startPIDTask(void const *argument __unused) { resetWatchdog(); ulTaskNotifyTake(pdTRUE, 2000); } +// Wait for PD if its in the middle of negotiation +#ifdef POW_PD +#if POW_PD == 1 + // This is an FUSB based PD capable device + while (USBPowerDelivery::negotiationInProgress()) { + resetWatchdog(); + ulTaskNotifyTake(pdTRUE, TICKS_100MS); + } +#endif +#endif int32_t x10WattsOut = 0; From fab395b7ffb50785b69978d2355171442d8386a8 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 18:49:12 +1100 Subject: [PATCH 56/86] Fixup staying in hibernate correctly --- source/Core/Threads/OperatingModes/Sleep.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/Sleep.cpp b/source/Core/Threads/OperatingModes/Sleep.cpp index 75c10b6a8a..ec97c25246 100644 --- a/source/Core/Threads/OperatingModes/Sleep.cpp +++ b/source/Core/Threads/OperatingModes/Sleep.cpp @@ -62,5 +62,9 @@ OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *c currentTempTargetDegC = 0; return OperatingMode::HomeScreen; } - return OperatingMode::Sleeping; + if (cxt->scratch_state.state4) { + return OperatingMode::Hibernating; + } else { + return OperatingMode::Sleeping; + } } From ed521189271249bf1f1ddc99ba713839ca7f4ef9 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 18:55:47 +1100 Subject: [PATCH 57/86] Warning timeout --- source/Core/Threads/OperatingModes/utils/ShowWarning.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp b/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp index 80bfa2df4b..3a33d41559 100644 --- a/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp +++ b/source/Core/Threads/OperatingModes/utils/ShowWarning.cpp @@ -4,6 +4,9 @@ bool warnUser(const char *warning, const ButtonState buttons) { OLED::clearScreen(); OLED::printWholeScreen(warning); - // TODO also timeout + // Also timeout after 5 seconds + if ((xTaskGetTickCount() - lastButtonTime) > TICKS_SECOND * 5) { + return true; + } return buttons != BUTTON_NONE; } From 869758abb94e6bf8e86382eef9d1ecab8e291058 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 18:58:35 +1100 Subject: [PATCH 58/86] Show reset settings warning --- source/Core/Src/settingsGUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index b934dfb69d..7ac8b52a69 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -947,7 +947,7 @@ static void displayPowerPulseDuration(void) { OLED::printNumber(getSettingValue( static bool setResetSettings(void) { if (userConfirmation(translatedString(Tr->SettingsResetWarning))) { resetSettings(); - // warnUser(translatedString(Tr->ResetOKMessage), buttons); //TODO + warnUser(translatedString(Tr->ResetOKMessage), getButtonState()); reboot(); } return false; From 9088379dc3db2d6481694d50e011653619f900a4 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 24 Dec 2023 19:22:56 +1100 Subject: [PATCH 59/86] Correctly compensate help text start time --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 9d7da355ad..75809a4a5a 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -45,7 +45,7 @@ void render_menu(const menuitem *item, guiContext *cxt) { *isRenderingHelp = 1; // Draw description const char *description = translatedString(Tr->SettingsDescriptions[item->description - 1]); - drawScrollingText(description, xTaskGetTickCount() - lastButtonTime); + drawScrollingText(description, (xTaskGetTickCount() - lastButtonTime) - HELP_TEXT_TIMEOUT_TICKS); } } From 5eda503e615998837e39bf44d2cab6799a69b724 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 27 Dec 2023 09:35:07 +1100 Subject: [PATCH 60/86] Update GUIThread.cpp --- source/Core/Threads/GUIThread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index f23a2e5827..305b5de639 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -50,8 +50,8 @@ OperatingMode guiHandleDraw(void) { } 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))) { + 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 { From 673034bfdb821f118929493cf7445f95db96975c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 12 Jan 2024 20:06:49 +1100 Subject: [PATCH 61/86] Update USBPD.cpp --- source/Core/Drivers/USBPD.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Drivers/USBPD.cpp b/source/Core/Drivers/USBPD.cpp index 427b313fa8..b4cb8987eb 100644 --- a/source/Core/Drivers/USBPD.cpp +++ b/source/Core/Drivers/USBPD.cpp @@ -54,7 +54,7 @@ void USBPowerDelivery::step() { void USBPowerDelivery::PPSTimerCallback() { pe.TimersCallback(); } bool USBPowerDelivery::negotiationInProgress() { if (USBPowerDelivery::negotiationComplete()) { - return true; + return false; } if (haveSeenCapabilityOffer) { return false; From c1cb92ddc572e61424924b7b632bb0845eff1c6c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 12 Jan 2024 20:07:39 +1100 Subject: [PATCH 62/86] . --- source/Core/Drivers/BMA223.cpp | 14 +++++++------- source/Core/Drivers/MMA8652FC.cpp | 26 +++++++++++++------------- source/Core/Drivers/MSA301.cpp | 10 +++++----- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/source/Core/Drivers/BMA223.cpp b/source/Core/Drivers/BMA223.cpp index feab820e5b..ab7757e589 100644 --- a/source/Core/Drivers/BMA223.cpp +++ b/source/Core/Drivers/BMA223.cpp @@ -22,13 +22,13 @@ bool BMA223::detect() { } static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = { - // - // - {BMA223_PMU_RANGE, 0b00000011, 0}, // 2G range - {BMA223_PMU_BW, 0b00001101, 0}, // 250Hz filter - {BMA223_PMU_LPW, 0b00000000, 0}, // Full power - {BMA223_ACCD_HBW, 0b00000000, 0}, // filtered data out - {BMA223_INT_OUT_CTRL, 0b00001010, 0}, // interrupt active low and OD to get it hi-z + // + // + { BMA223_PMU_RANGE, 0b00000011, 0}, // 2G range + { BMA223_PMU_BW, 0b00001101, 0}, // 250Hz filter + { BMA223_PMU_LPW, 0b00000000, 0}, // Full power + { BMA223_ACCD_HBW, 0b00000000, 0}, // filtered data out + { BMA223_INT_OUT_CTRL, 0b00001010, 0}, // interrupt active low and OD to get it hi-z {BMA223_INT_RST_LATCH, 0b10000000, 0}, // interrupt active low and OD to get it hi-z { BMA223_INT_EN_0, 0b01000000, 0}, // Enable orientation { BMA223_INT_A, 0b00100111, 0}, // Setup orientation detection diff --git a/source/Core/Drivers/MMA8652FC.cpp b/source/Core/Drivers/MMA8652FC.cpp index 81b1c104bf..d56f14eb0b 100644 --- a/source/Core/Drivers/MMA8652FC.cpp +++ b/source/Core/Drivers/MMA8652FC.cpp @@ -15,19 +15,19 @@ #include "cmsis_os.h" static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = { - {CTRL_REG2, 0, 0}, // Normal mode - {CTRL_REG2, 0x40, 2}, // Reset all registers to POR values - {FF_MT_CFG_REG, 0x78, 0}, // Enable motion detection for X, Y, Z axis, latch disabled - {PL_CFG_REG, 0x40, 0}, // Enable the orientation detection - {PL_COUNT_REG, 200, 0}, // 200 count debounce - {PL_BF_ZCOMP_REG, 0b01000111, 0}, // Set the threshold to 42 degrees - {P_L_THS_REG, 0b10011100, 0}, // Up the trip angles - {CTRL_REG4, 0x01 | (1 << 4), 0}, // Enable dataready interrupt & orientation interrupt - {CTRL_REG5, 0x01, 0}, // Route data ready interrupts to INT1 ->PB5 ->EXTI5, leaving orientation routed to INT2 - {CTRL_REG2, 0x12, 0}, // Set maximum resolution oversampling - {XYZ_DATA_CFG_REG, (1 << 4), 0}, // select high pass filtered data - {HP_FILTER_CUTOFF_REG, 0x03, 0}, // select high pass filtered data - {CTRL_REG1, 0x19, 0} // ODR=12 Hz, Active mode + { CTRL_REG2, 0, 0}, // Normal mode + { CTRL_REG2, 0x40, 2}, // Reset all registers to POR values + { FF_MT_CFG_REG, 0x78, 0}, // Enable motion detection for X, Y, Z axis, latch disabled + { PL_CFG_REG, 0x40, 0}, // Enable the orientation detection + { PL_COUNT_REG, 200, 0}, // 200 count debounce + { PL_BF_ZCOMP_REG, 0b01000111, 0}, // Set the threshold to 42 degrees + { P_L_THS_REG, 0b10011100, 0}, // Up the trip angles + { CTRL_REG4, 0x01 | (1 << 4), 0}, // Enable dataready interrupt & orientation interrupt + { CTRL_REG5, 0x01, 0}, // Route data ready interrupts to INT1 ->PB5 ->EXTI5, leaving orientation routed to INT2 + { CTRL_REG2, 0x12, 0}, // Set maximum resolution oversampling + { XYZ_DATA_CFG_REG, (1 << 4), 0}, // select high pass filtered data + {HP_FILTER_CUTOFF_REG, 0x03, 0}, // select high pass filtered data + { CTRL_REG1, 0x19, 0} // ODR=12 Hz, Active mode }; bool MMA8652FC::initalize() { return ACCEL_I2C_CLASS::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } diff --git a/source/Core/Drivers/MSA301.cpp b/source/Core/Drivers/MSA301.cpp index 7b3d2091aa..d732076963 100644 --- a/source/Core/Drivers/MSA301.cpp +++ b/source/Core/Drivers/MSA301.cpp @@ -13,11 +13,11 @@ bool MSA301::detect() { return ACCEL_I2C_CLASS::probe(MSA301_I2C_ADDRESS); } static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = { - // - // - {MSA301_REG_ODR, 0b00001000, 1}, // X/Y/Z enabled @ 250Hz - {MSA301_REG_POWERMODE, 0b0001001, 1}, // Normal mode - {MSA301_REG_RESRANGE, 0b00000001, 0}, // 14bit resolution @ 4G range + // + // + { MSA301_REG_ODR, 0b00001000, 1}, // X/Y/Z enabled @ 250Hz + {MSA301_REG_POWERMODE, 0b0001001, 1}, // Normal mode + { MSA301_REG_RESRANGE, 0b00000001, 0}, // 14bit resolution @ 4G range {MSA301_REG_ORIENT_HY, 0b01000000, 0}, // 4*62.5mg hyst, no blocking, symmetrical { MSA301_REG_INTSET0, 1 << 6, 0}, // Turn on orientation detection (by enabling its interrupt) }; From 93111adf131f91be6030b3a3d070ea9570b4ea65 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 12 Jan 2024 20:39:17 +1100 Subject: [PATCH 63/86] Fixup sleep time --- .../Core/Threads/OperatingModes/utils/printSleepCountdown.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp b/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp index ea53c5c8af..3e8a0f6e09 100644 --- a/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp +++ b/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp @@ -10,10 +10,10 @@ void printCountdownUntilSleep(int sleepThres) { 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::printNumber(downCount / 60000 , 2, FontStyle::SMALL); OLED::print(SmallSymbolMinutes, FontStyle::SMALL); } else { - OLED::printNumber(downCount / 1000 + 1, 2, FontStyle::SMALL); + OLED::printNumber(downCount / 1000 , 2, FontStyle::SMALL); OLED::print(SmallSymbolSeconds, FontStyle::SMALL); } } From fe83c01d39ab300099977b56bb003881dea945cd Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 12 Jan 2024 20:59:12 +1100 Subject: [PATCH 64/86] Update printSleepCountdown.cpp --- .../Core/Threads/OperatingModes/utils/printSleepCountdown.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp b/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp index 3e8a0f6e09..cc658b4835 100644 --- a/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp +++ b/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp @@ -10,10 +10,10 @@ void printCountdownUntilSleep(int sleepThres) { TickType_t lastEventTime = lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime; TickType_t downCount = sleepThres - xTaskGetTickCount() + lastEventTime; if (downCount > (99 * TICKS_SECOND)) { - OLED::printNumber(downCount / 60000 , 2, FontStyle::SMALL); + OLED::printNumber(downCount / 60000, 2, FontStyle::SMALL); OLED::print(SmallSymbolMinutes, FontStyle::SMALL); } else { - OLED::printNumber(downCount / 1000 , 2, FontStyle::SMALL); + OLED::printNumber(downCount / 1000, 2, FontStyle::SMALL); OLED::print(SmallSymbolSeconds, FontStyle::SMALL); } } From 9b514cd2175b20e0a4d4533663b53a2668e4fe11 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Sat, 13 Jan 2024 01:33:38 +0100 Subject: [PATCH 65/86] replacing countdown with big plus while in boost mode --- .../Core/Threads/OperatingModes/Soldering.cpp | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index 52d4650c7c..12424d30c3 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -115,25 +115,24 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { 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); - } - printCountdownUntilSleep(getSleepTimeout()); - } -#endif - if (cxt->scratch_state.state2) { // Boost mode is on if (OLED::getRotation()) { - OLED::setCursor(38, 8); + OLED::setCursor(41, 0); } else { - OLED::setCursor(55, 8); + OLED::setCursor(52, 0); } - OLED::print(SmallSymbolPlus, FontStyle::SMALL); + OLED::print(LargeSymbolPlus, FontStyle::LARGE); } else { +#ifndef NO_SLEEP_MODE + if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) { + if (OLED::getRotation()) { + OLED::setCursor(32, 0); + } else { + OLED::setCursor(47, 0); + } + printCountdownUntilSleep(getSleepTimeout()); + } +#endif if (OLED::getRotation()) { OLED::setCursor(32, 8); } else { From 39716faafe23728308765ca1893bc26227064af1 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Sat, 13 Jan 2024 01:37:04 +0100 Subject: [PATCH 66/86] bringing back the + 1 since it was missing when not in boost mode --- .../Threads/OperatingModes/utils/printSleepCountdown.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp b/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp index cc658b4835..a6b072a7e7 100644 --- a/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp +++ b/source/Core/Threads/OperatingModes/utils/printSleepCountdown.cpp @@ -10,11 +10,11 @@ void printCountdownUntilSleep(int sleepThres) { TickType_t lastEventTime = lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime; TickType_t downCount = sleepThres - xTaskGetTickCount() + lastEventTime; if (downCount > (99 * TICKS_SECOND)) { - OLED::printNumber(downCount / 60000, 2, FontStyle::SMALL); + OLED::printNumber(downCount / 60000 + 1, 2, FontStyle::SMALL); OLED::print(SmallSymbolMinutes, FontStyle::SMALL); } else { - OLED::printNumber(downCount / 1000, 2, FontStyle::SMALL); + OLED::printNumber(downCount / 1000 + 1, 2, FontStyle::SMALL); OLED::print(SmallSymbolSeconds, FontStyle::SMALL); } } -#endif \ No newline at end of file +#endif From 4e2bca36bced699a7af772fc968fb32e1ac45adc Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jan 2024 19:33:56 +1100 Subject: [PATCH 67/86] Bail on USB-PD check after 3 seconds incase of DC source --- source/Core/Threads/PIDThread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Core/Threads/PIDThread.cpp b/source/Core/Threads/PIDThread.cpp index 1d08740e8a..c8da6885ca 100644 --- a/source/Core/Threads/PIDThread.cpp +++ b/source/Core/Threads/PIDThread.cpp @@ -63,7 +63,8 @@ void startPIDTask(void const *argument __unused) { #ifdef POW_PD #if POW_PD == 1 // This is an FUSB based PD capable device - while (USBPowerDelivery::negotiationInProgress()) { + // Wait up to 3 seconds for USB-PD to settle + while (USBPowerDelivery::negotiationInProgress() && xTaskGetTickCount() < (TICKS_SECOND*3)) { resetWatchdog(); ulTaskNotifyTake(pdTRUE, TICKS_100MS); } From 47b4d15412b43c439c11e7bdcbb630ebd1dfcda2 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jan 2024 19:35:57 +1100 Subject: [PATCH 68/86] Fix hibernate --- source/Core/Threads/GUIThread.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 305b5de639..2db324df74 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -86,7 +86,7 @@ OperatingMode guiHandleDraw(void) { lastMovementTime = lastButtonTime = xTaskGetTickCount(); // Move forward so we dont go to sleep newMode = OperatingMode::Soldering; } else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::ZERO) { - lastMovementTime = lastButtonTime = xTaskGetTickCount(); // Move forward so we dont go to sleep + 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; @@ -222,18 +222,6 @@ void startGUITask(void const *argument) { OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1); - // // 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); - // } // Read boot button state if (getButtonA()) { buttonsAtDeviceBoot = BUTTON_F_LONG; From 17b716ec9497c7d9b0a11c83f822e1404a6b7dcd Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 17 Jan 2024 19:36:51 +1100 Subject: [PATCH 69/86] Update PIDThread.cpp --- source/Core/Threads/PIDThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Threads/PIDThread.cpp b/source/Core/Threads/PIDThread.cpp index c8da6885ca..83c53efd64 100644 --- a/source/Core/Threads/PIDThread.cpp +++ b/source/Core/Threads/PIDThread.cpp @@ -64,7 +64,7 @@ void startPIDTask(void const *argument __unused) { #if POW_PD == 1 // This is an FUSB based PD capable device // Wait up to 3 seconds for USB-PD to settle - while (USBPowerDelivery::negotiationInProgress() && xTaskGetTickCount() < (TICKS_SECOND*3)) { + while (USBPowerDelivery::negotiationInProgress() && xTaskGetTickCount() < (TICKS_SECOND * 3)) { resetWatchdog(); ulTaskNotifyTake(pdTRUE, TICKS_100MS); } From 51d9f3d8508f986a89b6f565ecc1139fa720982a Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Thu, 18 Jan 2024 02:30:05 +0100 Subject: [PATCH 70/86] did center plus symbol (boost mode) --- source/Core/Threads/OperatingModes/Soldering.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Core/Threads/OperatingModes/Soldering.cpp b/source/Core/Threads/OperatingModes/Soldering.cpp index 12424d30c3..0a64888919 100644 --- a/source/Core/Threads/OperatingModes/Soldering.cpp +++ b/source/Core/Threads/OperatingModes/Soldering.cpp @@ -117,9 +117,9 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) { if (cxt->scratch_state.state2) { // Boost mode is on if (OLED::getRotation()) { - OLED::setCursor(41, 0); + OLED::setCursor(34, 0); } else { - OLED::setCursor(52, 0); + OLED::setCursor(50, 0); } OLED::print(LargeSymbolPlus, FontStyle::LARGE); } else { From 6b696fdd657349873ce804774db27d1413b8d94f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 19 Jan 2024 21:39:07 +1100 Subject: [PATCH 71/86] Big refactor to not make settings increment handler handle the "is last item" return --- source/Core/Inc/Settings.h | 5 +- source/Core/Inc/Translation.h | 2 +- source/Core/Inc/settingsGUI.hpp | 6 +- source/Core/LangSupport/lang_multi.cpp | 3 +- source/Core/LangSupport/lang_single.cpp | 2 +- source/Core/Src/Settings.cpp | 33 +++++- source/Core/Src/settingsGUI.cpp | 107 ++++++------------ .../Threads/OperatingModes/SettingsMenu.cpp | 39 +++++-- 8 files changed, 101 insertions(+), 96 deletions(-) diff --git a/source/Core/Inc/Settings.h b/source/Core/Inc/Settings.h index f46df53bd9..e332580ee9 100644 --- a/source/Core/Inc/Settings.h +++ b/source/Core/Inc/Settings.h @@ -107,8 +107,9 @@ void resetSettings(); uint16_t getSettingValue(const enum SettingsOptions option); // Returns true if setting is now on the last value (next iteration will wrap) -bool nextSettingValue(const enum SettingsOptions option); -bool prevSettingValue(const enum SettingsOptions option); +void nextSettingValue(const enum SettingsOptions option); +void prevSettingValue(const enum SettingsOptions option); +bool isLastSettingValue(const enum SettingsOptions option); void setSettingValue(const enum SettingsOptions option, const uint16_t newValue); diff --git a/source/Core/Inc/Translation.h b/source/Core/Inc/Translation.h index f2b84ffa04..b0e3713126 100644 --- a/source/Core/Inc/Translation.h +++ b/source/Core/Inc/Translation.h @@ -187,6 +187,6 @@ const char *translatedString(uint16_t index); void prepareTranslations(); void settings_displayLanguageSwitch(void); bool settings_showLanguageSwitch(void); -bool settings_setLanguageSwitch(void); +void settings_setLanguageSwitch(void); #endif /* TRANSLATION_H_ */ diff --git a/source/Core/Inc/settingsGUI.hpp b/source/Core/Inc/settingsGUI.hpp index 07695f41a5..9bbc2dfef5 100644 --- a/source/Core/Inc/settingsGUI.hpp +++ b/source/Core/Inc/settingsGUI.hpp @@ -8,8 +8,8 @@ #ifndef GUI_HPP_ #define GUI_HPP_ #include "BSP.h" -#include "FreeRTOS.h" #include "Buttons.hpp" +#include "FreeRTOS.h" #include "Settings.h" #include "Translation.h" @@ -26,8 +26,8 @@ typedef struct { // The settings description index, please use the `SETTINGS_DESC` macro with // the `SettingsItemIndex` enum. Use 0 for no description. uint8_t description; - // return true if increment reached the maximum value - bool (*const incrementHandler)(void); + void (*const incrementHandler)(void); + // return true if at the last setting void (*const draw)(void); bool (*const isVisible)(void); // If this is set, we will automatically use the settings increment handler instead, set >= num settings to disable diff --git a/source/Core/LangSupport/lang_multi.cpp b/source/Core/LangSupport/lang_multi.cpp index 44e28ad209..73f2ec59b8 100644 --- a/source/Core/LangSupport/lang_multi.cpp +++ b/source/Core/LangSupport/lang_multi.cpp @@ -63,11 +63,10 @@ void prepareTranslations() { } } -bool settings_setLanguageSwitch(void) { +void settings_setLanguageSwitch(void) { selectedLangIndex = (selectedLangIndex + 1) % LanguageCount; writeSelectedLanguageToSettings(); prepareTranslations(); - return selectedLangIndex == (LanguageCount - 1); } bool settings_showLanguageSwitch(void) { return true; } diff --git a/source/Core/LangSupport/lang_single.cpp b/source/Core/LangSupport/lang_single.cpp index 019c0938c3..9c77734a8d 100644 --- a/source/Core/LangSupport/lang_single.cpp +++ b/source/Core/LangSupport/lang_single.cpp @@ -1,6 +1,6 @@ #include "Translation.h" -bool settings_setLanguageSwitch(void) { return false; } +void settings_setLanguageSwitch(void) {} void settings_displayLanguageSwitch(void) {} bool settings_showLanguageSwitch(void) { return false; } diff --git a/source/Core/Src/Settings.cpp b/source/Core/Src/Settings.cpp index 7ff16af78d..fe8b21c9c9 100644 --- a/source/Core/Src/Settings.cpp +++ b/source/Core/Src/Settings.cpp @@ -188,7 +188,7 @@ uint16_t getSettingValue(const enum SettingsOptions option) { return systemSetti // Increment by the step size to the next value. If past the end wrap to the minimum // Returns true if we are on the _last_ value -bool nextSettingValue(const enum SettingsOptions option) { +void nextSettingValue(const enum SettingsOptions option) { const auto constants = settingsConstants[(int)option]; if (systemSettings.settingsValues[(int)option] == (constants.max)) { // Already at max, wrap to the start @@ -200,13 +200,36 @@ bool nextSettingValue(const enum SettingsOptions option) { // Otherwise increment systemSettings.settingsValues[(int)option] += constants.increment; } - // Return if we are at the max - return constants.max == systemSettings.settingsValues[(int)option]; } +bool isLastSettingValue(const enum SettingsOptions option) { + const auto constants = settingsConstants[(int)option]; + uint16_t max = constants.max; + // handle temp unit limitations + if (option == SettingsOptions::SolderingTemp) { + if (getSettingValue(SettingsOptions::TemperatureInF)) { + max = MAX_TEMP_F; + } else { + max = MAX_TEMP_C; + } + } else if (option == SettingsOptions::BoostTemp) { + if (getSettingValue(SettingsOptions::TemperatureInF)) { + max = MAX_TEMP_F; + } else { + max = MAX_TEMP_C; + } + } else if (option == SettingsOptions::SleepTemp) { + if (getSettingValue(SettingsOptions::TemperatureInF)) { + max = 580; + } else { + max = 300; + } + } + return systemSettings.settingsValues[(int)option] >= max; +} // Step backwards on the settings item // Return true if we are at the end (min) -bool prevSettingValue(const enum SettingsOptions option) { +void prevSettingValue(const enum SettingsOptions option) { const auto constants = settingsConstants[(int)option]; if (systemSettings.settingsValues[(int)option] == (constants.min)) { // Already at min, wrap to the max @@ -218,8 +241,6 @@ bool prevSettingValue(const enum SettingsOptions option) { // Otherwise decrement systemSettings.settingsValues[(int)option] -= constants.increment; } - // Return if we are at the min - return constants.min == systemSettings.settingsValues[(int)option]; } uint16_t lookupHallEffectThreshold() { diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index 7ac8b52a69..daa8658e53 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -14,8 +14,6 @@ #include "configuration.h" #include "main.hpp" -void gui_Menu(const menuitem *menu); - #ifdef POW_DC static void displayInputVRange(void); static bool showInputVOptions(void); @@ -36,12 +34,12 @@ static void displayShutdownTime(void); static bool showSleepOptions(void); #ifndef NO_SLEEP_MODE -static bool setSleepTemp(void); +static void setSleepTemp(void); static void displaySleepTemp(void); static void displaySleepTime(void); #endif /* *not* NO_SLEEP_MODE */ -static bool setTempF(void); +static void setTempF(void); static void displayTempF(void); static void displayAdvancedSolderingScreens(void); static void displayAdvancedIDLEScreens(void); @@ -53,20 +51,20 @@ static void displayBluetoothLE(void); #endif /* BLE_ENABLED */ #ifndef NO_DISPLAY_ROTATE -static bool setDisplayRotation(void); +static void setDisplayRotation(void); static void displayDisplayRotation(void); #endif /* *not* NO_DISPLAY_ROTATE */ -static bool setBoostTemp(void); +static void setBoostTemp(void); static void displayBoostTemp(void); #ifdef PROFILE_SUPPORT -static bool setProfilePreheatTemp(); -static bool setProfilePhase1Temp(); -static bool setProfilePhase2Temp(); -static bool setProfilePhase3Temp(); -static bool setProfilePhase4Temp(); -static bool setProfilePhase5Temp(); +static void setProfilePreheatTemp(); +static void setProfilePhase1Temp(); +static void setProfilePhase2Temp(); +static void setProfilePhase3Temp(); +static void setProfilePhase4Temp(); +static void setProfilePhase5Temp(); static void displayProfilePhases(void); static void displayProfilePreheatTemp(void); static void displayProfilePreheatSpeed(void); @@ -91,13 +89,10 @@ static bool showProfilePhase5Options(void); static void displayAutomaticStartMode(void); static void displayLockingMode(void); static void displayCoolingBlinkEnabled(void); -static bool setResetSettings(void); -static void displayResetSettings(void); -static bool setCalibrate(void); +static void setResetSettings(void); +static void setCalibrate(void); static void displayCalibrate(void); -static bool setCalibrateVIN(void); -static void displayCalibrateVIN(void); -static void displayReverseButtonTempChangeEnabled(void); +static void setCalibrateVIN(void); static void displayTempChangeShortStep(void); static void displayTempChangeLongStep(void); static void displayPowerPulse(void); @@ -379,7 +374,7 @@ const menuitem UIMenu[] = { /* Scroll Speed for descriptions */ {SETTINGS_DESC(SettingsItemIndex::ScrollingSpeed), nullptr, displayScrollSpeed, nullptr, SettingsOptions::DescriptionScrollSpeed, SettingsItemIndex::ScrollingSpeed, 7}, /* Reverse Temp change buttons +/- */ - {SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, displayReverseButtonTempChangeEnabled, nullptr, SettingsOptions::ReverseButtonTempChangeEnabled, SettingsItemIndex::ReverseButtonTempChange, 7}, + {SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, nullptr, nullptr, SettingsOptions::ReverseButtonTempChangeEnabled, SettingsItemIndex::ReverseButtonTempChange, 7}, /* Animation Speed adjustment */ {SETTINGS_DESC(SettingsItemIndex::AnimSpeed), nullptr, displayAnimationSpeed, nullptr, SettingsOptions::AnimationSpeed, SettingsItemIndex::AnimSpeed, 7}, /* Animation Loop switch */ @@ -419,7 +414,7 @@ const menuitem advancedMenu[] = { /* Calibrate Cold Junktion Compensation at next boot */ {SETTINGS_DESC(SettingsItemIndex::CalibrateCJC), setCalibrate, displayCalibrate, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::CalibrateCJC, 7}, /* Voltage input cal */ - {SETTINGS_DESC(SettingsItemIndex::VoltageCalibration), setCalibrateVIN, displayCalibrateVIN, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::VoltageCalibration, 5}, + {SETTINGS_DESC(SettingsItemIndex::VoltageCalibration), setCalibrateVIN, nullptr, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::VoltageCalibration, 5}, /* Power Pulse adjustment */ {SETTINGS_DESC(SettingsItemIndex::PowerPulsePower), nullptr, displayPowerPulse, nullptr, SettingsOptions::KeepAwakePulse, SettingsItemIndex::PowerPulsePower, 5}, /* Power Pulse Wait adjustment */ @@ -427,7 +422,7 @@ const menuitem advancedMenu[] = { /* Power Pulse Duration adjustment */ {SETTINGS_DESC(SettingsItemIndex::PowerPulseDuration), nullptr, displayPowerPulseDuration, showPowerPulseOptions, SettingsOptions::KeepAwakePulseDuration, SettingsItemIndex::PowerPulseDuration, 7}, /* Resets settings */ - {SETTINGS_DESC(SettingsItemIndex::SettingsReset), setResetSettings, displayResetSettings, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::SettingsReset, 7}, + {SETTINGS_DESC(SettingsItemIndex::SettingsReset), setResetSettings, nullptr, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::SettingsReset, 7}, /* vvvv end of menu marker. DO NOT REMOVE vvvv */ {0, nullptr, nullptr, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0} /* ^^^^ end of menu marker. DO NOT REMOVE ^^^^ */ @@ -536,7 +531,7 @@ static void displayPDVpdo(void) { OLED::drawCheckbox(getSettingValue(SettingsOpt #endif /* POW_PD */ -static bool setBoostTemp(void) { +static void setBoostTemp(void) { uint16_t value = getSettingValue(SettingsOptions::BoostTemp); if (getSettingValue(SettingsOptions::TemperatureInF)) { if (value == 0) { @@ -549,7 +544,6 @@ static bool setBoostTemp(void) { value = 0; // jump to off } setSettingValue(SettingsOptions::BoostTemp, value); - return value >= (MAX_TEMP_F - 10); } if (value == 0) { value = MIN_BOOST_TEMP_C; // loop back at 250 @@ -560,7 +554,6 @@ static bool setBoostTemp(void) { value = 0; // Go to off state } setSettingValue(SettingsOptions::BoostTemp, value); - return value >= MAX_TEMP_C; } static void displayBoostTemp(void) { @@ -616,7 +609,7 @@ static void displayLockingMode(void) { static void displayProfilePhases(void) { OLED::printNumber(getSettingValue(SettingsOptions::ProfilePhases), 1, FontStyle::LARGE); } -static bool setProfileTemp(const enum SettingsOptions option) { +static void setProfileTemp(const enum SettingsOptions option) { // If in C, 5 deg, if in F 10 deg uint16_t temp = getSettingValue(option); if (getSettingValue(SettingsOptions::TemperatureInF)) { @@ -625,23 +618,21 @@ static bool setProfileTemp(const enum SettingsOptions option) { temp = MIN_TEMP_F; } setSettingValue(option, temp); - return temp == MAX_TEMP_F; } else { temp += 5; if (temp > MAX_TEMP_C) { temp = MIN_TEMP_C; } setSettingValue(option, temp); - return temp == MAX_TEMP_C; } } -static bool setProfilePreheatTemp(void) { return setProfileTemp(SettingsOptions::ProfilePreheatTemp); } -static bool setProfilePhase1Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase1Temp); } -static bool setProfilePhase2Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase2Temp); } -static bool setProfilePhase3Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase3Temp); } -static bool setProfilePhase4Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase4Temp); } -static bool setProfilePhase5Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase5Temp); } +static void setProfilePreheatTemp(void) { return setProfileTemp(SettingsOptions::ProfilePreheatTemp); } +static void setProfilePhase1Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase1Temp); } +static void setProfilePhase2Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase2Temp); } +static void setProfilePhase3Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase3Temp); } +static void setProfilePhase4Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase4Temp); } +static void setProfilePhase5Temp(void) { return setProfileTemp(SettingsOptions::ProfilePhase5Temp); } static void displayProfilePreheatTemp(void) { OLED::printNumber(getSettingValue(SettingsOptions::ProfilePreheatTemp), 3, FontStyle::LARGE); } static void displayProfilePhase1Temp(void) { OLED::printNumber(getSettingValue(SettingsOptions::ProfilePhase1Temp), 3, FontStyle::LARGE); } @@ -670,7 +661,7 @@ static bool showSleepOptions(void) { return getSettingValue(SettingsOptions::Sen #ifndef NO_SLEEP_MODE -static bool setSleepTemp(void) { +static void setSleepTemp(void) { // If in C, 10 deg, if in F 20 deg uint16_t temp = getSettingValue(SettingsOptions::SleepTemp); if (getSettingValue(SettingsOptions::TemperatureInF)) { @@ -679,14 +670,12 @@ static bool setSleepTemp(void) { temp = 60; } setSettingValue(SettingsOptions::SleepTemp, temp); - return temp == 580; } else { temp += 10; if (temp > 300) { temp = 10; } setSettingValue(SettingsOptions::SleepTemp, temp); - return temp == 300; } } @@ -737,8 +726,8 @@ static void setTempF(const enum SettingsOptions option) { setSettingValue(option, Temp); } -static bool setTempF(void) { - bool res = nextSettingValue(SettingsOptions::TemperatureInF); +static void setTempF(void) { + nextSettingValue(SettingsOptions::TemperatureInF); setTempF(SettingsOptions::BoostTemp); setTempF(SettingsOptions::SolderingTemp); #ifndef NO_SLEEP_MODE @@ -752,15 +741,14 @@ static bool setTempF(void) { setTempF(SettingsOptions::ProfilePhase4Temp); setTempF(SettingsOptions::ProfilePhase5Temp); #endif /* PROFILE_SUPPORT */ - return res; } static void displayTempF(void) { OLED::printSymbolDeg(FontStyle::LARGE); } #ifndef NO_DISPLAY_ROTATE -static bool setDisplayRotation(void) { - bool res = nextSettingValue(SettingsOptions::OrientationMode); +static void setDisplayRotation(void) { + nextSettingValue(SettingsOptions::OrientationMode); switch (getSettingValue(SettingsOptions::OrientationMode)) { case orientationMode_t::RIGHT: OLED::setRotation(false); @@ -774,7 +762,6 @@ static bool setDisplayRotation(void) { default: break; } - return res; } static void displayDisplayRotation(void) { @@ -869,7 +856,7 @@ static void displayPowerLimit(void) { } } -static bool setCalibrate(void) { +static void setCalibrate(void) { if (getSettingValue(SettingsOptions::CalibrateCJC) < 1) { if (userConfirmation(translatedString(Tr->SettingsCalibrationWarning))) { // User confirmed @@ -879,12 +866,11 @@ static bool setCalibrate(void) { } else { setSettingValue(SettingsOptions::CalibrateCJC, 0); } - return false; } static void displayCalibrate(void) { OLED::drawCheckbox(getSettingValue(SettingsOptions::CalibrateCJC)); } -static bool setCalibrateVIN(void) { +static void setCalibrateVIN(void) { // Jump to the voltage calibration subscreen OLED::clearScreen(); @@ -914,7 +900,7 @@ static bool setCalibrateVIN(void) { warnUser(translatedString(Tr->CalibrationDone), getButtonState()); OLED::refresh(); waitForButtonPressOrTimeout(0.5 * TICKS_SECOND); - return false; + return; case BUTTON_NONE: default: break; @@ -923,11 +909,8 @@ static bool setCalibrateVIN(void) { OLED::refresh(); osDelay(40); } - return false; } -static void displayCalibrateVIN(void) {} - static void displayPowerPulse(void) { if (getSettingValue(SettingsOptions::KeepAwakePulse)) { OLED::printNumber(getSettingValue(SettingsOptions::KeepAwakePulse) / 10, 1, FontStyle::LARGE); @@ -944,17 +927,14 @@ static void displayPowerPulseWait(void) { OLED::printNumber(getSettingValue(Sett static void displayPowerPulseDuration(void) { OLED::printNumber(getSettingValue(SettingsOptions::KeepAwakePulseDuration), 1, FontStyle::LARGE); } -static bool setResetSettings(void) { +static void setResetSettings(void) { if (userConfirmation(translatedString(Tr->SettingsResetWarning))) { resetSettings(); warnUser(translatedString(Tr->ResetOKMessage), getButtonState()); reboot(); } - return false; } -static void displayResetSettings(void) {} - // Indicates whether a menu transition is in progress, so that the menu icon // animation is paused during the transition. static bool animOpenState = false; @@ -1002,32 +982,13 @@ static void displayMenu(size_t index) { #if defined(POW_DC) || defined(POW_QC) static void displayPowerMenu(void) { displayMenu(0); } -static bool enterPowerMenu(void) { - gui_Menu(powerMenu); - return false; -} + #endif /* POW_DC or POW_QC */ static void displaySolderingMenu(void) { displayMenu(1); } -static bool enterSolderingMenu(void) { - gui_Menu(solderingMenu); - return false; -} static void displayPowerSavingMenu(void) { displayMenu(2); } -static bool enterPowerSavingMenu(void) { - gui_Menu(PowerSavingMenu); - return false; -} static void displayUIMenu(void) { displayMenu(3); } -static bool enterUIMenu(void) { - gui_Menu(HasFahrenheit ? UIMenu : UIMenu + 1); - return false; -} static void displayAdvancedMenu(void) { displayMenu(4); } -static bool enterAdvancedMenu(void) { - gui_Menu(advancedMenu); - return false; -} diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 75809a4a5a..9aaf3a2df5 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -31,7 +31,6 @@ static void printShortDescription(SettingsItemIndex settingsItemIndex, uint16_t // Render a menu, based on the position given // This will either draw the menu item, or the help text depending on how long its been since button press void render_menu(const menuitem *item, guiContext *cxt) { - // If recent interaction or not help text draw the entry if ((xTaskGetTickCount() - lastButtonTime < HELP_TEXT_TIMEOUT_TICKS) || item->description == 0) { @@ -144,6 +143,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // We walk the current menu to find the length *currentMenuLength = getMenuLength(currentMenu, 128 /* Max length of any menu*/); } + if (*isRenderingHelp == 0) { // Draw scroll @@ -154,13 +154,30 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { } // The height of the indicator is screen res height / total menu entries uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength; + if (indicatorHeight == 0) { indicatorHeight = 1; // always at least 1 pixel } uint16_t position = (OLED_HEIGHT * (uint16_t)currentVirtualPosition) / *currentMenuLength; - // Draw if not last item || flash if it is - if ((*currentMenuLength != currentVirtualPosition) || (xTaskGetTickCount() % 1000 < 500)) { + + bool showScrollbar = (currentVirtualPosition <= (*currentMenuLength - 2)); // Not the last item, the -2 is a hack. need to fix this + + // Store if its the last option for this setting + bool isLastOptionForSetting = false; + if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { + isLastOptionForSetting = isLastSettingValue(currentMenu[currentScreen].autoSettingOption); + } + + // Last settings menu entry, reset scroll show back so it flashes + if (isLastOptionForSetting) { + showScrollbar = false; + } + + // Or Flash it + showScrollbar |= (xTaskGetTickCount() % (TICKS_SECOND / 4) < (TICKS_SECOND / 8)); + + if (showScrollbar) { OLED::drawScrollIndicator((uint8_t)position, indicatorHeight); } } @@ -168,9 +185,9 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { auto callIncrementHandler = [&]() { if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { - return nextSettingValue(currentMenu[currentScreen].autoSettingOption); + nextSettingValue(currentMenu[currentScreen].autoSettingOption); } else if (currentMenu[currentScreen].incrementHandler != nullptr) { - return currentMenu[currentScreen].incrementHandler(); + currentMenu[currentScreen].incrementHandler(); } return false; }; @@ -196,7 +213,14 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { case BUTTON_F_LONG: if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) { - if (callIncrementHandler()) { + callIncrementHandler(); + // Update the check for if its the last version + bool isLastOptionForSetting = false; + if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { + isLastOptionForSetting = isLastSettingValue(currentMenu[currentScreen].autoSettingOption); + } + + if (isLastOptionForSetting) { (*autoRepeatTimer) = TICKS_SECOND * 2; } else { (*autoRepeatTimer) = 0; @@ -210,8 +234,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { if (*isRenderingHelp) { *isRenderingHelp = 0; } else { - uint16_t *currentMenuLength = &(cxt->scratch_state.state5); - *currentMenuLength = 0; + *currentMenuLength = 0; if (*subEntry == 0) { // In a root menu, if its null handler we enter the menu if (currentMenu[currentScreen].incrementHandler != nullptr) { From 4a6d82fd38ca538cb5a984187639a3085f67b27a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 19 Jan 2024 22:03:47 +1100 Subject: [PATCH 72/86] Fixup boot logo --- source/Core/Threads/GUIThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 2db324df74..654e1d6870 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -77,7 +77,7 @@ OperatingMode guiHandleDraw(void) { newMode = OperatingMode::InitialisationDone; #endif case OperatingMode::StartupLogo: - BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); // TODO needs refactor + 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 From dfdc80671c3c2758c0ca649ac3ac2c77dcf4d719 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 20 Jan 2024 15:17:35 +1100 Subject: [PATCH 73/86] Fix flashing --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 9aaf3a2df5..f9d5ce9498 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -161,7 +161,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { uint16_t position = (OLED_HEIGHT * (uint16_t)currentVirtualPosition) / *currentMenuLength; - bool showScrollbar = (currentVirtualPosition <= (*currentMenuLength - 2)); // Not the last item, the -2 is a hack. need to fix this + bool showScrollbar = true; // Store if its the last option for this setting bool isLastOptionForSetting = false; From 24476f56520422b284efb1fba4ced70e38c04b1e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 20 Jan 2024 15:36:12 +1100 Subject: [PATCH 74/86] Fixup recalculate the menu length on long hold --- source/Core/Inc/settingsGUI.hpp | 1 - source/Core/Threads/OperatingModes/SettingsMenu.cpp | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/Core/Inc/settingsGUI.hpp b/source/Core/Inc/settingsGUI.hpp index 9bbc2dfef5..25e12432c5 100644 --- a/source/Core/Inc/settingsGUI.hpp +++ b/source/Core/Inc/settingsGUI.hpp @@ -27,7 +27,6 @@ typedef struct { // the `SettingsItemIndex` enum. Use 0 for no description. uint8_t description; void (*const incrementHandler)(void); - // return true if at the last setting void (*const draw)(void); bool (*const isVisible)(void); // If this is set, we will automatically use the settings increment handler instead, set >= num settings to disable diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index f9d5ce9498..0b89f04885 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -227,6 +227,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { } (*autoRepeatTimer) += xTaskGetTickCount(); (*autoRepeatAcceleration) += PRESS_ACCEL_STEP; + *currentMenuLength = 0; // Reset incase menu visible changes } break; case BUTTON_F_SHORT: @@ -234,7 +235,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { if (*isRenderingHelp) { *isRenderingHelp = 0; } else { - *currentMenuLength = 0; + *currentMenuLength = 0; // Reset incase menu visible changes if (*subEntry == 0) { // In a root menu, if its null handler we enter the menu if (currentMenu[currentScreen].incrementHandler != nullptr) { @@ -258,6 +259,7 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { /* Fall through*/ case BUTTON_B_SHORT: // Increment menu item + newMode = moveToNextEntry(cxt); break; From e0060f140becb92731112c617001606041c7b1e4 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 20 Jan 2024 15:42:48 +1100 Subject: [PATCH 75/86] Fixup missing menu entries --- source/Core/Inc/settingsGUI.hpp | 2 +- source/Core/Src/settingsGUI.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/Core/Inc/settingsGUI.hpp b/source/Core/Inc/settingsGUI.hpp index 25e12432c5..6456da2a5b 100644 --- a/source/Core/Inc/settingsGUI.hpp +++ b/source/Core/Inc/settingsGUI.hpp @@ -27,7 +27,7 @@ typedef struct { // the `SettingsItemIndex` enum. Use 0 for no description. uint8_t description; void (*const incrementHandler)(void); - void (*const draw)(void); + void (*const draw)(void); // Must not be nullptr, as that marks end of menu bool (*const isVisible)(void); // If this is set, we will automatically use the settings increment handler instead, set >= num settings to disable SettingsOptions autoSettingOption; diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index daa8658e53..f9d0e695fa 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -186,6 +186,7 @@ static void displayAdvancedMenu(void); * */ +void noOpDisplay() {} /* vvv !!!DISABLE CLANG-FORMAT for menuitems initialization!!! vvv */ /* clang-format off */ @@ -374,7 +375,7 @@ const menuitem UIMenu[] = { /* Scroll Speed for descriptions */ {SETTINGS_DESC(SettingsItemIndex::ScrollingSpeed), nullptr, displayScrollSpeed, nullptr, SettingsOptions::DescriptionScrollSpeed, SettingsItemIndex::ScrollingSpeed, 7}, /* Reverse Temp change buttons +/- */ - {SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, nullptr, nullptr, SettingsOptions::ReverseButtonTempChangeEnabled, SettingsItemIndex::ReverseButtonTempChange, 7}, + {SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, noOpDisplay, nullptr, SettingsOptions::ReverseButtonTempChangeEnabled, SettingsItemIndex::ReverseButtonTempChange, 7}, /* Animation Speed adjustment */ {SETTINGS_DESC(SettingsItemIndex::AnimSpeed), nullptr, displayAnimationSpeed, nullptr, SettingsOptions::AnimationSpeed, SettingsItemIndex::AnimSpeed, 7}, /* Animation Loop switch */ @@ -414,7 +415,7 @@ const menuitem advancedMenu[] = { /* Calibrate Cold Junktion Compensation at next boot */ {SETTINGS_DESC(SettingsItemIndex::CalibrateCJC), setCalibrate, displayCalibrate, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::CalibrateCJC, 7}, /* Voltage input cal */ - {SETTINGS_DESC(SettingsItemIndex::VoltageCalibration), setCalibrateVIN, nullptr, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::VoltageCalibration, 5}, + {SETTINGS_DESC(SettingsItemIndex::VoltageCalibration), setCalibrateVIN, noOpDisplay, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::VoltageCalibration, 5}, /* Power Pulse adjustment */ {SETTINGS_DESC(SettingsItemIndex::PowerPulsePower), nullptr, displayPowerPulse, nullptr, SettingsOptions::KeepAwakePulse, SettingsItemIndex::PowerPulsePower, 5}, /* Power Pulse Wait adjustment */ @@ -422,7 +423,7 @@ const menuitem advancedMenu[] = { /* Power Pulse Duration adjustment */ {SETTINGS_DESC(SettingsItemIndex::PowerPulseDuration), nullptr, displayPowerPulseDuration, showPowerPulseOptions, SettingsOptions::KeepAwakePulseDuration, SettingsItemIndex::PowerPulseDuration, 7}, /* Resets settings */ - {SETTINGS_DESC(SettingsItemIndex::SettingsReset), setResetSettings, nullptr, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::SettingsReset, 7}, + {SETTINGS_DESC(SettingsItemIndex::SettingsReset), setResetSettings, noOpDisplay, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::SettingsReset, 7}, /* vvvv end of menu marker. DO NOT REMOVE vvvv */ {0, nullptr, nullptr, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0} /* ^^^^ end of menu marker. DO NOT REMOVE ^^^^ */ From abcf8619b6c2b74fc9d4a72839ad6908806fbd04 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 20 Jan 2024 15:59:14 +1100 Subject: [PATCH 76/86] Fix junk left on screen after user confirmation --- source/Core/Src/ScrollMessage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Src/ScrollMessage.cpp b/source/Core/Src/ScrollMessage.cpp index a99521a6c2..ff7a2b5135 100644 --- a/source/Core/Src/ScrollMessage.cpp +++ b/source/Core/Src/ScrollMessage.cpp @@ -37,7 +37,7 @@ static uint16_t str_display_len(const char *const str) { uint16_t messageWidth(const char *message) { return FONT_12_WIDTH * str_display_len(message); } void drawScrollingText(const char *message, TickType_t currentTickOffset) { - + OLED::clearScreen(); int16_t messageOffset; uint16_t msgWidth = messageWidth(message); if (msgWidth > OLED_WIDTH) { From 2c1cb6aa6a23ec2b8189968602810bfd463f50e8 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 22 Jan 2024 20:16:47 +1100 Subject: [PATCH 77/86] Re-order button handler to use custom, then default order to allow setting associated setting --- source/Core/Threads/OperatingModes/SettingsMenu.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/Core/Threads/OperatingModes/SettingsMenu.cpp b/source/Core/Threads/OperatingModes/SettingsMenu.cpp index 0b89f04885..b1f6e00ec1 100644 --- a/source/Core/Threads/OperatingModes/SettingsMenu.cpp +++ b/source/Core/Threads/OperatingModes/SettingsMenu.cpp @@ -184,10 +184,10 @@ OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) { // Now handle user button input auto callIncrementHandler = [&]() { - if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { - nextSettingValue(currentMenu[currentScreen].autoSettingOption); - } else if (currentMenu[currentScreen].incrementHandler != nullptr) { + if (currentMenu[currentScreen].incrementHandler != nullptr) { currentMenu[currentScreen].incrementHandler(); + } else if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) { + nextSettingValue(currentMenu[currentScreen].autoSettingOption); } return false; }; From f44d913a336c545ff812ac92ba127389fb40da86 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 22 Jan 2024 20:16:58 +1100 Subject: [PATCH 78/86] Attach setting for settings using custom handler --- source/Core/Src/settingsGUI.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index 819ba98935..f318649b3f 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -278,7 +278,7 @@ const menuitem solderingMenu[] = { * Profile Cooldown Max Temperature Change Per Second */ /* Boost Temp */ - {SETTINGS_DESC(SettingsItemIndex::BoostTemperature), setBoostTemp, displayBoostTemp, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::BoostTemperature, 5}, + {SETTINGS_DESC(SettingsItemIndex::BoostTemperature), setBoostTemp, displayBoostTemp, nullptr, SettingsOptions::BoostTemp, SettingsItemIndex::BoostTemperature, 5}, /* Auto start */ {SETTINGS_DESC(SettingsItemIndex::AutoStart), nullptr, displayAutomaticStartMode, nullptr, SettingsOptions::AutoStartMode, SettingsItemIndex::AutoStart, 7}, /* Temp change short step */ @@ -291,27 +291,27 @@ const menuitem solderingMenu[] = { /* Profile Phases */ {SETTINGS_DESC(SettingsItemIndex::ProfilePhases), nullptr, displayProfilePhases, nullptr, SettingsOptions::ProfilePhases, SettingsItemIndex::ProfilePhases, 7}, /* Profile Preheat Temp */ - {SETTINGS_DESC(SettingsItemIndex::ProfilePreheatTemp), setProfilePreheatTemp, displayProfilePreheatTemp, showProfileOptions, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::ProfilePreheatTemp, 5}, + {SETTINGS_DESC(SettingsItemIndex::ProfilePreheatTemp), setProfilePreheatTemp, displayProfilePreheatTemp, showProfileOptions, SettingsOptions::ProfilePreheatTemp, SettingsItemIndex::ProfilePreheatTemp, 5}, /* Profile Preheat Speed */ {SETTINGS_DESC(SettingsItemIndex::ProfilePreheatSpeed), nullptr, displayProfilePreheatSpeed, showProfileOptions, SettingsOptions::ProfilePreheatSpeed, SettingsItemIndex::ProfilePreheatSpeed, 5}, /* Phase 1 Temp */ - {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase1Temp, displayProfilePhase1Temp, showProfileOptions, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::ProfilePhase1Temp, 5}, + {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase1Temp, displayProfilePhase1Temp, showProfileOptions, SettingsOptions::ProfilePhase1Temp, SettingsItemIndex::ProfilePhase1Temp, 5}, /* Phase 1 Duration */ {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Duration), nullptr, displayProfilePhase1Duration, showProfileOptions, SettingsOptions::ProfilePhase1Duration, SettingsItemIndex::ProfilePhase1Duration, 5}, /* Phase 2 Temp */ - {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase2Temp, displayProfilePhase2Temp, showProfilePhase2Options, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::ProfilePhase2Temp, 5}, + {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase2Temp, displayProfilePhase2Temp, showProfilePhase2Options, SettingsOptions::ProfilePhase1Temp, SettingsItemIndex::ProfilePhase2Temp, 5}, /* Phase 2 Duration */ {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Duration), nullptr, displayProfilePhase2Duration, showProfilePhase2Options, SettingsOptions::ProfilePhase2Duration, SettingsItemIndex::ProfilePhase2Duration, 5}, /* Phase 3 Temp */ - {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase3Temp, displayProfilePhase3Temp, showProfilePhase3Options, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::ProfilePhase3Temp, 5}, + {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase3Temp, displayProfilePhase3Temp, showProfilePhase3Options, SettingsOptions::ProfilePhase1Temp, SettingsItemIndex::ProfilePhase3Temp, 5}, /* Phase 3 Duration */ {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Duration), nullptr, displayProfilePhase3Duration, showProfilePhase3Options, SettingsOptions::ProfilePhase3Duration, SettingsItemIndex::ProfilePhase3Duration, 5}, /* Phase 4 Temp */ - {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase4Temp, displayProfilePhase4Temp, showProfilePhase4Options, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::ProfilePhase4Temp, 5}, + {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase4Temp, displayProfilePhase4Temp, showProfilePhase4Options, SettingsOptions::ProfilePhase1Temp, SettingsItemIndex::ProfilePhase4Temp, 5}, /* Phase 4 Duration */ {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Duration), nullptr, displayProfilePhase4Duration, showProfilePhase4Options, SettingsOptions::ProfilePhase4Duration, SettingsItemIndex::ProfilePhase4Duration, 5}, /* Phase 5 Temp */ - {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase5Temp, displayProfilePhase5Temp, showProfilePhase5Options, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::ProfilePhase5Temp, 5}, + {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Temp), setProfilePhase5Temp, displayProfilePhase5Temp, showProfilePhase5Options, SettingsOptions::ProfilePhase1Temp, SettingsItemIndex::ProfilePhase5Temp, 5}, /* Phase 5 Duration */ {SETTINGS_DESC(SettingsItemIndex::ProfilePhase1Duration), nullptr, displayProfilePhase5Duration, showProfilePhase5Options, SettingsOptions::ProfilePhase5Duration, SettingsItemIndex::ProfilePhase5Duration, 5}, /* Profile Cooldown Speed */ @@ -334,7 +334,7 @@ const menuitem PowerSavingMenu[] = { {SETTINGS_DESC(SettingsItemIndex::MotionSensitivity), nullptr, displaySensitivity, nullptr, SettingsOptions::Sensitivity, SettingsItemIndex::MotionSensitivity, 7}, #ifndef NO_SLEEP_MODE /* Sleep Temp */ - {SETTINGS_DESC(SettingsItemIndex::SleepTemperature), setSleepTemp, displaySleepTemp, showSleepOptions, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::SleepTemperature, 5}, + {SETTINGS_DESC(SettingsItemIndex::SleepTemperature), setSleepTemp, displaySleepTemp, showSleepOptions, SettingsOptions::SleepTemp, SettingsItemIndex::SleepTemperature, 5}, /* Sleep Time */ {SETTINGS_DESC(SettingsItemIndex::SleepTimeout), nullptr, displaySleepTime, showSleepOptions, SettingsOptions::SleepTime, SettingsItemIndex::SleepTimeout, 5}, #endif /* *not* NO_SLEEP_MODE */ @@ -365,10 +365,10 @@ const menuitem UIMenu[] = { * Detailed Soldering */ /* Temperature units, this has to be the first element in the array to work with the logic in enterUIMenu() */ - {SETTINGS_DESC(SettingsItemIndex::TemperatureUnit), setTempF, displayTempF, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::TemperatureUnit, 7}, + {SETTINGS_DESC(SettingsItemIndex::TemperatureUnit), setTempF, displayTempF, nullptr, SettingsOptions::TemperatureInF, SettingsItemIndex::TemperatureUnit, 7}, #ifndef NO_DISPLAY_ROTATE /* Display Rotation */ - {SETTINGS_DESC(SettingsItemIndex::DisplayRotation), setDisplayRotation, displayDisplayRotation, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::DisplayRotation, 7}, + {SETTINGS_DESC(SettingsItemIndex::DisplayRotation), setDisplayRotation, displayDisplayRotation, nullptr, SettingsOptions::OrientationMode, SettingsItemIndex::DisplayRotation, 7}, #endif /* *not* NO_DISPLAY_ROTATE */ /* Cooling blink warning */ {SETTINGS_DESC(SettingsItemIndex::CooldownBlink), nullptr, displayCoolingBlinkEnabled, nullptr, SettingsOptions::CoolingTempBlink, SettingsItemIndex::CooldownBlink, 7}, @@ -413,7 +413,7 @@ const menuitem advancedMenu[] = { /* Power limit */ {SETTINGS_DESC(SettingsItemIndex::PowerLimit), nullptr, displayPowerLimit, nullptr, SettingsOptions::PowerLimit, SettingsItemIndex::PowerLimit, 4}, /* Calibrate Cold Junktion Compensation at next boot */ - {SETTINGS_DESC(SettingsItemIndex::CalibrateCJC), setCalibrate, displayCalibrate, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::CalibrateCJC, 7}, + {SETTINGS_DESC(SettingsItemIndex::CalibrateCJC), setCalibrate, displayCalibrate, nullptr, SettingsOptions::CalibrateCJC, SettingsItemIndex::CalibrateCJC, 7}, /* Voltage input cal */ {SETTINGS_DESC(SettingsItemIndex::VoltageCalibration), setCalibrateVIN, noOpDisplay, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::VoltageCalibration, 5}, /* Power Pulse adjustment */ From 8988fa0ff6a2f7ca0a9a608467f78618752e55d1 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 22 Jan 2024 20:24:41 +1100 Subject: [PATCH 79/86] Fix swap +/- keys --- source/Core/Src/settingsGUI.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index f318649b3f..af78ccf6a6 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -44,6 +44,7 @@ static void displayTempF(void); static void displayAdvancedSolderingScreens(void); static void displayAdvancedIDLEScreens(void); static void displayScrollSpeed(void); +static void displayReverseButtonTempChangeEnabled(void); static void displayPowerLimit(void); #ifdef BLE_ENABLED @@ -375,7 +376,7 @@ const menuitem UIMenu[] = { /* Scroll Speed for descriptions */ {SETTINGS_DESC(SettingsItemIndex::ScrollingSpeed), nullptr, displayScrollSpeed, nullptr, SettingsOptions::DescriptionScrollSpeed, SettingsItemIndex::ScrollingSpeed, 7}, /* Reverse Temp change buttons +/- */ - {SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, noOpDisplay, nullptr, SettingsOptions::ReverseButtonTempChangeEnabled, SettingsItemIndex::ReverseButtonTempChange, 7}, + {SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, displayReverseButtonTempChangeEnabled, nullptr, SettingsOptions::ReverseButtonTempChangeEnabled, SettingsItemIndex::ReverseButtonTempChange, 7}, /* Animation Speed adjustment */ {SETTINGS_DESC(SettingsItemIndex::AnimSpeed), nullptr, displayAnimationSpeed, nullptr, SettingsOptions::AnimationSpeed, SettingsItemIndex::AnimSpeed, 7}, /* Animation Loop switch */ From 1b1292343b5061e529b556844e26745cd3da4efe Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 22 Jan 2024 20:32:24 +1100 Subject: [PATCH 80/86] Fix boost temp --- source/Core/Src/settingsGUI.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index af78ccf6a6..f641b9d084 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -546,14 +546,15 @@ static void setBoostTemp(void) { value = 0; // jump to off } setSettingValue(SettingsOptions::BoostTemp, value); - } - if (value == 0) { - value = MIN_BOOST_TEMP_C; // loop back at 250 } else { - value += 10; // Go up 10C at a time - } - if (value > MAX_TEMP_C) { - value = 0; // Go to off state + if (value == 0) { + value = MIN_BOOST_TEMP_C; // loop back at 250 + } else { + value += 10; // Go up 10C at a time + } + if (value > MAX_TEMP_C) { + value = 0; // Go to off state + } } setSettingValue(SettingsOptions::BoostTemp, value); } From d6ebe2c38a7d4f39635951755177f8f9c395288c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 22 Jan 2024 20:46:01 +1100 Subject: [PATCH 81/86] Implement last menu option for Language selector --- source/Core/BSP/Pinecilv2/ble_handlers.cpp | 2 ++ source/Core/Inc/Translation.h | 1 + source/Core/LangSupport/lang_multi.cpp | 2 ++ source/Core/LangSupport/lang_single.cpp | 1 + source/Core/Src/Settings.cpp | 2 ++ 5 files changed, 8 insertions(+) diff --git a/source/Core/BSP/Pinecilv2/ble_handlers.cpp b/source/Core/BSP/Pinecilv2/ble_handlers.cpp index 98a795b7d9..28e6ffe5cb 100644 --- a/source/Core/BSP/Pinecilv2/ble_handlers.cpp +++ b/source/Core/BSP/Pinecilv2/ble_handlers.cpp @@ -203,6 +203,8 @@ int ble_char_read_bulk_value_callback(struct bt_conn *conn, const struct bt_gatt memcpy(buf, &id, sizeof(id)); return sizeof(id); } + default: + break; } return 0; } diff --git a/source/Core/Inc/Translation.h b/source/Core/Inc/Translation.h index 904c6811f1..a0c84b603e 100644 --- a/source/Core/Inc/Translation.h +++ b/source/Core/Inc/Translation.h @@ -184,5 +184,6 @@ void prepareTranslations(); void settings_displayLanguageSwitch(void); bool settings_showLanguageSwitch(void); void settings_setLanguageSwitch(void); +bool isLastLanguageOption(void); #endif /* TRANSLATION_H_ */ diff --git a/source/Core/LangSupport/lang_multi.cpp b/source/Core/LangSupport/lang_multi.cpp index 73f2ec59b8..8ce45f9643 100644 --- a/source/Core/LangSupport/lang_multi.cpp +++ b/source/Core/LangSupport/lang_multi.cpp @@ -71,3 +71,5 @@ void settings_setLanguageSwitch(void) { bool settings_showLanguageSwitch(void) { return true; } void settings_displayLanguageSwitch(void) { OLED::printWholeScreen(translatedString(Tr->SettingsShortNames[static_cast(SettingsItemIndex::LanguageSwitch)])); } + +bool isLastLanguageOption(void) { return selectedLangIndex == (LanguageCount - 1); } \ No newline at end of file diff --git a/source/Core/LangSupport/lang_single.cpp b/source/Core/LangSupport/lang_single.cpp index 9c77734a8d..48d6c8d55d 100644 --- a/source/Core/LangSupport/lang_single.cpp +++ b/source/Core/LangSupport/lang_single.cpp @@ -4,3 +4,4 @@ void settings_setLanguageSwitch(void) {} void settings_displayLanguageSwitch(void) {} bool settings_showLanguageSwitch(void) { return false; } +bool isLastLanguageOption(void) { return true; } \ No newline at end of file diff --git a/source/Core/Src/Settings.cpp b/source/Core/Src/Settings.cpp index d7b9530904..36317d3a4b 100644 --- a/source/Core/Src/Settings.cpp +++ b/source/Core/Src/Settings.cpp @@ -224,6 +224,8 @@ bool isLastSettingValue(const enum SettingsOptions option) { } else { max = 300; } + } else if (option == SettingsOptions::UILanguage) { + return isLastLanguageOption(); } return systemSettings.settingsValues[(int)option] >= max; } From 44e4b6b40c44a64d402efaffffd9312de9bab488 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 14 Feb 2024 20:36:05 +1100 Subject: [PATCH 82/86] Wait for init before CJC runs --- source/Core/Threads/OperatingModes/CJC.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/Core/Threads/OperatingModes/CJC.cpp b/source/Core/Threads/OperatingModes/CJC.cpp index e2847c6b63..cacb5eb18f 100644 --- a/source/Core/Threads/OperatingModes/CJC.cpp +++ b/source/Core/Threads/OperatingModes/CJC.cpp @@ -3,6 +3,14 @@ #include "OperatingModes.h" OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) { // Calibrate Cold Junction Compensation directly at boot, before internal components get warm. + + // While we wait for the pre-start checks to finish, we cant run CJC (as the pre-start checks control the tip) + if (preStartChecks() == 0) { + OLED::setCursor(0, 0); + OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL); + return OperatingMode::CJCCalibration; + } + if (!isTipDisconnected() && abs(int(TipThermoModel::getTipInC() - getHandleTemperature(0) / 10)) < 10) { // Take 16 samples, only sample if (cxt->scratch_state.state1 < 16) { From 1ff1e1379556e8700358a766a9bd495c80a6702c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 14 Feb 2024 20:43:29 +1100 Subject: [PATCH 83/86] Check last setting via increment value --- source/Core/Src/Settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Src/Settings.cpp b/source/Core/Src/Settings.cpp index 36317d3a4b..530cd86d01 100644 --- a/source/Core/Src/Settings.cpp +++ b/source/Core/Src/Settings.cpp @@ -227,7 +227,7 @@ bool isLastSettingValue(const enum SettingsOptions option) { } else if (option == SettingsOptions::UILanguage) { return isLastLanguageOption(); } - return systemSettings.settingsValues[(int)option] >= max; + return systemSettings.settingsValues[(int)option] >= (max - constants.increment); } // Step backwards on the settings item // Return true if we are at the end (min) From 52dee3210d3c59480faa920024445d02b9f84811 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 14 Feb 2024 20:45:23 +1100 Subject: [PATCH 84/86] Update BSP.cpp --- source/Core/BSP/Miniware/BSP.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/source/Core/BSP/Miniware/BSP.cpp b/source/Core/BSP/Miniware/BSP.cpp index df45516b5d..0ad8f4d42b 100644 --- a/source/Core/BSP/Miniware/BSP.cpp +++ b/source/Core/BSP/Miniware/BSP.cpp @@ -360,14 +360,7 @@ uint8_t preStartChecks() { } #endif -#ifdef POW_PD - // If we are in the middle of negotiating PD, wait until timeout - // Before turning on the heater - if (!USBPowerDelivery::negotiationComplete()) { - return 0; - } -#endif return 1; } uint64_t getDeviceID() { From 05ae1a5e92fba94c55b05a1e93e0438ed3116045 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:42:49 +0100 Subject: [PATCH 85/86] removed = from >= Otherwise incrementing would stop and the scroll bar would already flash at the second to last value. --- source/Core/Src/Settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Core/Src/Settings.cpp b/source/Core/Src/Settings.cpp index 530cd86d01..540c61549d 100644 --- a/source/Core/Src/Settings.cpp +++ b/source/Core/Src/Settings.cpp @@ -227,7 +227,7 @@ bool isLastSettingValue(const enum SettingsOptions option) { } else if (option == SettingsOptions::UILanguage) { return isLastLanguageOption(); } - return systemSettings.settingsValues[(int)option] >= (max - constants.increment); + return systemSettings.settingsValues[(int)option] > (max - constants.increment); } // Step backwards on the settings item // Return true if we are at the end (min) From 07ddd47fe027e473c3e27d1d4c3e5f093773abf4 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 17 Feb 2024 13:43:44 +1100 Subject: [PATCH 86/86] (Hacky) Fix for Settings reset --- source/Core/Src/settingsGUI.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/Core/Src/settingsGUI.cpp b/source/Core/Src/settingsGUI.cpp index f641b9d084..05fc6c63f8 100644 --- a/source/Core/Src/settingsGUI.cpp +++ b/source/Core/Src/settingsGUI.cpp @@ -945,7 +945,12 @@ static void displayPowerPulseDuration(void) { OLED::printNumber(getSettingValue( static void setResetSettings(void) { if (userConfirmation(translatedString(Tr->SettingsResetWarning))) { resetSettings(); - warnUser(translatedString(Tr->ResetOKMessage), getButtonState()); + OLED::clearScreen(); + while (!warnUser(translatedString(Tr->ResetOKMessage), getButtonState())) { + OLED::refresh(); + vTaskDelay(TICKS_100MS); + OLED::clearScreen(); + } reboot(); } }