1
0
forked from me/IronOS

Compare commits

...

41 Commits

Author SHA1 Message Date
Ben V. Brown
17bcc85e98 Settings menu -> Both buttons return a menu layer 2023-10-24 08:27:05 +11:00
Ben V. Brown
fd285b3364 Fixup for scrollbar
FIXUP! Debug menu returns to home screen

FIXUP! Up oled animation

Fix temp exit
2023-10-24 08:27:05 +11:00
Ben V. Brown
9385758593 Miniware -> Only Bit-Bang I2C 2023-10-24 08:27:05 +11:00
Ben V. Brown
296aecab00 Make I2C mag optional 2023-10-24 08:27:05 +11:00
Ben V. Brown
1396363eaa Make all accelerometers I2C bus aware
Update accelerometers_common.h
2023-10-24 08:27:05 +11:00
Ben V. Brown
964d37a8e8 Link up/down on debug meny 2023-10-24 08:27:05 +11:00
Ben V. Brown
a80db0af5a OLED Up animation 2023-10-24 08:27:05 +11:00
Ben V. Brown
627d8f8be1 Fixup settings acceleration 2023-10-24 08:27:05 +11:00
Ben V. Brown
86fed6bfbe Fixes for some animations not running
Dont bail on animations if keypress is still held
2023-10-24 08:27:05 +11:00
Ben V. Brown
bf00e1bc58 Save Settings 2023-10-24 08:27:05 +11:00
Ben V. Brown
2196e76e22 Fixup transition on enter soldering mode 2023-10-24 08:27:05 +11:00
Ben V. Brown
6bb0b015c8 Update GUIRendering.md 2023-10-24 08:27:05 +11:00
Ben V. Brown
3627338b8d Fkit use bit-bang I2C for Miniware 2023-10-24 08:27:05 +11:00
Ben V. Brown
33e1a7756f Style cleanup 2023-10-24 08:27:05 +11:00
Ben V. Brown
886c956c3c silence some warnings 2023-10-24 08:27:05 +11:00
Ben V. Brown
1e2d9676c9 Fixup not showing right menu options 2023-10-24 08:27:05 +11:00
Ben V. Brown
ea35b264ab Fix PD debug at boot 2023-10-24 08:27:05 +11:00
Ben V. Brown
2d8378c39d Rework button handling 2023-10-24 08:27:05 +11:00
Ben V. Brown
1a936b84f2 Update OLED.cpp 2023-10-24 08:27:05 +11:00
Ben V. Brown
00711f6e4c Update I2C_Wrapper.cpp 2023-10-24 08:27:05 +11:00
Ben V. Brown
bf962ce51f Update settingsGUI.cpp 2023-10-24 08:27:05 +11:00
Ben V. Brown
76902ee65f Refactor moving down the settings list 2023-10-24 08:27:05 +11:00
Ben V. Brown
c85fa4affa Force write screen on side animation cancel
.
2023-10-24 08:27:05 +11:00
Ben V. Brown
3347bc6bde I2C testing 2023-10-24 08:27:05 +11:00
Ben V. Brown
26bb81ce58 Update Setup.cpp 2023-10-24 08:27:05 +11:00
Ben V. Brown
3a725aa3c1 Update USBPDDebug_HUSB238.cpp 2023-10-24 08:27:05 +11:00
Ben V. Brown
d6c5b0214b Miniware: Use IT for I2C writes 2023-10-24 08:27:05 +11:00
Ben V. Brown
7e13686276 Add auto-repeat to settings menu 2023-10-24 08:27:05 +11:00
Ben V. Brown
63db049311 Update push.yml 2023-10-24 08:27:05 +11:00
Ben V. Brown
a9da730894 Update TemperatureAdjust.cpp 2023-10-24 08:27:05 +11:00
Ben V. Brown
4d1cfcf2e6 Transitions
Update SolderingProfile.cpp

Hook in transistions
2023-10-24 08:27:05 +11:00
Ben V. Brown
5b86637e48 Fixup 2023-10-24 08:27:05 +11:00
Ben V. Brown
d3a193096e More settings rendering 2023-10-24 08:27:05 +11:00
Ben V. Brown
b38a5396f0 More settings rework 2023-10-24 08:27:04 +11:00
Ben V. Brown
5120235e2e Update SettingsMenu.cpp 2023-10-24 08:27:04 +11:00
Ben V. Brown
6002cc3270 FIXUP! Fix typo's
.
2023-10-24 08:27:04 +11:00
Ben V. Brown
553f5fd273 Better home screen button handler 2023-10-24 08:27:04 +11:00
Ben V. Brown
ae5b9e9717 Fixup! Hook in the init starter helper 2023-10-24 08:27:04 +11:00
Ben V. Brown
3888bdc04a Roughing some transition work 2023-10-24 08:27:04 +11:00
Ben V. Brown
0ec45f29a4 Update TemperatureAdjust.cpp 2023-10-24 08:27:04 +11:00
Ben V. Brown
5303d27f96 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
2023-10-24 08:27:04 +11:00
52 changed files with 1550 additions and 6738 deletions

View File

@@ -1,6 +1,16 @@
name: CI name: CI
on: [push, pull_request] on:
push:
branches:
- master
- dev
- main
pull_request:
branches:
- master
- dev
- main
jobs: jobs:

View File

@@ -1,91 +0,0 @@
/*
* FRToSI2C.cpp
*
* Created on: 14Apr.,2018
* Author: Ralim
*/
#include "BSP.h"
#include "Setup.h"
#include <I2C_Wrapper.hpp>
SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr;
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
void FRToSI2C::CpltCallback() {
hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error)
if (I2CSemaphore) {
xSemaphoreGiveFromISR(I2CSemaphore, NULL);
}
}
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
if (!lock())
return false;
if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
I2C_Unstick();
unlock();
return false;
}
unlock();
return true;
}
bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); }
uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) {
uint8_t tx_data[1];
Mem_Read(add, reg, tx_data, 1);
return tx_data[0];
}
bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
if (!lock())
return false;
if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
I2C_Unstick();
unlock();
return false;
}
unlock();
return true;
}
bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
if (!lock())
return false;
if (HAL_I2C_Master_Transmit_IT(&hi2c1, DevAddress, pData, Size) != HAL_OK) {
I2C_Unstick();
unlock();
return false;
}
return true;
}
bool FRToSI2C::probe(uint16_t DevAddress) {
if (!lock())
return false;
uint8_t buffer[1];
bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK;
unlock();
return worked;
}
void FRToSI2C::I2C_Unstick() { unstick_I2C(); }
void FRToSI2C::unlock() { xSemaphoreGive(I2CSemaphore); }
bool FRToSI2C::lock() { return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; }
bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) {
for (int index = 0; index < registersLength; index++) {
if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) {
return false;
}
if (registers[index].pause_ms)
delay_ms(registers[index].pause_ms);
}
return true;
}

View File

@@ -23,12 +23,6 @@ void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc) {
} }
} }
} }
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
extern osThreadId POWTaskHandle; extern osThreadId POWTaskHandle;

View File

