Beginnings of the shuffle
This commit is contained in:
19
workspace/TS100/Core/BSP/Defines.h
Normal file
19
workspace/TS100/Core/BSP/Defines.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Defines.h
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BSP_DEFINES_H_
|
||||||
|
#define BSP_DEFINES_H_
|
||||||
|
|
||||||
|
|
||||||
|
enum Orientation {
|
||||||
|
ORIENTATION_LEFT_HAND = 0, ORIENTATION_RIGHT_HAND = 1, ORIENTATION_FLAT = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
//It is assumed that all hardware implements an 8Hz update period at this time
|
||||||
|
#define PID_TIM_HZ (8)
|
||||||
|
|
||||||
|
#endif /* BSP_DEFINES_H_ */
|
||||||
212
workspace/TS100/Core/BSP/Miniware/BSP.cpp
Normal file
212
workspace/TS100/Core/BSP/Miniware/BSP.cpp
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
//BSP mapping functions
|
||||||
|
|
||||||
|
#include "BSP.h"
|
||||||
|
#include "Setup.h"
|
||||||
|
#include "history.hpp"
|
||||||
|
#include "Pins.h"
|
||||||
|
#include "history.hpp"
|
||||||
|
volatile uint16_t PWMSafetyTimer = 0;
|
||||||
|
volatile uint8_t pendingPWM = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//2 second filter (ADC is PID_TIM_HZ Hz)
|
||||||
|
history<uint16_t, PID_TIM_HZ> rawTempFilter = { { 0 }, 0, 0 };
|
||||||
|
void resetWatchdog() {
|
||||||
|
HAL_IWDG_Refresh(&hiwdg);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getHandleTemperature() {
|
||||||
|
// We return the current handle temperature in X10 C
|
||||||
|
// TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for
|
||||||
|
// example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) =
|
||||||
|
// 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125
|
||||||
|
// mV per count So we need to subtract an offset of 0.5V to center on 0C
|
||||||
|
// (4964.8 counts)
|
||||||
|
//
|
||||||
|
int32_t result = getADC(0);
|
||||||
|
result -= 4965; // remove 0.5V offset
|
||||||
|
// 10mV per C
|
||||||
|
// 99.29 counts per Deg C above 0C
|
||||||
|
result *= 100;
|
||||||
|
result /= 993;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getTipInstantTemperature() {
|
||||||
|
uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits
|
||||||
|
uint16_t readings[8];
|
||||||
|
//Looking to reject the highest outlier readings.
|
||||||
|
//As on some hardware these samples can run into the op-amp recovery time
|
||||||
|
//Once this time is up the signal stabilises quickly, so no need to reject minimums
|
||||||
|
readings[0] = hadc1.Instance->JDR1;
|
||||||
|
readings[1] = hadc1.Instance->JDR2;
|
||||||
|
readings[2] = hadc1.Instance->JDR3;
|
||||||
|
readings[3] = hadc1.Instance->JDR4;
|
||||||
|
readings[4] = hadc2.Instance->JDR1;
|
||||||
|
readings[5] = hadc2.Instance->JDR2;
|
||||||
|
readings[6] = hadc2.Instance->JDR3;
|
||||||
|
readings[7] = hadc2.Instance->JDR4;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
sum += readings[i];
|
||||||
|
}
|
||||||
|
return sum; // 8x over sample
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getTipRawTemp(uint8_t refresh) {
|
||||||
|
if (refresh) {
|
||||||
|
uint16_t lastSample = getTipInstantTemperature();
|
||||||
|
rawTempFilter.update(lastSample);
|
||||||
|
return lastSample;
|
||||||
|
} else {
|
||||||
|
return rawTempFilter.average();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
|
||||||
|
// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN
|
||||||
|
// Therefore we can divide down from there
|
||||||
|
// Multiplying ADC max by 4 for additional calibration options,
|
||||||
|
// ideal term is 467
|
||||||
|
#ifdef MODEL_TS100
|
||||||
|
#define BATTFILTERDEPTH 32
|
||||||
|
#else
|
||||||
|
#define BATTFILTERDEPTH 8
|
||||||
|
|
||||||
|
#endif
|
||||||
|
static uint8_t preFillneeded = 10;
|
||||||
|
static uint32_t samples[BATTFILTERDEPTH];
|
||||||
|
static uint8_t index = 0;
|
||||||
|
if (preFillneeded) {
|
||||||
|
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
|
||||||
|
samples[i] = getADC(1);
|
||||||
|
preFillneeded--;
|
||||||
|
}
|
||||||
|
if (sample) {
|
||||||
|
samples[index] = getADC(1);
|
||||||
|
index = (index + 1) % BATTFILTERDEPTH;
|
||||||
|
}
|
||||||
|
uint32_t sum = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
|
||||||
|
sum += samples[i];
|
||||||
|
|
||||||
|
sum /= BATTFILTERDEPTH;
|
||||||
|
return sum * 4 / divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTipPWM(uint8_t pulse) {
|
||||||
|
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
||||||
|
// disabled if the PID task is not scheduled often enough.
|
||||||
|
|
||||||
|
pendingPWM = pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are called by the HAL after the corresponding events from the system
|
||||||
|
// timers.
|
||||||
|
|
||||||
|
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
|
||||||
|
// Period has elapsed
|
||||||
|
if (htim->Instance == TIM2) {
|
||||||
|
// we want to turn on the output again
|
||||||
|
PWMSafetyTimer--;
|
||||||
|
// We decrement this safety value so that lockups in the
|
||||||
|
// scheduler will not cause the PWM to become locked in an
|
||||||
|
// active driving state.
|
||||||
|
// While we could assume this could never happen, its a small price for
|
||||||
|
// increased safety
|
||||||
|
htim2.Instance->CCR4 = pendingPWM;
|
||||||
|
if (htim2.Instance->CCR4 && PWMSafetyTimer) {
|
||||||
|
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
|
||||||
|
} else {
|
||||||
|
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
|
||||||
|
}
|
||||||
|
} else if (htim->Instance == TIM1) {
|
||||||
|
// STM uses this for internal functions as a counter for timeouts
|
||||||
|
HAL_IncTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
|
||||||
|
// This was a when the PWM for the output has timed out
|
||||||
|
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) {
|
||||||
|
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void unstick_I2C() {
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
|
int timeout = 100;
|
||||||
|
int timeout_cnt = 0;
|
||||||
|
|
||||||
|
// 1. Clear PE bit.
|
||||||
|
hi2c1.Instance->CR1 &= ~(0x0001);
|
||||||
|
/**I2C1 GPIO Configuration
|
||||||
|
PB6 ------> I2C1_SCL
|
||||||
|
PB7 ------> I2C1_SDA
|
||||||
|
*/
|
||||||
|
// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||||
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
|
|
||||||
|
GPIO_InitStruct.Pin = SCL_Pin;
|
||||||
|
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
|
||||||
|
|
||||||
|
GPIO_InitStruct.Pin = SDA_Pin;
|
||||||
|
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
|
||||||
|
|
||||||
|
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) {
|
||||||
|
//Move clock to release I2C
|
||||||
|
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
asm("nop");
|
||||||
|
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
|
||||||
|
|
||||||
|
timeout_cnt++;
|
||||||
|
if (timeout_cnt > timeout)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||||
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
|
|
||||||
|
GPIO_InitStruct.Pin = SCL_Pin;
|
||||||
|
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
GPIO_InitStruct.Pin = SDA_Pin;
|
||||||
|
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
|
||||||
|
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
|
||||||
|
|
||||||
|
// 13. Set SWRST bit in I2Cx_CR1 register.
|
||||||
|
hi2c1.Instance->CR1 |= 0x8000;
|
||||||
|
|
||||||
|
asm("nop");
|
||||||
|
|
||||||
|
// 14. Clear SWRST bit in I2Cx_CR1 register.
|
||||||
|
hi2c1.Instance->CR1 &= ~0x8000;
|
||||||
|
|
||||||
|
asm("nop");
|
||||||
|
|
||||||
|
// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
|
||||||
|
hi2c1.Instance->CR1 |= 0x0001;
|
||||||
|
|
||||||
|
// Call initialization function.
|
||||||
|
HAL_I2C_Init(&hi2c1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getButtonA() {
|
||||||
|
return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ?
|
||||||
|
1 : 0;
|
||||||
|
}
|
||||||
|
uint8_t getButtonB() {
|
||||||
|
return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ?
|
||||||
|
1 : 0;
|
||||||
|
}
|
||||||
@@ -1,27 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Hardware.h
|
* Pins.h
|
||||||
*
|
*
|
||||||
* Created on: 29Aug.,2017
|
* Created on: 29 May 2020
|
||||||
* Author: Ben V. Brown
|
* Author: Ralim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HARDWARE_H_
|
#ifndef BSP_MINIWARE_PINS_H_
|
||||||
#define HARDWARE_H_
|
#define BSP_MINIWARE_PINS_H_
|
||||||
#include "Setup.h"
|
|
||||||
#include "stm32f1xx_hal.h"
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "stm32f1xx_hal.h"
|
|
||||||
#include "cmsis_os.h"
|
|
||||||
#include "unit.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum Orientation {
|
|
||||||
ORIENTATION_LEFT_HAND = 0, ORIENTATION_RIGHT_HAND = 1, ORIENTATION_FLAT = 3
|
|
||||||
};
|
|
||||||
#define PID_TIM_HZ (8)
|
|
||||||
#if defined(MODEL_TS100) + defined(MODEL_TS80) > 1
|
#if defined(MODEL_TS100) + defined(MODEL_TS80) > 1
|
||||||
#error "Multiple models defined!"
|
#error "Multiple models defined!"
|
||||||
#elif defined(MODEL_TS100) + defined(MODEL_TS80) == 0
|
#elif defined(MODEL_TS100) + defined(MODEL_TS80) == 0
|
||||||
@@ -94,55 +80,4 @@ enum Orientation {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
#endif /* BSP_MINIWARE_PINS_H_ */
|
||||||
* Keep in a uint8_t range for the ID's
|
|
||||||
*/
|
|
||||||
#ifdef MODEL_TS100
|
|
||||||
enum TipType {
|
|
||||||
TS_B2 = 0,
|
|
||||||
TS_D24 = 1,
|
|
||||||
TS_BC2 = 2,
|
|
||||||
TS_C1 = 3,
|
|
||||||
Tip_MiniWare = 4,
|
|
||||||
HAKKO_BC2 = 4,
|
|
||||||
Tip_Hakko = 5,
|
|
||||||
Tip_Custom = 5,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
#ifdef MODEL_TS80
|
|
||||||
enum TipType {
|
|
||||||
TS_B02 = 0, TS_D25 = 1, Tip_MiniWare = 2, Tip_Custom = 3,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
extern uint16_t tipGainCalValue ;
|
|
||||||
|
|
||||||
uint16_t lookupTipDefaultCalValue(enum TipType tipID);
|
|
||||||
uint16_t getHandleTemperature();
|
|
||||||
uint16_t getTipRawTemp(uint8_t refresh);
|
|
||||||
uint16_t getInputVoltageX10(uint16_t divisor,uint8_t sample);
|
|
||||||
|
|
||||||
void setTipPWM(uint8_t pulse);
|
|
||||||
uint16_t ctoTipMeasurement(uint16_t temp);
|
|
||||||
uint16_t tipMeasurementToC(uint16_t raw);
|
|
||||||
uint16_t ftoTipMeasurement(uint16_t temp);
|
|
||||||
#ifdef ENABLED_FAHRENHEIT_SUPPORT
|
|
||||||
uint16_t tipMeasurementToF(uint16_t raw);
|
|
||||||
#endif
|
|
||||||
void seekQC(int16_t Vx10, uint16_t divisor);
|
|
||||||
void setCalibrationOffset(int16_t offSet);
|
|
||||||
void setTipType(enum TipType tipType, uint8_t manualCalGain);
|
|
||||||
uint32_t calculateTipR();
|
|
||||||
int16_t calculateMaxVoltage(uint8_t useHP);
|
|
||||||
void startQC(uint16_t divisor); // Tries to negotiate QC for highest voltage, must be run after
|
|
||||||
// RToS
|
|
||||||
// This will try for 12V, failing that 9V, failing that 5V
|
|
||||||
// If input is over 12V returns -1
|
|
||||||
// If the input is [5-12] Will return the value.
|
|
||||||
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
|
|
||||||
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) ;
|
|
||||||
void vApplicationIdleHook(void);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HARDWARE_H_ */
|
|
||||||
18
workspace/TS100/Core/BSP/Miniware/UnitSettings.h
Normal file
18
workspace/TS100/Core/BSP/Miniware/UnitSettings.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* UnitSettings.h
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BSP_MINIWARE_UNITSETTINGS_H_
|
||||||
|
#define BSP_MINIWARE_UNITSETTINGS_H_
|
||||||
|
//On the TS80, the LIS accel is mounted backwards
|
||||||
|
#ifdef MODEL_TS80
|
||||||
|
#define LIS_ORI_FLIP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* BSP_MINIWARE_UNITSETTINGS_H_ */
|
||||||
35
workspace/TS100/Core/Inc/Buttons.hpp
Normal file
35
workspace/TS100/Core/Inc/Buttons.hpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Buttons.h
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
#include "BSP.h"
|
||||||
|
#ifndef INC_BUTTONS_H_
|
||||||
|
#define INC_BUTTONS_H_
|
||||||
|
|
||||||
|
extern uint32_t lastButtonTime;
|
||||||
|
|
||||||
|
enum ButtonState {
|
||||||
|
BUTTON_NONE = 0, /* No buttons pressed / < filter time*/
|
||||||
|
BUTTON_F_SHORT = 1, /* User has pressed the front button*/
|
||||||
|
BUTTON_B_SHORT = 2, /* User has pressed the back button*/
|
||||||
|
BUTTON_F_LONG = 4, /* User is holding the front button*/
|
||||||
|
BUTTON_B_LONG = 8, /* User is holding the back button*/
|
||||||
|
BUTTON_BOTH = 16, /* User has pressed both buttons*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note:
|
||||||
|
* Pressed means press + release, we trigger on a full \__/ pulse
|
||||||
|
* holding means it has gone low, and been low for longer than filter time
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
//Returns what buttons are pressed (if any)
|
||||||
|
ButtonState getButtonState();
|
||||||
|
//Helpers
|
||||||
|
void waitForButtonPressOrTimeout(uint32_t timeout);
|
||||||
|
void waitForButtonPress();
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* INC_BUTTONS_H_ */
|
||||||
@@ -25,10 +25,12 @@ public:
|
|||||||
|
|
||||||
static void CpltCallback(); //Normal Tx Callback
|
static void CpltCallback(); //Normal Tx Callback
|
||||||
|
|
||||||
static void Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
|
static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
|
||||||
uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
||||||
static void Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
|
static void Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
|
||||||
uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
||||||
|
//Returns true if device ACK's being addressed
|
||||||
|
static bool probe(uint16_t DevAddress);
|
||||||
|
|
||||||
static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
|
static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
|
||||||
static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data);
|
static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data);
|
||||||
|
|||||||
28
workspace/TS100/Core/Inc/FreeRTOSHooks.h
Normal file
28
workspace/TS100/Core/Inc/FreeRTOSHooks.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOSHooks.h
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOSHOOKS_H_
|
||||||
|
#define INC_FREERTOSHOOKS_H_
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "cmsis_os.h"
|
||||||
|
#include "unit.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// RToS
|
||||||
|
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||||
|
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize);
|
||||||
|
void vApplicationIdleHook(void);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* INC_FREERTOSHOOKS_H_ */
|
||||||
@@ -10,11 +10,8 @@
|
|||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
#include "FRToSI2C.hpp"
|
#include "FRToSI2C.hpp"
|
||||||
#include "LIS2DH12_defines.hpp"
|
#include "LIS2DH12_defines.hpp"
|
||||||
#include "hardware.h"
|
#include "BSP.h"
|
||||||
|
|
||||||
#ifdef MODEL_TS80
|
|
||||||
#define LIS_ORI_FLIP
|
|
||||||
#endif
|
|
||||||
class LIS2DH12 {
|
class LIS2DH12 {
|
||||||
public:
|
public:
|
||||||
static bool detect();
|
static bool detect();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
#include "MMA8652FC_defines.h"
|
#include "MMA8652FC_defines.h"
|
||||||
#include "FRToSI2C.hpp"
|
#include "FRToSI2C.hpp"
|
||||||
#include "hardware.h"
|
#include "BSP.h"
|
||||||
|
|
||||||
class MMA8652FC {
|
class MMA8652FC {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#ifndef OLED_HPP_
|
#ifndef OLED_HPP_
|
||||||
#define OLED_HPP_
|
#define OLED_HPP_
|
||||||
#include <hardware.h>
|
#include <BSP.h>
|
||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
21
workspace/TS100/Core/Inc/QC3.h
Normal file
21
workspace/TS100/Core/Inc/QC3.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* QC3.h
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_QC3_H_
|
||||||
|
#define INC_QC3_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void seekQC(int16_t Vx10, uint16_t divisor);
|
||||||
|
void startQC(uint16_t divisor); // Tries to negotiate QC for highest voltage, must be run after
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* INC_QC3_H_ */
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef SRC_TIPTHERMOMODEL_H_
|
#ifndef SRC_TIPTHERMOMODEL_H_
|
||||||
#define SRC_TIPTHERMOMODEL_H_
|
#define SRC_TIPTHERMOMODEL_H_
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "hardware.h"
|
#include "BSP.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
class TipThermoModel {
|
class TipThermoModel {
|
||||||
public:
|
public:
|
||||||
@@ -9,13 +9,12 @@
|
|||||||
#define GUI_HPP_
|
#define GUI_HPP_
|
||||||
#include "Translation.h"
|
#include "Translation.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "hardware.h"
|
#include "BSP.h"
|
||||||
|
|
||||||
#define PRESS_ACCEL_STEP 3
|
#define PRESS_ACCEL_STEP 3
|
||||||
#define PRESS_ACCEL_INTERVAL_MIN 10
|
#define PRESS_ACCEL_INTERVAL_MIN 10
|
||||||
#define PRESS_ACCEL_INTERVAL_MAX 30
|
#define PRESS_ACCEL_INTERVAL_MAX 30
|
||||||
|
|
||||||
|
|
||||||
//GUI holds the menu structure and all its methods for the menu itself
|
//GUI holds the menu structure and all its methods for the menu itself
|
||||||
|
|
||||||
//Declarations for all the methods for the settings menu (at end of this file)
|
//Declarations for all the methods for the settings menu (at end of this file)
|
||||||
@@ -33,6 +32,7 @@ typedef struct {
|
|||||||
} menuitem;
|
} menuitem;
|
||||||
|
|
||||||
void enterSettingsMenu();
|
void enterSettingsMenu();
|
||||||
|
void GUIDelay();
|
||||||
extern const menuitem rootSettingsMenu[];
|
extern const menuitem rootSettingsMenu[];
|
||||||
|
|
||||||
#endif /* GUI_HPP_ */
|
#endif /* GUI_HPP_ */
|
||||||
|
|||||||
@@ -7,25 +7,7 @@
|
|||||||
extern uint8_t PCBVersion;
|
extern uint8_t PCBVersion;
|
||||||
extern uint32_t currentTempTargetDegC;
|
extern uint32_t currentTempTargetDegC;
|
||||||
extern bool settingsWereReset;
|
extern bool settingsWereReset;
|
||||||
enum ButtonState {
|
|
||||||
BUTTON_NONE = 0, /* No buttons pressed / < filter time*/
|
|
||||||
BUTTON_F_SHORT = 1, /* User has pressed the front button*/
|
|
||||||
BUTTON_B_SHORT = 2, /* User has pressed the back button*/
|
|
||||||
BUTTON_F_LONG = 4, /* User is holding the front button*/
|
|
||||||
BUTTON_B_LONG = 8, /* User is holding the back button*/
|
|
||||||
BUTTON_BOTH = 16, /* User has pressed both buttons*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note:
|
|
||||||
* Pressed means press + release, we trigger on a full \__/ pulse
|
|
||||||
* holding means it has gone low, and been low for longer than filter time
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
ButtonState getButtonState();
|
|
||||||
void waitForButtonPressOrTimeout(uint32_t timeout);
|
|
||||||
void waitForButtonPress();
|
|
||||||
void GUIDelay();
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include <history.hpp>
|
#include <history.hpp>
|
||||||
#include "hardware.h"
|
#include "BSP.h"
|
||||||
#include "expMovingAverage.h"
|
#include "expMovingAverage.h"
|
||||||
#ifndef POWER_HPP_
|
#ifndef POWER_HPP_
|
||||||
#define POWER_HPP_
|
#define POWER_HPP_
|
||||||
|
|||||||
115
workspace/TS100/Core/Src/Buttons.cpp
Normal file
115
workspace/TS100/Core/Src/Buttons.cpp
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Buttons.c
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
#include <Buttons.hpp>
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "gui.hpp"
|
||||||
|
uint32_t lastButtonTime = 0;
|
||||||
|
|
||||||
|
ButtonState getButtonState() {
|
||||||
|
/*
|
||||||
|
* Read in the buttons and then determine if a state change needs to occur
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the previous state was 00 Then we want to latch the new state if
|
||||||
|
* different & update time
|
||||||
|
* If the previous state was !00 Then we want to search if we trigger long
|
||||||
|
* press (buttons still down), or if release we trigger press
|
||||||
|
* (downtime>filter)
|
||||||
|
*/
|
||||||
|
static uint8_t previousState = 0;
|
||||||
|
static uint32_t previousStateChange = 0;
|
||||||
|
const uint16_t timeout = 40;
|
||||||
|
uint8_t currentState;
|
||||||
|
currentState = (getButtonA()) << 0;
|
||||||
|
currentState |= (getButtonB()) << 1;
|
||||||
|
|
||||||
|
if (currentState)
|
||||||
|
lastButtonTime = xTaskGetTickCount();
|
||||||
|
if (currentState == previousState) {
|
||||||
|
if (currentState == 0)
|
||||||
|
return BUTTON_NONE;
|
||||||
|
if ((xTaskGetTickCount() - previousStateChange) > timeout) {
|
||||||
|
// User has been holding the button down
|
||||||
|
// We want to send a button is held message
|
||||||
|
if (currentState == 0x01)
|
||||||
|
return BUTTON_F_LONG;
|
||||||
|
else if (currentState == 0x02)
|
||||||
|
return BUTTON_B_LONG;
|
||||||
|
else
|
||||||
|
return BUTTON_NONE; // Both being held case, we dont long hold this
|
||||||
|
} else
|
||||||
|
return BUTTON_NONE;
|
||||||
|
} else {
|
||||||
|
// A change in button state has occurred
|
||||||
|
ButtonState retVal = BUTTON_NONE;
|
||||||
|
if (currentState) {
|
||||||
|
// User has pressed a button down (nothing done on down)
|
||||||
|
if (currentState != previousState) {
|
||||||
|
// There has been a change in the button states
|
||||||
|
// If there is a rising edge on one of the buttons from double press we
|
||||||
|
// want to mask that out As users are having issues with not release
|
||||||
|
// both at once
|
||||||
|
if (previousState == 0x03)
|
||||||
|
currentState = 0x03;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// User has released buttons
|
||||||
|
// If they previously had the buttons down we want to check if they were <
|
||||||
|
// long hold and trigger a press
|
||||||
|
if ((xTaskGetTickCount() - previousStateChange) < timeout) {
|
||||||
|
// The user didn't hold the button for long
|
||||||
|
// So we send button press
|
||||||
|
|
||||||
|
if (previousState == 0x01)
|
||||||
|
retVal = BUTTON_F_SHORT;
|
||||||
|
else if (previousState == 0x02)
|
||||||
|
retVal = BUTTON_B_SHORT;
|
||||||
|
else
|
||||||
|
retVal = BUTTON_BOTH; // Both being held case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previousState = currentState;
|
||||||
|
previousStateChange = xTaskGetTickCount();
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
return BUTTON_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitForButtonPress() {
|
||||||
|
// we are just lazy and sleep until user confirms button press
|
||||||
|
// This also eats the button press event!
|
||||||
|
ButtonState buttons = getButtonState();
|
||||||
|
while (buttons) {
|
||||||
|
buttons = getButtonState();
|
||||||
|
GUIDelay();
|
||||||
|
}
|
||||||
|
while (!buttons) {
|
||||||
|
buttons = getButtonState();
|
||||||
|
GUIDelay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitForButtonPressOrTimeout(uint32_t timeout) {
|
||||||
|
timeout += xTaskGetTickCount();
|
||||||
|
// calculate the exit point
|
||||||
|
|
||||||
|
ButtonState buttons = getButtonState();
|
||||||
|
while (buttons) {
|
||||||
|
buttons = getButtonState();
|
||||||
|
GUIDelay();
|
||||||
|
if (xTaskGetTickCount() > timeout)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (!buttons) {
|
||||||
|
buttons = getButtonState();
|
||||||
|
GUIDelay();
|
||||||
|
if (xTaskGetTickCount() > timeout)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
* Created on: 14Apr.,2018
|
* Created on: 14Apr.,2018
|
||||||
* Author: Ralim
|
* Author: Ralim
|
||||||
*/
|
*/
|
||||||
#include "hardware.h"
|
#include "BSP.h"
|
||||||
#include "FRToSI2C.hpp"
|
#include "FRToSI2C.hpp"
|
||||||
#define I2CUSESDMA
|
#define I2CUSESDMA
|
||||||
I2C_HandleTypeDef *FRToSI2C::i2c;
|
I2C_HandleTypeDef *FRToSI2C::i2c;
|
||||||
@@ -18,13 +18,14 @@ void FRToSI2C::CpltCallback() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
|
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
|
||||||
uint16_t MemAddSize, uint8_t *pData, uint16_t Size) {
|
uint16_t MemAddSize, uint8_t *pData, uint16_t Size) {
|
||||||
|
|
||||||
if (I2CSemaphore == NULL) {
|
if (I2CSemaphore == NULL) {
|
||||||
// no RToS, run blocking code
|
// no RToS, run blocking code
|
||||||
HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size,
|
HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size,
|
||||||
5000);
|
5000);
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// RToS is active, run threading
|
// RToS is active, run threading
|
||||||
// Get the mutex so we can use the I2C port
|
// Get the mutex so we can use the I2C port
|
||||||
@@ -36,15 +37,23 @@ void FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
|
|||||||
|
|
||||||
I2C1_ClearBusyFlagErratum();
|
I2C1_ClearBusyFlagErratum();
|
||||||
xSemaphoreGive(I2CSemaphore);
|
xSemaphoreGive(I2CSemaphore);
|
||||||
}
|
return false;
|
||||||
|
} else {
|
||||||
xSemaphoreGive(I2CSemaphore);
|
xSemaphoreGive(I2CSemaphore);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size,
|
if (HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size,
|
||||||
5000);
|
5000)==HAL_OK){
|
||||||
xSemaphoreGive(I2CSemaphore);
|
xSemaphoreGive(I2CSemaphore);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
xSemaphoreGive(I2CSemaphore);
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,71 +128,15 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t* pData, uint16_t Size) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FRToSI2C::probe(uint16_t DevAddress) {
|
||||||
|
uint8_t buffer[1];
|
||||||
|
if (Mem_Read(DevAddress, 0, I2C_MEMADD_SIZE_8BIT, buffer, 1)) {
|
||||||
|
//ACK'd
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void FRToSI2C::I2C1_ClearBusyFlagErratum() {
|
void FRToSI2C::I2C1_ClearBusyFlagErratum() {
|
||||||
GPIO_InitTypeDef GPIO_InitStruct;
|
unstick_I2C();
|
||||||
int timeout = 100;
|
|
||||||
int timeout_cnt = 0;
|
|
||||||
|
|
||||||
// 1. Clear PE bit.
|
|
||||||
i2c->Instance->CR1 &= ~(0x0001);
|
|
||||||
/**I2C1 GPIO Configuration
|
|
||||||
PB6 ------> I2C1_SCL
|
|
||||||
PB7 ------> I2C1_SDA
|
|
||||||
*/
|
|
||||||
// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
||||||
|
|
||||||
GPIO_InitStruct.Pin = SCL_Pin;
|
|
||||||
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
|
|
||||||
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
|
|
||||||
|
|
||||||
GPIO_InitStruct.Pin = SDA_Pin;
|
|
||||||
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
|
|
||||||
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
|
|
||||||
|
|
||||||
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) {
|
|
||||||
//Move clock to release I2C
|
|
||||||
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
|
|
||||||
asm("nop");
|
|
||||||
asm("nop");
|
|
||||||
asm("nop");
|
|
||||||
asm("nop");
|
|
||||||
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
|
|
||||||
|
|
||||||
timeout_cnt++;
|
|
||||||
if (timeout_cnt > timeout)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
||||||
|
|
||||||
GPIO_InitStruct.Pin = SCL_Pin;
|
|
||||||
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
|
|
||||||
|
|
||||||
GPIO_InitStruct.Pin = SDA_Pin;
|
|
||||||
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
|
|
||||||
|
|
||||||
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
|
|
||||||
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
|
|
||||||
|
|
||||||
// 13. Set SWRST bit in I2Cx_CR1 register.
|
|
||||||
i2c->Instance->CR1 |= 0x8000;
|
|
||||||
|
|
||||||
asm("nop");
|
|
||||||
|
|
||||||
// 14. Clear SWRST bit in I2Cx_CR1 register.
|
|
||||||
i2c->Instance->CR1 &= ~0x8000;
|
|
||||||
|
|
||||||
asm("nop");
|
|
||||||
|
|
||||||
// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
|
|
||||||
i2c->Instance->CR1 |= 0x0001;
|
|
||||||
|
|
||||||
// Call initialization function.
|
|
||||||
HAL_I2C_Init(i2c);
|
|
||||||
}
|
}
|
||||||
|
|||||||
24
workspace/TS100/Core/Src/FreeRTOSHooks.c
Normal file
24
workspace/TS100/Core/Src/FreeRTOSHooks.c
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOSHooks.c
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FreeRTOSHooks.h"
|
||||||
|
#include "BSP.h"
|
||||||
|
void vApplicationIdleHook(void) {
|
||||||
|
resetWatchdog();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
|
||||||
|
static StaticTask_t xIdleTaskTCBBuffer;
|
||||||
|
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
|
||||||
|
|
||||||
|
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||||
|
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
|
||||||
|
*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
|
||||||
|
*ppxIdleTaskStackBuffer = &xIdleStack[0];
|
||||||
|
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
||||||
|
/* place for user code */
|
||||||
|
}
|
||||||
@@ -19,14 +19,13 @@
|
|||||||
#include "TipThermoModel.h"
|
#include "TipThermoModel.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "../../configuration.h"
|
#include "../../configuration.h"
|
||||||
|
#include "Buttons.hpp"
|
||||||
extern uint8_t PCBVersion;
|
extern uint8_t PCBVersion;
|
||||||
// File local variables
|
// File local variables
|
||||||
extern uint32_t currentTempTargetDegC;
|
extern uint32_t currentTempTargetDegC;
|
||||||
extern uint8_t accelInit;
|
extern uint8_t accelInit;
|
||||||
extern uint32_t lastMovementTime;
|
extern uint32_t lastMovementTime;
|
||||||
extern int16_t idealQCVoltage;
|
extern int16_t idealQCVoltage;
|
||||||
uint32_t lastButtonTime = 0;
|
|
||||||
extern osThreadId GUITaskHandle;
|
extern osThreadId GUITaskHandle;
|
||||||
extern osThreadId MOVTaskHandle;
|
extern osThreadId MOVTaskHandle;
|
||||||
extern osThreadId PIDTaskHandle;
|
extern osThreadId PIDTaskHandle;
|
||||||
@@ -87,113 +86,8 @@ void gui_drawTipTemp(bool symbol) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonState getButtonState() {
|
|
||||||
/*
|
|
||||||
* Read in the buttons and then determine if a state change needs to occur
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the previous state was 00 Then we want to latch the new state if
|
|
||||||
* different & update time
|
|
||||||
* If the previous state was !00 Then we want to search if we trigger long
|
|
||||||
* press (buttons still down), or if release we trigger press
|
|
||||||
* (downtime>filter)
|
|
||||||
*/
|
|
||||||
static uint8_t previousState = 0;
|
|
||||||
static uint32_t previousStateChange = 0;
|
|
||||||
const uint16_t timeout = 40;
|
|
||||||
uint8_t currentState;
|
|
||||||
currentState = (
|
|
||||||
HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ?
|
|
||||||
1 : 0) << 0;
|
|
||||||
currentState |= (
|
|
||||||
HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ?
|
|
||||||
1 : 0) << 1;
|
|
||||||
|
|
||||||
if (currentState)
|
|
||||||
lastButtonTime = xTaskGetTickCount();
|
|
||||||
if (currentState == previousState) {
|
|
||||||
if (currentState == 0)
|
|
||||||
return BUTTON_NONE;
|
|
||||||
if ((xTaskGetTickCount() - previousStateChange) > timeout) {
|
|
||||||
// User has been holding the button down
|
|
||||||
// We want to send a buttong is held message
|
|
||||||
if (currentState == 0x01)
|
|
||||||
return BUTTON_F_LONG;
|
|
||||||
else if (currentState == 0x02)
|
|
||||||
return BUTTON_B_LONG;
|
|
||||||
else
|
|
||||||
return BUTTON_NONE; // Both being held case, we dont long hold this
|
|
||||||
} else
|
|
||||||
return BUTTON_NONE;
|
|
||||||
} else {
|
|
||||||
// A change in button state has occurred
|
|
||||||
ButtonState retVal = BUTTON_NONE;
|
|
||||||
if (currentState) {
|
|
||||||
// User has pressed a button down (nothing done on down)
|
|
||||||
if (currentState != previousState) {
|
|
||||||
// There has been a change in the button states
|
|
||||||
// If there is a rising edge on one of the buttons from double press we
|
|
||||||
// want to mask that out As users are having issues with not release
|
|
||||||
// both at once
|
|
||||||
if (previousState == 0x03)
|
|
||||||
currentState = 0x03;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// User has released buttons
|
|
||||||
// If they previously had the buttons down we want to check if they were <
|
|
||||||
// long hold and trigger a press
|
|
||||||
if ((xTaskGetTickCount() - previousStateChange) < timeout) {
|
|
||||||
// The user didn't hold the button for long
|
|
||||||
// So we send button press
|
|
||||||
|
|
||||||
if (previousState == 0x01)
|
|
||||||
retVal = BUTTON_F_SHORT;
|
|
||||||
else if (previousState == 0x02)
|
|
||||||
retVal = BUTTON_B_SHORT;
|
|
||||||
else
|
|
||||||
retVal = BUTTON_BOTH; // Both being held case
|
|
||||||
}
|
|
||||||
}
|
|
||||||
previousState = currentState;
|
|
||||||
previousStateChange = xTaskGetTickCount();
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
return BUTTON_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void waitForButtonPress() {
|
|
||||||
// we are just lazy and sleep until user confirms button press
|
|
||||||
// This also eats the button press event!
|
|
||||||
ButtonState buttons = getButtonState();
|
|
||||||
while (buttons) {
|
|
||||||
buttons = getButtonState();
|
|
||||||
GUIDelay();
|
|
||||||
}
|
|
||||||
while (!buttons) {
|
|
||||||
buttons = getButtonState();
|
|
||||||
GUIDelay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void waitForButtonPressOrTimeout(uint32_t timeout) {
|
|
||||||
timeout += xTaskGetTickCount();
|
|
||||||
// calculate the exit point
|
|
||||||
|
|
||||||
ButtonState buttons = getButtonState();
|
|
||||||
while (buttons) {
|
|
||||||
buttons = getButtonState();
|
|
||||||
GUIDelay();
|
|
||||||
if (xTaskGetTickCount() > timeout)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (!buttons) {
|
|
||||||
buttons = getButtonState();
|
|
||||||
GUIDelay();
|
|
||||||
if (xTaskGetTickCount() > timeout)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef MODEL_TS100
|
#ifdef MODEL_TS100
|
||||||
// returns true if undervoltage has occured
|
// returns true if undervoltage has occured
|
||||||
static bool checkVoltageForExit() {
|
static bool checkVoltageForExit() {
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ typedef struct {
|
|||||||
const uint8_t value;
|
const uint8_t value;
|
||||||
} LIS_REG;
|
} LIS_REG;
|
||||||
|
|
||||||
static const LIS_REG i2c_registers[] =
|
static const LIS_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17 }, // 25Hz
|
||||||
{ { LIS_CTRL_REG1, 0x17 }, // 25Hz
|
|
||||||
{ LIS_CTRL_REG2, 0b00001000 }, // Highpass filter off
|
{ LIS_CTRL_REG2, 0b00001000 }, // Highpass filter off
|
||||||
{ LIS_CTRL_REG3, 0b01100000 }, // Setup interrupt pins
|
{ LIS_CTRL_REG3, 0b01100000 }, // Setup interrupt pins
|
||||||
{ LIS_CTRL_REG4, 0b00001000 }, // Block update mode off, HR on
|
{ LIS_CTRL_REG4, 0b00001000 }, // Block update mode off, HR on
|
||||||
@@ -49,12 +48,5 @@ void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool LIS2DH12::detect() {
|
bool LIS2DH12::detect() {
|
||||||
uint8_t buffer[1];
|
return FRToSI2C::probe(LIS2DH_I2C_ADDRESS);
|
||||||
if (HAL_I2C_Mem_Read(&hi2c1, 25 << 1, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1,
|
|
||||||
1000) == HAL_OK) {
|
|
||||||
//ACK'd
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//NAK'd
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,12 +84,5 @@ void MMA8652FC::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MMA8652FC::detect() {
|
bool MMA8652FC::detect() {
|
||||||
uint8_t buffer[1];
|
return FRToSI2C::probe(MMA8652FC_I2C_ADDRESS);
|
||||||
if (HAL_I2C_Mem_Read(&hi2c1, 29 << 1, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1,
|
|
||||||
1000) == HAL_OK) {
|
|
||||||
//The device ACK'd
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//NAK'd
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,10 +95,6 @@ void OLED::initialize() {
|
|||||||
displayOffset = 0;
|
displayOffset = 0;
|
||||||
memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
|
memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
|
||||||
|
|
||||||
HAL_Delay(50);
|
|
||||||
HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET);
|
|
||||||
HAL_Delay(50);
|
|
||||||
|
|
||||||
// Set the display to be ON once the settings block is sent and send the
|
// Set the display to be ON once the settings block is sent and send the
|
||||||
// initialisation data to the OLED.
|
// initialisation data to the OLED.
|
||||||
|
|
||||||
|
|||||||
203
workspace/TS100/Core/Src/QC3.c
Normal file
203
workspace/TS100/Core/Src/QC3.c
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* QC3.c
|
||||||
|
*
|
||||||
|
* Created on: 29 May 2020
|
||||||
|
* Author: Ralim
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//Quick charge 3.0 supporting functions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODEL_TS80
|
||||||
|
void DPlusZero_Six() {
|
||||||
|
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+
|
||||||
|
}
|
||||||
|
void DNegZero_Six() {
|
||||||
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
|
||||||
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
|
||||||
|
}
|
||||||
|
void DPlusThree_Three() {
|
||||||
|
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); // pull up D+
|
||||||
|
}
|
||||||
|
void DNegThree_Three() {
|
||||||
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
|
||||||
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QC_Seek9V() {
|
||||||
|
DNegZero_Six();
|
||||||
|
DPlusThree_Three();
|
||||||
|
}
|
||||||
|
void QC_Seek12V() {
|
||||||
|
DNegZero_Six();
|
||||||
|
DPlusZero_Six();
|
||||||
|
}
|
||||||
|
void QC_Seek20V() {
|
||||||
|
DNegThree_Three();
|
||||||
|
DPlusThree_Three();
|
||||||
|
}
|
||||||
|
void QC_SeekContMode() {
|
||||||
|
DNegThree_Three();
|
||||||
|
DPlusZero_Six();
|
||||||
|
}
|
||||||
|
void QC_SeekContPlus() {
|
||||||
|
QC_SeekContMode();
|
||||||
|
vTaskDelay(3);
|
||||||
|
QC_Seek20V();
|
||||||
|
vTaskDelay(1);
|
||||||
|
QC_SeekContMode();
|
||||||
|
}
|
||||||
|
void QC_SeekContNeg() {
|
||||||
|
QC_SeekContMode();
|
||||||
|
vTaskDelay(3);
|
||||||
|
QC_Seek12V();
|
||||||
|
vTaskDelay(1);
|
||||||
|
QC_SeekContMode();
|
||||||
|
}
|
||||||
|
uint8_t QCMode = 0;
|
||||||
|
uint8_t QCTries = 0;
|
||||||
|
void seekQC(int16_t Vx10, uint16_t divisor) {
|
||||||
|
if (QCMode == 5)
|
||||||
|
startQC(divisor);
|
||||||
|
if (QCMode == 0)
|
||||||
|
return; // NOT connected to a QC Charger
|
||||||
|
|
||||||
|
if (Vx10 < 45)
|
||||||
|
return;
|
||||||
|
if (xTaskGetTickCount() < 100)
|
||||||
|
return;
|
||||||
|
if (Vx10 > 130)
|
||||||
|
Vx10 = 130; //Cap max value at 13V
|
||||||
|
// Seek the QC to the Voltage given if this adapter supports continuous mode
|
||||||
|
// try and step towards the wanted value
|
||||||
|
|
||||||
|
// 1. Measure current voltage
|
||||||
|
int16_t vStart = getInputVoltageX10(divisor, 1);
|
||||||
|
int difference = Vx10 - vStart;
|
||||||
|
|
||||||
|
// 2. calculate ideal steps (0.2V changes)
|
||||||
|
|
||||||
|
int steps = difference / 2;
|
||||||
|
if (QCMode == 3) {
|
||||||
|
if (steps > -2 && steps < 2)
|
||||||
|
return; // dont bother with small steps
|
||||||
|
while (steps < 0) {
|
||||||
|
QC_SeekContNeg();
|
||||||
|
vTaskDelay(3);
|
||||||
|
steps++;
|
||||||
|
}
|
||||||
|
while (steps > 0) {
|
||||||
|
QC_SeekContPlus();
|
||||||
|
vTaskDelay(3);
|
||||||
|
steps--;
|
||||||
|
}
|
||||||
|
vTaskDelay(10);
|
||||||
|
}
|
||||||
|
#ifdef ENABLE_QC2
|
||||||
|
// Re-measure
|
||||||
|
/* Disabled due to nothing to test and code space of around 1k*/
|
||||||
|
steps = vStart - getInputVoltageX10(divisor, 1);
|
||||||
|
if (steps < 0)
|
||||||
|
steps = -steps;
|
||||||
|
if (steps > 4) {
|
||||||
|
// No continuous mode, so QC2
|
||||||
|
QCMode = 2;
|
||||||
|
// Goto nearest
|
||||||
|
if (Vx10 > 110) {
|
||||||
|
// request 12V
|
||||||
|
// D- = 0.6V, D+ = 0.6V
|
||||||
|
// Clamp PB3
|
||||||
|
QC_Seek12V();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// request 9V
|
||||||
|
QC_Seek9V();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// Must be called after FreeRToS Starts
|
||||||
|
void startQC(uint16_t divisor) {
|
||||||
|
// Pre check that the input could be >5V already, and if so, dont both
|
||||||
|
// negotiating as someone is feeding in hv
|
||||||
|
uint16_t vin = getInputVoltageX10(divisor, 1);
|
||||||
|
if (vin > 100) {
|
||||||
|
QCMode = 1; // Already at 12V, user has probably over-ridden this
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
|
GPIO_InitStruct.Pin = GPIO_PIN_3;
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||||
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
|
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10;
|
||||||
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
|
//Turn off output mode on pins that we can
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
|
GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_14 | GPIO_PIN_13;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Tries to negotiate QC for 9V
|
||||||
|
// This is a multiple step process.
|
||||||
|
// 1. Set around 0.6V on D+ for 1.25 Seconds or so
|
||||||
|
// 2. After this It should un-short D+->D- and instead add a 20k pulldown on
|
||||||
|
// D-
|
||||||
|
DPlusZero_Six();
|
||||||
|
|
||||||
|
// Delay 1.25 seconds
|
||||||
|
uint8_t enteredQC = 0;
|
||||||
|
for (uint16_t i = 0; i < 200 && enteredQC == 0; i++) {
|
||||||
|
vTaskDelay(1); //10mS pause
|
||||||
|
if (i > 130) {
|
||||||
|
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET) {
|
||||||
|
enteredQC = 1;
|
||||||
|
}
|
||||||
|
if (i == 140) {
|
||||||
|
//For some marginal QC chargers, we try adding a pulldown
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||||
|
GPIO_InitStruct.Pin = GPIO_PIN_11;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
|
GPIO_InitStruct.Pin = GPIO_PIN_11;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
if (enteredQC) {
|
||||||
|
// We have a QC capable charger
|
||||||
|
QC_Seek9V();
|
||||||
|
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10;
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
QC_Seek9V();
|
||||||
|
// Wait for frontend ADC to stabilise
|
||||||
|
QCMode = 4;
|
||||||
|
for (uint8_t i = 0; i < 10; i++) {
|
||||||
|
if (getInputVoltageX10(divisor, 1) > 80) {
|
||||||
|
// yay we have at least QC2.0 or QC3.0
|
||||||
|
QCMode = 3; // We have at least QC2, pray for 3
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vTaskDelay(10); // 100mS
|
||||||
|
}
|
||||||
|
QCMode = 5;
|
||||||
|
QCTries++;
|
||||||
|
if (QCTries > 10) // 10 goes to get it going
|
||||||
|
QCMode = 0;
|
||||||
|
} else {
|
||||||
|
// no QC
|
||||||
|
QCMode = 0;
|
||||||
|
}
|
||||||
|
if (QCTries > 10)
|
||||||
|
QCMode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "TipThermoModel.h"
|
#include "TipThermoModel.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "hardware.h"
|
#include "BSP.h"
|
||||||
#include "../../configuration.h"
|
#include "../../configuration.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "../../configuration.h"
|
#include "../../configuration.h"
|
||||||
|
#include "Buttons.hpp"
|
||||||
extern uint32_t lastButtonTime;
|
extern uint32_t lastButtonTime;
|
||||||
void gui_Menu(const menuitem *menu);
|
void gui_Menu(const menuitem *menu);
|
||||||
|
|
||||||
|
|||||||
@@ -1,393 +0,0 @@
|
|||||||
/*
|
|
||||||
* hardware.c
|
|
||||||
*
|
|
||||||
* Created on: 2Sep.,2017
|
|
||||||
* Author: Ben V. Brown
|
|
||||||
*/
|
|
||||||
|
|
||||||
// These are all the functions for interacting with the hardware
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "history.hpp"
|
|
||||||
volatile uint16_t PWMSafetyTimer = 0;
|
|
||||||
|
|
||||||
uint16_t getHandleTemperature() {
|
|
||||||
// We return the current handle temperature in X10 C
|
|
||||||
// TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for
|
|
||||||
// example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) =
|
|
||||||
// 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125
|
|
||||||
// mV per count So we need to subtract an offset of 0.5V to center on 0C
|
|
||||||
// (4964.8 counts)
|
|
||||||
//
|
|
||||||
int32_t result = getADC(0);
|
|
||||||
result -= 4965; // remove 0.5V offset
|
|
||||||
// 10mV per C
|
|
||||||
// 99.29 counts per Deg C above 0C
|
|
||||||
result *= 100;
|
|
||||||
result /= 993;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t getTipInstantTemperature() {
|
|
||||||
uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits
|
|
||||||
uint16_t readings[8];
|
|
||||||
//Looking to reject the highest outlier readings.
|
|
||||||
//As on some hardware these samples can run into the op-amp recovery time
|
|
||||||
//Once this time is up the signal stabilises quickly, so no need to reject minimums
|
|
||||||
readings[0] = hadc1.Instance->JDR1;
|
|
||||||
readings[1] = hadc1.Instance->JDR2;
|
|
||||||
readings[2] = hadc1.Instance->JDR3;
|
|
||||||
readings[3] = hadc1.Instance->JDR4;
|
|
||||||
readings[4] = hadc2.Instance->JDR1;
|
|
||||||
readings[5] = hadc2.Instance->JDR2;
|
|
||||||
readings[6] = hadc2.Instance->JDR3;
|
|
||||||
readings[7] = hadc2.Instance->JDR4;
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
sum += readings[i];
|
|
||||||
}
|
|
||||||
return sum; // 8x over sample
|
|
||||||
}
|
|
||||||
|
|
||||||
//2 second filter (ADC is PID_TIM_HZ Hz)
|
|
||||||
history<uint16_t, PID_TIM_HZ> rawTempFilter = { { 0 }, 0, 0 };
|
|
||||||
|
|
||||||
uint16_t getTipRawTemp(uint8_t refresh) {
|
|
||||||
if (refresh) {
|
|
||||||
uint16_t lastSample = getTipInstantTemperature();
|
|
||||||
rawTempFilter.update(lastSample);
|
|
||||||
return lastSample;
|
|
||||||
} else {
|
|
||||||
return rawTempFilter.average();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
|
|
||||||
// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN
|
|
||||||
// Therefore we can divide down from there
|
|
||||||
// Multiplying ADC max by 4 for additional calibration options,
|
|
||||||
// ideal term is 467
|
|
||||||
#ifdef MODEL_TS100
|
|
||||||
#define BATTFILTERDEPTH 32
|
|
||||||
#else
|
|
||||||
#define BATTFILTERDEPTH 8
|
|
||||||
|
|
||||||
#endif
|
|
||||||
static uint8_t preFillneeded = 10;
|
|
||||||
static uint32_t samples[BATTFILTERDEPTH];
|
|
||||||
static uint8_t index = 0;
|
|
||||||
if (preFillneeded) {
|
|
||||||
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
|
|
||||||
samples[i] = getADC(1);
|
|
||||||
preFillneeded--;
|
|
||||||
}
|
|
||||||
if (sample) {
|
|
||||||
samples[index] = getADC(1);
|
|
||||||
index = (index + 1) % BATTFILTERDEPTH;
|
|
||||||
}
|
|
||||||
uint32_t sum = 0;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
|
|
||||||
sum += samples[i];
|
|
||||||
|
|
||||||
sum /= BATTFILTERDEPTH;
|
|
||||||
return sum * 4 / divisor;
|
|
||||||
}
|
|
||||||
#ifdef MODEL_TS80
|
|
||||||
void DPlusZero_Six() {
|
|
||||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+
|
|
||||||
}
|
|
||||||
void DNegZero_Six() {
|
|
||||||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
|
|
||||||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
|
|
||||||
}
|
|
||||||
void DPlusThree_Three() {
|
|
||||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); // pull up D+
|
|
||||||
}
|
|
||||||
void DNegThree_Three() {
|
|
||||||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
|
|
||||||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QC_Seek9V() {
|
|
||||||
DNegZero_Six();
|
|
||||||
DPlusThree_Three();
|
|
||||||
}
|
|
||||||
void QC_Seek12V() {
|
|
||||||
DNegZero_Six();
|
|
||||||
DPlusZero_Six();
|
|
||||||
}
|
|
||||||
void QC_Seek20V() {
|
|
||||||
DNegThree_Three();
|
|
||||||
DPlusThree_Three();
|
|
||||||
}
|
|
||||||
void QC_SeekContMode() {
|
|
||||||
DNegThree_Three();
|
|
||||||
DPlusZero_Six();
|
|
||||||
}
|
|
||||||
void QC_SeekContPlus() {
|
|
||||||
QC_SeekContMode();
|
|
||||||
vTaskDelay(3);
|
|
||||||
QC_Seek20V();
|
|
||||||
vTaskDelay(1);
|
|
||||||
QC_SeekContMode();
|
|
||||||
}
|
|
||||||
void QC_SeekContNeg() {
|
|
||||||
QC_SeekContMode();
|
|
||||||
vTaskDelay(3);
|
|
||||||
QC_Seek12V();
|
|
||||||
vTaskDelay(1);
|
|
||||||
QC_SeekContMode();
|
|
||||||
}
|
|
||||||
uint8_t QCMode = 0;
|
|
||||||
uint8_t QCTries = 0;
|
|
||||||
void seekQC(int16_t Vx10, uint16_t divisor) {
|
|
||||||
if (QCMode == 5)
|
|
||||||
startQC(divisor);
|
|
||||||
if (QCMode == 0)
|
|
||||||
return; // NOT connected to a QC Charger
|
|
||||||
|
|
||||||
if (Vx10 < 45)
|
|
||||||
return;
|
|
||||||
if (xTaskGetTickCount() < 100)
|
|
||||||
return;
|
|
||||||
if (Vx10 > 130)
|
|
||||||
Vx10 = 130; //Cap max value at 13V
|
|
||||||
// Seek the QC to the Voltage given if this adapter supports continuous mode
|
|
||||||
// try and step towards the wanted value
|
|
||||||
|
|
||||||
// 1. Measure current voltage
|
|
||||||
int16_t vStart = getInputVoltageX10(divisor, 1);
|
|
||||||
int difference = Vx10 - vStart;
|
|
||||||
|
|
||||||
// 2. calculate ideal steps (0.2V changes)
|
|
||||||
|
|
||||||
int steps = difference / 2;
|
|
||||||
if (QCMode == 3) {
|
|
||||||
if (steps > -2 && steps < 2)
|
|
||||||
return; // dont bother with small steps
|
|
||||||
while (steps < 0) {
|
|
||||||
QC_SeekContNeg();
|
|
||||||
vTaskDelay(3);
|
|
||||||
steps++;
|
|
||||||
}
|
|
||||||
while (steps > 0) {
|
|
||||||
QC_SeekContPlus();
|
|
||||||
vTaskDelay(3);
|
|
||||||
steps--;
|
|
||||||
}
|
|
||||||
vTaskDelay(10);
|
|
||||||
}
|
|
||||||
#ifdef ENABLE_QC2
|
|
||||||
// Re-measure
|
|
||||||
/* Disabled due to nothing to test and code space of around 1k*/
|
|
||||||
steps = vStart - getInputVoltageX10(divisor, 1);
|
|
||||||
if (steps < 0)
|
|
||||||
steps = -steps;
|
|
||||||
if (steps > 4) {
|
|
||||||
// No continuous mode, so QC2
|
|
||||||
QCMode = 2;
|
|
||||||
// Goto nearest
|
|
||||||
if (Vx10 > 110) {
|
|
||||||
// request 12V
|
|
||||||
// D- = 0.6V, D+ = 0.6V
|
|
||||||
// Clamp PB3
|
|
||||||
QC_Seek12V();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// request 9V
|
|
||||||
QC_Seek9V();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
// Must be called after FreeRToS Starts
|
|
||||||
void startQC(uint16_t divisor) {
|
|
||||||
// Pre check that the input could be >5V already, and if so, dont both
|
|
||||||
// negotiating as someone is feeding in hv
|
|
||||||
uint16_t vin = getInputVoltageX10(divisor, 1);
|
|
||||||
if (vin > 100) {
|
|
||||||
QCMode = 1; // Already at 12V, user has probably over-ridden this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GPIO_InitTypeDef GPIO_InitStruct;
|
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_3;
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
||||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10;
|
|
||||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
|
||||||
//Turn off output mode on pins that we can
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_14 | GPIO_PIN_13;
|
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
||||||
|
|
||||||
// Tries to negotiate QC for 9V
|
|
||||||
// This is a multiple step process.
|
|
||||||
// 1. Set around 0.6V on D+ for 1.25 Seconds or so
|
|
||||||
// 2. After this It should un-short D+->D- and instead add a 20k pulldown on
|
|
||||||
// D-
|
|
||||||
DPlusZero_Six();
|
|
||||||
|
|
||||||
// Delay 1.25 seconds
|
|
||||||
uint8_t enteredQC = 0;
|
|
||||||
for (uint16_t i = 0; i < 200 && enteredQC == 0; i++) {
|
|
||||||
vTaskDelay(1); //10mS pause
|
|
||||||
if (i > 130) {
|
|
||||||
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET) {
|
|
||||||
enteredQC = 1;
|
|
||||||
}
|
|
||||||
if (i == 140) {
|
|
||||||
//For some marginal QC chargers, we try adding a pulldown
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_11;
|
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_11;
|
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
||||||
if (enteredQC) {
|
|
||||||
// We have a QC capable charger
|
|
||||||
QC_Seek9V();
|
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10;
|
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
||||||
QC_Seek9V();
|
|
||||||
// Wait for frontend ADC to stabilise
|
|
||||||
QCMode = 4;
|
|
||||||
for (uint8_t i = 0; i < 10; i++) {
|
|
||||||
if (getInputVoltageX10(divisor, 1) > 80) {
|
|
||||||
// yay we have at least QC2.0 or QC3.0
|
|
||||||
QCMode = 3; // We have at least QC2, pray for 3
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vTaskDelay(10); // 100mS
|
|
||||||
}
|
|
||||||
QCMode = 5;
|
|
||||||
QCTries++;
|
|
||||||
if (QCTries > 10) // 10 goes to get it going
|
|
||||||
QCMode = 0;
|
|
||||||
} else {
|
|
||||||
// no QC
|
|
||||||
QCMode = 0;
|
|
||||||
}
|
|
||||||
if (QCTries > 10)
|
|
||||||
QCMode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int sqrt32(unsigned long n) {
|
|
||||||
unsigned int c = 0x8000;
|
|
||||||
unsigned int g = 0x8000;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (g * g > n)
|
|
||||||
g ^= c;
|
|
||||||
c >>= 1;
|
|
||||||
if (c == 0)
|
|
||||||
return g;
|
|
||||||
g |= c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int16_t calculateMaxVoltage(uint8_t useHP) {
|
|
||||||
// This measures the tip resistance, then it calculates the appropriate
|
|
||||||
// voltage To stay under ~18W. Mosfet is "9A", so no issues there
|
|
||||||
// QC3.0 supports up to 18W, which is 2A @9V and 1.5A @12V
|
|
||||||
uint32_t milliOhms = 4500;
|
|
||||||
// Check no tip
|
|
||||||
if (milliOhms > 10000)
|
|
||||||
return -1;
|
|
||||||
//Because of tolerance, if a user has asked for the higher power mode, then just goto 12V and call it a day
|
|
||||||
if (useHP)
|
|
||||||
return 120;
|
|
||||||
//
|
|
||||||
// V = sqrt(18W*R)
|
|
||||||
// Convert this to sqrt(18W)*sqrt(milli ohms)*sqrt(1/1000)
|
|
||||||
|
|
||||||
uint32_t Vx = sqrt32(milliOhms);
|
|
||||||
if (useHP)
|
|
||||||
Vx *= 1549; //sqrt(24)*sqrt(1/1000)*10000
|
|
||||||
else
|
|
||||||
Vx *= 1342; // sqrt(18) * sqrt(1/1000)*10000
|
|
||||||
|
|
||||||
// Round to nearest 200mV,
|
|
||||||
// So divide by 100 to start, to get in Vxx
|
|
||||||
Vx /= 100;
|
|
||||||
if (Vx % 10 >= 5)
|
|
||||||
Vx += 10;
|
|
||||||
Vx /= 10;
|
|
||||||
// Round to nearest increment of 2
|
|
||||||
if (Vx % 2 == 1)
|
|
||||||
Vx++;
|
|
||||||
//Because of how bad the tolerance is on detecting the tip resistance is
|
|
||||||
//Its more functional to bin this
|
|
||||||
if (Vx < 90)
|
|
||||||
Vx = 90;
|
|
||||||
else if (Vx >= 105)
|
|
||||||
Vx = 120;
|
|
||||||
return Vx;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
volatile uint8_t pendingPWM = 0;
|
|
||||||
|
|
||||||
void setTipPWM(uint8_t pulse) {
|
|
||||||
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
|
||||||
// disabled if the PID task is not scheduled often enough.
|
|
||||||
|
|
||||||
pendingPWM = pulse;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are called by the HAL after the corresponding events from the system
|
|
||||||
// timers.
|
|
||||||
|
|
||||||
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
|
|
||||||
// Period has elapsed
|
|
||||||
if (htim->Instance == TIM2) {
|
|
||||||
// we want to turn on the output again
|
|
||||||
PWMSafetyTimer--;
|
|
||||||
// We decrement this safety value so that lockups in the
|
|
||||||
// scheduler will not cause the PWM to become locked in an
|
|
||||||
// active driving state.
|
|
||||||
// While we could assume this could never happen, its a small price for
|
|
||||||
// increased safety
|
|
||||||
htim2.Instance->CCR4 = pendingPWM;
|
|
||||||
if (htim2.Instance->CCR4 && PWMSafetyTimer) {
|
|
||||||
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
|
|
||||||
} else {
|
|
||||||
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
|
|
||||||
}
|
|
||||||
} else if (htim->Instance == TIM1) {
|
|
||||||
// STM uses this for internal functions as a counter for timeouts
|
|
||||||
HAL_IncTick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
|
|
||||||
// This was a when the PWM for the output has timed out
|
|
||||||
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) {
|
|
||||||
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vApplicationIdleHook(void) {
|
|
||||||
HAL_IWDG_Refresh(&hiwdg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
|
|
||||||
static StaticTask_t xIdleTaskTCBBuffer;
|
|
||||||
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
|
|
||||||
|
|
||||||
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
|
|
||||||
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
|
|
||||||
*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
|
|
||||||
*ppxIdleTaskStackBuffer = &xIdleStack[0];
|
|
||||||
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
|
||||||
/* place for user code */
|
|
||||||
}
|
|
||||||
/* USER CODE END GET_IDLE_TASK_MEMORY */
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include <power.hpp>
|
#include <power.hpp>
|
||||||
#include <Settings.h>
|
#include <Settings.h>
|
||||||
#include <hardware.h>
|
#include <BSP.h>
|
||||||
|
|
||||||
const uint16_t powerPWM = 255;
|
const uint16_t powerPWM = 255;
|
||||||
const uint16_t totalPWM = 255 + 17; //htim2.Init.Period, the full PWM cycle
|
const uint16_t totalPWM = 255 + 17; //htim2.Init.Period, the full PWM cycle
|
||||||
|
|||||||
Reference in New Issue
Block a user