mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
Big overhaul of the UI framework (#1749)
* Starting GUI render refactor to be more immediate mode Update TemperatureAdjust.cpp . Cleanup Soldering Sleep SolderingProfiles Soldering Rework Rough pass GUI Temp Adjust Cleanup old OperatingMode Debug Menu * Update TemperatureAdjust.cpp * Roughing some transition work * Fixup! Hook in the init starter helper * Better home screen button handler * FIXUP! Fix typo's . * Update SettingsMenu.cpp * More settings rework * More settings rendering * Fixup * Transitions Update SolderingProfile.cpp Hook in transistions * Update TemperatureAdjust.cpp * Update push.yml * Add auto-repeat to settings menu * Miniware: Use IT for I2C writes * Update USBPDDebug_HUSB238.cpp * Force write screen on side animation cancel . * Refactor moving down the settings list * Update settingsGUI.cpp * Update I2C_Wrapper.cpp * Update OLED.cpp * Rework button handling * Fix PD debug at boot * Fixup not showing right menu options * silence some warnings * Style cleanup * Fkit use bit-bang I2C for Miniware * Update GUIRendering.md * Fixup transition on enter soldering mode * Save Settings * Fixes for some animations not running Dont bail on animations if keypress is still held * Fixup settings acceleration * OLED Up animation * Link up/down on debug meny * Make all accelerometers I2C bus aware Update accelerometers_common.h * Make I2C mag optional * Miniware -> Only Bit-Bang I2C * Fixup for scrollbar FIXUP! Debug menu returns to home screen FIXUP! Up oled animation Fix temp exit * Settings menu -> Both buttons return a menu layer * Merge fixup * Update BMA223.cpp * Re-Enable OLED sleep * Save Setting on temp adjust exit * WiP on startup mode * Some autostart working * Add hibernation mode & more autostart fixes * If cant CJC; go to startup * Hibernate in sleep * Cleanup scroll indicator * FIXUP! Ensure startup warnings are linked in * FIXUP! Ensure we render out temp change before timing out * Ensure 100ms delay between CJC samples * Fix not re-calculating menu length on entering menu * Implement NegotiationinProgress for USB-PD * Mask heating until PD finishes negotiation * Fixup staying in hibernate correctly * Warning timeout * Show reset settings warning * Correctly compensate help text start time * Update GUIThread.cpp * Update USBPD.cpp * . * Fixup sleep time * Update printSleepCountdown.cpp * replacing countdown with big plus while in boost mode * bringing back the + 1 since it was missing when not in boost mode * Bail on USB-PD check after 3 seconds incase of DC source * Fix hibernate * Update PIDThread.cpp * did center plus symbol (boost mode) * Big refactor to not make settings increment handler handle the "is last item" return * Fixup boot logo * Fix flashing * Fixup recalculate the menu length on long hold * Fixup missing menu entries * Fix junk left on screen after user confirmation * Re-order button handler to use custom, then default order to allow setting associated setting * Attach setting for settings using custom handler * Fix swap +/- keys * Fix boost temp * Implement last menu option for Language selector * Wait for init before CJC runs * Check last setting via increment value * Update BSP.cpp * removed = from >= Otherwise incrementing would stop and the scroll bar would already flash at the second to last value. * (Hacky) Fix for Settings reset --------- Co-authored-by: discip <53649486+discip@users.noreply.github.com>
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -1,639 +1,5 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_i2c.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header file of I2C HAL module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
|
||||
*
|
||||
* 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****/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -257,6 +263,10 @@
|
||||
#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 ACCEL_I2CBB1 1
|
||||
#define SC7_ORI_FLIP
|
||||
#endif /* TS80P */
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include "cmsis_os.h"
|
||||
#include <array>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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,10 +318,14 @@ 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;
|
||||
}
|
||||
}
|
||||
refresh(); //
|
||||
}
|
||||
|
||||
void OLED::useSecondaryFramebuffer(bool useSecondary) {
|
||||
@@ -330,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
|
||||
@@ -337,8 +343,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
|
||||
@@ -365,9 +372,9 @@ void OLED::transitionScrollDown() {
|
||||
// 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);
|
||||
@@ -375,7 +382,62 @@ 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
|
||||
return;
|
||||
}
|
||||
refresh(); // Now refresh to write out the contents to the new page
|
||||
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[secondStripPos] << 1) | ((secondFrameBuffer[firstStripPos] & 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
|
||||
@@ -428,14 +490,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
|
||||
|
||||
@@ -149,9 +149,10 @@ public:
|
||||
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);
|
||||
static void transitionScrollUp(const TickType_t viewEnterTime);
|
||||
|
||||
private:
|
||||
static bool checkDisplayBufferChecksum() {
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
#include "Si7210_defines.h"
|
||||
#include "accelerometers_common.h"
|
||||
#include <Si7210.h>
|
||||
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
|
||||
@@ -7,7 +7,10 @@
|
||||
|
||||
#ifndef CORE_DRIVERS_SI7210_H_
|
||||
#define CORE_DRIVERS_SI7210_H_
|
||||
#include "configuration.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef MAG_SLEEP_SUPPORT
|
||||
class Si7210 {
|
||||
public:
|
||||
// Return true if present
|
||||
@@ -23,5 +26,5 @@ private:
|
||||
static bool get_field_strength(int16_t *field);
|
||||
static bool set_high_range();
|
||||
};
|
||||
|
||||
#endif // MAG_SLEEP_SUPPORT
|
||||
#endif /* CORE_DRIVERS_SI7210_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
|
||||
|
||||
@@ -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 false;
|
||||
}
|
||||
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);
|
||||
|
||||
|
||||
@@ -4,50 +4,21 @@
|
||||
#include "portmacro.h"
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* 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_ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ const char *translatedString(uint16_t index);
|
||||
void prepareTranslations();
|
||||
void settings_displayLanguageSwitch(void);
|
||||
bool settings_showLanguageSwitch(void);
|
||||
bool settings_setLanguageSwitch(void);
|
||||
void settings_setLanguageSwitch(void);
|
||||
bool isLastLanguageOption(void);
|
||||
|
||||
#endif /* TRANSLATION_H_ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef TYPES_H_
|
||||
#define TYPES_H_
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Used for temperature represented in C or x10C.
|
||||
//
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
#ifndef GUI_HPP_
|
||||
#define GUI_HPP_
|
||||
#include "BSP.h"
|
||||
#include "Buttons.hpp"
|
||||
#include "FreeRTOS.h"
|
||||
#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)
|
||||
@@ -26,9 +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 draw)(void);
|
||||
void (*const incrementHandler)(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;
|
||||
@@ -36,8 +35,9 @@ typedef struct {
|
||||
uint8_t shortDescriptionSize;
|
||||
} menuitem;
|
||||
|
||||
void enterSettingsMenu();
|
||||
void warnUser(const char *warning, const TickType_t timeout);
|
||||
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_ */
|
||||
|
||||
@@ -63,12 +63,13 @@ 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; }
|
||||
void settings_displayLanguageSwitch(void) { OLED::printWholeScreen(translatedString(Tr->SettingsShortNames[static_cast<uint8_t>(SettingsItemIndex::LanguageSwitch)])); }
|
||||
|
||||
bool isLastLanguageOption(void) { return selectedLangIndex == (LanguageCount - 1); }
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Translation.h"
|
||||
|
||||
bool settings_setLanguageSwitch(void) { return false; }
|
||||
void settings_setLanguageSwitch(void) {}
|
||||
|
||||
void settings_displayLanguageSwitch(void) {}
|
||||
bool settings_showLanguageSwitch(void) { return false; }
|
||||
bool isLastLanguageOption(void) { return true; }
|
||||
@@ -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;
|
||||
|
||||
if (messageStart == 0) {
|
||||
messageStart = currentTick;
|
||||
lcdRefresh = true;
|
||||
}
|
||||
void drawScrollingText(const char *message, TickType_t currentTickOffset) {
|
||||
OLED::clearScreen();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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,38 @@ 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;
|
||||
}
|
||||
} else if (option == SettingsOptions::UILanguage) {
|
||||
return isLastLanguageOption();
|
||||
}
|
||||
return systemSettings.settingsValues[(int)option] > (max - constants.increment);
|
||||
}
|
||||
// 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 +243,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() {
|
||||
|
||||
@@ -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,16 +34,17 @@ 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);
|
||||
static void displayScrollSpeed(void);
|
||||
static void displayReverseButtonTempChangeEnabled(void);
|
||||
static void displayPowerLimit(void);
|
||||
|
||||
#ifdef BLE_ENABLED
|
||||
@@ -53,20 +52,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 +90,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);
|
||||
@@ -120,17 +116,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
|
||||
@@ -196,6 +187,7 @@ static bool enterAdvancedMenu(void);
|
||||
*
|
||||
*/
|
||||
|
||||
void noOpDisplay() {}
|
||||
/* vvv !!!DISABLE CLANG-FORMAT for menuitems initialization!!! vvv */
|
||||
|
||||
/* clang-format off */
|
||||
@@ -216,16 +208,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 */
|
||||
@@ -287,7 +279,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 */
|
||||
@@ -300,27 +292,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 */
|
||||
@@ -343,7 +335,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 */
|
||||
@@ -374,10 +366,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},
|
||||
@@ -422,9 +414,9 @@ 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, displayCalibrateVIN, 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 */
|
||||
@@ -432,7 +424,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, 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 ^^^^ */
|
||||
@@ -440,6 +432,12 @@ const menuitem advancedMenu[] = {
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
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 +458,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 +478,8 @@ static int userConfirmation(const char *message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lcdRefresh) {
|
||||
OLED::refresh();
|
||||
osDelay(40);
|
||||
}
|
||||
OLED::refresh();
|
||||
osDelay(40);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -538,7 +533,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) {
|
||||
@@ -551,18 +546,17 @@ 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
|
||||
} 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);
|
||||
return value >= MAX_TEMP_C;
|
||||
}
|
||||
|
||||
static void displayBoostTemp(void) {
|
||||
@@ -618,7 +612,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)) {
|
||||
@@ -627,23 +621,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); }
|
||||
@@ -678,7 +670,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)) {
|
||||
@@ -687,14 +679,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,8 +741,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
|
||||
@@ -766,15 +756,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);
|
||||
@@ -788,7 +777,6 @@ static bool setDisplayRotation(void) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void displayDisplayRotation(void) {
|
||||
@@ -838,13 +826,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));
|
||||
}
|
||||
|
||||
@@ -883,7 +871,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
|
||||
@@ -893,12 +881,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();
|
||||
|
||||
@@ -925,10 +912,10 @@ 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;
|
||||
return;
|
||||
case BUTTON_NONE:
|
||||
default:
|
||||
break;
|
||||
@@ -937,11 +924,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);
|
||||
@@ -958,17 +942,19 @@ 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), 3 * TICKS_SECOND);
|
||||
OLED::clearScreen();
|
||||
while (!warnUser(translatedString(Tr->ResetOKMessage), getButtonState())) {
|
||||
OLED::refresh();
|
||||
vTaskDelay(TICKS_100MS);
|
||||
OLED::clearScreen();
|
||||
}
|
||||
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;
|
||||
@@ -1016,243 +1002,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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
40
source/Core/Threads/GUIRendering.md
Normal file
40
source/Core/Threads/GUIRendering.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# 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
|
||||
|
||||
## 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.
|
||||
|
||||
```
|
||||
┌───────────┐
|
||||
│ Debug 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.
|
||||
This ensures there is a good working copy in the buffer before the transition changes the view.
|
||||
|
||||
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.
|
||||
@@ -32,8 +32,179 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// File local variables
|
||||
#define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
#define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
|
||||
extern bool heaterThermalRunaway;
|
||||
ButtonState buttonsAtDeviceBoot; // We record button state at startup, incase of jumping to debug modes
|
||||
OperatingMode currentOperatingMode = OperatingMode::InitialisationDone; // Current mode we are rendering
|
||||
guiContext context; // Context passed to functions to aid in state during render passes
|
||||
|
||||
OperatingMode handle_post_init_state();
|
||||
OperatingMode guiHandleDraw(void) {
|
||||
OLED::clearScreen(); // Clear ready for render pass
|
||||
// Read button state
|
||||
ButtonState buttons = getButtonState();
|
||||
// Enforce screen on if buttons pressed, movement, hot tip etc
|
||||
if (buttons != BUTTON_NONE) {
|
||||
OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
} else {
|
||||
// Buttons are none; check if we can sleep display
|
||||
uint32_t tipTemp = TipThermoModel::getTipInC();
|
||||
if ((tipTemp < 50) && getSettingValue(SettingsOptions::Sensitivity) &&
|
||||
(((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) {
|
||||
OLED::setDisplayState(OLED::DisplayState::OFF);
|
||||
setStatusLED(LED_OFF);
|
||||
} else {
|
||||
OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
if (tipTemp > 55) {
|
||||
setStatusLED(LED_COOLING_STILL_HOT);
|
||||
} else {
|
||||
setStatusLED(LED_STANDBY);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dispatch button state to gui mode
|
||||
OperatingMode newMode = currentOperatingMode;
|
||||
switch (currentOperatingMode) {
|
||||
case OperatingMode::StartupWarnings:
|
||||
newMode = showWarnings(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::UsbPDDebug:
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
newMode = showPDDebug(buttons, &context);
|
||||
break;
|
||||
#else
|
||||
newMode = OperatingMode::InitialisationDone;
|
||||
#endif
|
||||
case OperatingMode::StartupLogo:
|
||||
showBootLogo();
|
||||
|
||||
if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SLEEP) {
|
||||
lastMovementTime = lastButtonTime = 0; // We mask the values so that sleep goes until user moves again or presses a button
|
||||
newMode = OperatingMode::Sleeping;
|
||||
} else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::SOLDER) {
|
||||
lastMovementTime = lastButtonTime = xTaskGetTickCount(); // Move forward so we dont go to sleep
|
||||
newMode = OperatingMode::Soldering;
|
||||
} else if (getSettingValue(SettingsOptions::AutoStartMode) == autoStartMode_t::ZERO) {
|
||||
lastMovementTime = lastButtonTime = 0; // We mask the values so that sleep goes until user moves again or presses a button
|
||||
newMode = OperatingMode::Hibernating;
|
||||
} else {
|
||||
newMode = OperatingMode::HomeScreen;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
/* Fallthrough */
|
||||
case OperatingMode::HomeScreen:
|
||||
newMode = drawHomeScreen(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::Soldering:
|
||||
context.scratch_state.state4 = 0;
|
||||
newMode = gui_solderingMode(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::SolderingProfile:
|
||||
newMode = gui_solderingProfileMode(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::Sleeping:
|
||||
newMode = gui_SolderingSleepingMode(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::TemperatureAdjust:
|
||||
newMode = gui_solderingTempAdjust(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::DebugMenuReadout:
|
||||
newMode = showDebugMenu(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::CJCCalibration:
|
||||
newMode = performCJCC(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::SettingsMenu:
|
||||
newMode = gui_SettingsMenu(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::InitialisationDone:
|
||||
newMode = handle_post_init_state();
|
||||
break;
|
||||
case OperatingMode::Hibernating:
|
||||
context.scratch_state.state4 = 1;
|
||||
gui_SolderingSleepingMode(buttons, &context);
|
||||
if (lastButtonTime > 0 || lastMovementTime > 0) {
|
||||
newMode = OperatingMode::Soldering;
|
||||
}
|
||||
break;
|
||||
case OperatingMode::ThermalRunaway:
|
||||
/*TODO*/
|
||||
newMode = OperatingMode::HomeScreen;
|
||||
break;
|
||||
};
|
||||
return newMode;
|
||||
}
|
||||
void guiRenderLoop(void) {
|
||||
OperatingMode newMode = guiHandleDraw(); // This does the screen drawing
|
||||
|
||||
// Post draw we handle any state transitions
|
||||
|
||||
if (newMode != currentOperatingMode) {
|
||||
context.viewEnterTime = xTaskGetTickCount();
|
||||
context.previousMode = currentOperatingMode;
|
||||
// If the previous mode is the startup logo; we dont want to return to it, but instead dispatch out to either home or soldering
|
||||
if (currentOperatingMode == OperatingMode::StartupLogo) {
|
||||
if (getSettingValue(SettingsOptions::AutoStartMode)) {
|
||||
context.previousMode = OperatingMode::Soldering;
|
||||
} else {
|
||||
newMode = OperatingMode::HomeScreen;
|
||||
}
|
||||
}
|
||||
memset(&context.scratch_state, 0, sizeof(context.scratch_state));
|
||||
currentOperatingMode = newMode;
|
||||
}
|
||||
// If the transition marker is set, we need to make the next draw occur to the secondary buffer so we have something to transition to
|
||||
if (context.transitionMode != TransitionAnimation::None) {
|
||||
OLED::useSecondaryFramebuffer(true);
|
||||
// Now we need to fill the secondary buffer with the _next_ frame to transistion to
|
||||
guiHandleDraw();
|
||||
OLED::useSecondaryFramebuffer(false);
|
||||
// Now dispatch the transition
|
||||
switch (context.transitionMode) {
|
||||
case TransitionAnimation::Down:
|
||||
OLED::transitionScrollDown(context.viewEnterTime);
|
||||
break;
|
||||
case TransitionAnimation::Left:
|
||||
OLED::transitionSecondaryFramebuffer(false, context.viewEnterTime);
|
||||
break;
|
||||
case TransitionAnimation::Right:
|
||||
OLED::transitionSecondaryFramebuffer(true, context.viewEnterTime);
|
||||
break;
|
||||
case TransitionAnimation::Up:
|
||||
OLED::transitionScrollUp(context.viewEnterTime);
|
||||
|
||||
case TransitionAnimation::None:
|
||||
default:
|
||||
break; // Do nothing on unknown
|
||||
}
|
||||
|
||||
context.transitionMode = TransitionAnimation::None; // Clear transition flag
|
||||
}
|
||||
// Render done, draw it out
|
||||
OLED::refresh();
|
||||
}
|
||||
|
||||
OperatingMode handle_post_init_state() {
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
#ifdef DEBUG_POWER_MENU_BUTTON_B
|
||||
if (buttonsAtDeviceBoot == BUTTON_B_LONG || buttonsAtDeviceBoot == BUTTON_B_SHORT) {
|
||||
#else
|
||||
if (buttonsAtDeviceBoot == BUTTON_F_LONG || buttonsAtDeviceBoot == BUTTON_F_SHORT) {
|
||||
#endif
|
||||
buttonsAtDeviceBoot = BUTTON_NONE;
|
||||
return OperatingMode::UsbPDDebug;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
|
||||
return OperatingMode::CJCCalibration;
|
||||
}
|
||||
|
||||
return OperatingMode::StartupWarnings;
|
||||
}
|
||||
|
||||
/* StartGUITask function */
|
||||
void startGUITask(void const *argument) {
|
||||
@@ -47,42 +218,22 @@ void startGUITask(void const *argument) {
|
||||
bool buttonLockout = false;
|
||||
renderHomeScreenAssets();
|
||||
getTipRawTemp(1); // reset filter
|
||||
memset(&context, 0, sizeof(context));
|
||||
|
||||
OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1);
|
||||
// If the front button is held down, on supported devices, show PD debugging metrics
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
#ifdef DEBUG_POWER_MENU_BUTTON_B
|
||||
if (getButtonB()) {
|
||||
#else
|
||||
|
||||
// Read boot button state
|
||||
if (getButtonA()) {
|
||||
#endif
|
||||
showPDDebug();
|
||||
buttonsAtDeviceBoot = BUTTON_F_LONG;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
|
||||
performCJCC();
|
||||
if (getButtonB()) {
|
||||
buttonsAtDeviceBoot = BUTTON_B_LONG;
|
||||
}
|
||||
|
||||
uint16_t logoMode = getSettingValue(SettingsOptions::LOGOTime);
|
||||
uint16_t startMode = getSettingValue(SettingsOptions::AutoStartMode);
|
||||
// If the boot logo is enabled (but it times out) and the autostart mode is enabled (but not set to sleep w/o heat), start heating during boot logo
|
||||
if (logoMode && logoMode < logoMode_t::ONETIME && startMode && startMode < autoStartMode_t::ZERO) {
|
||||
uint16_t sleepTempDegC = getSettingValue(SettingsOptions::SleepTemp);
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
sleepTempDegC = TipThermoModel::convertFtoC(sleepTempDegC);
|
||||
}
|
||||
// Only heat to sleep temperature (but no higher than 75°C for safety)
|
||||
currentTempTargetDegC = min(sleepTempDegC, 75);
|
||||
TickType_t startRender = xTaskGetTickCount();
|
||||
for (;;) {
|
||||
guiRenderLoop();
|
||||
resetWatchdog();
|
||||
vTaskDelayUntil(&startRender, TICKS_100MS * 4 / 10); // Try and maintain 20-25fps ish update rate, way to fast but if we can its nice
|
||||
}
|
||||
|
||||
showBootLogo();
|
||||
showWarnings();
|
||||
if (getSettingValue(SettingsOptions::AutoStartMode)) {
|
||||
// jump directly to the autostart mode
|
||||
gui_solderingMode(getSettingValue(SettingsOptions::AutoStartMode) - 1);
|
||||
buttonLockout = true;
|
||||
}
|
||||
|
||||
drawHomeScreen(buttonLockout);
|
||||
}
|
||||
|
||||
@@ -1,39 +1,49 @@
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
// 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) {
|
||||
uint16_t setoffset = 0;
|
||||
// Take 16 samples, only sample
|
||||
if (cxt->scratch_state.state1 < 16) {
|
||||
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);
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
for (uint8_t x = 0; x < (cxt->scratch_state.state1 / 4); x++) {
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
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->CalibrationDone), 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::StartupWarnings;
|
||||
}
|
||||
|
||||
@@ -1,111 +1,102 @@
|
||||
#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[cxt->scratch_state.state1], 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;
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
b = getButtonState();
|
||||
if (b == BUTTON_B_SHORT) {
|
||||
return;
|
||||
} else if (b == BUTTON_F_SHORT) {
|
||||
screen++;
|
||||
#ifdef HALL_SENSOR
|
||||
screen = screen % 17;
|
||||
#else
|
||||
screen = screen % 16;
|
||||
#endif
|
||||
}
|
||||
|
||||
GUIDelay();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (buttons == BUTTON_B_SHORT) {
|
||||
cxt->transitionMode = TransitionAnimation::Down;
|
||||
return OperatingMode::HomeScreen;
|
||||
} else if (buttons == BUTTON_F_SHORT) {
|
||||
cxt->scratch_state.state1++;
|
||||
#ifdef HALL_SENSOR
|
||||
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 17;
|
||||
#else
|
||||
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 16;
|
||||
#endif
|
||||
}
|
||||
return OperatingMode::DebugMenuReadout; // Stay in debug menu
|
||||
}
|
||||
|
||||
@@ -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,59 +20,50 @@ void renderHomeScreenAssets(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void handleButtons(bool *buttonLockout) {
|
||||
ButtonState buttons = getButtonState();
|
||||
if (buttons != BUTTON_NONE) {
|
||||
OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
}
|
||||
if (buttons != BUTTON_NONE && *buttonLockout) {
|
||||
buttons = BUTTON_NONE;
|
||||
OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) {
|
||||
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();
|
||||
cxt->transitionMode = TransitionAnimation::Up;
|
||||
return OperatingMode::DebugMenuReadout;
|
||||
break;
|
||||
case BUTTON_F_LONG:
|
||||
#ifdef PROFILE_SUPPORT
|
||||
if (!isTipDisconnected()) {
|
||||
gui_solderingProfileMode(); // enter profile mode
|
||||
*buttonLockout = true;
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::SolderingProfile;
|
||||
} else {
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
#else
|
||||
gui_solderingTempAdjust();
|
||||
saveSettings();
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::TemperatureAdjust;
|
||||
#endif
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
if (!isTipDisconnected()) {
|
||||
gui_solderingMode(0); // enter soldering mode
|
||||
*buttonLockout = true;
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::Soldering;
|
||||
}
|
||||
break;
|
||||
case BUTTON_B_SHORT:
|
||||
currentMode = OperatingMode::settings;
|
||||
enterSettingsMenu(); // enter the settings menu
|
||||
{
|
||||
OLED::useSecondaryFramebuffer(true);
|
||||
showExitMenuTransition = true;
|
||||
}
|
||||
*buttonLockout = true;
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return OperatingMode::SettingsMenu;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
|
||||
void drawDetailedHomeScreen(uint32_t tipTemp) {
|
||||
@@ -181,55 +168,22 @@ void drawSimplifiedHomeScreen(uint32_t tipTemp) {
|
||||
}
|
||||
}
|
||||
}
|
||||
void drawHomeScreen(bool buttonLockout) {
|
||||
OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt) {
|
||||
|
||||
for (;;) {
|
||||
currentMode = OperatingMode::idle;
|
||||
handleButtons(&buttonLockout);
|
||||
currentTempTargetDegC = 0; // ensure tip is off
|
||||
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
|
||||
uint32_t tipTemp = TipThermoModel::getTipInC();
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 handleHomeButtons(buttons, cxt);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,3 @@
|
||||
//
|
||||
|
||||
#include "OperatingModes.h"
|
||||
|
||||
// Global variables
|
||||
OperatingMode currentMode = OperatingMode::idle;
|
||||
@@ -24,29 +24,64 @@ 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.
|
||||
};
|
||||
|
||||
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 {
|
||||
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
|
||||
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_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
|
||||
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
|
||||
|
||||
275
source/Core/Threads/OperatingModes/SettingsMenu.cpp
Normal file
275
source/Core/Threads/OperatingModes/SettingsMenu.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
#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<uint8_t>(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 {
|
||||
|
||||
uint16_t *isRenderingHelp = &(cxt->scratch_state.state6);
|
||||
*isRenderingHelp = 1;
|
||||
// Draw description
|
||||
const char *description = translatedString(Tr->SettingsDescriptions[item->description - 1]);
|
||||
drawScrollingText(description, (xTaskGetTickCount() - lastButtonTime) - HELP_TEXT_TIMEOUT_TICKS);
|
||||
}
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
OperatingMode moveToNextEntry(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 *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();
|
||||
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
|
||||
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) - 1].isVisible != nullptr && !subSettingsMenus[*mainEntry][(*subEntry) - 1].isVisible()) {
|
||||
// We need to move on as this one isn't visible
|
||||
return moveToNextEntry(cxt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OperatingMode::SettingsMenu;
|
||||
}
|
||||
|
||||
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);
|
||||
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
|
||||
uint16_t currentScreen;
|
||||
if (*subEntry == 0) {
|
||||
// Drawing main menu
|
||||
currentMenu = rootSettingsMenu;
|
||||
currentScreen = *mainEntry;
|
||||
} else {
|
||||
// Drawing sub menu
|
||||
currentMenu = subSettingsMenus[*mainEntry];
|
||||
currentScreen = (*subEntry) - 1;
|
||||
}
|
||||
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, 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);
|
||||
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) {
|
||||
indicatorHeight = 1; // always at least 1 pixel
|
||||
}
|
||||
|
||||
uint16_t position = (OLED_HEIGHT * (uint16_t)currentVirtualPosition) / *currentMenuLength;
|
||||
|
||||
bool showScrollbar = true;
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
// Now handle user button input
|
||||
|
||||
auto callIncrementHandler = [&]() {
|
||||
if (currentMenu[currentScreen].incrementHandler != nullptr) {
|
||||
currentMenu[currentScreen].incrementHandler();
|
||||
} else if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) {
|
||||
nextSettingValue(currentMenu[currentScreen].autoSettingOption);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
//
|
||||
OperatingMode newMode = OperatingMode::SettingsMenu;
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
(*autoRepeatAcceleration) = 0; // reset acceleration
|
||||
(*autoRepeatTimer) = 0; // reset acceleration
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
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:
|
||||
if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) {
|
||||
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;
|
||||
}
|
||||
(*autoRepeatTimer) += xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
|
||||
*currentMenuLength = 0; // Reset incase menu visible changes
|
||||
}
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
// Increment setting
|
||||
if (*isRenderingHelp) {
|
||||
*isRenderingHelp = 0;
|
||||
} else {
|
||||
*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) {
|
||||
currentMenu[currentScreen].incrementHandler();
|
||||
} else {
|
||||
(*subEntry) += 1;
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
}
|
||||
} else {
|
||||
callIncrementHandler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BUTTON_B_LONG:
|
||||
if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) {
|
||||
(*autoRepeatTimer) = xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
/* Fall through*/
|
||||
case BUTTON_B_SHORT:
|
||||
// Increment menu item
|
||||
|
||||
newMode = moveToNextEntry(cxt);
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,56 +1,95 @@
|
||||
#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);
|
||||
}
|
||||
#ifdef DEVICE_HAS_VALIDATION_SUPPORT
|
||||
if (getDeviceValidationStatus()) {
|
||||
// Warn user this device might be counterfeit
|
||||
warnUser(translatedString(Tr->DeviceFailedValidationWarning), 10 * TICKS_SECOND);
|
||||
}
|
||||
#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);
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
cxt->scratch_state.state1 = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: // Device validations
|
||||
#ifdef DEVICE_HAS_VALIDATION_SUPPORT
|
||||
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;
|
||||
}
|
||||
#else
|
||||
cxt->scratch_state.state1 = 2;
|
||||
#endif
|
||||
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) {
|
||||
|
||||
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:
|
||||
|
||||
#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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
#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) {
|
||||
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;
|
||||
#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::StartupLogo;
|
||||
}
|
||||
#endif /*NO_WARN_MISSING*/
|
||||
|
||||
return OperatingMode::StartupWarnings; // Stay in warnings
|
||||
}
|
||||
|
||||
@@ -1,64 +1,70 @@
|
||||
#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::Soldering;
|
||||
#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;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
GUIDelay();
|
||||
|
||||
if (!shouldBeSleeping(autoStarted)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shouldShutdown()) {
|
||||
// shutdown
|
||||
currentTempTargetDegC = 0;
|
||||
// we want to exit soldering mode
|
||||
return 1;
|
||||
}
|
||||
if (checkForUnderVoltage()) {
|
||||
return OperatingMode::HomeScreen; // return non-zero on error
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
if (cxt->scratch_state.state4) {
|
||||
// Hibernating mode
|
||||
currentTempTargetDegC = 0;
|
||||
} else {
|
||||
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::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);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
GUIDelay();
|
||||
|
||||
if (!shouldBeSleeping()) {
|
||||
return cxt->previousMode;
|
||||
}
|
||||
|
||||
if (shouldShutdown()) {
|
||||
// shutdown
|
||||
currentTempTargetDegC = 0;
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
if (cxt->scratch_state.state4) {
|
||||
return OperatingMode::Hibernating;
|
||||
} else {
|
||||
return OperatingMode::Sleeping;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,62 @@
|
||||
|
||||
#include "OperatingModes.h"
|
||||
#include "SolderingCommon.h"
|
||||
// State 1 = button locking
|
||||
// State 2 = boost mode
|
||||
// State 3 = buzzer timer
|
||||
|
||||
extern OperatingMode currentMode;
|
||||
|
||||
void gui_solderingMode(uint8_t jumpToSleep) {
|
||||
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:
|
||||
/*Fall through*/
|
||||
case BUTTON_B_LONG:
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
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:
|
||||
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;
|
||||
}
|
||||
}
|
||||
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,98 +71,58 @@ 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;
|
||||
|
||||
if (jumpToSleep) {
|
||||
if (gui_SolderingSleepingMode(jumpToSleep == 2, true) == 1) {
|
||||
lastButtonTime = xTaskGetTickCount();
|
||||
return; // If the function returns non-0 then exit
|
||||
// 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)) {
|
||||
// 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);
|
||||
|
||||
if (cxt->scratch_state.state2) { // Boost mode is on
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(50, 0);
|
||||
OLED::setCursor(34, 0);
|
||||
} else {
|
||||
OLED::setCursor(-1, 0);
|
||||
OLED::setCursor(50, 0);
|
||||
}
|
||||
|
||||
gui_drawTipTemp(true, FontStyle::LARGE);
|
||||
|
||||
OLED::print(LargeSymbolPlus, FontStyle::LARGE);
|
||||
} else {
|
||||
#ifndef NO_SLEEP_MODE
|
||||
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
|
||||
if (OLED::getRotation()) {
|
||||
@@ -121,69 +133,43 @@ void gui_solderingMode(uint8_t jumpToSleep) {
|
||||
printCountdownUntilSleep(getSleepTimeout());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (boostModeOn) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(38, 8);
|
||||
} else {
|
||||
OLED::setCursor(55, 8);
|
||||
}
|
||||
OLED::print(SmallSymbolPlus, FontStyle::SMALL);
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(32, 8);
|
||||
} else {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(32, 8);
|
||||
} else {
|
||||
OLED::setCursor(47, 8);
|
||||
}
|
||||
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
|
||||
OLED::setCursor(47, 8);
|
||||
}
|
||||
|
||||
detailedPowerStatus();
|
||||
|
||||
} else {
|
||||
basicSolderingStatus(boostModeOn);
|
||||
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
// Update the setpoints for the temperature
|
||||
if (boostModeOn) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
detailedPowerStatus();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// slow down ui update rate
|
||||
GUIDelay();
|
||||
} else {
|
||||
basicSolderingStatus(cxt->scratch_state.state2);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -2,222 +2,212 @@
|
||||
#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;
|
||||
uint16_t tipTemp = 0;
|
||||
|
||||
bool waitForRelease = true;
|
||||
TickType_t phaseStartTime = xTaskGetTickCount();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
tipTemp = getTipTemp();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determine current target temp
|
||||
if (phaseStartTemp < phaseEndTemp) {
|
||||
if (profileCurrentTargetTemp < phaseEndTemp) {
|
||||
profileCurrentTargetTemp = phaseStartTemp + ((xTaskGetTickCount() - phaseStartTime) / phaseTicksPerDegree);
|
||||
}
|
||||
} else {
|
||||
if (profileCurrentTargetTemp > phaseEndTemp) {
|
||||
profileCurrentTargetTemp = phaseStartTemp - ((xTaskGetTickCount() - phaseStartTime) / phaseTicksPerDegree);
|
||||
}
|
||||
}
|
||||
|
||||
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::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);
|
||||
}
|
||||
|
||||
// print time progress / preheat / cooldown
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
detailedPowerStatus();
|
||||
|
||||
} else {
|
||||
basicSolderingStatus(false);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
// Update the setpoints for the temperature
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(profileCurrentTargetTemp);
|
||||
} else {
|
||||
currentTempTargetDegC = profileCurrentTargetTemp;
|
||||
}
|
||||
|
||||
if (checkExitSoldering() || (buzzerEnd != 0 && xTaskGetTickCount() >= buzzerEnd)) {
|
||||
setBuzzer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update LED status
|
||||
if (profilePhase == 0) {
|
||||
setStatusLED(LED_HEATING);
|
||||
} else if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
setStatusLED(LED_COOLING_STILL_HOT);
|
||||
} else {
|
||||
setStatusLED(LED_HOT);
|
||||
}
|
||||
|
||||
// slow down ui update rate
|
||||
GUIDelay();
|
||||
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:
|
||||
case BUTTON_B_SHORT:
|
||||
case BUTTON_NONE:
|
||||
// Not used yet
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
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 {
|
||||
phaseTicksPerDegree = (cxt->scratch_state.state2 * TICKS_SECOND) / (cxt->scratch_state.state6 - cxt->scratch_state.state5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 (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 {
|
||||
OLED::setCursor(0, 0);
|
||||
}
|
||||
|
||||
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
|
||||
OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL);
|
||||
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
// print phase
|
||||
if (cxt->scratch_state.state1 > 0 && cxt->scratch_state.state1 <= getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(36, 0);
|
||||
} else {
|
||||
OLED::setCursor(55, 0);
|
||||
}
|
||||
OLED::printNumber(cxt->scratch_state.state1, 1, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
// print time progress / preheat / cooldown
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(42, 8);
|
||||
} else {
|
||||
OLED::setCursor(0, 8);
|
||||
}
|
||||
|
||||
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 {
|
||||
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 < 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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return OperatingMode::SolderingProfile;
|
||||
}
|
||||
|
||||
@@ -1,120 +1,106 @@
|
||||
#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 buttonIn, guiContext *cxt) {
|
||||
|
||||
if (buttons != BUTTON_NONE) {
|
||||
// Temp adjust entered by long-pressing F button.
|
||||
waitForRelease = true;
|
||||
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) {
|
||||
buttons = BUTTON_NONE;
|
||||
} else {
|
||||
(*waitForRelease)++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ButtonState buttons;
|
||||
#endif
|
||||
|
||||
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 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;
|
||||
OLED::setCursor(0, 0);
|
||||
|
||||
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);
|
||||
int16_t delta = 0;
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
// stay
|
||||
(*autoRepeatAcceleration) = 0;
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
// exit
|
||||
saveSettings();
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return cxt->previousMode;
|
||||
case BUTTON_B_LONG:
|
||||
if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
delta = -getSettingValue(SettingsOptions::TempChangeLongStep);
|
||||
(*autoRepeatTimer) = xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += 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() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
delta = getSettingValue(SettingsOptions::TempChangeLongStep);
|
||||
(*autoRepeatTimer) = xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
|
||||
}
|
||||
|
||||
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();
|
||||
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 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 (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
if (newTemp > MAX_TEMP_F) {
|
||||
newTemp = MAX_TEMP_F;
|
||||
} else if (newTemp < MIN_TEMP_F) {
|
||||
newTemp = MIN_TEMP_F;
|
||||
}
|
||||
} else {
|
||||
if (newTemp > MAX_TEMP_C) {
|
||||
newTemp = MAX_TEMP_C;
|
||||
} else if (newTemp < MIN_TEMP_C) {
|
||||
newTemp = MIN_TEMP_C;
|
||||
}
|
||||
}
|
||||
setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -2,93 +2,85 @@
|
||||
|
||||
#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;
|
||||
|
||||
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) += 1;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
} 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
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
screen = 0;
|
||||
}
|
||||
(*screen) = 0;
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
b = getButtonState();
|
||||
if (b == BUTTON_B_SHORT) {
|
||||
return;
|
||||
} else if (b == BUTTON_F_SHORT) {
|
||||
screen++;
|
||||
}
|
||||
|
||||
GUIDelay();
|
||||
}
|
||||
if (buttons == BUTTON_B_SHORT) {
|
||||
return OperatingMode::InitialisationDone;
|
||||
} else if (buttons == BUTTON_F_SHORT) {
|
||||
(*screen) += 1;
|
||||
}
|
||||
return OperatingMode::UsbPDDebug;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
@@ -44,13 +44,14 @@ void showPDDebug(void) {
|
||||
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
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "OperatingModeUtilities.h"
|
||||
#include "OperatingModes.h"
|
||||
#include "SolderingCommon.h"
|
||||
#include "TipThermoModel.h"
|
||||
|
||||
void gui_drawTipTemp(bool symbol, const FontStyle font) {
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#ifndef OPERATING_MODE_UTILITIES_H_
|
||||
#define OPERATING_MODE_UTILITIES_H_
|
||||
#include "Buttons.hpp"
|
||||
#include "OLED.hpp"
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
||||
@@ -1,8 +1,12 @@
|
||||
#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);
|
||||
// Also timeout after 5 seconds
|
||||
if ((xTaskGetTickCount() - lastButtonTime) > TICKS_SECOND * 5) {
|
||||
return true;
|
||||
}
|
||||
return buttons != BUTTON_NONE;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "SolderingCommon.h"
|
||||
#include "OperatingModes.h"
|
||||
#include "Types.h"
|
||||
#include "configuration.h"
|
||||
#include "history.hpp"
|
||||
|
||||
@@ -106,30 +107,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;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#ifndef SOLDERING_COMMON_H
|
||||
#define SOLDERING_COMMON_H
|
||||
#include "Types.h"
|
||||
#include <stdint.h>
|
||||
#ifndef SOLDERING_COMMON_H_
|
||||
#define SOLDERING_COMMON_H_
|
||||
|
||||
void detailedPowerStatus();
|
||||
void basicSolderingStatus(bool boostModeOn);
|
||||
bool checkExitSoldering();
|
||||
void detailedPowerStatus();
|
||||
void basicSolderingStatus(bool boostModeOn);
|
||||
bool checkExitSoldering();
|
||||
TemperatureType_t getTipTemp(void);
|
||||
|
||||
#endif //SOLDERING_COMMON_H
|
||||
#endif // SOLDERING_COMMON_H_
|
||||
|
||||
@@ -17,4 +17,4 @@ void printCountdownUntilSleep(int sleepThres) {
|
||||
OLED::print(SmallSymbolSeconds, FontStyle::SMALL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -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,17 @@ 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
|
||||
// Wait up to 3 seconds for USB-PD to settle
|
||||
while (USBPowerDelivery::negotiationInProgress() && xTaskGetTickCount() < (TICKS_SECOND * 3)) {
|
||||
resetWatchdog();
|
||||
ulTaskNotifyTake(pdTRUE, TICKS_100MS);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int32_t x10WattsOut = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user