@@ -18,12 +18,7 @@
extern "C" { extern "C" {
#endif #endif
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc); void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc);
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_GPIO_EXTI_Callback(uint16_t); void HAL_GPIO_EXTI_Callback(uint16_t);
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -13,10 +13,6 @@ ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2; ADC_HandleTypeDef hadc2;
DMA_HandleTypeDef hdma_adc1; DMA_HandleTypeDef hdma_adc1;
I2C_HandleTypeDef hi2c1;
DMA_HandleTypeDef hdma_i2c1_rx;
DMA_HandleTypeDef hdma_i2c1_tx;
IWDG_HandleTypeDef hiwdg; IWDG_HandleTypeDef hiwdg;
TIM_HandleTypeDef htimADC; TIM_HandleTypeDef htimADC;
TIM_HandleTypeDef htimTip; TIM_HandleTypeDef htimTip;
@@ -27,7 +23,6 @@ uint16_t ADCReadings[ADC_SAMPLES]; // Used to store the adc readings for the han
// Functions // Functions
static void SystemClock_Config(void); static void SystemClock_Config(void);
static void MX_ADC1_Init(void); static void MX_ADC1_Init(void);
static void MX_I2C1_Init(void);
static void MX_IWDG_Init(void); static void MX_IWDG_Init(void);
static void MX_TIP_CONTROL_TIMER_Init(void); static void MX_TIP_CONTROL_TIMER_Init(void);
static void MX_ADC_CONTROL_TIMER_Init(void); static void MX_ADC_CONTROL_TIMER_Init(void);
@@ -45,9 +40,6 @@ void Setup_HAL() {
MX_GPIO_Init(); MX_GPIO_Init();
MX_DMA_Init(); MX_DMA_Init();
#ifndef I2C_SOFT_BUS_1
MX_I2C1_Init();
#endif
MX_ADC1_Init(); MX_ADC1_Init();
MX_ADC2_Init(); MX_ADC2_Init();
MX_TIP_CONTROL_TIMER_Init(); MX_TIP_CONTROL_TIMER_Init();
@@ -277,20 +269,6 @@ static void MX_ADC2_Init(void) {
; ;
} }
} }
/* I2C1 init function */
static void MX_I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 75000;
// OLED doesnt handle >100k when its asleep (off).
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
}
/* IWDG init function */ /* IWDG init function */
static void MX_IWDG_Init(void) { static void MX_IWDG_Init(void) {

View File

@@ -18,10 +18,6 @@ extern ADC_HandleTypeDef hadc1;
extern ADC_HandleTypeDef hadc2; extern ADC_HandleTypeDef hadc2;
extern DMA_HandleTypeDef hdma_adc1; extern DMA_HandleTypeDef hdma_adc1;
extern DMA_HandleTypeDef hdma_i2c1_rx;
extern DMA_HandleTypeDef hdma_i2c1_tx;
extern I2C_HandleTypeDef hi2c1;
extern IWDG_HandleTypeDef hiwdg; extern IWDG_HandleTypeDef hiwdg;
extern TIM_HandleTypeDef htimADC; extern TIM_HandleTypeDef htimADC;

View File

@@ -1,639 +1,5 @@
/**
******************************************************************************
* @file stm32f1xx_hal_i2c.h
* @author MCD Application Team
* @brief Header file of I2C HAL module.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 #ifndef __STM32F1xx_HAL_I2C_H
#define __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 */ #endif /* __STM32F1xx_HAL_I2C_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

File diff suppressed because it is too large Load Diff

View File

@@ -86,7 +86,7 @@
#define POWER_PULSE_DEFAULT 0 #define POWER_PULSE_DEFAULT 0
#else #else
#define POWER_PULSE_DEFAULT 5 #define POWER_PULSE_DEFAULT 5
#endif /* TS100 */ #endif /* TS100 */
#define POWER_PULSE_WAIT_DEFAULT 4 // Default rate of the power pulse: 4*2500 = 10000 ms = 10 s #define POWER_PULSE_WAIT_DEFAULT 4 // Default rate of the power pulse: 4*2500 = 10000 ms = 10 s
#define POWER_PULSE_DURATION_DEFAULT 1 // Default duration of the power pulse: 1*250 = 250 ms #define POWER_PULSE_DURATION_DEFAULT 1 // Default duration of the power pulse: 1*250 = 250 ms
@@ -172,6 +172,9 @@
#define TIP_RESISTANCE 75 // x10 ohms, 7.5 typical for ts100 tips #define TIP_RESISTANCE 75 // x10 ohms, 7.5 typical for ts100 tips
#define POW_DC #define POW_DC
#define I2C_SOFT_BUS_1 1
#define OLED_I2CBB1 1
#define ACCEL_I2CBB1 1
#define TEMP_TMP36 #define TEMP_TMP36
#endif /* TS100 */ #endif /* TS100 */
@@ -234,6 +237,9 @@
#define POW_QC #define POW_QC
#define TEMP_TMP36 #define TEMP_TMP36
#define I2C_SOFT_BUS_1 1
#define OLED_I2CBB1 1
#define ACCEL_I2CBB1 1
#endif /* TS80 */ #endif /* TS80 */
#ifdef MODEL_TS80P #ifdef MODEL_TS80P
@@ -248,6 +254,9 @@
#define POW_QC 1 #define POW_QC 1
#define TEMP_NTC #define TEMP_NTC
#define I2C_SOFT_BUS_2 1 #define I2C_SOFT_BUS_2 1
#define I2C_SOFT_BUS_1 1
#define OLED_I2CBB1 1
#define ACCEL_I2CBB1 1
#define SC7_ORI_FLIP #define SC7_ORI_FLIP
#endif /* TS80P */ #endif /* TS80P */
@@ -255,8 +264,8 @@
#define FLASH_LOGOADDR (0x08000000 + (126 * 1024)) #define FLASH_LOGOADDR (0x08000000 + (126 * 1024))
#define SETTINGS_START_PAGE (0x08000000 + (127 * 1024)) #define SETTINGS_START_PAGE (0x08000000 + (127 * 1024))
#else #else
#define FLASH_LOGOADDR (0x08000000 + (62 * 1024)) #define FLASH_LOGOADDR (0x08000000 + (62 * 1024))
#define SETTINGS_START_PAGE (0x08000000 + (63 * 1024)) #define SETTINGS_START_PAGE (0x08000000 + (63 * 1024))
#endif /* TS101 */ #endif /* TS101 */
#endif /* CONFIGURATION_H_ */ #endif /* CONFIGURATION_H_ */

View File

@@ -25,7 +25,4 @@ void preRToSInit() {
#ifdef I2C_SOFT_BUS_1 #ifdef I2C_SOFT_BUS_1
I2CBB1::init(); I2CBB1::init();
#endif #endif
/* Init the IPC objects */
FRToSI2C::FRToSInit();
} }

View File

@@ -81,55 +81,6 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) {
} }
} }
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) {
GPIO_InitTypeDef GPIO_InitStruct;
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = SCL_Pin | SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* I2C1 DMA Init */
/* I2C1_RX Init */
hdma_i2c1_rx.Instance = DMA1_Channel7;
hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c1_rx.Init.Mode = DMA_NORMAL;
hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_LOW;
HAL_DMA_Init(&hdma_i2c1_rx);
__HAL_LINKDMA(hi2c, hdmarx, hdma_i2c1_rx);
/* I2C1_TX Init */
hdma_i2c1_tx.Instance = DMA1_Channel6;
hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&hdma_i2c1_tx);
__HAL_LINKDMA(hi2c, hdmatx, hdma_i2c1_tx);
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) { void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) {
if (htim_base->Instance == TIM3) { if (htim_base->Instance == TIM3) {
/* Peripheral clock enable */ /* Peripheral clock enable */

View File

@@ -57,12 +57,12 @@ void TIM4_IRQHandler(void) {
HAL_TIM_IRQHandler(handle); HAL_TIM_IRQHandler(handle);
} }
void I2C1_EV_IRQHandler(void) { HAL_I2C_EV_IRQHandler(&hi2c1); } void I2C1_EV_IRQHandler(void) {}
void I2C1_ER_IRQHandler(void) { HAL_I2C_ER_IRQHandler(&hi2c1); } void I2C1_ER_IRQHandler(void) {}
void DMA1_Channel6_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_tx); } void DMA1_Channel6_IRQHandler(void) {}
void DMA1_Channel7_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_rx); } void DMA1_Channel7_IRQHandler(void) {}
void EXTI9_5_IRQHandler(void) { void EXTI9_5_IRQHandler(void) {
#ifdef INT_PD_Pin #ifdef INT_PD_Pin

View File

@@ -282,7 +282,7 @@ typedef union {
*/ */
#define __RV_CSR_SWAP(csr, val) \ #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"); \ __ASM volatile("csrrw %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \
__v; \ __v; \
}) })
@@ -297,7 +297,7 @@ typedef union {
*/ */
#define __RV_CSR_READ(csr) \ #define __RV_CSR_READ(csr) \
({ \ ({ \
register rv_csr_t __v; \ volatile rv_csr_t __v; \
__ASM volatile("csrr %0, " STRINGIFY(csr) : "=r"(__v) : : "memory"); \ __ASM volatile("csrr %0, " STRINGIFY(csr) : "=r"(__v) : : "memory"); \
__v; \ __v; \
}) })
@@ -312,7 +312,7 @@ typedef union {
*/ */
#define __RV_CSR_WRITE(csr, val) \ #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"); \ __ASM volatile("csrw " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \
}) })
@@ -328,7 +328,7 @@ typedef union {
*/ */
#define __RV_CSR_READ_SET(csr, val) \ #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"); \ __ASM volatile("csrrs %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \
__v; \ __v; \
}) })
@@ -343,7 +343,7 @@ typedef union {
*/ */
#define __RV_CSR_SET(csr, val) \ #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"); \ __ASM volatile("csrs " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \
}) })
@@ -359,7 +359,7 @@ typedef union {
*/ */
#define __RV_CSR_READ_CLEAR(csr, val) \ #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"); \ __ASM volatile("csrrc %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \
__v; \ __v; \
}) })
@@ -374,7 +374,7 @@ typedef union {
*/ */
#define __RV_CSR_CLEAR(csr, val) \ #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"); \ __ASM volatile("csrc " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \
}) })
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */

View File

@@ -86,7 +86,7 @@
#define POWER_PULSE_DEFAULT 0 #define POWER_PULSE_DEFAULT 0
#else #else
#define POWER_PULSE_DEFAULT 5 #define POWER_PULSE_DEFAULT 5
#endif /* Pinecil */ #endif /* Pinecil */
#define POWER_PULSE_WAIT_DEFAULT 4 // Default rate of the power pulse: 4*2500 = 10000 ms = 10 s #define POWER_PULSE_WAIT_DEFAULT 4 // Default rate of the power pulse: 4*2500 = 10000 ms = 10 s
#define POWER_PULSE_DURATION_DEFAULT 1 // Default duration of the power pulse: 1*250 = 250 ms #define POWER_PULSE_DURATION_DEFAULT 1 // Default duration of the power pulse: 1*250 = 250 ms
@@ -145,12 +145,13 @@
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C #define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F #define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
#define POW_PD 1 #define POW_PD 1
#define POW_PD_EXT 0 #define POW_PD_EXT 0
#define POW_QC 1 #define POW_QC 1
#define POW_DC 1 #define POW_DC 1
#define POW_QC_20V 1 #define POW_QC_20V 1
#define ENABLE_QC2 1 #define ENABLE_QC2 1
#define MAG_SLEEP_SUPPORT 1
#define TEMP_TMP36 #define TEMP_TMP36
#define ACCEL_BMA #define ACCEL_BMA
#define ACCEL_SC7 #define ACCEL_SC7

View File

@@ -34,7 +34,7 @@
#endif #endif
extern TickType_t lastMovementTime; 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) { 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) { 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; break;
case 13: case 13:
// Operating mode // Operating mode
temp = currentMode; temp = (uint32_t)currentOperatingMode;
memcpy(buf, &temp, sizeof(temp)); memcpy(buf, &temp, sizeof(temp));
return sizeof(temp); return sizeof(temp);
break; 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::getTipMaxInC(), // 9 - max temp
TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), // 10 - Raw tip in μV TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), // 10 - Raw tip in μV
abs(getRawHallEffect()), // 11 - hall sensor abs(getRawHallEffect()), // 11 - hall sensor
currentMode, // 12 - Operating mode (uint32_t)currentOperatingMode, // 12 - Operating mode
x10WattHistory.average(), // 13 - Estimated Wattage *10 x10WattHistory.average(), // 13 - Estimated Wattage *10
}; };
int lenToCopy = sizeof(bulkData) - offset; int lenToCopy = sizeof(bulkData) - offset;

View File

@@ -152,6 +152,7 @@
#define POW_QC_20V 1 // Supported features #define POW_QC_20V 1 // Supported features
#define POW_EPR 1 #define POW_EPR 1
#define ENABLE_QC2 1 #define ENABLE_QC2 1
#define MAG_SLEEP_SUPPORT 1
#define DEVICE_HAS_VALIDATION_SUPPORT #define DEVICE_HAS_VALIDATION_SUPPORT
#define TEMP_NTC #define TEMP_NTC
#define ACCEL_BMA #define ACCEL_BMA

View File

@@ -5,14 +5,16 @@
* Author: Ralim * Author: Ralim
*/ */
#include "accelerometers_common.h"
#include <BMA223.hpp> #include <BMA223.hpp>
#include <array> #include <array>
bool BMA223::detect() { bool BMA223::detect() {
if (FRToSI2C::probe(BMA223_ADDRESS)) { if (ACCEL_I2C_CLASS::probe(BMA223_ADDRESS)) {
// Read chip id to ensure its not an address collision // Read chip id to ensure its not an address collision
uint8_t id = 0; uint8_t id = 0;
if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_BGW_CHIPID, &id, 1)) { if (ACCEL_I2C_CLASS::Mem_Read(BMA223_ADDRESS, BMA223_BGW_CHIPID, &id, 1)) {
return id == 0b11111000; return id == 0b11111000;
} }
} }
@@ -20,7 +22,7 @@ bool BMA223::detect() {
return false; return false;
} }
static const FRToSI2C::I2C_REG i2c_registers[] = { static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
// //
// //
{BMA223_PMU_RANGE, 0b00000011, 0}, // 2G range {BMA223_PMU_RANGE, 0b00000011, 0}, // 2G range
@@ -44,7 +46,7 @@ bool BMA223::initalize() {
// Hysteresis is set to ~ 16 counts // Hysteresis is set to ~ 16 counts
// Theta blocking is set to 0b10 // Theta blocking is set to 0b10
return FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); return ACCEL_I2C_CLASS::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
} }
void BMA223::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { void BMA223::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
@@ -52,7 +54,7 @@ void BMA223::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
// And yet there are MSB and LSB registers _sigh_. // And yet there are MSB and LSB registers _sigh_.
uint8_t sensorData[6] = {0, 0, 0, 0, 0, 0}; uint8_t sensorData[6] = {0, 0, 0, 0, 0, 0};
if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) { if (ACCEL_I2C_CLASS::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) {
x = y = z = 0; x = y = z = 0;
return; return;
} }

View File

@@ -9,6 +9,7 @@
#define CORE_DRIVERS_BMA223_HPP_ #define CORE_DRIVERS_BMA223_HPP_
#include "BMA223_defines.h" #include "BMA223_defines.h"
#include "BSP.h" #include "BSP.h"
#include "accelerometers_common.h"
#include "I2C_Wrapper.hpp" #include "I2C_Wrapper.hpp"
class BMA223 { class BMA223 {
@@ -17,7 +18,7 @@ public:
static bool initalize(); static bool initalize();
// 1 = rh, 2,=lh, 8=flat // 1 = rh, 2,=lh, 8=flat
static Orientation getOrientation() { static Orientation getOrientation() {
uint8_t val = FRToSI2C::I2C_RegisterRead(BMA223_ADDRESS, BMA223_INT_STATUS_3); uint8_t val = ACCEL_I2C_CLASS::I2C_RegisterRead(BMA223_ADDRESS, BMA223_INT_STATUS_3);
val >>= 4; // we dont need high values val >>= 4; // we dont need high values
val &= 0b11; val &= 0b11;
if (val & 0b10) { if (val & 0b10) {

View File

@@ -8,9 +8,10 @@
#include <array> #include <array>
#include "MMA8652FC.hpp" #include "MMA8652FC.hpp"
#include "accelerometers_common.h"
#include "cmsis_os.h" #include "cmsis_os.h"
static const FRToSI2C::I2C_REG i2c_registers[] = { static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
{CTRL_REG2, 0, 0}, // Normal mode {CTRL_REG2, 0, 0}, // Normal mode
{CTRL_REG2, 0x40, 2}, // Reset all registers to POR values {CTRL_REG2, 0x40, 2}, // Reset all registers to POR values
{FF_MT_CFG_REG, 0x78, 0}, // Enable motion detection for X, Y, Z axis, latch disabled {FF_MT_CFG_REG, 0x78, 0}, // Enable motion detection for X, Y, Z axis, latch disabled
@@ -26,11 +27,11 @@ static const FRToSI2C::I2C_REG i2c_registers[] = {
{CTRL_REG1, 0x19, 0} // ODR=12 Hz, Active mode {CTRL_REG1, 0x19, 0} // ODR=12 Hz, Active mode
}; };
bool MMA8652FC::initalize() { return FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } bool MMA8652FC::initalize() { return ACCEL_I2C_CLASS::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); }
Orientation MMA8652FC::getOrientation() { Orientation MMA8652FC::getOrientation() {
// First read the PL_STATUS register // First read the PL_STATUS register
uint8_t plStatus = FRToSI2C::I2C_RegisterRead(MMA8652FC_I2C_ADDRESS, PL_STATUS_REG); uint8_t plStatus = ACCEL_I2C_CLASS::I2C_RegisterRead(MMA8652FC_I2C_ADDRESS, PL_STATUS_REG);
if ((plStatus & 0b10000000) == 0b10000000) { if ((plStatus & 0b10000000) == 0b10000000) {
plStatus >>= 1; // We don't need the up/down bit plStatus >>= 1; // We don't need the up/down bit
plStatus &= 0x03; // mask to the two lower bits plStatus &= 0x03; // mask to the two lower bits
@@ -47,11 +48,11 @@ Orientation MMA8652FC::getOrientation() {
void MMA8652FC::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { void MMA8652FC::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
std::array<int16_t, 3> sensorData; std::array<int16_t, 3> sensorData;
FRToSI2C::Mem_Read(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG, reinterpret_cast<uint8_t *>(sensorData.begin()), sensorData.size() * sizeof(int16_t)); ACCEL_I2C_CLASS::Mem_Read(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG, reinterpret_cast<uint8_t *>(sensorData.begin()), sensorData.size() * sizeof(int16_t));
x = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[0]))); x = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[0])));
y = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[1]))); y = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[1])));
z = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[2]))); z = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[2])));
} }
bool MMA8652FC::detect() { return FRToSI2C::probe(MMA8652FC_I2C_ADDRESS); } bool MMA8652FC::detect() { return ACCEL_I2C_CLASS::probe(MMA8652FC_I2C_ADDRESS); }

View File

@@ -6,11 +6,12 @@
*/ */
#include "MSA301_defines.h" #include "MSA301_defines.h"
#include "accelerometers_common.h"
#include <MSA301.h> #include <MSA301.h>
#define MSA301_I2C_ADDRESS 0x26 << 1 #define MSA301_I2C_ADDRESS 0x26 << 1
bool MSA301::detect() { return FRToSI2C::probe(MSA301_I2C_ADDRESS); } bool MSA301::detect() { return ACCEL_I2C_CLASS::probe(MSA301_I2C_ADDRESS); }
static const FRToSI2C::I2C_REG i2c_registers[] = { static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
// //
// //
{MSA301_REG_ODR, 0b00001000, 1}, // X/Y/Z enabled @ 250Hz {MSA301_REG_ODR, 0b00001000, 1}, // X/Y/Z enabled @ 250Hz
@@ -21,11 +22,11 @@ static const FRToSI2C::I2C_REG i2c_registers[] = {
}; };
bool MSA301::initalize() { return FRToSI2C::writeRegistersBulk(MSA301_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } bool MSA301::initalize() { return ACCEL_I2C_CLASS::writeRegistersBulk(MSA301_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); }
Orientation MSA301::getOrientation() { Orientation MSA301::getOrientation() {
uint8_t temp = 0; uint8_t temp = 0;
FRToSI2C::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_ORIENT_STATUS, &temp, 1); ACCEL_I2C_CLASS::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_ORIENT_STATUS, &temp, 1);
switch (temp) { switch (temp) {
case 112: case 112:
return Orientation::ORIENTATION_LEFT_HAND; return Orientation::ORIENTATION_LEFT_HAND;
@@ -39,7 +40,7 @@ Orientation MSA301::getOrientation() {
void MSA301::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { void MSA301::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
uint8_t temp[6]; uint8_t temp[6];
// Bulk read all 6 regs // Bulk read all 6 regs
FRToSI2C::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_OUT_X_L, temp, 6); ACCEL_I2C_CLASS::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_OUT_X_L, temp, 6);
x = int16_t(((int16_t)temp[1]) << 8 | temp[0]) >> 2; x = int16_t(((int16_t)temp[1]) << 8 | temp[0]) >> 2;
y = int16_t(((int16_t)temp[3]) << 8 | temp[2]) >> 2; y = int16_t(((int16_t)temp[3]) << 8 | temp[2]) >> 2;
z = int16_t(((int16_t)temp[5]) << 8 | temp[4]) >> 2; z = int16_t(((int16_t)temp[5]) << 8 | temp[4]) >> 2;

View File

@@ -262,7 +262,8 @@ void OLED::maskScrollIndicatorOnOLED() {
* If forward is true, this displays a forward navigation to the second framebuffer contents. * 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. * 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]; uint8_t *stripBackPointers[4];
stripBackPointers[0] = &secondFrameBuffer[FRAMEBUFFER_START + 0]; stripBackPointers[0] = &secondFrameBuffer[FRAMEBUFFER_START + 0];
stripBackPointers[1] = &secondFrameBuffer[FRAMEBUFFER_START + OLED_WIDTH]; 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 refresh(); // Now refresh to write out the contents to the new page
vTaskDelayUntil(&startDraw, TICKS_100MS / 7); 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; return;
} }
} }
refresh(); //
} }
void OLED::useSecondaryFramebuffer(bool useSecondary) { void OLED::useSecondaryFramebuffer(bool useSecondary) {
@@ -330,6 +335,7 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) {
setFramebuffer(screenBuffer); setFramebuffer(screenBuffer);
} }
} }
/** /**
* This assumes that the current display output buffer has the current on screen contents * 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 * 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** * **This function blocks until the transition has completed or user presses button**
*/ */
void OLED::transitionScrollDown() { void OLED::transitionScrollDown(const TickType_t viewEnterTime) {
TickType_t startDraw = xTaskGetTickCount(); TickType_t startDraw = xTaskGetTickCount();
bool buttonsReleased = getButtonState() == BUTTON_NONE;
for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) { for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) {
// For each line, we shuffle all bits up a row // 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 // Finally on the bottom row; we shuffle it up ready
secondFrameBuffer[fourthStripPos] >>= 1; secondFrameBuffer[fourthStripPos] >>= 1;
#else #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); 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); screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] >> 1) | ((secondFrameBuffer[firstStripPos] & 0x01) << 7);
// Finally, do the shuffle on the second frame buffer // Finally, do the shuffle on the second frame buffer
secondFrameBuffer[firstStripPos] = (secondFrameBuffer[firstStripPos] >> 1) | ((secondFrameBuffer[secondStripPos] & 0x01) << 7); secondFrameBuffer[firstStripPos] = (secondFrameBuffer[firstStripPos] >> 1) | ((secondFrameBuffer[secondStripPos] & 0x01) << 7);
@@ -375,7 +382,62 @@ void OLED::transitionScrollDown() {
secondFrameBuffer[secondStripPos] >>= 1; secondFrameBuffer[secondStripPos] >>= 1;
#endif /* OLED_128x32 */ #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 // Exit early, but have to transition whole buffer
memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START); memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START);
refresh(); // Now refresh to write out the contents to the new page 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) { void OLED::setBrightness(uint8_t contrast) {
OLED_Setup_Array[15].val = contrast; if (OLED_Setup_Array[15].val != contrast) {
I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, &OLED_Setup_Array[14], 2); OLED_Setup_Array[15].val = contrast;
I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, &OLED_Setup_Array[14], 2);
}
} }
void OLED::setInverseDisplay(bool inverse) { void OLED::setInverseDisplay(bool inverse) {
uint8_t normalInverseCmd = inverse ? 0xA7 : 0xA6; uint8_t normalInverseCmd = inverse ? 0xA7 : 0xA6;
OLED_Setup_Array[21].val = normalInverseCmd; if (OLED_Setup_Array[21].val != normalInverseCmd) {
I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, 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 // print a string to the current cursor location, len chars MAX

View File

@@ -46,9 +46,9 @@ extern "C" {
#define OLED_GRAM_START_FLIP 0 #define OLED_GRAM_START_FLIP 0
#define OLED_GRAM_END_FLIP 0x7F #define OLED_GRAM_END_FLIP 0x7F
#define OLED_VCOM_LAYOUT 0x12 #define OLED_VCOM_LAYOUT 0x12
#define OLED_SEGMENT_MAP_REVERSED #define OLED_SEGMENT_MAP_REVERSED
#define OLED_DIVIDER 0xD3 #define OLED_DIVIDER 0xD3
#else #else
@@ -59,14 +59,14 @@ extern "C" {
#define OLED_GRAM_START_FLIP 0 #define OLED_GRAM_START_FLIP 0
#define OLED_GRAM_END_FLIP 95 #define OLED_GRAM_END_FLIP 95
#define OLED_VCOM_LAYOUT 0x02 #define OLED_VCOM_LAYOUT 0x02
#define OLED_SEGMENT_MAP 0xA0 #define OLED_SEGMENT_MAP 0xA0
#define OLED_DIVIDER 0xD5 #define OLED_DIVIDER 0xD5
#endif /* OLED_128x32 */ #endif /* OLED_128x32 */
#define OLED_ON 0xAF #define OLED_ON 0xAF
#define OLED_OFF 0xAE #define OLED_OFF 0xAE
#define FRAMEBUFFER_START 17 #define FRAMEBUFFER_START 17
@@ -78,7 +78,10 @@ enum class FontStyle {
class OLED { class OLED {
public: public:
enum DisplayState : bool { OFF = false, ON = true }; enum DisplayState : bool {
OFF = false,
ON = true
};
static void initialize(); // Startup the I2C coms (brings screen out of reset etc) static void initialize(); // Startup the I2C coms (brings screen out of reset etc)
static bool isInitDone(); static bool isInitDone();
@@ -117,10 +120,10 @@ public:
static void setInverseDisplay(bool inverted); static void setInverseDisplay(bool inverted);
static int16_t getCursorX() { return cursor_x; } static int16_t getCursorX() { return cursor_x; }
// Draw a string to the current location, with selected font; optionally - with MAX length only // Draw a string to the current location, with selected font; optionally - with MAX length only
static void print(const char *string, FontStyle fontStyle, uint8_t length = 255); static void print(const char *string, FontStyle fontStyle, uint8_t length = 255);
static void printWholeScreen(const char *string); static void printWholeScreen(const char *string);
// Print *F or *C - in font style of Small, Large (by default) or Extra based on input arg // Print *F or *C - in font style of Small, Large (by default) or Extra based on input arg
static void printSymbolDeg(FontStyle fontStyle = FontStyle::LARGE); static void printSymbolDeg(FontStyle fontStyle = FontStyle::LARGE);
// Set the cursor location by pixels // Set the cursor location by pixels
static void setCursor(int16_t x, int16_t y) { static void setCursor(int16_t x, int16_t y) {
cursor_x = x; cursor_x = x;
@@ -146,9 +149,10 @@ public:
static void drawHeatSymbol(uint8_t state); static void drawHeatSymbol(uint8_t state);
static void drawScrollIndicator(uint8_t p, uint8_t h); // Draws a scrolling position indicator static void drawScrollIndicator(uint8_t p, uint8_t h); // Draws a scrolling position indicator
static void maskScrollIndicatorOnOLED(); 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 useSecondaryFramebuffer(bool useSecondary);
static void transitionScrollDown(); static void transitionScrollDown(const TickType_t viewEnterTime);
static void transitionScrollUp(const TickType_t viewEnterTime);
private: private:
static bool checkDisplayBufferChecksum() { static bool checkDisplayBufferChecksum() {

View File

@@ -6,6 +6,7 @@
*/ */
#include "LIS2DH12_defines.hpp" #include "LIS2DH12_defines.hpp"
#include "accelerometers_common.h"
#include <SC7A20.hpp> #include <SC7A20.hpp>
#include <SC7A20_defines.h> #include <SC7A20_defines.h>
#include <array> #include <array>
@@ -17,20 +18,20 @@ bool SC7A20::isInImitationMode;
*/ */
bool SC7A20::detect() { bool SC7A20::detect() {
if (FRToSI2C::probe(SC7A20_ADDRESS)) { if (ACCEL_I2C_CLASS::probe(SC7A20_ADDRESS)) {
// Read chip id to ensure its not an address collision // Read chip id to ensure its not an address collision
uint8_t id = 0; uint8_t id = 0;
if (FRToSI2C::Mem_Read(SC7A20_ADDRESS, SC7A20_WHO_AMI_I, &id, 1)) { if (ACCEL_I2C_CLASS::Mem_Read(SC7A20_ADDRESS, SC7A20_WHO_AMI_I, &id, 1)) {
if (id == SC7A20_WHO_AM_I_VALUE) { if (id == SC7A20_WHO_AM_I_VALUE) {
isInImitationMode = false; isInImitationMode = false;
return true; return true;
} }
} }
} }
if (FRToSI2C::probe(SC7A20_ADDRESS2)) { if (ACCEL_I2C_CLASS::probe(SC7A20_ADDRESS2)) {
// Read chip id to ensure its not an address collision // Read chip id to ensure its not an address collision
uint8_t id = 0; uint8_t id = 0;
if (FRToSI2C::Mem_Read(SC7A20_ADDRESS2, SC7A20_WHO_AMI_I, &id, 1)) { if (ACCEL_I2C_CLASS::Mem_Read(SC7A20_ADDRESS2, SC7A20_WHO_AMI_I, &id, 1)) {
if (id == SC7A20_WHO_AM_I_VALUE) { if (id == SC7A20_WHO_AM_I_VALUE) {
isInImitationMode = true; isInImitationMode = true;
return true; return true;
@@ -40,7 +41,7 @@ bool SC7A20::detect() {
return false; return false;
} }
static const FRToSI2C::I2C_REG i2c_registers[] = { static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
// //
// //
{SC7A20_CTRL_REG1, 0b01100111, 0}, // 200Hz, XYZ enabled {SC7A20_CTRL_REG1, 0b01100111, 0}, // 200Hz, XYZ enabled
@@ -59,19 +60,19 @@ static const FRToSI2C::I2C_REG i2c_registers[] = {
// //
}; };
static const FRToSI2C::I2C_REG i2c_registers_alt[] = {{LIS_CTRL_REG1, 0b00110111, 0}, // 200Hz XYZ static const ACCEL_I2C_CLASS::I2C_REG i2c_registers_alt[] = {{LIS_CTRL_REG1, 0b00110111, 0}, // 200Hz XYZ
{LIS_CTRL_REG2, 0b00000000, 0}, // {LIS_CTRL_REG2, 0b00000000, 0}, //
{LIS_CTRL_REG3, 0b01100000, 0}, // Setup interrupt pins {LIS_CTRL_REG3, 0b01100000, 0}, // Setup interrupt pins
{LIS_CTRL_REG4, 0b00001000, 0}, // Block update mode off, HR on {LIS_CTRL_REG4, 0b00001000, 0}, // Block update mode off, HR on
{LIS_CTRL_REG5, 0b00000010, 0}, // {LIS_CTRL_REG5, 0b00000010, 0}, //
{LIS_CTRL_REG6, 0b01100010, 0}, {LIS_CTRL_REG6, 0b01100010, 0},
// Basically setup the unit to run, and enable 4D orientation detection // Basically setup the unit to run, and enable 4D orientation detection
{LIS_INT2_CFG, 0b01111110, 0}, // setup for movement detection {LIS_INT2_CFG, 0b01111110, 0}, // setup for movement detection
{LIS_INT2_THS, 0x28, 0}, // {LIS_INT2_THS, 0x28, 0}, //
{LIS_INT2_DURATION, 64, 0}, // {LIS_INT2_DURATION, 64, 0}, //
{LIS_INT1_CFG, 0b01111110, 0}, // {LIS_INT1_CFG, 0b01111110, 0}, //
{LIS_INT1_THS, 0x28, 0}, // {LIS_INT1_THS, 0x28, 0}, //
{LIS_INT1_DURATION, 64, 0}}; {LIS_INT1_DURATION, 64, 0}};
bool SC7A20::initalize() { bool SC7A20::initalize() {
// Setup acceleration readings // Setup acceleration readings
@@ -83,9 +84,9 @@ bool SC7A20::initalize() {
// Hysteresis is set to ~ 16 counts // Hysteresis is set to ~ 16 counts
// Theta blocking is set to 0b10 // Theta blocking is set to 0b10
if (isInImitationMode) { if (isInImitationMode) {
return FRToSI2C::writeRegistersBulk(SC7A20_ADDRESS2, i2c_registers_alt, sizeof(i2c_registers_alt) / sizeof(i2c_registers_alt[0])); return ACCEL_I2C_CLASS::writeRegistersBulk(SC7A20_ADDRESS2, i2c_registers_alt, sizeof(i2c_registers_alt) / sizeof(i2c_registers_alt[0]));
} else { } else {
return FRToSI2C::writeRegistersBulk(SC7A20_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); return ACCEL_I2C_CLASS::writeRegistersBulk(SC7A20_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
} }
} }
@@ -93,7 +94,7 @@ void SC7A20::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
// We can tell the accelerometer to output in LE mode which makes this simple // We can tell the accelerometer to output in LE mode which makes this simple
uint16_t sensorData[3] = {0, 0, 0}; uint16_t sensorData[3] = {0, 0, 0};
if (FRToSI2C::Mem_Read(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, isInImitationMode ? SC7A20_OUT_X_L_ALT : SC7A20_OUT_X_L, (uint8_t *)sensorData, 6) == false) { if (ACCEL_I2C_CLASS::Mem_Read(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, isInImitationMode ? SC7A20_OUT_X_L_ALT : SC7A20_OUT_X_L, (uint8_t *)sensorData, 6) == false) {
x = y = z = 0; x = y = z = 0;
return; return;
} }

View File

@@ -10,6 +10,8 @@
#include "BSP.h" #include "BSP.h"
#include "I2C_Wrapper.hpp" #include "I2C_Wrapper.hpp"
#include "SC7A20_defines.h" #include "SC7A20_defines.h"
#include "accelerometers_common.h"
class SC7A20 { class SC7A20 {
public: public:
@@ -17,7 +19,7 @@ public:
static bool initalize(); static bool initalize();
// 1 = rh, 2,=lh, 8=flat // 1 = rh, 2,=lh, 8=flat
static Orientation getOrientation() { static Orientation getOrientation() {
uint8_t val = ((FRToSI2C::I2C_RegisterRead(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, SC7A20_INT2_SOURCE) >> 2) - 1); uint8_t val = ((ACCEL_I2C_CLASS::I2C_RegisterRead(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, SC7A20_INT2_SOURCE) >> 2) - 1);
if (val == 1) { if (val == 1) {
#ifdef SC7_ORI_FLIP #ifdef SC7_ORI_FLIP
return Orientation::ORIENTATION_RIGHT_HAND; return Orientation::ORIENTATION_RIGHT_HAND;

View File

@@ -13,6 +13,7 @@
#include "I2C_Wrapper.hpp" #include "I2C_Wrapper.hpp"
#include "Si7210_defines.h" #include "Si7210_defines.h"
#include <Si7210.h> #include <Si7210.h>
#ifdef MAG_SLEEP_SUPPORT
bool Si7210::detect() { return FRToSI2C::wakePart(SI7210_ADDRESS); } bool Si7210::detect() { return FRToSI2C::wakePart(SI7210_ADDRESS); }
bool Si7210::init() { bool Si7210::init() {
@@ -175,3 +176,4 @@ bool Si7210::set_high_range() {
worked &= write_reg(SI7210_A5, 0, val); worked &= write_reg(SI7210_A5, 0, val);
return worked; return worked;
} }
#endif // MAG_SLEEP_SUPPORT

View File

@@ -7,7 +7,10 @@
#ifndef CORE_DRIVERS_SI7210_H_ #ifndef CORE_DRIVERS_SI7210_H_
#define CORE_DRIVERS_SI7210_H_ #define CORE_DRIVERS_SI7210_H_
#include "configuration.h"
#include <stdint.h> #include <stdint.h>
#ifdef MAG_SLEEP_SUPPORT
class Si7210 { class Si7210 {
public: public:
// Return true if present // Return true if present
@@ -23,5 +26,5 @@ private:
static bool get_field_strength(int16_t *field); static bool get_field_strength(int16_t *field);
static bool set_high_range(); static bool set_high_range();
}; };
#endif // MAG_SLEEP_SUPPORT
#endif /* CORE_DRIVERS_SI7210_H_ */ #endif /* CORE_DRIVERS_SI7210_H_ */

View File

@@ -1,6 +1,6 @@
#ifndef CORE_DRIVERS_ACCELEROMTERS_COMMON_H_ #ifndef CORE_DRIVERS_ACCELEROMTERS_COMMON_H_
#define CORE_DRIVERS_ACCELEROMTERS_COMMON_H_ #define CORE_DRIVERS_ACCELEROMTERS_COMMON_H_
#include "configuration.h"
#if defined(ACCEL_I2CBB2) #if defined(ACCEL_I2CBB2)
#include "I2CBB2.hpp" #include "I2CBB2.hpp"
#define ACCEL_I2C_CLASS I2CBB2 #define ACCEL_I2C_CLASS I2CBB2

View File

@@ -4,50 +4,21 @@
#include "portmacro.h" #include "portmacro.h"
#include <stdint.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 * Draw and update the scroll message if needed.
* font and taking into account multi-byte chars. *
* * This function does not call `OLED::refresh()`. If this function
* @param message The null-terminated message string. * returns `true`, the caller shall call `OLED::refresh()` to draw the
*/ * modified framebuffer to the OLED screen.
static uint16_t messageWidth(const char *message); *
* @param message The null-terminated message string. This must be the
public: * same string as the previous call, unless this `ScrollMessage` instance
ScrollMessage() {} * 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.
/** */
* Resets this `ScrollMessage` instance to its initial state. void drawScrollingText(const char *message, TickType_t currentTickOffset);
*/
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);
};
#endif /* SCROLL_MESSAGE_HPP_ */ #endif /* SCROLL_MESSAGE_HPP_ */

View File

@@ -9,10 +9,10 @@
#define GUI_HPP_ #define GUI_HPP_
#include "BSP.h" #include "BSP.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "Buttons.hpp"
#include "Settings.h" #include "Settings.h"
#include "Translation.h" #include "Translation.h"
#define PRESS_ACCEL_STEP (TICKS_100MS / 3) #define PRESS_ACCEL_STEP (TICKS_100MS / 3)
#define PRESS_ACCEL_INTERVAL_MIN TICKS_100MS #define PRESS_ACCEL_INTERVAL_MIN TICKS_100MS
#define PRESS_ACCEL_INTERVAL_MAX (TICKS_100MS * 3) #define PRESS_ACCEL_INTERVAL_MAX (TICKS_100MS * 3)
@@ -36,8 +36,9 @@ typedef struct {
uint8_t shortDescriptionSize; uint8_t shortDescriptionSize;
} menuitem; } menuitem;
void enterSettingsMenu(); void enterSettingsMenu();
void warnUser(const char *warning, const TickType_t timeout); bool warnUser(const char *warning, const ButtonState buttons);
extern const menuitem rootSettingsMenu[]; extern const menuitem rootSettingsMenu[];
extern const menuitem *subSettingsMenus[];
#endif /* GUI_HPP_ */ #endif /* GUI_HPP_ */

View File

@@ -28,19 +28,20 @@ static uint16_t str_display_len(const char *const str) {
return count; 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) { void drawScrollingText(const char *message, TickType_t currentTickOffset) {
bool lcdRefresh = false;
if (messageStart == 0) {
messageStart = currentTick;
lcdRefresh = true;
}
int16_t messageOffset; int16_t messageOffset;
uint16_t msgWidth = messageWidth(message); uint16_t msgWidth = messageWidth(message);
if (msgWidth > OLED_WIDTH) { 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 messageOffset %= msgWidth + OLED_WIDTH; // Roll around at the end
if (messageOffset < OLED_WIDTH) { if (messageOffset < OLED_WIDTH) {
// Snap the message to the left edge. // 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; messageOffset = (OLED_WIDTH - msgWidth) / 2 + msgWidth;
} }
if (lastOffset != messageOffset) { //^ Rolling offset based on time
OLED::clearScreen(); OLED::setCursor((OLED_WIDTH - messageOffset), 0);
OLED::print(message, FontStyle::LARGE);
//^ Rolling offset based on time
OLED::setCursor((OLED_WIDTH - messageOffset), 0);
OLED::print(message, FontStyle::LARGE);
lastOffset = messageOffset;
lcdRefresh = true;
}
return lcdRefresh;
} }

View File

@@ -120,17 +120,12 @@ static bool showHallEffect(void);
#if defined(POW_DC) || defined(POW_QC) #if defined(POW_DC) || defined(POW_QC)
static void displayPowerMenu(void); static void displayPowerMenu(void);
static bool enterPowerMenu(void);
#endif /* POW_DC or POW_QC */ #endif /* POW_DC or POW_QC */
static void displaySolderingMenu(void); static void displaySolderingMenu(void);
static bool enterSolderingMenu(void);
static void displayPowerSavingMenu(void); static void displayPowerSavingMenu(void);
static bool enterPowerSavingMenu(void);
static void displayUIMenu(void); static void displayUIMenu(void);
static bool enterUIMenu(void);
static void displayAdvancedMenu(void); static void displayAdvancedMenu(void);
static bool enterAdvancedMenu(void);
/* /*
* Root Settings Menu * Root Settings Menu
@@ -216,16 +211,16 @@ const menuitem rootSettingsMenu[] {
*/ */
#if defined(POW_DC) || defined(POW_QC) #if defined(POW_DC) || defined(POW_QC)
/* Power */ /* Power */
{0, enterPowerMenu, displayPowerMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, {0, nullptr, displayPowerMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
#endif #endif
/* Soldering */ /* Soldering */
{0, enterSolderingMenu, displaySolderingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, {0, nullptr, displaySolderingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
/* Sleep Options Menu */ /* 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 */ /* UI Menu */
{0, enterUIMenu, displayUIMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, {0, nullptr, displayUIMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
/* Advanced Menu */ /* Advanced Menu */
{0, enterAdvancedMenu, displayAdvancedMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, {0, nullptr, displayAdvancedMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
/* Language Switch */ /* Language Switch */
{0, settings_setLanguageSwitch, settings_displayLanguageSwitch, settings_showLanguageSwitch, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0}, {0, settings_setLanguageSwitch, settings_displayLanguageSwitch, settings_showLanguageSwitch, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
/* vvvv end of menu marker. DO NOT REMOVE vvvv */ /* vvvv end of menu marker. DO NOT REMOVE vvvv */
@@ -440,6 +435,12 @@ const menuitem advancedMenu[] = {
/* clang-format on */ /* 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!!! ^^^ */ /* ^^^ !!!ENABLE CLANG-FORMAT back!!! ^^^ */
/** /**
@@ -460,10 +461,9 @@ static void printShortDescription(SettingsItemIndex settingsItemIndex, uint16_t
} }
static int userConfirmation(const char *message) { static int userConfirmation(const char *message) {
ScrollMessage scrollMessage; TickType_t tickStart = xTaskGetTickCount();
for (;;) { for (;;) {
bool lcdRefresh = scrollMessage.drawUpdate(message, xTaskGetTickCount()); drawScrollingText(message, xTaskGetTickCount() - tickStart);
ButtonState buttons = getButtonState(); ButtonState buttons = getButtonState();
switch (buttons) { switch (buttons) {
@@ -481,10 +481,8 @@ static int userConfirmation(const char *message) {
return 0; return 0;
} }
if (lcdRefresh) { OLED::refresh();
OLED::refresh(); osDelay(40);
osDelay(40);
}
} }
return 0; return 0;
} }
@@ -826,13 +824,13 @@ static void displayAnimationLoop(void) { OLED::drawCheckbox(getSettingValue(Sett
static void displayBrightnessLevel(void) { static void displayBrightnessLevel(void) {
OLED::printNumber((getSettingValue(SettingsOptions::OLEDBrightness) / BRIGHTNESS_STEP + 1), 1, FontStyle::LARGE); 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)); OLED::setBrightness(getSettingValue(SettingsOptions::OLEDBrightness));
} }
static void displayInvertColor(void) { static void displayInvertColor(void) {
OLED::drawCheckbox(getSettingValue(SettingsOptions::OLEDInversion)); 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)); OLED::setInverseDisplay(getSettingValue(SettingsOptions::OLEDInversion));
} }
@@ -942,7 +940,7 @@ static void displayPowerPulseDuration(void) { OLED::printNumber(getSettingValue(
static bool setResetSettings(void) { static bool setResetSettings(void) {
if (userConfirmation(translatedString(Tr->SettingsResetWarning))) { if (userConfirmation(translatedString(Tr->SettingsResetWarning))) {
resetSettings(); resetSettings();
warnUser(translatedString(Tr->ResetOKMessage), 3 * TICKS_SECOND); // warnUser(translatedString(Tr->ResetOKMessage), buttons); //TODO
reboot(); reboot();
} }
return false; return false;
@@ -1026,214 +1024,3 @@ static bool enterAdvancedMenu(void) {
gui_Menu(advancedMenu); gui_Menu(advancedMenu);
return false; 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();
}

View 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.

View File

@@ -31,8 +31,159 @@ extern "C" {
#include "pd.h" #include "pd.h"
#endif #endif
// File local variables // 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:
BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); // TODO needs refactor
if (getSettingValue(SettingsOptions::AutoStartMode) == 1) {
// jump directly to the autostart mode
newMode = OperatingMode::Sleeping;
} else if (getSettingValue(SettingsOptions::AutoStartMode) == 2) {
newMode = OperatingMode::Hibernating;
} else {
newMode = OperatingMode::HomeScreen;
}
break;
default:
/* Fallthrough */
case OperatingMode::HomeScreen:
newMode = drawHomeScreen(buttons, &context);
break;
case OperatingMode::Soldering:
newMode = gui_solderingMode(buttons, &context);
break;
case OperatingMode::SolderingProfile:
newMode = gui_solderingProfileMode(buttons, &context);
break;
case OperatingMode::Sleeping:
newMode = gui_SolderingSleepingMode(buttons, &context);
break;
case OperatingMode::TemperatureAdjust:
newMode = gui_solderingTempAdjust(buttons, &context);
break;
case OperatingMode::DebugMenuReadout:
newMode = showDebugMenu(buttons, &context);
break;
case OperatingMode::CJCCalibration:
newMode = performCJCC(buttons, &context);
break;
case OperatingMode::SettingsMenu:
newMode = gui_SettingsMenu(buttons, &context);
break;
case OperatingMode::InitialisationDone:
newMode = handle_post_init_state();
break;
case OperatingMode::Hibernating:
newMode = OperatingMode::HomeScreen;
break;
case OperatingMode::ThermalRunaway:
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;
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::StartupLogo;
}
/* StartGUITask function */ /* StartGUITask function */
void startGUITask(void const *argument) { void startGUITask(void const *argument) {
@@ -46,43 +197,34 @@ void startGUITask(void const *argument) {
bool buttonLockout = false; bool buttonLockout = false;
renderHomeScreenAssets(); renderHomeScreenAssets();
getTipRawTemp(1); // reset filter getTipRawTemp(1); // reset filter
memset(&context, 0, sizeof(context));
OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1); 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 // // If the boot logo is enabled with timeout and the autostart mode is enabled (but not set to sleep w/o heat), start heating during boot logo
#ifdef DEBUG_POWER_MENU_BUTTON_B // if (getSettingValue(SettingsOptions::LOGOTime) > 0 && getSettingValue(SettingsOptions::LOGOTime) < 5 && getSettingValue(SettingsOptions::AutoStartMode) > 0
if (getButtonB()) { // && getSettingValue(SettingsOptions::AutoStartMode) < 3) {
#else // uint16_t sleepTempDegC;
// if (getSettingValue(SettingsOptions::TemperatureInF)) {
// sleepTempDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SleepTemp));
// } else {
// sleepTempDegC = getSettingValue(SettingsOptions::SleepTemp);
// }
// // Only heat to sleep temperature (but no higher than 75°C for safety)
// currentTempTargetDegC = min(sleepTempDegC, 75);
// }
// Read boot button state
if (getButtonA()) { if (getButtonA()) {
#endif buttonsAtDeviceBoot = BUTTON_F_LONG;
showPDDebug();
} }
#endif if (getButtonB()) {
buttonsAtDeviceBoot = BUTTON_B_LONG;
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
performCJCC();
} }
// 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 TickType_t startRender = xTaskGetTickCount();
if (getSettingValue(SettingsOptions::LOGOTime) > 0 && getSettingValue(SettingsOptions::LOGOTime) < 5 && getSettingValue(SettingsOptions::AutoStartMode) > 0 for (;;) {
&& getSettingValue(SettingsOptions::AutoStartMode) < 3) { guiRenderLoop();
uint16_t sleepTempDegC; resetWatchdog();
if (getSettingValue(SettingsOptions::TemperatureInF)) { vTaskDelayUntil(&startRender, TICKS_100MS * 4 / 10); // Try and maintain 20-25fps ish update rate, way to fast but if we can its nice
sleepTempDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SleepTemp));
} else {
sleepTempDegC = getSettingValue(SettingsOptions::SleepTemp);
}
// Only heat to sleep temperature (but no higher than 75°C for safety)
currentTempTargetDegC = min(sleepTempDegC, 75);
} }
showBootLogo();
showWarnings();
if (getSettingValue(SettingsOptions::AutoStartMode)) {
// jump directly to the autostart mode
gui_solderingMode(getSettingValue(SettingsOptions::AutoStartMode) - 1);
buttonLockout = true;
}
drawHomeScreen(buttonLockout);
} }

View File

@@ -1,39 +1,38 @@
#include "OperatingModes.h" #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. // Calibrate Cold Junction Compensation directly at boot, before internal components get warm.
OLED::refresh();
osDelay(50);
if (!isTipDisconnected() && abs(int(TipThermoModel::getTipInC() - getHandleTemperature(0) / 10)) < 10) { if (!isTipDisconnected() && abs(int(TipThermoModel::getTipInC() - getHandleTemperature(0) / 10)) < 10) {
uint16_t setoffset = 0; // Take 16 samples
if (cxt->scratch_state.state1 < 16) {
cxt->scratch_state.state3 += getTipRawTemp(1);
OLED::setCursor(0, 0);
OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
for (uint8_t x = 0; x < (cxt->scratch_state.state1 / 4); x++) {
OLED::print(SmallSymbolDot, FontStyle::SMALL);
}
cxt->scratch_state.state1++;
return OperatingMode::CJCCalibration;
}
// If the thermo-couple at the end of the tip, and the handle are at // 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 // equilibrium, then the output should be zero, as there is no temperature
// differential. // differential.
while (setoffset == 0) {
uint32_t offset = 0; uint16_t setOffset = TipThermoModel::convertTipRawADCTouV(cxt->scratch_state.state3 / 16, true);
for (uint8_t i = 0; i < 16; i++) { setSettingValue(SettingsOptions::CalibrationOffset, setOffset);
offset += getTipRawTemp(1); if (warnUser(translatedString(Tr->CJCCalibrationDone), buttons)) {
// cycle through the filter a fair bit to ensure we're stable. // Preventing to repeat calibration at boot automatically (only one shot).
OLED::clearScreen(); setSettingValue(SettingsOptions::CalibrateCJC, 0);
OLED::setCursor(0, 0); saveSettings();
OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL); return OperatingMode::InitialisationDone;
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);
} }
setSettingValue(SettingsOptions::CalibrationOffset, setoffset); return OperatingMode::CJCCalibration;
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();
} }
// Cant run calibration without the tip and for temps to be close
return OperatingMode::InitialisationDone;
} }

View File

@@ -1,111 +1,102 @@
#include "OperatingModes.h" #include "OperatingModes.h"
extern osThreadId GUITaskHandle; extern osThreadId GUITaskHandle;
extern osThreadId MOVTaskHandle; extern osThreadId MOVTaskHandle;
extern osThreadId PIDTaskHandle; extern osThreadId PIDTaskHandle;
extern OperatingMode currentMode;
void showDebugMenu(void) { OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) {
currentMode = OperatingMode::debug; OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
uint8_t screen = 0; OLED::print(SmallSymbolVersionNumber, FontStyle::SMALL); // Print version number
ButtonState b; OLED::setCursor(0, 8); // second line
for (;;) { OLED::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL);
OLED::clearScreen(); // Ensure the buffer starts clean switch (cxt->scratch_state.state1) {
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) case 0: // Build Date
OLED::print(SmallSymbolVersionNumber, FontStyle::SMALL); // Print version number break;
OLED::setCursor(0, 8); // second line case 1: // Device ID
OLED::print(DebugMenu[screen], FontStyle::SMALL); {
switch (screen) { uint64_t id = getDeviceID();
case 0: // Build Date
break;
case 1: // Device ID
{
uint64_t id = getDeviceID();
#ifdef DEVICE_HAS_VALIDATION_CODE #ifdef DEVICE_HAS_VALIDATION_CODE
// If device has validation code; then we want to take over both lines of the screen // If device has validation code; then we want to take over both lines of the screen
OLED::clearScreen(); // Ensure the buffer starts clean OLED::clearScreen(); // Ensure the buffer starts clean
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(DebugMenu[screen], FontStyle::SMALL); OLED::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL);
OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8); OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8);
OLED::setCursor(0, 8); // second line OLED::setCursor(0, 8); // second line
#endif #endif
OLED::drawHex((uint32_t)(id >> 32), FontStyle::SMALL, 8); OLED::drawHex((uint32_t)(id >> 32), FontStyle::SMALL, 8);
OLED::drawHex((uint32_t)(id & 0xFFFFFFFF), FontStyle::SMALL, 8); OLED::drawHex((uint32_t)(id & 0xFFFFFFFF), FontStyle::SMALL, 8);
} break; } break;
case 2: // ACC Type case 2: // ACC Type
OLED::print(AccelTypeNames[(int)DetectedAccelerometerVersion], FontStyle::SMALL); OLED::print(AccelTypeNames[(int)DetectedAccelerometerVersion], FontStyle::SMALL);
break; break;
case 3: // Power Negotiation Status case 3: // Power Negotiation Status
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL); OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL);
break; break;
case 4: // Input Voltage case 4: // Input Voltage
printVoltage(); printVoltage();
break; break;
case 5: // Temp in °C case 5: // Temp in °C
OLED::printNumber(TipThermoModel::getTipInC(), 6, FontStyle::SMALL); OLED::printNumber(TipThermoModel::getTipInC(), 6, FontStyle::SMALL);
break; break;
case 6: // Handle Temp in °C case 6: // Handle Temp in °C
OLED::printNumber(getHandleTemperature(0) / 10, 6, FontStyle::SMALL); OLED::printNumber(getHandleTemperature(0) / 10, 6, FontStyle::SMALL);
OLED::print(SmallSymbolDot, FontStyle::SMALL); OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(getHandleTemperature(0) % 10, 1, FontStyle::SMALL); OLED::printNumber(getHandleTemperature(0) % 10, 1, FontStyle::SMALL);
break; break;
case 7: // Max Temp Limit in °C case 7: // Max Temp Limit in °C
OLED::printNumber(TipThermoModel::getTipMaxInC(), 6, FontStyle::SMALL); OLED::printNumber(TipThermoModel::getTipMaxInC(), 6, FontStyle::SMALL);
break; break;
case 8: // System Uptime case 8: // System Uptime
OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 8, FontStyle::SMALL); OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 8, FontStyle::SMALL);
break; break;
case 9: // Movement Timestamp case 9: // Movement Timestamp
OLED::printNumber(lastMovementTime / TICKS_100MS, 8, FontStyle::SMALL); OLED::printNumber(lastMovementTime / TICKS_100MS, 8, FontStyle::SMALL);
break; break;
case 10: // Tip Resistance in Ω large to pad over so that we cover ID left overs case 10: // Tip Resistance in Ω
OLED::printNumber(getTipResistanceX10() / 10, 6, FontStyle::SMALL); OLED::printNumber(getTipResistanceX10() / 10, 6, FontStyle::SMALL); // large to pad over so that we cover ID left overs
OLED::print(SmallSymbolDot, FontStyle::SMALL); OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(getTipResistanceX10() % 10, 1, FontStyle::SMALL); OLED::printNumber(getTipResistanceX10() % 10, 1, FontStyle::SMALL);
break; break;
case 11: // Raw Tip in µV case 11: // Raw Tip in µV
OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), 8, FontStyle::SMALL); OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), 8, FontStyle::SMALL);
break; break;
case 12: // Tip Cold Junction Compensation Offset in µV case 12: // Tip Cold Junction Compensation Offset in µV
OLED::printNumber(getSettingValue(SettingsOptions::CalibrationOffset), 8, FontStyle::SMALL); OLED::printNumber(getSettingValue(SettingsOptions::CalibrationOffset), 8, FontStyle::SMALL);
break; break;
case 13: // High Water Mark for GUI case 13: // High Water Mark for GUI
OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 8, FontStyle::SMALL); OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 8, FontStyle::SMALL);
break; break;
case 14: // High Water Mark for Movement Task case 14: // High Water Mark for Movement Task
OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 8, FontStyle::SMALL); OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 8, FontStyle::SMALL);
break; break;
case 15: // High Water Mark for PID Task case 15: // High Water Mark for PID Task
OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 8, FontStyle::SMALL); OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 8, FontStyle::SMALL);
break; break;
break; break;
#ifdef HALL_SENSOR #ifdef HALL_SENSOR
case 16: // Raw Hall Effect Value case 16: // Raw Hall Effect Value
{ {
int16_t hallEffectStrength = getRawHallEffect(); int16_t hallEffectStrength = getRawHallEffect();
if (hallEffectStrength < 0) { if (hallEffectStrength < 0) {
hallEffectStrength = -hallEffectStrength; hallEffectStrength = -hallEffectStrength;
} }
OLED::printNumber(hallEffectStrength, 6, FontStyle::SMALL); OLED::printNumber(hallEffectStrength, 6, FontStyle::SMALL);
} break; } break;
#endif #endif
default: default:
break; 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();
} }
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
} }

View File

@@ -2,14 +2,10 @@
#include "Buttons.hpp" #include "Buttons.hpp"
#include "OperatingModes.h" #include "OperatingModes.h"
#define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ) uint8_t buttonAF[sizeof(buttonA)];
#define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ) uint8_t buttonBF[sizeof(buttonB)];
uint8_t disconnectedTipF[sizeof(disconnectedTip)];
uint8_t buttonAF[sizeof(buttonA)]; bool showExitMenuTransition = false;
uint8_t buttonBF[sizeof(buttonB)];
uint8_t disconnectedTipF[sizeof(disconnectedTip)];
extern OperatingMode currentMode;
bool showExitMenuTransition = false;
void renderHomeScreenAssets(void) { void renderHomeScreenAssets(void) {
@@ -24,59 +20,50 @@ void renderHomeScreenAssets(void) {
} }
} }
void handleButtons(bool *buttonLockout) { OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) {
ButtonState buttons = getButtonState(); if (buttons != BUTTON_NONE && cxt->scratch_state.state1 == 0) {
if (buttons != BUTTON_NONE) { return OperatingMode::HomeScreen; // Ignore button press
OLED::setDisplayState(OLED::DisplayState::ON);
}
if (buttons != BUTTON_NONE && *buttonLockout) {
buttons = BUTTON_NONE;
} else { } else {
*buttonLockout = false; cxt->scratch_state.state1 = 1;
} }
switch (buttons) { switch (buttons) {
case BUTTON_NONE: case BUTTON_NONE:
// Do nothing // Do nothing
break; break;
case BUTTON_BOTH: case BUTTON_BOTH:
// Not used yet
// In multi-language this might be used to reset language on a long hold
// or some such
break; break;
case BUTTON_B_LONG: case BUTTON_B_LONG:
// Show the version information cxt->transitionMode = TransitionAnimation::Up;
showDebugMenu(); return OperatingMode::DebugMenuReadout;
break; break;
case BUTTON_F_LONG: case BUTTON_F_LONG:
#ifdef PROFILE_SUPPORT #ifdef PROFILE_SUPPORT
if (!isTipDisconnected()) { if (!isTipDisconnected()) {
gui_solderingProfileMode(); // enter profile mode cxt->transitionMode = TransitionAnimation::Left;
*buttonLockout = true; return OperatingMode::SolderingProfile;
} else {
return OperatingMode::HomeScreen;
} }
#else #else
gui_solderingTempAdjust(); cxt->transitionMode = TransitionAnimation::Left;
saveSettings(); return OperatingMode::TemperatureAdjust;
#endif #endif
break; break;
case BUTTON_F_SHORT: case BUTTON_F_SHORT:
if (!isTipDisconnected()) { if (!isTipDisconnected()) {
gui_solderingMode(0); // enter soldering mode cxt->transitionMode = TransitionAnimation::Left;
*buttonLockout = true; return OperatingMode::Soldering;
} }
break; break;
case BUTTON_B_SHORT: case BUTTON_B_SHORT:
currentMode = OperatingMode::settings; cxt->transitionMode = TransitionAnimation::Right;
enterSettingsMenu(); // enter the settings menu return OperatingMode::SettingsMenu;
{
OLED::useSecondaryFramebuffer(true);
showExitMenuTransition = true;
}
*buttonLockout = true;
break; break;
default: default:
break; break;
} }
return OperatingMode::HomeScreen;
} }
void drawDetailedHomeScreen(uint32_t tipTemp) { 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 (;;) { currentTempTargetDegC = 0; // ensure tip is off
currentMode = OperatingMode::idle; getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
handleButtons(&buttonLockout); uint32_t tipTemp = TipThermoModel::getTipInC();
currentTempTargetDegC = 0; // ensure tip is off // Setup LCD Cursor location
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0); if (OLED::getRotation()) {
uint32_t tipTemp = TipThermoModel::getTipInC(); OLED::setCursor(50, 0);
// Preemptively turn the display on. Turn it off if and only if } else {
// the tip temperature is below 50 degrees C *and* motion sleep OLED::setCursor(-1, 0);
// 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();
}
} }
if (getSettingValue(SettingsOptions::DetailedIDLE)) {
drawDetailedHomeScreen(tipTemp);
} else {
drawSimplifiedHomeScreen(tipTemp);
}
return handleHomeButtons(buttons, cxt);
} }

View File

@@ -3,6 +3,3 @@
// //
#include "OperatingModes.h" #include "OperatingModes.h"
// Global variables
OperatingMode currentMode = OperatingMode::idle;

View File

@@ -24,29 +24,64 @@ extern "C" {
#include "pd.h" #include "pd.h"
#endif #endif
// Exposed modes enum class OperatingMode {
enum OperatingMode { StartupLogo = 0, // Showing the startup logo
idle = 0, CJCCalibration, // Cold Junction Calibration
soldering = 1, StartupWarnings, // Startup checks and warnings
boost = 2, InitialisationDone, // Special state we use just before we to home screen at first startup. Allows jumping to extra startup states
sleeping = 3, HomeScreen, // Home/Idle screen that is the main launchpad to other modes
settings = 4, Soldering, // Main soldering operating mode
debug = 5 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 // Main functions
void performCJCC(void); // Used to calibrate the Cold Junction offset OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt); // Sleep mode
void gui_solderingTempAdjust(void); // For adjusting the setpoint temperature of the iron OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt); // Main mode for hot pointy tool
int gui_SolderingSleepingMode(bool stayOff, bool autoStarted); // Sleep mode OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt); // For adjusting the setpoint temperature of the iron
void gui_solderingMode(uint8_t jumpToSleep); // Main mode for hot pointy tool OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt); // IDLE / Home screen
void gui_solderingProfileMode(); // Profile mode for hot likely-not-so-pointy tool OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt); //
void showDebugMenu(void); // Debugging values
void showPDDebug(void); // Debugging menu that shows PD adaptor info OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt); // Profile mode for hot likely-not-so-pointy tool
void showWarnings(void); // Shows user warnings if required OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt); // Used to calibrate the Cold Junction offset
void drawHomeScreen(bool buttonLockout) __attribute__((noreturn)); // IDLE / Home screen OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt); // Debugging values
void renderHomeScreenAssets(void); // Called to act as start delay and used to render out flipped images for home screen graphics 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 // Common helpers
int8_t getPowerSourceNumber(void); // Returns number ID of power source 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) void renderHomeScreenAssets(void); // Called to act as start delay and used to render out flipped images for home screen graphics
extern bool heaterThermalRunaway;
#endif #endif

View File

@@ -0,0 +1,233 @@
#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);
}
}
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++) {
if (menu[pos].draw == nullptr) {
return counter;
}
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 *isRenderingHelp = &(cxt->scratch_state.state6);
if (*isRenderingHelp) {
*isRenderingHelp = 0;
} else {
// Scroll down
// We can increment freely _once_
cxt->transitionMode = TransitionAnimation::Down;
if (*subEntry == 0) {
(*mainEntry) += 1;
if (rootSettingsMenu[*mainEntry].draw == nullptr) {
// We are off the end of the menu now
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, 64);
}
if (*isRenderingHelp == 0) {
// Draw scroll
uint16_t currentVirtualPosition = getMenuLength(currentMenu, currentScreen + 1) - 1;
uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength;
uint8_t position = (OLED_HEIGHT * currentVirtualPosition) / *currentMenuLength;
// Draw if not last item
if ((*currentMenuLength != currentVirtualPosition) || xTaskGetTickCount() % 1000 < 500) {
OLED::drawScrollIndicator(position, indicatorHeight);
}
}
// Now handle user button input
auto callIncrementHandler = [&]() {
if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) {
return nextSettingValue(currentMenu[currentScreen].autoSettingOption);
} else if (currentMenu[currentScreen].incrementHandler != nullptr) {
return currentMenu[currentScreen].incrementHandler();
}
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) {
if (callIncrementHandler()) {
(*autoRepeatTimer) = TICKS_SECOND * 2;
} else {
(*autoRepeatTimer) = 0;
}
(*autoRepeatTimer) += xTaskGetTickCount();
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
}
break;
case BUTTON_F_SHORT:
// Increment setting
if (*isRenderingHelp) {
*isRenderingHelp = 0;
} else {
if (*subEntry == 0) {
// In a root menu, if its null handler we enter the menu
if (currentMenu[currentScreen].incrementHandler != nullptr) {
currentMenu[currentScreen].incrementHandler();
} else {
(*subEntry) += 1;
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;
}

View File

@@ -1,56 +1,78 @@
#include "HUB238.hpp" #include "HUB238.hpp"
#include "OperatingModes.h" #include "OperatingModes.h"
void showWarnings(void) { OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) {
// Display alert if settings were reset // 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 switch (cxt->scratch_state.state1) {
// We also want to alert if accel or pd is not detected / not responding case 0: // Settings reset warning
// In this case though, we dont want to nag the user _too_ much if (settingsWereReset) {
// So only show first 2 times if (warnUser(translatedString(Tr->SettingsResetMessage), buttons)) {
while (DetectedAccelerometerVersion == AccelType::Scanning) { settingsWereReset = false;
osDelay(5); cxt->scratch_state.state1 = 1;
resetWatchdog(); }
}
// Display alert if accelerometer is not detected
if (DetectedAccelerometerVersion == AccelType::None) {
if (getSettingValue(SettingsOptions::AccelMissingWarningCounter) < 2) {
nextSettingValue(SettingsOptions::AccelMissingWarningCounter);
saveSettings();
warnUser(translatedString(Tr->NoAccelerometerMessage), 10 * TICKS_SECOND);
} }
} break;
case 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;
#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) {
nextSettingValue(SettingsOptions::AccelMissingWarningCounter);
saveSettings();
if (warnUser(translatedString(Tr->NoAccelerometerMessage), buttons)) {
cxt->scratch_state.state1 = 3;
}
}
}
break;
case 3:
#ifdef POW_PD #ifdef POW_PD
// We expect pd to be present // We expect pd to be present
resetWatchdog(); if (!USBPowerDelivery::fusbPresent()) {
if (!USBPowerDelivery::fusbPresent()) { if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) {
if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { nextSettingValue(SettingsOptions::PDMissingWarningCounter);
nextSettingValue(SettingsOptions::PDMissingWarningCounter); saveSettings();
saveSettings(); if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) {
warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND); cxt->scratch_state.state1 = 4;
}
}
} }
} #else
#endif /*POW_PD*/
#if POW_PD_EXT == 1 #if POW_PD_EXT == 1
if (!hub238_probe()) { if (!hub238_probe()) {
if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) { if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) {
nextSettingValue(SettingsOptions::PDMissingWarningCounter); nextSettingValue(SettingsOptions::PDMissingWarningCounter);
saveSettings(); saveSettings();
warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND); if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) {
cxt->scratch_state.state1 = 4;
}
}
} }
} #else
cxt->scratch_state.state1 = 4;
#endif /*POW_PD_EXT==1*/ #endif /*POW_PD_EXT==1*/
// If tip looks to be shorted, yell at user and dont auto dismiss #endif /*POW_PD*/
if (isTipShorted()) {
warnUser(translatedString(Tr->WarningTipShorted), portMAX_DELAY); break;
default:
// We are off the end, warnings done
return OperatingMode::InitialisationDone;
} }
#endif /*NO_WARN_MISSING*/
return OperatingMode::StartupWarnings; // Stay in warnings
} }

View File

@@ -1,64 +1,60 @@
#include "OperatingModes.h" #include "OperatingModes.h"
extern OperatingMode currentMode; OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt) {
#ifdef NO_SLEEP_MODE
int gui_SolderingSleepingMode(bool stayOff, bool autoStarted) { return OperatingMode::Soldering;
#ifndef NO_SLEEP_MODE #endif
// Drop to sleep temperature and display until movement or button press // 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
// user moved or pressed a button, go back to soldering // If in the first two seconds we disable this to let accelerometer warm up
// If in the first two seconds we disable this to let accelerometer warm up
#ifdef POW_DC #ifdef POW_DC
if (checkForUnderVoltage()) { if (checkForUnderVoltage()) {
// return non-zero on error return OperatingMode::HomeScreen; // 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;
}
} }
#endif #endif
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();
return 0; 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;
}
return OperatingMode::Sleeping;
} }

View File

@@ -1,10 +1,62 @@
#include "OperatingModes.h" #include "OperatingModes.h"
#include "SolderingCommon.h" #include "SolderingCommon.h"
// State 1 = button locking
// State 2 = boost mode
// State 3 = buzzer timer
extern OperatingMode currentMode; OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) {
if (cxt->scratch_state.state1 == 1) {
void gui_solderingMode(uint8_t jumpToSleep) { // 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) * * Soldering (gui_solderingMode)
* -> Main loop where we draw temp, and animations * -> Main loop where we draw temp, and animations
@@ -19,171 +71,106 @@ void gui_solderingMode(uint8_t jumpToSleep) {
* --> Double button to exit * --> Double button to exit
* --> Long hold double button to toggle key lock * --> Long hold double button to toggle key lock
*/ */
bool boostModeOn = false;
bool buttonsLocked = false;
bool converged = false;
currentMode = OperatingMode::soldering;
TickType_t buzzerEnd = 0; // Update the setpoints for the temperature
if (cxt->scratch_state.state2) {
if (jumpToSleep) { if (getSettingValue(SettingsOptions::TemperatureInF)) {
if (gui_SolderingSleepingMode(jumpToSleep == 2, true) == 1) { currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp));
lastButtonTime = xTaskGetTickCount(); } else {
return; // If the function returns non-0 then exit currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp));
}
} else {
if (getSettingValue(SettingsOptions::TemperatureInF)) {
currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp));
} else {
currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp));
} }
} }
for (;;) {
ButtonState buttons = getButtonState(); // Update status
if (buttonsLocked && (getSettingValue(SettingsOptions::LockingMode) != 0)) { // If buttons locked int error = currentTempTargetDegC - TipThermoModel::getTipInC();
switch (buttons) { if (error >= -10 && error <= 10) {
case BUTTON_NONE: // converged
boostModeOn = false; if (!cxt->scratch_state.state5) {
break; setBuzzer(true);
case BUTTON_BOTH_LONG: cxt->scratch_state.state3 = xTaskGetTickCount() + TICKS_SECOND / 3;
// Unlock buttons cxt->scratch_state.state5 = true;
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;
}
} }
// 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
// Draw in the screen details if (getSettingValue(SettingsOptions::DetailedSoldering)) {
if (getSettingValue(SettingsOptions::DetailedSoldering)) { if (OLED::getRotation()) {
if (OLED::getRotation()) { OLED::setCursor(50, 0);
OLED::setCursor(50, 0); } else {
} else { OLED::setCursor(-1, 0);
OLED::setCursor(-1, 0); }
}
gui_drawTipTemp(true, FontStyle::LARGE); gui_drawTipTemp(true, FontStyle::LARGE);
#ifndef NO_SLEEP_MODE #ifndef NO_SLEEP_MODE
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) { if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
if (OLED::getRotation()) { if (OLED::getRotation()) {
OLED::setCursor(32, 0); OLED::setCursor(32, 0);
} else { } else {
OLED::setCursor(47, 0); OLED::setCursor(47, 0);
}
printCountdownUntilSleep(getSleepTimeout());
} }
printCountdownUntilSleep(getSleepTimeout());
}
#endif #endif
if (boostModeOn) { if (cxt->scratch_state.state2) { // Boost mode is on
if (OLED::getRotation()) { if (OLED::getRotation()) {
OLED::setCursor(38, 8); OLED::setCursor(38, 8);
} else {
OLED::setCursor(55, 8);
}
OLED::print(SmallSymbolPlus, FontStyle::SMALL);
} else { } else {
if (OLED::getRotation()) { OLED::setCursor(55, 8);
OLED::setCursor(32, 8);
} else {
OLED::setCursor(47, 8);
}
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
} }
OLED::print(SmallSymbolPlus, FontStyle::SMALL);
detailedPowerStatus();
} else { } else {
basicSolderingStatus(boostModeOn); if (OLED::getRotation()) {
} OLED::setCursor(32, 8);
OLED::refresh();
// Update the setpoints for the temperature
if (boostModeOn) {
if (getSettingValue(SettingsOptions::TemperatureInF)) {
currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp));
} else { } else {
currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp)); OLED::setCursor(47, 8);
}
} else {
if (getSettingValue(SettingsOptions::TemperatureInF)) {
currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp));
} else {
currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp));
} }
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
} }
if (checkExitSoldering()) { detailedPowerStatus();
setBuzzer(false);
return;
}
// Update status } else {
int error = currentTempTargetDegC - TipThermoModel::getTipInC(); basicSolderingStatus(cxt->scratch_state.state2);
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();
} }
// 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);
} }

View File

@@ -2,222 +2,212 @@
#include "OperatingModes.h" #include "OperatingModes.h"
#include "SolderingCommon.h" #include "SolderingCommon.h"
extern OperatingMode currentMode; OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt) {
void gui_solderingProfileMode() {
/* /*
* * Soldering (gui_solderingMode) * * Soldering
* -> Main loop where we draw temp, and animations * -> Main loop where we draw temp, and animations
* PID control
* --> Long hold back button to exit * --> Long hold back button to exit
* --> Double button to exit * --> Double button to exit
*/ */
currentMode = OperatingMode::soldering;
TickType_t buzzerEnd = 0; uint16_t tipTemp = 0;
bool waitForRelease = true; // If this is during init, start at preheat
TickType_t phaseStartTime = xTaskGetTickCount(); if (cxt->scratch_state.state1 == 0) {
cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePreheatTemp);
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);
uint16_t phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfilePreheatSpeed); uint16_t phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfilePreheatSpeed);
uint16_t profileCurrentTargetTemp = 0; uint16_t profileCurrentTargetTemp = 0;
for (;;) { switch (buttons) {
ButtonState buttons = getButtonState(); case BUTTON_BOTH:
if (buttons) { case BUTTON_B_LONG:
if (waitForRelease) { cxt->transitionMode = TransitionAnimation::Right;
buttons = BUTTON_NONE; return OperatingMode::HomeScreen; // exit on back long hold
} case BUTTON_F_LONG:
} else { case BUTTON_F_SHORT:
waitForRelease = false; case BUTTON_B_SHORT:
} case BUTTON_NONE:
// Not used yet
switch (buttons) { break;
case BUTTON_NONE: default:
break; 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();
} }
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;
} }

View File

@@ -1,120 +1,104 @@
#include "OperatingModes.h" #include "OperatingModes.h"
void gui_solderingTempAdjust(void) { OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cxt) {
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();
if (buttons != BUTTON_NONE) { currentTempTargetDegC = 0; // Turn off heater while adjusting temp
// Temp adjust entered by long-pressing F button. uint16_t *waitForRelease = &(cxt->scratch_state.state1);
waitForRelease = true; 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::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;
if (getSettingValue(SettingsOptions::TemperatureInF)) { int16_t delta = 0;
if (newTemp > MAX_TEMP_F) { switch (buttons) {
newTemp = MAX_TEMP_F; case BUTTON_NONE:
} // stay
if (newTemp < MIN_TEMP_F) { (*autoRepeatAcceleration) = 0;
newTemp = MIN_TEMP_F; break;
} case BUTTON_BOTH:
} else { // exit
if (newTemp > MAX_TEMP_C) { cxt->transitionMode = TransitionAnimation::Right;
newTemp = MAX_TEMP_C; return cxt->previousMode;
} case BUTTON_B_LONG:
if (newTemp < MIN_TEMP_C) { if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) {
newTemp = MIN_TEMP_C; delta = -getSettingValue(SettingsOptions::TempChangeLongStep);
} (*autoRepeatTimer) = xTaskGetTickCount();
} (*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp);
} }
if (xTaskGetTickCount() - lastChange > (TICKS_SECOND * 2)) { break;
return; // exit if user just doesn't press anything for a bit 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;
if (OLED::getRotation()) { case BUTTON_F_SHORT:
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE); delta = getSettingValue(SettingsOptions::TempChangeShortStep);
} else { break;
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE); default:
} break;
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();
} }
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 (xTaskGetTickCount() - lastButtonTime > (TICKS_SECOND * 3)) {
cxt->transitionMode = TransitionAnimation::Right;
return cxt->previousMode; // exit if user just doesn't press anything for a bit
}
if (OLED::getRotation()) {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
} else {
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);
}
return OperatingMode::TemperatureAdjust; // Stay in temp adjust
} }

View File

@@ -2,93 +2,85 @@
#ifdef POW_PD #ifdef POW_PD
#ifdef HAS_POWER_DEBUG_MENU #ifdef HAS_POWER_DEBUG_MENU
void showPDDebug(void) { OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
// Print out the USB-PD state // Print out the USB-PD state
// Basically this is like the Debug menu, but instead we want to print out the PD status // Basically this is like the Debug menu, but instead we want to print out the PD status
uint8_t screen = 0; uint16_t *screen = &(cxt->scratch_state.state1);
ButtonState b; OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
for (;;) { OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::clearScreen(); // Ensure the buffer starts clean OLED::setCursor(0, 8); // second line
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) if ((*screen) == 0) {
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title // Print the PD state machine
OLED::setCursor(0, 8); // second line OLED::print(SmallSymbolState, FontStyle::SMALL);
if (screen == 0) { OLED::print(SmallSymbolSpace, FontStyle::SMALL);
// Print the PD state machine OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolState, FontStyle::SMALL); OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL); // Also print vbus mod status
OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true); if (USBPowerDelivery::fusbPresent()) {
OLED::print(SmallSymbolSpace, FontStyle::SMALL); if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) {
// Also print vbus mod status if (!USBPowerDelivery::isVBUSConnected()) {
if (USBPowerDelivery::fusbPresent()) { OLED::print(SmallSymbolNoVBus, FontStyle::SMALL);
if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) { } else {
if (!USBPowerDelivery::isVBUSConnected()) { OLED::print(SmallSymbolVBus, FontStyle::SMALL);
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 { } else {
// Print out the Proposed power options one by one (*screen) = 0;
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;
}
} }
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
#endif #endif

View File

@@ -2,7 +2,7 @@
#include "OperatingModes.h" #include "OperatingModes.h"
#if POW_PD_EXT == 1 #if POW_PD_EXT == 1
#ifdef HAS_POWER_DEBUG_MENU #ifdef HAS_POWER_DEBUG_MENU
void showPDDebug(void) { OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
// Print out the USB-PD state // Print out the USB-PD state
// Basically this is like the Debug menu, but instead we want to print out the PD status // Basically this is like the Debug menu, but instead we want to print out the PD status
uint8_t screen = 0; uint8_t screen = 0;
@@ -44,13 +44,14 @@ void showPDDebug(void) {
OLED::refresh(); OLED::refresh();
b = getButtonState(); b = getButtonState();
if (b == BUTTON_B_SHORT) { if (b == BUTTON_B_SHORT) {
return; return OperatingMode::InitialisationDone;
} else if (b == BUTTON_F_SHORT) { } else if (b == BUTTON_F_SHORT) {
screen++; screen++;
} }
GUIDelay(); GUIDelay();
} }
return OperatingMode::UsbPDDebug;
} }
#endif #endif
#endif #endif

View File

@@ -1,5 +1,6 @@
#include "OperatingModeUtilities.h" #include "OperatingModeUtilities.h"
#include "OperatingModes.h" #include "OperatingModes.h"
#include "SolderingCommon.h"
#include "TipThermoModel.h" #include "TipThermoModel.h"
void gui_drawTipTemp(bool symbol, const FontStyle font) { void gui_drawTipTemp(bool symbol, const FontStyle font) {

View File

@@ -1,18 +1,19 @@
#ifndef OPERATING_MODE_UTILITIES_H_ #ifndef OPERATING_MODE_UTILITIES_H_
#define OPERATING_MODE_UTILITIES_H_ #define OPERATING_MODE_UTILITIES_H_
#include "Buttons.hpp"
#include "OLED.hpp" #include "OLED.hpp"
#include <stdbool.h> #include <stdbool.h>
void GUIDelay(); // void GUIDelay(); //
bool checkForUnderVoltage(void); // bool checkForUnderVoltage(void); //
uint32_t getSleepTimeout(void); // uint32_t getSleepTimeout(void); //
bool shouldBeSleeping(bool inAutoStart); // bool shouldBeSleeping(); //
bool shouldShutdown(void); // bool shouldShutdown(void); //
void gui_drawTipTemp(bool symbol, const FontStyle font); // void gui_drawTipTemp(bool symbol, const FontStyle font); //
void printVoltage(void); // void printVoltage(void); //
void warnUser(const char *warning, const TickType_t timeout); // bool warnUser(const char *warning, const ButtonState buttons); //
void gui_drawBatteryIcon(void); // void gui_drawBatteryIcon(void); //
bool checkForUnderVoltage(void); // bool checkForUnderVoltage(void); //
uint16_t min(uint16_t a, uint16_t b); // uint16_t min(uint16_t a, uint16_t b); //
void printCountdownUntilSleep(int sleepThres); // void printCountdownUntilSleep(int sleepThres); //
#endif #endif

View File

@@ -1,8 +1,9 @@
#include "Buttons.hpp" #include "Buttons.hpp"
#include "OperatingModeUtilities.h" #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::clearScreen();
OLED::printWholeScreen(warning); OLED::printWholeScreen(warning);
OLED::refresh(); // TODO also timeout
waitForButtonPressOrTimeout(timeout); return buttons != BUTTON_NONE;
} }

View File

@@ -106,30 +106,8 @@ bool checkExitSoldering(void) {
} }
} }
#endif #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 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; return false;
} }

View File

@@ -1,8 +1,10 @@
#ifndef SOLDERING_COMMON_H #ifndef SOLDERING_COMMON_H
#define SOLDERING_COMMON_H #define SOLDERING_COMMON_H
#include <stdint.h>
void detailedPowerStatus(); void detailedPowerStatus();
void basicSolderingStatus(bool boostModeOn); void basicSolderingStatus(bool boostModeOn);
bool checkExitSoldering(); bool checkExitSoldering();
uint16_t getTipTemp(void);
#endif //SOLDERING_COMMON_H #endif // SOLDERING_COMMON_H

View File

@@ -4,15 +4,13 @@
TickType_t lastHallEffectSleepStart = 0; TickType_t lastHallEffectSleepStart = 0;
extern TickType_t lastMovementTime; extern TickType_t lastMovementTime;
bool shouldBeSleeping(bool inAutoStart) { bool shouldBeSleeping() {
#ifndef NO_SLEEP_MODE #ifndef NO_SLEEP_MODE
// Return true if the iron should be in sleep mode // Return true if the iron should be in sleep mode
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) { if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
if (inAutoStart) { // In auto start we are asleep until movement
// In auto start we are asleep until movement if (lastMovementTime == 0 && lastButtonTime == 0) {
if (lastMovementTime == 0 && lastButtonTime == 0) { return true;
return true;
}
} }
if (lastMovementTime > 0 || lastButtonTime > 0) { if (lastMovementTime > 0 || lastButtonTime > 0) {
if (((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout()) && ((xTaskGetTickCount() - lastButtonTime) > getSleepTimeout())) { if (((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout()) && ((xTaskGetTickCount() - lastButtonTime) > getSleepTimeout())) {