1
0
forked from me/IronOS

Merge pull request #672 from Ralim/supporting-FUSB302

Adding support for the TS80P using FUSB302 for USB-PD
This commit is contained in:
Ben V. Brown
2020-08-15 17:10:35 +10:00
committed by GitHub
64 changed files with 5487 additions and 1665 deletions

View File

@@ -2,7 +2,7 @@
#include "BSP_Power.h" #include "BSP_Power.h"
#include "BSP_QC.h" #include "BSP_QC.h"
#include "Defines.h" #include "Defines.h"
#include "UnitSettings.h" #include "Model_Config.h"
#include "stdint.h" #include "stdint.h"
/* /*
* BSP.h -- Board Support * BSP.h -- Board Support
@@ -47,8 +47,11 @@ void reboot();
// If the user has programmed in a bootup logo, draw it to the screen from flash // If the user has programmed in a bootup logo, draw it to the screen from flash
// Returns 1 if the logo was printed so that the unit waits for the timeout or button // Returns 1 if the logo was printed so that the unit waits for the timeout or button
uint8_t showBootLogoIfavailable(); uint8_t showBootLogoIfavailable();
//delay wrapper for delay using the hardware timer (used before RTOS)
void delay_ms(uint16_t count) ;
//Used to allow knowledge of if usb_pd is being used
uint8_t usb_pd_detect();
void delay_ms(uint16_t count);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -0,0 +1,16 @@
/*
* BSP_PD.h
*
* Created on: 21 Jul 2020
* Author: Ralim
*/
#ifndef USER_BSP_PD_H_
#define USER_BSP_PD_H_
#include "BSP.h"
/*
* An array of all of the desired voltages & minimum currents in preferred order
*/
extern const uint16_t USB_PD_Desired_Levels[];
extern const uint8_t USB_PD_Desired_Levels_Len;
#endif /* USER_BSP_PD_H_ */

View File

@@ -12,9 +12,6 @@
extern "C" { extern "C" {
#endif #endif
// Called once at startup, after RToS
// This can handle negotiations for QC/PD etc
void power_probe();
// Called periodically in the movement handling thread // Called periodically in the movement handling thread
// Can be used to check any details for the power system // Can be used to check any details for the power system

View File

@@ -7,6 +7,7 @@
#include "Pins.h" #include "Pins.h"
#include "main.hpp" #include "main.hpp"
#include "history.hpp" #include "history.hpp"
#include "Model_Config.h"
#include "I2C_Wrapper.hpp" #include "I2C_Wrapper.hpp"
volatile uint16_t PWMSafetyTimer = 0; volatile uint16_t PWMSafetyTimer = 0;
volatile uint8_t pendingPWM = 0; volatile uint8_t pendingPWM = 0;
@@ -16,8 +17,89 @@ history<uint16_t, PID_TIM_HZ> rawTempFilter = { { 0 }, 0, 0 };
void resetWatchdog() { void resetWatchdog() {
HAL_IWDG_Refresh(&hiwdg); HAL_IWDG_Refresh(&hiwdg);
} }
#ifdef TEMP_NTC
//Lookup table for the NTC
//Stored as ADCReading,Temp in degC
static const uint16_t NTCHandleLookup[] = {
//ADC Reading , Temp in C
29189, 0, //
29014, 1, //
28832, 2, //
28644, 3, //
28450, 4, //
28249, 5, //
28042, 6, //
27828, 7, //
27607, 8, //
27380, 9, //
27146, 10, //
26906, 11, //
26660, 12, //
26407, 13, //
26147, 14, //
25882, 15, //
25610, 16, //
25332, 17, //
25049, 18, //
24759, 19, //
24465, 20, //
24164, 21, //
23859, 22, //
23549, 23, //
23234, 24, //
22915, 25, //
22591, 26, //
22264, 27, //
21933, 28, //
21599, 29, //
// 21261, 30, //
// 20921, 31, //
// 20579, 32, //
// 20234, 33, //
// 19888, 34, //
// 19541, 35, //
// 19192, 36, //
// 18843, 37, //
// 18493, 38, //
// 18143, 39, //
// 17793, 40, //
// 17444, 41, //
// 17096, 42, //
// 16750, 43, //
// 16404, 44, //
// 16061, 45, //
// 15719, 46, //
// 15380, 47, //
// 15044, 48, //
// 14710, 49, //
// 14380, 50, //
// 14053, 51, //
// 13729, 52, //
// 13410, 53, //
// 13094, 54, //
// 12782, 55, //
// 12475, 56, //
// 12172, 57, //
// 11874, 58, //
// 11580, 59, //
// 11292, 60, //
};
#endif
uint16_t getHandleTemperature() { uint16_t getHandleTemperature() {
#ifdef TEMP_NTC
//TS80P uses 100k NTC resistors instead
//NTCG104EF104FT1X from TDK
//For now not doing interpolation
int32_t result = getADC(0);
for (uint32_t i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t)));
i++) {
if (result > NTCHandleLookup[(i * 2) + 0]) {
return NTCHandleLookup[(i * 2) + 1] * 10;
}
}
return 0;
#endif
#ifdef TEMP_TMP36
// We return the current handle temperature in X10 C // 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 // 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) = // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) =
@@ -32,14 +114,15 @@ uint16_t getHandleTemperature() {
result *= 100; result *= 100;
result /= 993; result /= 993;
return result; return result;
#endif
} }
uint16_t getTipInstantTemperature() { uint16_t getTipInstantTemperature() {
uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits
uint16_t readings[8]; uint16_t readings[8];
//Looking to reject the highest outlier readings. //Looking to reject the highest outlier readings.
//As on some hardware these samples can run into the op-amp recovery time //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 //Once this time is up the signal stabilises quickly, so no need to reject minimums
readings[0] = hadc1.Instance->JDR1; readings[0] = hadc1.Instance->JDR1;
readings[1] = hadc1.Instance->JDR2; readings[1] = hadc1.Instance->JDR2;
readings[2] = hadc1.Instance->JDR3; readings[2] = hadc1.Instance->JDR3;
@@ -66,10 +149,10 @@ uint16_t getTipRawTemp(uint8_t refresh) {
} }
uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN
// Therefore we can divide down from there // Therefore we can divide down from there
// Multiplying ADC max by 4 for additional calibration options, // Multiplying ADC max by 4 for additional calibration options,
// ideal term is 467 // ideal term is 467
#ifdef MODEL_TS100 #ifdef MODEL_TS100
#define BATTFILTERDEPTH 32 #define BATTFILTERDEPTH 32
#else #else
@@ -94,6 +177,9 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
sum += samples[i]; sum += samples[i];
sum /= BATTFILTERDEPTH; sum /= BATTFILTERDEPTH;
if (divisor == 0) {
divisor = 1;
}
return sum * 4 / divisor; return sum * 4 / divisor;
} }
@@ -140,13 +226,13 @@ void unstick_I2C() {
int timeout = 100; int timeout = 100;
int timeout_cnt = 0; int timeout_cnt = 0;
// 1. Clear PE bit. // 1. Clear PE bit.
hi2c1.Instance->CR1 &= ~(0x0001); hi2c1.Instance->CR1 &= ~(0x0001);
/**I2C1 GPIO Configuration /**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA PB7 ------> I2C1_SDA
*/ */
// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). // 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.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
@@ -173,7 +259,7 @@ void unstick_I2C() {
return; return;
} }
// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. // 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
@@ -187,20 +273,20 @@ void unstick_I2C() {
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
// 13. Set SWRST bit in I2Cx_CR1 register. // 13. Set SWRST bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 |= 0x8000; hi2c1.Instance->CR1 |= 0x8000;
asm("nop"); asm("nop");
// 14. Clear SWRST bit in I2Cx_CR1 register. // 14. Clear SWRST bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 &= ~0x8000; hi2c1.Instance->CR1 &= ~0x8000;
asm("nop"); asm("nop");
// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
hi2c1.Instance->CR1 |= 0x0001; hi2c1.Instance->CR1 |= 0x0001;
// Call initialization function. // Call initialization function.
HAL_I2C_Init(&hi2c1); HAL_I2C_Init(&hi2c1);
} }
@@ -214,6 +300,7 @@ uint8_t getButtonB() {
} }
void reboot() { void reboot() {
NVIC_SystemReset(); NVIC_SystemReset();
} }

View File

@@ -0,0 +1,22 @@
/*
* BSP_PD.c
*
* Created on: 21 Jul 2020
* Author: Ralim
*/
#include "BSP_PD.h"
#include "Model_Config.h"
#ifdef POW_PD
/*
* An array of all of the desired voltages & minimum currents in preferred order
*/
const uint16_t USB_PD_Desired_Levels[] = {
//mV desired input, mA minimum required current
12000, 2400, //12V @ 2.4A
9000, 2000, //9V @ 2A
5000, 100, //5V @ whatever
};
const uint8_t USB_PD_Desired_Levels_Len = 3;
#endif

View File

@@ -6,6 +6,7 @@
*/ */
#include "IRQ.h" #include "IRQ.h"
#include "int_n.h"
/* /*
* Catch the IRQ that says that the conversion is done on the temperature * Catch the IRQ that says that the conversion is done on the temperature
* readings coming in Once these have come in we can unblock the PID so that it * readings coming in Once these have come in we can unblock the PID so that it
@@ -41,3 +42,8 @@ void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c __unused) {
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) {
FRToSI2C::CpltCallback(); FRToSI2C::CpltCallback();
} }
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
(void)GPIO_Pin;
InterruptHandler::irqCallback();
}

View File

@@ -24,6 +24,7 @@ void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_GPIO_EXTI_Callback(uint16_t);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,44 @@
/*
* Model_Config.h
*
* Created on: 25 Jul 2020
* Author: Ralim
*/
#ifndef BSP_MINIWARE_MODEL_CONFIG_H_
#define BSP_MINIWARE_MODEL_CONFIG_H_
/*
* Lookup for mapping features <-> Models
*/
#if defined(MODEL_TS100) + defined(MODEL_TS80)+defined(MODEL_TS80P) > 1
#error "Multiple models defined!"
#elif defined(MODEL_TS100) + defined(MODEL_TS80)+ defined(MODEL_TS80P) == 0
#error "No model defined!"
#endif
#ifdef MODEL_TS100
#define ACCEL_MMA
#define ACCEL_LIS
#define TEMP_TMP36
#endif
#ifdef MODEL_TS80
#define ACCEL_LIS
#define POW_QC
#define TEMP_TMP36
#define LIS_ORI_FLIP
#define OLED_FLIP
#endif
#ifdef MODEL_TS80P
#define ACCEL_LIS
#define POW_PD
#define POW_QC
#define TEMP_NTC
#define I2C_SOFT
#define LIS_ORI_FLIP
#define OLED_FLIP
#endif
#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */

View File

@@ -7,12 +7,7 @@
#ifndef BSP_MINIWARE_PINS_H_ #ifndef BSP_MINIWARE_PINS_H_
#define BSP_MINIWARE_PINS_H_ #define BSP_MINIWARE_PINS_H_
#include "Model_Config.h"
#if defined(MODEL_TS100) + defined(MODEL_TS80) > 1
#error "Multiple models defined!"
#elif defined(MODEL_TS100) + defined(MODEL_TS80) == 0
#error "No model defined!"
#endif
#ifdef MODEL_TS100 #ifdef MODEL_TS100
@@ -45,8 +40,8 @@
#define SCL_GPIO_Port GPIOB #define SCL_GPIO_Port GPIOB
#define SDA_Pin GPIO_PIN_7 #define SDA_Pin GPIO_PIN_7
#define SDA_GPIO_Port GPIOB #define SDA_GPIO_Port GPIOB
#endif
#else #ifdef MODEL_TS80
// TS80 pin map // TS80 pin map
#define KEY_B_Pin GPIO_PIN_0 #define KEY_B_Pin GPIO_PIN_0
#define KEY_B_GPIO_Port GPIOB #define KEY_B_GPIO_Port GPIOB
@@ -77,6 +72,51 @@
#define SCL_GPIO_Port GPIOB #define SCL_GPIO_Port GPIOB
#define SDA_Pin GPIO_PIN_7 #define SDA_Pin GPIO_PIN_7
#define SDA_GPIO_Port GPIOB #define SDA_GPIO_Port GPIOB
#define SCL2_Pin GPIO_PIN_5
#define SCL2_GPIO_Port GPIOA
#define SDA2_Pin GPIO_PIN_1
#define SDA2_GPIO_Port GPIOA
#define INT_PD_Pin GPIO_PIN_9
#define INT_PD_GPIO_Port GPIOA
#endif
#ifdef MODEL_TS80P
// TS80P pin map
#define KEY_B_Pin GPIO_PIN_0
#define KEY_B_GPIO_Port GPIOB
#define TMP36_INPUT_Pin GPIO_PIN_4
#define TMP36_INPUT_GPIO_Port GPIOA
#define TMP36_ADC1_CHANNEL ADC_CHANNEL_4
#define TIP_TEMP_Pin GPIO_PIN_3
#define TIP_TEMP_GPIO_Port GPIOA
#define TIP_TEMP_ADC1_CHANNEL ADC_CHANNEL_3
#define TIP_TEMP_ADC2_CHANNEL ADC_CHANNEL_3
#define VIN_Pin GPIO_PIN_2
#define VIN_GPIO_Port GPIOA
#define VIN_ADC1_CHANNEL ADC_CHANNEL_2
#define VIN_ADC2_CHANNEL ADC_CHANNEL_2
#define OLED_RESET_Pin GPIO_PIN_15
#define OLED_RESET_GPIO_Port GPIOA
#define KEY_A_Pin GPIO_PIN_1
#define KEY_A_GPIO_Port GPIOB
#define INT_Orientation_Pin GPIO_PIN_4
#define INT_Orientation_GPIO_Port GPIOB
#define PWM_Out_Pin GPIO_PIN_6
#define PWM_Out_GPIO_Port GPIOA
#define PWM_Out_CHANNEL TIM_CHANNEL_1
#define INT_Movement_Pin GPIO_PIN_5
#define INT_Movement_GPIO_Port GPIOB
#define SCL_Pin GPIO_PIN_6
#define SCL_GPIO_Port GPIOB
#define SDA_Pin GPIO_PIN_7
#define SDA_GPIO_Port GPIOB
#define SCL2_Pin GPIO_PIN_5
#define SCL2_GPIO_Port GPIOA
#define SDA2_Pin GPIO_PIN_1
#define SDA2_GPIO_Port GPIOA
#define INT_PD_Pin GPIO_PIN_9
#define INT_PD_GPIO_Port GPIOA
#endif #endif

View File

@@ -2,20 +2,35 @@
#include "BSP_Power.h" #include "BSP_Power.h"
#include "QC3.h" #include "QC3.h"
#include "Settings.h" #include "Settings.h"
void power_probe() { #include "Pins.h"
// If TS80 probe for QC #include "fusbpd.h"
// If TS100 - noop #include "Model_Config.h"
#ifdef MODEL_TS80 #include "policy_engine.h"
startQC(systemSettings.voltageDiv); #include "int_n.h"
bool FUSB302_present = false;
seekQC((systemSettings.cutoutSetting) ? 120 : 90,
systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with
#endif
}
void power_check() { void power_check() {
#ifdef MODEL_TS80 #ifdef POW_PD
QC_resync(); if (FUSB302_present) {
//Cant start QC until either PD works or fails
if (PolicyEngine::setupCompleteOrTimedOut() == false) {
return;
}
if (PolicyEngine::pdHasNegotiated()) {
return;
}
}
#endif #endif
} #ifdef POW_QC
QC_resync();
#endif
}
uint8_t usb_pd_detect() {
#ifdef POW_PD
FUSB302_present = fusb302_detect();
return FUSB302_present;
#endif
return false;
}

View File

@@ -9,6 +9,8 @@
#include "QC3.h" #include "QC3.h"
#include "Settings.h" #include "Settings.h"
#include "stm32f1xx_hal.h" #include "stm32f1xx_hal.h"
#include "Model_Config.h"
#ifdef POW_QC
void QC_DPlusZero_Six() { void QC_DPlusZero_Six() {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+
} }
@@ -65,10 +67,10 @@ void QC_Post_Probe_En() {
} }
uint8_t QC_DM_PulledDown() { return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET ? 1 : 0; } uint8_t QC_DM_PulledDown() { return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET ? 1 : 0; }
#endif
void QC_resync() { void QC_resync() {
#ifdef MODEL_TS80 #ifdef POW_QC
seekQC((systemSettings.cutoutSetting) ? 120 : 90, seekQC((systemSettings.cutoutSetting) ? 120 : 90,
systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much
#endif #endif
} }

View File

@@ -35,7 +35,7 @@ void Setup_HAL() {
SystemClock_Config(); SystemClock_Config();
__HAL_AFIO_REMAP_SWJ_DISABLE() __HAL_AFIO_REMAP_SWJ_DISABLE()
; ;
// __HAL_AFIO_REMAP_SWJ_NOJTAG();
MX_GPIO_Init(); MX_GPIO_Init();
MX_DMA_Init(); MX_DMA_Init();
MX_I2C1_Init(); MX_I2C1_Init();
@@ -458,3 +458,8 @@ static void MX_GPIO_Init(void) {
HAL_Delay(30); HAL_Delay(30);
HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET);
} }
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line){
asm("bkpt");
}
#endif

View File

@@ -0,0 +1,27 @@
/*
* Software_I2C.h
*
* Created on: 25 Jul 2020
* Author: Ralim
*/
#ifndef BSP_MINIWARE_SOFTWARE_I2C_H_
#define BSP_MINIWARE_SOFTWARE_I2C_H_
#include "Model_Config.h"
#include "BSP.h"
#include "stm32f1xx_hal.h"
#ifdef I2C_SOFT
#define SOFT_SCL_HIGH() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_SET)
#define SOFT_SCL_LOW() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_RESET)
#define SOFT_SDA_HIGH() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_SET)
#define SOFT_SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET)
#define SOFT_SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0)
#define SOFT_SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0)
#define SOFT_I2C_DELAY() {for(int xx=0;xx<40;xx++){asm("nop");}}
#endif
#endif /* BSP_MINIWARE_SOFTWARE_I2C_H_ */

View File

@@ -1,18 +0,0 @@
/*
* 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_ */

View File

@@ -291,7 +291,7 @@ typedef struct
/** @defgroup RCC_Flag Flags /** @defgroup RCC_Flag Flags
* Elements values convention: XXXYYYYYb * Elements values convention: XXXYYYYYb
* - YYYYY : Flag position in the register * - YYYYY : Flag position in the register
* - XXX : Register index * - X XX : Register index
* - 001: CR register * - 001: CR register
* - 010: BDCR register * - 010: BDCR register
* - 011: CSR register * - 011: CSR register

View File

@@ -1041,32 +1041,32 @@ HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef* hadc, ADC_I
/* conversions is forced to 0x00 for alignment over all STM32 devices. */ /* conversions is forced to 0x00 for alignment over all STM32 devices. */
/* - if scan mode is enabled, injected channels sequence length is set to */ /* - if scan mode is enabled, injected channels sequence length is set to */
/* parameter "InjectedNbrOfConversion". */ /* parameter "InjectedNbrOfConversion". */
if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) // if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE)
{ // {
if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1) // if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1)
{ // {
/* Clear the old SQx bits for all injected ranks */ // /* Clear the old SQx bits for all injected ranks */
MODIFY_REG(hadc->Instance->JSQR , // MODIFY_REG(hadc->Instance->JSQR ,
ADC_JSQR_JL | // ADC_JSQR_JL |
ADC_JSQR_JSQ4 | // ADC_JSQR_JSQ4 |
ADC_JSQR_JSQ3 | // ADC_JSQR_JSQ3 |
ADC_JSQR_JSQ2 | // ADC_JSQR_JSQ2 |
ADC_JSQR_JSQ1 , // ADC_JSQR_JSQ1 ,
ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel, // ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel,
ADC_INJECTED_RANK_1, // ADC_INJECTED_RANK_1,
0x01U)); // 0x01U));
} // }
/* If another injected rank than rank1 was intended to be set, and could */ // /* If another injected rank than rank1 was intended to be set, and could */
/* not due to ScanConvMode disabled, error is reported. */ // /* not due to ScanConvMode disabled, error is reported. */
else // else
{ // {
/* Update ADC state machine to error */ // /* Update ADC state machine to error */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); // SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
//
tmp_hal_status = HAL_ERROR; // tmp_hal_status = HAL_ERROR;
} // }
} // }
else // else
{ {
/* Since injected channels rank conv. order depends on total number of */ /* Since injected channels rank conv. order depends on total number of */
/* injected conversions, selected rank must be below or equal to total */ /* injected conversions, selected rank must be below or equal to total */

View File

@@ -3479,6 +3479,7 @@ void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
} }
} }
/* Slave mode selected */ /* Slave mode selected */
#if 0
else else
{ {
/* ADDR set --------------------------------------------------------------*/ /* ADDR set --------------------------------------------------------------*/
@@ -3520,6 +3521,7 @@ void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
} }
} }
} }
#endif
} }
/** /**

View File

@@ -369,57 +369,6 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
/*------------------------------- HSE Configuration ------------------------*/ /*------------------------------- HSE Configuration ------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
{
/* Check the parameters */
assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
/* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_HSE)
|| ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)))
{
if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
{
return HAL_ERROR;
}
}
else
{
/* Set the new HSE configuration ---------------------------------------*/
__HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
/* Check the HSE State */
if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
{
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till HSE is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
{
if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till HSE is disabled */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET)
{
if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
}
/*----------------------------- HSI Configuration --------------------------*/ /*----------------------------- HSI Configuration --------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
{ {
@@ -486,121 +435,9 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
} }
} }
/*------------------------------ LSI Configuration -------------------------*/ /*------------------------------ LSI Configuration -------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
{
/* Check the parameters */
assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
/* Check the LSI State */
if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
{
/* Enable the Internal Low Speed oscillator (LSI). */
__HAL_RCC_LSI_ENABLE();
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till LSI is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET)
{
if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* To have a fully stabilized clock in the specified range, a software delay of 1ms
should be added.*/
RCC_Delay(1);
}
else
{
/* Disable the Internal Low Speed oscillator (LSI). */
__HAL_RCC_LSI_DISABLE();
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till LSI is disabled */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET)
{
if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
/*------------------------------ LSE Configuration -------------------------*/ /*------------------------------ LSE Configuration -------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
{
FlagStatus pwrclkchanged = RESET;
/* Check the parameters */
assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
/* Update LSE configuration in Backup Domain control register */
/* Requires to enable write access to Backup Domain of necessary */
if(__HAL_RCC_PWR_IS_CLK_DISABLED())
{
__HAL_RCC_PWR_CLK_ENABLE();
pwrclkchanged = SET;
}
if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
{
/* Enable write access to Backup domain */
SET_BIT(PWR->CR, PWR_CR_DBP);
/* Wait for Backup domain Write protection disable */
tickstart = HAL_GetTick();
while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
{
if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
/* Set the new LSE configuration -----------------------------------------*/
__HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
/* Check the LSE State */
if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
{
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till LSE is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
{
if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till LSE is disabled */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET)
{
if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
/* Require to disable power clock if necessary */
if(pwrclkchanged == SET)
{
__HAL_RCC_PWR_CLK_DISABLE();
}
}
#if defined(RCC_CR_PLL2ON) #if defined(RCC_CR_PLL2ON)
/*-------------------------------- PLL2 Configuration -----------------------*/ /*-------------------------------- PLL2 Configuration -----------------------*/

View File

@@ -3968,129 +3968,129 @@ HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockCo
} }
break; break;
case TIM_CLOCKSOURCE_ETRMODE1: // case TIM_CLOCKSOURCE_ETRMODE1:
{ // {
/* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/ // /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/
assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance));
//
/* Check ETR input conditioning related parameters */ // /* Check ETR input conditioning related parameters */
assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); // assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); // assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); // assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
//
/* Configure the ETR Clock source */ // /* Configure the ETR Clock source */
TIM_ETR_SetConfig(htim->Instance, // TIM_ETR_SetConfig(htim->Instance,
sClockSourceConfig->ClockPrescaler, // sClockSourceConfig->ClockPrescaler,
sClockSourceConfig->ClockPolarity, // sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter); // sClockSourceConfig->ClockFilter);
/* Get the TIMx SMCR register value */ // /* Get the TIMx SMCR register value */
tmpsmcr = htim->Instance->SMCR; // tmpsmcr = htim->Instance->SMCR;
/* Reset the SMS and TS Bits */ // /* Reset the SMS and TS Bits */
tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); // tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS);
/* Select the External clock mode1 and the ETRF trigger */ // /* Select the External clock mode1 and the ETRF trigger */
tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1); // tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1);
/* Write to TIMx SMCR */ // /* Write to TIMx SMCR */
htim->Instance->SMCR = tmpsmcr; // htim->Instance->SMCR = tmpsmcr;
} // }
break; // break;
//
case TIM_CLOCKSOURCE_ETRMODE2: // case TIM_CLOCKSOURCE_ETRMODE2:
{ // {
/* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/ // /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/
assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance));
//
/* Check ETR input conditioning related parameters */ // /* Check ETR input conditioning related parameters */
assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); // assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); // assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); // assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
//
/* Configure the ETR Clock source */ // /* Configure the ETR Clock source */
TIM_ETR_SetConfig(htim->Instance, // TIM_ETR_SetConfig(htim->Instance,
sClockSourceConfig->ClockPrescaler, // sClockSourceConfig->ClockPrescaler,
sClockSourceConfig->ClockPolarity, // sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter); // sClockSourceConfig->ClockFilter);
/* Enable the External clock mode2 */ // /* Enable the External clock mode2 */
htim->Instance->SMCR |= TIM_SMCR_ECE; // htim->Instance->SMCR |= TIM_SMCR_ECE;
} // }
break; // break;
//
case TIM_CLOCKSOURCE_TI1: // case TIM_CLOCKSOURCE_TI1:
{ // {
/* Check whether or not the timer instance supports external clock mode 1 */ // /* Check whether or not the timer instance supports external clock mode 1 */
assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
//
/* Check TI1 input conditioning related parameters */ // /* Check TI1 input conditioning related parameters */
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); // assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); // assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
//
TIM_TI1_ConfigInputStage(htim->Instance, // TIM_TI1_ConfigInputStage(htim->Instance,
sClockSourceConfig->ClockPolarity, // sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter); // sClockSourceConfig->ClockFilter);
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1); // TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1);
} // }
break; // break;
case TIM_CLOCKSOURCE_TI2: // case TIM_CLOCKSOURCE_TI2:
{ // {
/* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/ // /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/
assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
//
/* Check TI2 input conditioning related parameters */ // /* Check TI2 input conditioning related parameters */
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); // assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); // assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
//
TIM_TI2_ConfigInputStage(htim->Instance, // TIM_TI2_ConfigInputStage(htim->Instance,
sClockSourceConfig->ClockPolarity, // sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter); // sClockSourceConfig->ClockFilter);
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2); // TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2);
} // }
break; // break;
case TIM_CLOCKSOURCE_TI1ED: // case TIM_CLOCKSOURCE_TI1ED:
{ // {
/* Check whether or not the timer instance supports external clock mode 1 */ // /* Check whether or not the timer instance supports external clock mode 1 */
assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
//
/* Check TI1 input conditioning related parameters */ // /* Check TI1 input conditioning related parameters */
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); // assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); // assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
//
TIM_TI1_ConfigInputStage(htim->Instance, // TIM_TI1_ConfigInputStage(htim->Instance,
sClockSourceConfig->ClockPolarity, // sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter); // sClockSourceConfig->ClockFilter);
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED); // TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED);
} // }
break; // break;
case TIM_CLOCKSOURCE_ITR0: // case TIM_CLOCKSOURCE_ITR0:
{ // {
/* Check whether or not the timer instance supports external clock mode 1 */ // /* Check whether or not the timer instance supports external clock mode 1 */
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
//
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0); // TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0);
} // }
break; // break;
case TIM_CLOCKSOURCE_ITR1: // case TIM_CLOCKSOURCE_ITR1:
{ // {
/* Check whether or not the timer instance supports external clock mode 1 */ // /* Check whether or not the timer instance supports external clock mode 1 */
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
//
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1); // TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1);
} // }
break; // break;
case TIM_CLOCKSOURCE_ITR2: // case TIM_CLOCKSOURCE_ITR2:
{ // {
/* Check whether or not the timer instance supports external clock mode 1 */ // /* Check whether or not the timer instance supports external clock mode 1 */
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
//
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2); // TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2);
} // }
break; // break;
case TIM_CLOCKSOURCE_ITR3: // case TIM_CLOCKSOURCE_ITR3:
{ // {
/* Check whether or not the timer instance supports external clock mode 1 */ // /* Check whether or not the timer instance supports external clock mode 1 */
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); // assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
//
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3); // TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3);
} // }
break; // break;
default: default:
break; break;

View File

@@ -0,0 +1,270 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Model_Config.h"
#ifdef POW_PD
#include "BSP.h"
#include "fusb302b.h"
#include "I2CBB.hpp"
#include <pd.h>
#include "int_n.h"
/*
* Read a single byte from the FUSB302B
*
* cfg: The FUSB302B to communicate with
* addr: The memory address from which to read
*
* Returns the value read from addr.
*/
static uint8_t fusb_read_byte(uint8_t addr) {
uint8_t data[1];
if (!I2CBB::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) data, 1)) {
return 0;
}
return data[0];
}
/*
* Read multiple bytes from the FUSB302B
*
* cfg: The FUSB302B to communicate with
* addr: The memory address from which to read
* size: The number of bytes to read
* buf: The buffer into which data will be read
*/
static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) {
return I2CBB::Mem_Read(FUSB302B_ADDR, addr, buf, size);
}
/*
* Write a single byte to the FUSB302B
*
* cfg: The FUSB302B to communicate with
* addr: The memory address to which we will write
* byte: The value to write
*/
static bool fusb_write_byte(uint8_t addr, uint8_t byte) {
return I2CBB::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1);
}
/*
* Write multiple bytes to the FUSB302B
*
* cfg: The FUSB302B to communicate with
* addr: The memory address to which we will write
* size: The number of bytes to write
* buf: The buffer to write
*/
static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) {
return I2CBB::Mem_Write(FUSB302B_ADDR, addr, buf, size);
}
void fusb_send_message(const union pd_msg *msg) {
if (!I2CBB::lock2()) {
return;
}
/* Token sequences for the FUSB302B */
static uint8_t sop_seq[5] = {
FUSB_FIFO_TX_SOP1,
FUSB_FIFO_TX_SOP1,
FUSB_FIFO_TX_SOP1,
FUSB_FIFO_TX_SOP2,
FUSB_FIFO_TX_PACKSYM };
static const uint8_t eop_seq[4] = {
FUSB_FIFO_TX_JAM_CRC,
FUSB_FIFO_TX_EOP,
FUSB_FIFO_TX_TXOFF,
FUSB_FIFO_TX_TXON };
/* Take the I2C2 mutex now so there can't be a race condition on sop_seq */
/* Get the length of the message: a two-octet header plus NUMOBJ four-octet
* data objects */
uint8_t msg_len = 2 + 4 * PD_NUMOBJ_GET(msg);
/* Set the number of bytes to be transmitted in the packet */
sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len;
/* Write all three parts of the message to the TX FIFO */
fusb_write_buf( FUSB_FIFOS, 5, sop_seq);
fusb_write_buf( FUSB_FIFOS, msg_len, msg->bytes);
fusb_write_buf( FUSB_FIFOS, 4, eop_seq);
I2CBB::unlock2();
}
uint8_t fusb_read_message(union pd_msg *msg) {
if (!I2CBB::lock2()) {
asm("bkpt");
}
static uint8_t garbage[4];
uint8_t numobj;
// Read the header. If its not a SOP we dont actually want it at all
// But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck
fusb_read_byte( FUSB_FIFOS);
/* Read the message header into msg */
fusb_read_buf( FUSB_FIFOS, 2, msg->bytes);
/* Get the number of data objects */
numobj = PD_NUMOBJ_GET(msg);
/* If there is at least one data object, read the data objects */
if (numobj > 0) {
fusb_read_buf( FUSB_FIFOS, numobj * 4, msg->bytes + 2);
}
/* Throw the CRC32 in the garbage, since the PHY already checked it. */
fusb_read_buf( FUSB_FIFOS, 4, garbage);
I2CBB::unlock2();
return 0;
}
void fusb_send_hardrst() {
if (!I2CBB::lock2()) {
return;
}
/* Send a hard reset */
fusb_write_byte( FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET);
I2CBB::unlock2();
}
void fusb_setup() {
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 12, 0);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
if (!I2CBB::lock2()) {
return;
}
}
/* Fully reset the FUSB302B */
fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES);
osDelay(2);
if (!fusb_read_id()) {
return;
}
/* Turn on all power */
fusb_write_byte( FUSB_POWER, 0x0F);
/* Set interrupt masks */
//Setting to 0 so interrupts are allowed
fusb_write_byte( FUSB_MASK1, 0x00);
fusb_write_byte( FUSB_MASKA, 0x00);
fusb_write_byte( FUSB_MASKB, 0x00);
fusb_write_byte( FUSB_CONTROL0, 0b11 << 2);
/* Enable automatic retransmission */
fusb_write_byte( FUSB_CONTROL3, 0x07);
//set defaults
fusb_write_byte( FUSB_CONTROL2, 0x00);
/* Flush the RX buffer */
fusb_write_byte( FUSB_CONTROL1,
FUSB_CONTROL1_RX_FLUSH);
/* Measure CC1 */
fusb_write_byte( FUSB_SWITCHES0, 0x07);
osDelay(10);
uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
/* Measure CC2 */
fusb_write_byte( FUSB_SWITCHES0, 0x0B);
osDelay(10);
uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
/* Select the correct CC line for BMC signaling; also enable AUTO_CRC */
if (cc1 > cc2) {
fusb_write_byte( FUSB_SWITCHES1, 0x25);
fusb_write_byte( FUSB_SWITCHES0, 0x07);
} else {
fusb_write_byte( FUSB_SWITCHES1, 0x26);
fusb_write_byte( FUSB_SWITCHES0, 0x0B);
}
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
I2CBB::unlock2();
}
fusb_reset();
}
void fusb_get_status(union fusb_status *status) {
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
if (!I2CBB::lock2()) {
return;
}
}
/* Read the interrupt and status flags into status */
fusb_read_buf( FUSB_STATUS0A, 7, status->bytes);
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
I2CBB::unlock2();
}
}
enum fusb_typec_current fusb_get_typec_current() {
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
if (!I2CBB::lock2()) {
return fusb_tcc_none;
}
}
/* Read the BC_LVL into a variable */
enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte(
FUSB_STATUS0) & FUSB_STATUS0_BC_LVL);
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
I2CBB::unlock2();
}
return bc_lvl;
}
void fusb_reset() {
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
if (!I2CBB::lock2()) {
return;
}
}
/* Flush the TX buffer */
fusb_write_byte( FUSB_CONTROL0, 0x44);
/* Flush the RX buffer */
fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
/* Reset the PD logic */
// fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET);
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
I2CBB::unlock2();
}
}
bool fusb_read_id() {
//Return true if read of the revision ID is sane
uint8_t version = 0;
fusb_read_buf(FUSB_DEVICE_ID, 1, &version);
if (version == 0 || version == 0xFF)
return false;
return true;
}
uint8_t fusb302_detect() {
//Probe the I2C bus for its address
return I2CBB::probe(FUSB302B_ADDR);
}
#endif

View File

@@ -8,7 +8,12 @@
#include "stdlib.h" #include "stdlib.h"
#include "task.h" #include "task.h"
#include "I2C_Wrapper.hpp" #include "I2C_Wrapper.hpp"
#include "fusbpd.h"
void postRToSInit() { void postRToSInit() {
// Any after RTos setup // Any after RTos setup
FRToSI2C::FRToSInit(); FRToSI2C::FRToSInit();
#ifdef POW_PD
//Spawn all of the USB-C processors
fusb302_start_processing();
#endif
} }

View File

@@ -9,6 +9,9 @@
#include "BSP.h" #include "BSP.h"
#include "Setup.h" #include "Setup.h"
#include "Pins.h" #include "Pins.h"
#include "I2CBB.hpp"
#include "fusbpd.h"
#include "Model_Config.h"
void preRToSInit() { void preRToSInit() {
/* Reset of all peripherals, Initializes the Flash interface and the Systick. /* Reset of all peripherals, Initializes the Flash interface and the Systick.
*/ */
@@ -18,5 +21,9 @@ void preRToSInit() {
HAL_Delay(50); HAL_Delay(50);
HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET);
HAL_Delay(50); HAL_Delay(50);
#ifdef I2C_SOFT
I2CBB::init();
#endif
} }

View File

@@ -82,3 +82,6 @@ void DMA1_Channel6_IRQHandler(void) {
void DMA1_Channel7_IRQHandler(void) { void DMA1_Channel7_IRQHandler(void) {
HAL_DMA_IRQHandler(&hdma_i2c1_rx); HAL_DMA_IRQHandler(&hdma_i2c1_rx);
} }
void EXTI9_5_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
}

View File

@@ -11,6 +11,7 @@
#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
/* #define DATA_IN_ExtSRAM */ /* #define DATA_IN_ExtSRAM */
#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
//#define LOCAL_BUILD
#ifndef LOCAL_BUILD #ifndef LOCAL_BUILD
#define VECT_TAB_OFFSET 0x00004000U /*!< Vector Table base offset field. #define VECT_TAB_OFFSET 0x00004000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */ This value must be a multiple of 0x200. */

View File

@@ -24,7 +24,7 @@ ButtonState getButtonState() {
*/ */
static uint8_t previousState = 0; static uint8_t previousState = 0;
static uint32_t previousStateChange = 0; static uint32_t previousStateChange = 0;
const uint16_t timeout = 40; const uint16_t timeout = 400;
uint8_t currentState; uint8_t currentState;
currentState = (getButtonA()) << 0; currentState = (getButtonA()) << 0;
currentState |= (getButtonB()) << 1; currentState |= (getButtonB()) << 1;

View File

@@ -0,0 +1,305 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_FUSB302B_H
#define PDB_FUSB302B_H
#include <stdint.h>
#include "pd.h"
#include <pdb_msg.h>
/* I2C addresses of the FUSB302B chips */
#define FUSB302B_ADDR (0x22<<1)
#define FUSB302B01_ADDR (0x23<<1)
#define FUSB302B10_ADDR (0x24<<1)
#define FUSB302B11_ADDR (0x25<<1)
/* Device ID register */
#define FUSB_DEVICE_ID 0x01
#define FUSB_DEVICE_ID_VERSION_ID_SHIFT 4
#define FUSB_DEVICE_ID_VERSION_ID (0xF << FUSB_DEVICE_ID_VERSION_ID_SHIFT)
#define FUSB_DEVICE_ID_PRODUCT_ID_SHIFT 2
#define FUSB_DEVICE_ID_PRODUCT_ID (0x3 << FUSB_DEVICE_ID_PRODUCT_ID_SHIFT)
#define FUSB_DEVICE_ID_REVISION_ID_SHIFT 0
#define FUSB_DEVICE_ID_REVISION_ID (0x3 << FUSB_DEVICE_ID_REVISION_ID_SHIFT)
/* Switches0 register */
#define FUSB_SWITCHES0 0x02
#define FUSB_SWITCHES0_PU_EN2 (1 << 7)
#define FUSB_SWITCHES0_PU_EN1 (1 << 6)
#define FUSB_SWITCHES0_VCONN_CC2 (1 << 5)
#define FUSB_SWITCHES0_VCONN_CC1 (1 << 4)
#define FUSB_SWITCHES0_MEAS_CC2 (1 << 3)
#define FUSB_SWITCHES0_MEAS_CC1 (1 << 2)
#define FUSB_SWITCHES0_PDWN_2 (1 << 1)
#define FUSB_SWITCHES0_PDWN_1 1
/* Switches1 register */
#define FUSB_SWITCHES1 0x03
#define FUSB_SWITCHES1_POWERROLE (1 << 7)
#define FUSB_SWITCHES1_SPECREV_SHIFT 5
#define FUSB_SWITCHES1_SPECREV (0x3 << FUSB_SWITCHES1_SPECREV_SHIFT)
#define FUSB_SWITCHES1_DATAROLE (1 << 4)
#define FUSB_SWITCHES1_AUTO_CRC (1 << 2)
#define FUSB_SWITCHES1_TXCC2 (1 << 1)
#define FUSB_SWITCHES1_TXCC1 1
/* Measure register */
#define FUSB_MEASURE 0x04
#define FUSB_MEASURE_MEAS_VBUS (1 << 6)
#define FUSB_MEASURE_MDAC_SHIFT 0
#define FUSB_MEASURE_MDAC (0x3F << FUSB_MEASURE_MDAC_SHIFT)
/* Slice register */
#define FUSB_SLICE 0x05
#define FUSB_SLICE_SDAC_HYS_SHIFT 6
#define FUSB_SLICE_SDAC_HYS (0x3 << FUSB_SLICE_SDAC_HYS_SHIFT)
#define FUSB_SLICE_SDAC_SHIFT 0
#define FUSB_SLICE_SDAC (0x3F << FUSB_SLICE_SDAC_SHIFT)
/* Control0 register */
#define FUSB_CONTROL0 0x06
#define FUSB_CONTROL0_TX_FLUSH (1 << 6)
#define FUSB_CONTROL0_INT_MASK (1 << 5)
#define FUSB_CONTROL0_HOST_CUR_SHIFT 2
#define FUSB_CONTROL0_HOST_CUR (0x3 << FUSB_CONTROL0_HOST_CUR_SHIFT)
#define FUSB_CONTROL0_AUTO_PRE (1 << 1)
#define FUSB_CONTROL0_TX_START 1
/* Control1 register */
#define FUSB_CONTROL1 0x07
#define FUSB_CONTROL1_ENSOP2DB (1 << 6)
#define FUSB_CONTROL1_ENSOP1DB (1 << 5)
#define FUSB_CONTROL1_BIST_MODE2 (1 << 4)
#define FUSB_CONTROL1_RX_FLUSH (1 << 2)
#define FUSB_CONTROL1_ENSOP2 (1 << 1)
#define FUSB_CONTROL1_ENSOP1 1
/* Control2 register */
#define FUSB_CONTROL2 0x08
#define FUSB_CONTROL2_TOG_SAVE_PWR_SHIFT 6
#define FUSB_CONTROL2_TOG_SAVE_PWR (0x3 << FUSB_CONTROL2_TOG_SAVE_PWR)
#define FUSB_CONTROL2_TOG_RD_ONLY (1 << 5)
#define FUSB_CONTROL2_WAKE_EN (1 << 3)
#define FUSB_CONTROL2_MODE_SHIFT 1
#define FUSB_CONTROL2_MODE (0x3 << FUSB_CONTROL2_MODE_SHIFT)
#define FUSB_CONTROL2_TOGGLE 1
/* Control3 register */
#define FUSB_CONTROL3 0x09
#define FUSB_CONTROL3_SEND_HARD_RESET (1 << 6)
#define FUSB_CONTROL3_BIST_TMODE (1 << 5)
#define FUSB_CONTROL3_AUTO_HARDRESET (1 << 4)
#define FUSB_CONTROL3_AUTO_SOFTRESET (1 << 3)
#define FUSB_CONTROL3_N_RETRIES_SHIFT 1
#define FUSB_CONTROL3_N_RETRIES (0x3 << FUSB_CONTROL3_N_RETRIES_SHIFT)
#define FUSB_CONTROL3_AUTO_RETRY 1
/* Mask1 register */
#define FUSB_MASK1 0x0A
#define FUSB_MASK1_M_VBUSOK (1 << 7)
#define FUSB_MASK1_M_ACTIVITY (1 << 6)
#define FUSB_MASK1_M_COMP_CHNG (1 << 5)
#define FUSB_MASK1_M_CRC_CHK (1 << 4)
#define FUSB_MASK1_M_ALERT (1 << 3)
#define FUSB_MASK1_M_WAKE (1 << 2)
#define FUSB_MASK1_M_COLLISION (1 << 1)
#define FUSB_MASK1_M_BC_LVL (1 << 0)
/* Power register */
#define FUSB_POWER 0x0B
#define FUSB_POWER_PWR3 (1 << 3)
#define FUSB_POWER_PWR2 (1 << 2)
#define FUSB_POWER_PWR1 (1 << 1)
#define FUSB_POWER_PWR0 1
/* Reset register */
#define FUSB_RESET 0x0C
#define FUSB_RESET_PD_RESET (1 << 1)
#define FUSB_RESET_SW_RES 1
/* OCPreg register */
#define FUSB_OCPREG 0x0D
#define FUSB_OCPREG_OCP_RANGE (1 << 3)
#define FUSB_OCPREG_OCP_CUR_SHIFT 0
#define FUSB_OCPREG_OCP_CUR (0x7 << FUSB_OCPREG_OCP_CUR_SHIFT)
/* Maska register */
#define FUSB_MASKA 0x0E
#define FUSB_MASKA_M_OCP_TEMP (1 << 7)
#define FUSB_MASKA_M_TOGDONE (1 << 6)
#define FUSB_MASKA_M_SOFTFAIL (1 << 5)
#define FUSB_MASKA_M_RETRYFAIL (1 << 4)
#define FUSB_MASKA_M_HARDSENT (1 << 3)
#define FUSB_MASKA_M_TXSENT (1 << 2)
#define FUSB_MASKA_M_SOFTRST (1 << 1)
#define FUSB_MASKA_M_HARDRST 1
/* Maskb register */
#define FUSB_MASKB 0x0F
#define FUSB_MASKB_M_GCRCSENT 1
/* Control4 register */
#define FUSB_CONTROL4 0x10
#define FUSB_CONTROL4_TOG_EXIT_AUD 1
/* Status0a register */
#define FUSB_STATUS0A 0x3C
#define FUSB_STATUS0A_SOFTFAIL (1 << 5)
#define FUSB_STATUS0A_RETRYFAIL (1 << 4)
#define FUSB_STATUS0A_POWER3 (1 << 3)
#define FUSB_STATUS0A_POWER2 (1 << 2)
#define FUSB_STATUS0A_SOFTRST (1 << 1)
#define FUSB_STATUS0A_HARDRST 1
/* Status1a register */
#define FUSB_STATUS1A 0x3D
#define FUSB_STATUS1A_TOGSS_SHIFT 3
#define FUSB_STATUS1A_TOGSS (0x7 << FUSB_STATUS1A_TOGSS_SHIFT)
#define FUSB_STATUS1A_RXSOP2DB (1 << 2)
#define FUSB_STATUS1A_RXSOP1DB (1 << 1)
#define FUSB_STATUS1A_RXSOP 1
/* Interrupta register */
#define FUSB_INTERRUPTA 0x3E
#define FUSB_INTERRUPTA_I_OCP_TEMP (1 << 7)
#define FUSB_INTERRUPTA_I_TOGDONE (1 << 6)
#define FUSB_INTERRUPTA_I_SOFTFAIL (1 << 5)
#define FUSB_INTERRUPTA_I_RETRYFAIL (1 << 4)
#define FUSB_INTERRUPTA_I_HARDSENT (1 << 3)
#define FUSB_INTERRUPTA_I_TXSENT (1 << 2)
#define FUSB_INTERRUPTA_I_SOFTRST (1 << 1)
#define FUSB_INTERRUPTA_I_HARDRST 1
/* Interruptb register */
#define FUSB_INTERRUPTB 0x3F
#define FUSB_INTERRUPTB_I_GCRCSENT 1
/* Status0 register */
#define FUSB_STATUS0 0x40
#define FUSB_STATUS0_VBUSOK (1 << 7)
#define FUSB_STATUS0_ACTIVITY (1 << 6)
#define FUSB_STATUS0_COMP (1 << 5)
#define FUSB_STATUS0_CRC_CHK (1 << 4)
#define FUSB_STATUS0_ALERT (1 << 3)
#define FUSB_STATUS0_WAKE (1 << 2)
#define FUSB_STATUS0_BC_LVL_SHIFT 0
#define FUSB_STATUS0_BC_LVL (0x3 << FUSB_STATUS0_BC_LVL_SHIFT)
/* Status1 register */
#define FUSB_STATUS1 0x41
#define FUSB_STATUS1_RXSOP2 (1 << 7)
#define FUSB_STATUS1_RXSOP1 (1 << 6)
#define FUSB_STATUS1_RX_EMPTY (1 << 5)
#define FUSB_STATUS1_RX_FULL (1 << 4)
#define FUSB_STATUS1_TX_EMPTY (1 << 3)
#define FUSB_STATUS1_TX_FULL (1 << 2)
#define FUSB_STATUS1_OVRTEMP (1 << 1)
#define FUSB_STATUS1_OCP 1
/* Interrupt register */
#define FUSB_INTERRUPT 0x42
#define FUSB_INTERRUPT_I_VBUSOK (1 << 7)
#define FUSB_INTERRUPT_I_ACTIVITY (1 << 6)
#define FUSB_INTERRUPT_I_COMP_CHNG (1 << 5)
#define FUSB_INTERRUPT_I_CRC_CHK (1 << 4)
#define FUSB_INTERRUPT_I_ALERT (1 << 3)
#define FUSB_INTERRUPT_I_WAKE (1 << 2)
#define FUSB_INTERRUPT_I_COLLISION (1 << 1)
#define FUSB_INTERRUPT_I_BC_LVL 1
/* FIFOs register */
#define FUSB_FIFOS 0x43
#define FUSB_FIFO_TX_TXON 0xA1
#define FUSB_FIFO_TX_SOP1 0x12
#define FUSB_FIFO_TX_SOP2 0x13
#define FUSB_FIFO_TX_SOP3 0x1B
#define FUSB_FIFO_TX_RESET1 0x15
#define FUSB_FIFO_TX_RESET2 0x16
#define FUSB_FIFO_TX_PACKSYM 0x80
#define FUSB_FIFO_TX_JAM_CRC 0xFF
#define FUSB_FIFO_TX_EOP 0x14
#define FUSB_FIFO_TX_TXOFF 0xFE
#define FUSB_FIFO_RX_TOKEN_BITS 0xE0
#define FUSB_FIFO_RX_SOP 0xE0
#define FUSB_FIFO_RX_SOP1 0xC0
#define FUSB_FIFO_RX_SOP2 0xA0
#define FUSB_FIFO_RX_SOP1DB 0x80
#define FUSB_FIFO_RX_SOP2DB 0x60
/*
* FUSB status union
*
* Provides a nicer structure than just an array of uint8_t for working with
* the FUSB302B status and interrupt flags.
*/
union fusb_status {
uint8_t bytes[7];
struct {
uint8_t status0a;
uint8_t status1a;
uint8_t interrupta;
uint8_t interruptb;
uint8_t status0;
uint8_t status1;
uint8_t interrupt;
};
};
/* FUSB functions */
/*
* Send a USB Power Delivery message to the FUSB302B
*/
void fusb_send_message(const union pd_msg *msg);
/*
* Read a USB Power Delivery message from the FUSB302B
*/
uint8_t fusb_read_message(union pd_msg *msg);
/*
* Tell the FUSB302B to send a hard reset signal
*/
void fusb_send_hardrst();
/*
* Read the FUSB302B status and interrupt flags into *status
*/
void fusb_get_status(union fusb_status *status);
/*
* Read the FUSB302B BC_LVL as an enum fusb_typec_current
*/
enum fusb_typec_current fusb_get_typec_current();
/*
* Initialization routine for the FUSB302B
*/
void fusb_setup();
/*
* Reset the FUSB302B
*/
void fusb_reset();
bool fusb_read_id();
#endif /* PDB_FUSB302B_H */

View File

@@ -0,0 +1,38 @@
/*
* fusbpd.cpp
*
* Created on: 13 Jun 2020
* Author: Ralim
*/
#include "Model_Config.h"
#ifdef POW_PD
#include <fusbpd.h>
#include <pd.h>
#include "BSP.h"
#include "I2CBB.hpp"
#include "fusb302b.h"
#include "policy_engine.h"
#include "protocol_rx.h"
#include "protocol_tx.h"
#include "int_n.h"
#include "hard_reset.h"
void fusb302_start_processing() {
/* Initialize the FUSB302B */
resetWatchdog();
fusb_setup();
resetWatchdog();
/* Create the policy engine thread. */
PolicyEngine::init();
/* Create the protocol layer threads. */
ProtocolReceive::init();
ProtocolTransmit::init();
ResetHandler::init();
resetWatchdog();
/* Create the INT_N thread. */
InterruptHandler::init();
}
#endif

View File

@@ -0,0 +1,18 @@
/*
* fusbpd.h
*
* Created on: 13 Jun 2020
* Author: Ralim
*/
#ifndef DRIVERS_FUSB302_FUSBPD_H_
#define DRIVERS_FUSB302_FUSBPD_H_
//Wrapper for all of the FUSB302 PD work
extern struct pdb_config pdb_config_data;
#include <stdint.h>
//returns 1 if the FUSB302 is on the I2C bus
uint8_t fusb302_detect();
void fusb302_start_processing();
#endif /* DRIVERS_FUSB302_FUSBPD_H_ */

View File

@@ -0,0 +1,152 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hard_reset.h"
#include "fusbpd.h"
#include <pd.h>
#include "policy_engine.h"
#include "protocol_rx.h"
#include "protocol_tx.h"
#include "fusb302b.h"
osThreadId ResetHandler::TaskHandle = NULL;
uint32_t ResetHandler::TaskBuffer[ResetHandler::TaskStackSize];
osStaticThreadDef_t ResetHandler::TaskControlBlock;
/*
* PRL_HR_Reset_Layer state
*/
ResetHandler::hardrst_state ResetHandler::hardrst_reset_layer() {
/* First, wait for the signal to run a hard reset. */
eventmask_t evt = waitForEvent(
PDB_EVT_HARDRST_RESET | PDB_EVT_HARDRST_I_HARDRST);
if (evt & (PDB_EVT_HARDRST_RESET | PDB_EVT_HARDRST_I_HARDRST)) {
/* Reset the Protocol RX machine */
ProtocolReceive::notify( PDB_EVT_PRLRX_RESET);
taskYIELD();
/* Reset the Protocol TX machine */
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET);
taskYIELD();
/* Continue the process based on what event started the reset. */
if (evt & PDB_EVT_HARDRST_RESET) {
/* Policy Engine started the reset. */
return PRLHRRequestHardReset;
} else {
/* PHY started the reset */
return PRLHRIndicateHardReset;
}
} else {
return PRLHRResetLayer;
}
}
ResetHandler::hardrst_state ResetHandler::hardrst_indicate_hard_reset() {
/* Tell the PE that we're doing a hard reset */
PolicyEngine::notify( PDB_EVT_PE_RESET);
return PRLHRWaitPE;
}
ResetHandler::hardrst_state ResetHandler::hardrst_request_hard_reset() {
/* Tell the PHY to send a hard reset */
fusb_send_hardrst();
return PRLHRWaitPHY;
}
ResetHandler::hardrst_state ResetHandler::hardrst_wait_phy() {
/* Wait for the PHY to tell us that it's done sending the hard reset */
waitForEvent(PDB_EVT_HARDRST_I_HARDSENT, PD_T_HARD_RESET_COMPLETE);
/* Move on no matter what made us stop waiting. */
return PRLHRHardResetRequested;
}
ResetHandler::hardrst_state ResetHandler::hardrst_hard_reset_requested() {
/* Tell the PE that the hard reset was sent */
PolicyEngine::notify( PDB_EVT_PE_HARD_SENT);
return PRLHRWaitPE;
}
ResetHandler::hardrst_state ResetHandler::hardrst_wait_pe() {
/* Wait for the PE to tell us that it's done */
waitForEvent(PDB_EVT_HARDRST_DONE);
return PRLHRComplete;
}
ResetHandler::hardrst_state ResetHandler::hardrst_complete() {
/* I'm not aware of anything we have to tell the FUSB302B, so just finish
* the reset routine. */
return PRLHRResetLayer;
}
void ResetHandler::init() {
osThreadStaticDef(rstHand, Thread, PDB_PRIO_PRL, 0, TaskStackSize,
TaskBuffer, &TaskControlBlock);
TaskHandle = osThreadCreate(osThread(rstHand), NULL);
}
void ResetHandler::notify(uint32_t notification) {
if (TaskHandle != NULL) {
xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits);
}
}
void ResetHandler::Thread(const void *arg) {
(void) arg;
ResetHandler::hardrst_state state = PRLHRResetLayer;
while (true) {
switch (state) {
case PRLHRResetLayer:
state = hardrst_reset_layer();
break;
case PRLHRIndicateHardReset:
state = hardrst_indicate_hard_reset();
break;
case PRLHRRequestHardReset:
state = hardrst_request_hard_reset();
break;
case PRLHRWaitPHY:
state = hardrst_wait_phy();
break;
case PRLHRHardResetRequested:
state = hardrst_hard_reset_requested();
break;
case PRLHRWaitPE:
state = hardrst_wait_pe();
break;
case PRLHRComplete:
state = hardrst_complete();
break;
default:
/* This is an error. It really shouldn't happen. We might
* want to handle it anyway, though. */
state = PRLHRResetLayer;
break;
}
}
}
uint32_t ResetHandler::waitForEvent(uint32_t mask, uint32_t ticksToWait) {
uint32_t pulNotificationValue;
xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait);
return pulNotificationValue;
}

View File

@@ -0,0 +1,63 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_HARD_RESET_H
#define PDB_HARD_RESET_H
#include <pd.h>
/* Events for the Hard Reset thread */
#define PDB_EVT_HARDRST_RESET EVENT_MASK(0)
#define PDB_EVT_HARDRST_I_HARDRST EVENT_MASK(1)
#define PDB_EVT_HARDRST_I_HARDSENT EVENT_MASK(2)
#define PDB_EVT_HARDRST_DONE EVENT_MASK(3)
class ResetHandler {
public:
static void init();
static void notify(uint32_t notification);
private:
static void Thread(const void *arg);
static osThreadId TaskHandle;
static const size_t TaskStackSize = 1536 / 2;
static uint32_t TaskBuffer[TaskStackSize];
static osStaticThreadDef_t TaskControlBlock;
static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait =
portMAX_DELAY);
/*
* Hard Reset machine states
*/
enum hardrst_state {
PRLHRResetLayer,
PRLHRIndicateHardReset,
PRLHRRequestHardReset,
PRLHRWaitPHY,
PRLHRHardResetRequested,
PRLHRWaitPE,
PRLHRComplete
};
static hardrst_state hardrst_reset_layer();
static hardrst_state hardrst_indicate_hard_reset();
static hardrst_state hardrst_request_hard_reset();
static hardrst_state hardrst_wait_phy();
static hardrst_state hardrst_hard_reset_requested();
static hardrst_state hardrst_wait_pe();
static hardrst_state hardrst_complete();
};
#endif /* PDB_HARD_RESET_H */

View File

@@ -0,0 +1,108 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "int_n.h"
#include "fusbpd.h"
#include <pd.h>
#include "fusb302b.h"
#include "protocol_rx.h"
#include "protocol_tx.h"
#include "hard_reset.h"
#include "policy_engine.h"
#include "protocol_rx.h"
#include "protocol_tx.h"
#include "task.h"
#include "BSP.h"
osThreadId InterruptHandler::TaskHandle=NULL;
uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize];
osStaticThreadDef_t InterruptHandler::TaskControlBlock;
void InterruptHandler::init() {
osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize,
TaskBuffer, &TaskControlBlock);
TaskHandle = osThreadCreate(osThread(intTask), NULL);
}
void InterruptHandler::Thread(const void *arg) {
(void) arg;
union fusb_status status;
volatile uint32_t events;
bool notifSent = false;
while (true) {
/* If the INT_N line is low */
if (xTaskNotifyWait(0x00, 0x0F, NULL,
PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 10) == pdPASS) {
//delay slightly so we catch the crc with better timing
osDelay(1);
}
notifSent = false;
/* Read the FUSB302B status and interrupt registers */
fusb_get_status(&status);
/* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX
* thread */
if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) {
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT);
notifSent = true;
}
if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) {
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
notifSent = true;
}
/* If the I_GCRCSENT flag is set, tell the Protocol RX thread */
//This means a message was recieved with a good CRC
if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) {
ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT);
notifSent = true;
}
/* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset
* thread */
if (notifSent == false) {
events = 0;
if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) {
events |= PDB_EVT_HARDRST_I_HARDRST;
notifSent = true;
} else if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) {
events |= PDB_EVT_HARDRST_I_HARDSENT;
notifSent = true;
}
if (events) {
ResetHandler::notify(events);
}
}
/* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy
* Engine thread */
if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP
&& status.status1 & FUSB_STATUS1_OVRTEMP) {
PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP);
notifSent = true;
}
}
}
void InterruptHandler::irqCallback() {
if (TaskHandle != NULL) {
BaseType_t taskWoke = pdFALSE;
xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits,
&taskWoke);
portYIELD_FROM_ISR(taskWoke);
}
}

View File

@@ -0,0 +1,57 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_INT_N_OLD_H
#define PDB_INT_N_OLD_H
#include <pd.h>
class InterruptHandler {
public:
//Creates the thread to handle the Interrupt pin
static void init();
static void irqCallback();
private:
static void Thread(const void *arg);
static osThreadId TaskHandle;
static const size_t TaskStackSize = 1536 / 3;
static uint32_t TaskBuffer[TaskStackSize];
static osStaticThreadDef_t TaskControlBlock;
/*
* Hard Reset machine states
*/
enum hardrst_state {
PRLHRResetLayer,
PRLHRIndicateHardReset,
PRLHRRequestHardReset,
PRLHRWaitPHY,
PRLHRHardResetRequested,
PRLHRWaitPE,
PRLHRComplete
};
static enum hardrst_state hardrst_reset_layer();
static enum hardrst_state hardrst_indicate_hard_reset();
static enum hardrst_state hardrst_request_hard_reset();
static enum hardrst_state hardrst_wait_phy();
static enum hardrst_state hardrst_hard_reset_requested();
static enum hardrst_state hardrst_wait_pe();
static enum hardrst_state hardrst_complete();
};
#endif /* PDB_INT_N_OLD_H */

View File

@@ -0,0 +1,400 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_PD_H
#define PDB_PD_H
#include <stdint.h>
#include "FreeRTOS.h"
#include "pdb_msg.h"
#include "cmsis_os.h"
#include "pdb_conf.h"
/*
* Macros for working with USB Power Delivery messages.
*
* This file is mostly written from the PD Rev. 2.0 spec, but the header is
* written from the Rev. 3.0 spec.
*/
/*
* PD Header
*/
#define PD_HDR_MSGTYPE_SHIFT 0
#define PD_HDR_MSGTYPE (0x1F << PD_HDR_MSGTYPE_SHIFT)
#define PD_HDR_DATAROLE_SHIFT 5
#define PD_HDR_DATAROLE (0x1 << PD_HDR_DATAROLE_SHIFT)
#define PD_HDR_SPECREV_SHIFT 6
#define PD_HDR_SPECREV (0x3 << PD_HDR_SPECREV_SHIFT)
#define PD_HDR_POWERROLE_SHIFT 8
#define PD_HDR_POWERROLE (1 << PD_HDR_POWERROLE_SHIFT)
#define PD_HDR_MESSAGEID_SHIFT 9
#define PD_HDR_MESSAGEID (0x7 << PD_HDR_MESSAGEID_SHIFT)
#define PD_HDR_NUMOBJ_SHIFT 12
#define PD_HDR_NUMOBJ (0x7 << PD_HDR_NUMOBJ_SHIFT)
#define PD_HDR_EXT (1 << 15)
/* Message types */
#define PD_MSGTYPE_GET(msg) (((msg)->hdr & PD_HDR_MSGTYPE) >> PD_HDR_MSGTYPE_SHIFT)
/* Control Message */
#define PD_MSGTYPE_GOODCRC 0x01
#define PD_MSGTYPE_GOTOMIN 0x02
#define PD_MSGTYPE_ACCEPT 0x03
#define PD_MSGTYPE_REJECT 0x04
#define PD_MSGTYPE_PING 0x05
#define PD_MSGTYPE_PS_RDY 0x06
#define PD_MSGTYPE_GET_SOURCE_CAP 0x07
#define PD_MSGTYPE_GET_SINK_CAP 0x08
#define PD_MSGTYPE_DR_SWAP 0x09
#define PD_MSGTYPE_PR_SWAP 0x0A
#define PD_MSGTYPE_VCONN_SWAP 0x0B
#define PD_MSGTYPE_WAIT 0x0C
#define PD_MSGTYPE_SOFT_RESET 0x0D
#define PD_MSGTYPE_NOT_SUPPORTED 0x10
#define PD_MSGTYPE_GET_SOURCE_CAP_EXTENDED 0x11
#define PD_MSGTYPE_GET_STATUS 0x12
#define PD_MSGTYPE_FR_SWAP 0x13
#define PD_MSGTYPE_GET_PPS_STATUS 0x14
#define PD_MSGTYPE_GET_COUNTRY_CODES 0x15
/* Data Message */
#define PD_MSGTYPE_SOURCE_CAPABILITIES 0x01
#define PD_MSGTYPE_REQUEST 0x02
#define PD_MSGTYPE_BIST 0x03
#define PD_MSGTYPE_SINK_CAPABILITIES 0x04
#define PD_MSGTYPE_BATTERY_STATUS 0x05
#define PD_MSGTYPE_ALERT 0x06
#define PD_MSGTYPE_GET_COUNTRY_INFO 0x07
#define PD_MSGTYPE_VENDOR_DEFINED 0x0F
/* Extended Message */
#define PD_MSGTYPE_SOURCE_CAPABILITIES_EXTENDED 0x01
#define PD_MSGTYPE_STATUS 0x02
#define PD_MSGTYPE_GET_BATTERY_CAP 0x03
#define PD_MSGTYPE_GET_BATTERY_STATUS 0x04
#define PD_MSGTYPE_BATTERY_CAPABILITIES 0x05
#define PD_MSGTYPE_GET_MANUFACTURER_INFO 0x06
#define PD_MSGTYPE_MANUFACTURER_INFO 0x07
#define PD_MSGTYPE_SECURITY_REQUEST 0x08
#define PD_MSGTYPE_SECURITY_RESPONSE 0x09
#define PD_MSGTYPE_FIRMWARE_UPDATE_REQUEST 0x0A
#define PD_MSGTYPE_FIRMWARE_UPDATE_RESPONSE 0x0B
#define PD_MSGTYPE_PPS_STATUS 0x0C
#define PD_MSGTYPE_COUNTRY_INFO 0x0D
#define PD_MSGTYPE_COUNTRY_CODES 0x0E
/* Data roles */
#define PD_DATAROLE_UFP (0x0 << PD_HDR_DATAROLE_SHIFT)
#define PD_DATAROLE_DFP (0x1 << PD_HDR_DATAROLE_SHIFT)
/* Specification revisions */
#define PD_SPECREV_1_0 (0x0 << PD_HDR_SPECREV_SHIFT)
#define PD_SPECREV_2_0 (0x1 << PD_HDR_SPECREV_SHIFT)
#define PD_SPECREV_3_0 (0x2 << PD_HDR_SPECREV_SHIFT)
/* Port power roles */
#define PD_POWERROLE_SINK (0x0 << PD_HDR_POWERROLE_SHIFT)
#define PD_POWERROLE_SOURCE (0x1 << PD_HDR_POWERROLE_SHIFT)
/* Message ID */
#define PD_MESSAGEID_GET(msg) (((msg)->hdr & PD_HDR_MESSAGEID) >> PD_HDR_MESSAGEID_SHIFT)
/* Number of data objects */
#define PD_NUMOBJ(n) (((n) << PD_HDR_NUMOBJ_SHIFT) & PD_HDR_NUMOBJ)
#define PD_NUMOBJ_GET(msg) (((msg)->hdr & PD_HDR_NUMOBJ) >> PD_HDR_NUMOBJ_SHIFT)
/*
* PD Extended Message Header
*/
#define PD_EXTHDR_DATA_SIZE_SHIFT 0
#define PD_EXTHDR_DATA_SIZE (0x1FF << PD_EXTHDR_DATA_SIZE_SHIFT)
#define PD_EXTHDR_REQUEST_CHUNK_SHIFT 10
#define PD_EXTHDR_REQUEST_CHUNK (1 << PD_EXTHDR_REQUEST_CHUNK_SHIFT)
#define PD_EXTHDR_CHUNK_NUMBER_SHIFT 11
#define PD_EXTHDR_CHUNK_NUMBER (0xF << PD_EXTHDR_CHUNK_NUMBER_SHIFT)
#define PD_EXTHDR_CHUNKED_SHIFT 15
#define PD_EXTHDR_CHUNKED (1 << PD_EXTHDR_CHUNKED_SHIFT)
/* Data size */
#define PD_DATA_SIZE(n) (((n) << PD_EXTHDR_DATA_SIZE_SHIFT) & PD_EXTHDR_DATA_SIZE)
#define PD_DATA_SIZE_GET(msg) (((msg)->exthdr & PD_EXTHDR_DATA_SIZE) >> PD_EXTHDR_DATA_SIZE_SHIFT)
/* Chunk number */
#define PD_CHUNK_NUMBER(n) (((n) << PD_EXTHDR_CHUNK_NUMBER_SHIFT) & PD_EXTHDR_CHUNK_NUMBER)
#define PD_CHUNK_NUMBER_GET(msg) (((msg)->exthdr & PD_EXTHDR_CHUNK_NUMBER) >> PD_EXTHDR_CHUNK_NUMBER_SHIFT)
/*
* PD Power Data Object
*/
#define PD_PDO_TYPE_SHIFT 30
#define PD_PDO_TYPE (0x3 << PD_PDO_TYPE_SHIFT)
/* PDO types */
#define PD_PDO_TYPE_FIXED ((unsigned) (0x0 << PD_PDO_TYPE_SHIFT))
#define PD_PDO_TYPE_BATTERY ((unsigned) (0x1 << PD_PDO_TYPE_SHIFT))
#define PD_PDO_TYPE_VARIABLE ((unsigned) (0x2 << PD_PDO_TYPE_SHIFT))
#define PD_PDO_TYPE_AUGMENTED ((unsigned) (0x3 << PD_PDO_TYPE_SHIFT))
#define PD_APDO_TYPE_SHIFT 28
#define PD_APDO_TYPE (0x3 << PD_APDO_TYPE_SHIFT)
/* APDO types */
#define PD_APDO_TYPE_PPS (0x0 << PD_APDO_TYPE_SHIFT)
/* PD Source Fixed PDO */
#define PD_PDO_SRC_FIXED_DUAL_ROLE_PWR_SHIFT 29
#define PD_PDO_SRC_FIXED_DUAL_ROLE_PWR (1 << PD_PDO_SRC_FIXED_DUAL_ROLE_PWR_SHIFT)
#define PD_PDO_SRC_FIXED_USB_SUSPEND_SHIFT 28
#define PD_PDO_SRC_FIXED_USB_SUSPEND (1 << PD_PDO_SRC_FIXED_USB_SUSPEND_SHIFT)
#define PD_PDO_SRC_FIXED_UNCONSTRAINED_SHIFT 27
#define PD_PDO_SRC_FIXED_UNCONSTRAINED (1 << PD_PDO_SRC_FIXED_UNCONSTRAINED_SHIFT)
#define PD_PDO_SRC_FIXED_USB_COMMS_SHIFT 26
#define PD_PDO_SRC_FIXED_USB_COMMS (1 << PD_PDO_SRC_FIXED_USB_COMMS_SHIFT)
#define PD_PDO_SRC_FIXED_DUAL_ROLE_DATA_SHIFT 25
#define PD_PDO_SRC_FIXED_DUAL_ROLE_DATA (1 << PD_PDO_SRC_FIXED_DUAL_ROLE_DATA_SHIFT)
#define PD_PDO_SRC_FIXED_UNCHUNKED_EXT_MSG_SHIFT 24
#define PD_PDO_SRC_FIXED_UNCHUNKED_EXT_MSG (1 << PD_PDO_SRC_FIXED_UNCHUNKED_EXT_MSG_SHIFT)
#define PD_PDO_SRC_FIXED_PEAK_CURRENT_SHIFT 20
#define PD_PDO_SRC_FIXED_PEAK_CURRENT (0x3 << PD_PDO_SRC_FIXED_PEAK_CURRENT_SHIFT)
#define PD_PDO_SRC_FIXED_VOLTAGE_SHIFT 10
#define PD_PDO_SRC_FIXED_VOLTAGE (0x3FF << PD_PDO_SRC_FIXED_VOLTAGE_SHIFT)
#define PD_PDO_SRC_FIXED_CURRENT_SHIFT 0
#define PD_PDO_SRC_FIXED_CURRENT (0x3FF << PD_PDO_SRC_FIXED_CURRENT_SHIFT)
/* PD Source Fixed PDO current */
#define PD_PDO_SRC_FIXED_CURRENT_GET(pdo) (((pdo) & PD_PDO_SRC_FIXED_CURRENT) >> PD_PDO_SRC_FIXED_CURRENT_SHIFT)
/* PD Source Fixed PDO voltage */
#define PD_PDO_SRC_FIXED_VOLTAGE_GET(pdo) (((pdo) & PD_PDO_SRC_FIXED_VOLTAGE) >> PD_PDO_SRC_FIXED_VOLTAGE_SHIFT)
/* PD Programmable Power Supply APDO */
#define PD_APDO_PPS_MAX_VOLTAGE_SHIFT 17
#define PD_APDO_PPS_MAX_VOLTAGE (0xFF << PD_APDO_PPS_MAX_VOLTAGE_SHIFT)
#define PD_APDO_PPS_MIN_VOLTAGE_SHIFT 8
#define PD_APDO_PPS_MIN_VOLTAGE (0xFF << PD_APDO_PPS_MIN_VOLTAGE_SHIFT)
#define PD_APDO_PPS_CURRENT_SHIFT 0
#define PD_APDO_PPS_CURRENT (0x7F << PD_APDO_PPS_CURRENT_SHIFT)
/* PD Programmable Power Supply APDO voltages */
#define PD_APDO_PPS_MAX_VOLTAGE_GET(pdo) (((pdo) & PD_APDO_PPS_MAX_VOLTAGE) >> PD_APDO_PPS_MAX_VOLTAGE_SHIFT)
#define PD_APDO_PPS_MIN_VOLTAGE_GET(pdo) (((pdo) & PD_APDO_PPS_MIN_VOLTAGE) >> PD_APDO_PPS_MIN_VOLTAGE_SHIFT)
#define PD_APDO_PPS_MAX_VOLTAGE_SET(v) (((v) << PD_APDO_PPS_MAX_VOLTAGE_SHIFT) & PD_APDO_PPS_MAX_VOLTAGE)
#define PD_APDO_PPS_MIN_VOLTAGE_SET(v) (((v) << PD_APDO_PPS_MIN_VOLTAGE_SHIFT) & PD_APDO_PPS_MIN_VOLTAGE)
/* PD Programmable Power Supply APDO current */
#define PD_APDO_PPS_CURRENT_GET(pdo) ((uint8_t) (((pdo) & PD_APDO_PPS_CURRENT) >> PD_APDO_PPS_CURRENT_SHIFT))
#define PD_APDO_PPS_CURRENT_SET(i) (((i) << PD_APDO_PPS_CURRENT_SHIFT) & PD_APDO_PPS_CURRENT)
/* PD Sink Fixed PDO */
#define PD_PDO_SNK_FIXED_DUAL_ROLE_PWR_SHIFT 29
#define PD_PDO_SNK_FIXED_DUAL_ROLE_PWR (1 << PD_PDO_SNK_FIXED_DUAL_ROLE_PWR_SHIFT)
#define PD_PDO_SNK_FIXED_HIGHER_CAP_SHIFT 28
#define PD_PDO_SNK_FIXED_HIGHER_CAP (1 << PD_PDO_SNK_FIXED_HIGHER_CAP_SHIFT)
#define PD_PDO_SNK_FIXED_UNCONSTRAINED_SHIFT 27
#define PD_PDO_SNK_FIXED_UNCONSTRAINED (1 << PD_PDO_SNK_FIXED_UNCONSTRAINED_SHIFT)
#define PD_PDO_SNK_FIXED_USB_COMMS_SHIFT 26
#define PD_PDO_SNK_FIXED_USB_COMMS (1 << PD_PDO_SNK_FIXED_USB_COMMS_SHIFT)
#define PD_PDO_SNK_FIXED_DUAL_ROLE_DATA_SHIFT 25
#define PD_PDO_SNK_FIXED_DUAL_ROLE_DATA (1 << PD_PDO_SNK_FIXED_DUAL_ROLE_DATA_SHIFT)
#define PD_PDO_SNK_FIXED_VOLTAGE_SHIFT 10
#define PD_PDO_SNK_FIXED_VOLTAGE (0x3FF << PD_PDO_SNK_FIXED_VOLTAGE_SHIFT)
#define PD_PDO_SNK_FIXED_CURRENT_SHIFT 0
#define PD_PDO_SNK_FIXED_CURRENT (0x3FF << PD_PDO_SNK_FIXED_CURRENT_SHIFT)
/* PD Sink Fixed PDO current */
#define PD_PDO_SNK_FIXED_CURRENT_SET(i) (((i) << PD_PDO_SNK_FIXED_CURRENT_SHIFT) & PD_PDO_SNK_FIXED_CURRENT)
/* PD Sink Fixed PDO voltage */
#define PD_PDO_SNK_FIXED_VOLTAGE_SET(v) (((v) << PD_PDO_SNK_FIXED_VOLTAGE_SHIFT) & PD_PDO_SNK_FIXED_VOLTAGE)
/*
* PD Request Data Object
*/
#define PD_RDO_OBJPOS_SHIFT 28
#define PD_RDO_OBJPOS (0x7 << PD_RDO_OBJPOS_SHIFT)
#define PD_RDO_GIVEBACK_SHIFT 27
#define PD_RDO_GIVEBACK (1 << PD_RDO_GIVEBACK_SHIFT)
#define PD_RDO_CAP_MISMATCH_SHIFT 26
#define PD_RDO_CAP_MISMATCH (1 << PD_RDO_CAP_MISMATCH_SHIFT)
#define PD_RDO_USB_COMMS_SHIFT 25
#define PD_RDO_USB_COMMS (1 << PD_RDO_USB_COMMS_SHIFT)
#define PD_RDO_NO_USB_SUSPEND_SHIFT 24
#define PD_RDO_NO_USB_SUSPEND (1 << PD_RDO_NO_USB_SUSPEND_SHIFT)
#define PD_RDO_UNCHUNKED_EXT_MSG_SHIFT 23
#define PD_RDO_UNCHUNKED_EXT_MSG (1 << PD_RDO_UNCHUNKED_EXT_MSG_SHIFT)
#define PD_RDO_OBJPOS_SET(i) (((i) << PD_RDO_OBJPOS_SHIFT) & PD_RDO_OBJPOS)
#define PD_RDO_OBJPOS_GET(msg) (((msg)->obj[0] & PD_RDO_OBJPOS) >> PD_RDO_OBJPOS_SHIFT)
/* Fixed and Variable RDO, no GiveBack support */
#define PD_RDO_FV_CURRENT_SHIFT 10
#define PD_RDO_FV_CURRENT (0x3FF << PD_RDO_FV_CURRENT_SHIFT)
#define PD_RDO_FV_MAX_CURRENT_SHIFT 0
#define PD_RDO_FV_MAX_CURRENT (0x3FF << PD_RDO_FV_MAX_CURRENT_SHIFT)
#define PD_RDO_FV_CURRENT_SET(i) (((i) << PD_RDO_FV_CURRENT_SHIFT) & PD_RDO_FV_CURRENT)
#define PD_RDO_FV_MAX_CURRENT_SET(i) (((i) << PD_RDO_FV_MAX_CURRENT_SHIFT) & PD_RDO_FV_MAX_CURRENT)
/* Fixed and Variable RDO with GiveBack support */
#define PD_RDO_FV_MIN_CURRENT_SHIFT 0
#define PD_RDO_FV_MIN_CURRENT (0x3FF << PD_RDO_FV_MIN_CURRENT_SHIFT)
#define PD_RDO_FV_MIN_CURRENT_SET(i) (((i) << PD_RDO_FV_MIN_CURRENT_SHIFT) & PD_RDO_FV_MIN_CURRENT)
/* TODO: Battery RDOs */
/* Programmable RDO */
#define PD_RDO_PROG_VOLTAGE_SHIFT 9
#define PD_RDO_PROG_VOLTAGE (0x7FF << PD_RDO_PROG_VOLTAGE_SHIFT)
#define PD_RDO_PROG_CURRENT_SHIFT 0
#define PD_RDO_PROG_CURRENT (0x7F << PD_RDO_PROG_CURRENT_SHIFT)
#define PD_RDO_PROG_VOLTAGE_SET(i) (((i) << PD_RDO_PROG_VOLTAGE_SHIFT) & PD_RDO_PROG_VOLTAGE)
#define PD_RDO_PROG_CURRENT_SET(i) (((i) << PD_RDO_PROG_CURRENT_SHIFT) & PD_RDO_PROG_CURRENT)
/*
* Time values
*
* Where a range is specified, the middle of the range (rounded down to the
* nearest millisecond) is used.
*/
#define PD_T_CHUNKING_NOT_SUPPORTED (450)
#define PD_T_HARD_RESET_COMPLETE (1000)
#define PD_T_PS_TRANSITION (5000)
#define PD_T_SENDER_RESPONSE (2700)
#define PD_T_SINK_REQUEST (1000)
#define PD_T_TYPEC_SINK_WAIT_CAP (1000)
#define PD_T_PD_DEBOUNCE (2000)
/*
* Counter maximums
*/
#define PD_N_HARD_RESET_COUNT 2
/*
* Value parameters
*/
#define PD_MAX_EXT_MSG_LEN 260
#define PD_MAX_EXT_MSG_CHUNK_LEN 26
#define PD_MAX_EXT_MSG_LEGACY_LEN 26
/*
* Unit conversions
*
* V: volt
* CV: centivolt
* MV: millivolt
* PRV: Programmable RDO voltage unit (20 mV)
* PDV: Power Delivery voltage unit (50 mV)
* PAV: PPS APDO voltage unit (100 mV)
*
* A: ampere
* CA: centiampere
* MA: milliampere
* PDI: Power Delivery current unit (10 mA)
* PAI: PPS APDO current unit (50 mA)
*
* W: watt
* CW: centiwatt
* MW: milliwatt
*
* O: ohm
* CO: centiohm
* MO: milliohm
*/
#define PD_MV2PRV(mv) ((mv) / 20)
#define PD_MV2PDV(mv) ((mv) / 50)
#define PD_MV2PAV(mv) ((mv) / 100)
#define PD_PRV2MV(prv) ((prv) * 20)
#define PD_PDV2MV(pdv) ((pdv) * 50)
#define PD_PAV2MV(pav) ((pav) * 100)
#define PD_MA2CA(ma) (((ma) + 10 - 1) / 10)
#define PD_MA2PDI(ma) (((ma) + 10 - 1) / 10)
#define PD_MA2PAI(ma) (((ma) + 50 - 1) / 50)
#define PD_CA2PAI(ca) (((ca) + 5 - 1) / 5)
#define PD_PDI2MA(pdi) ((pdi) * 10)
#define PD_PAI2MA(pai) ((pai) * 50)
#define PD_PAI2CA(pai) ((pai) * 5)
#define PD_MW2CW(mw) ((mw) / 10)
#define PD_MO2CO(mo) ((mo) / 10)
/* Get portions of a voltage in more normal units */
#define PD_MV_V(mv) ((mv) / 1000)
#define PD_MV_MV(mv) ((mv) % 1000)
#define PD_PDV_V(pdv) ((pdv) / 20)
#define PD_PDV_CV(pdv) (5 * ((pdv) % 20))
#define PD_PAV_V(pav) ((pav) / 10)
#define PD_PAV_CV(pav) (10 * ((pav) % 10))
/* Get portions of a PD current in more normal units */
#define PD_PDI_A(pdi) ((pdi) / 100)
#define PD_PDI_CA(pdi) ((pdi) % 100)
#define PD_PAI_A(pai) ((pai) / 20)
#define PD_PAI_CA(pai) (5 * ((pai) % 20))
/* Get portions of a power in more normal units */
#define PD_CW_W(cw) ((cw) / 100)
#define PD_CW_CW(cw) ((cw) % 100)
/* Get portions of a resistance in more normal units */
#define PD_CO_O(co) ((co) / 100)
#define PD_CO_CO(co) ((co) % 100)
/*
* Unit constants
*/
#define PD_MV_MIN 0
#define PD_MV_MAX 21000
#define PD_PDV_MIN PD_MV2PDV(PD_MV_MIN)
#define PD_PDV_MAX PD_MV2PDV(PD_MV_MAX)
#define PD_MA_MIN 0
#define PD_MA_MAX 5000
#define PD_CA_MIN PD_MA2CA(PD_MA_MIN)
#define PD_CA_MAX PD_MA2CA(PD_MA_MAX)
#define PD_PDI_MIN PD_MA2PDI(PD_MA_MIN)
#define PD_PDI_MAX PD_MA2PDI(PD_MA_MAX)
#define PD_MW_MIN 0
#define PD_MW_MAX 100000
#define PD_MO_MIN 500
#define PD_MO_MAX 655350
/*
* FUSB Type-C Current level enum
*/
enum fusb_typec_current {
fusb_tcc_none = 0,
fusb_tcc_default = 1,
fusb_tcc_1_5 = 2,
fusb_sink_tx_ng = 2,
fusb_tcc_3_0 = 3,
fusb_sink_tx_ok = 3
};
#endif /* PDB_PD_H */

View File

@@ -0,0 +1,32 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_CONF_H
#define PDB_CONF_H
/* Number of messages in the message pool */
#define PDB_MSG_POOL_SIZE 4
#define EVENT_MASK(x) (1<<x)
#define eventmask_t uint32_t
/* PD Buddy thread priorities */
#define PDB_PRIO_PE (osPriorityNormal)
#define PDB_PRIO_PRL (osPriorityBelowNormal)
#define PDB_PRIO_PRL_INT_N (osPriorityLow)
#endif /* PDB_CONF_H */

View File

@@ -0,0 +1,55 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_MSG_H
#define PDB_MSG_H
#include <stdint.h>
/*
* PD message union
*
* This can be safely read from or written to in any form without any
* transformations because everything in the system is little-endian.
*
* Two bytes of padding are required at the start to prevent problems due to
* alignment. Specifically, without the padding, &obj[0] != &bytes[2], making
* the statement in the previous paragraph invalid.
*/
union pd_msg {
struct {
uint8_t _pad1[2];
uint8_t bytes[30];
} __attribute__((packed));
struct {
uint8_t _pad2[2];
uint16_t hdr;
union {
uint32_t obj[7];
struct {
uint16_t exthdr;
uint8_t data[26];
};
};
} __attribute__((packed));
};
#endif /* PDB_MSG_H */

View File

@@ -0,0 +1,699 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "policy_engine.h"
#include <stdbool.h>
#include "int_n.h"
#include <pd.h>
#include "protocol_tx.h"
#include "hard_reset.h"
#include "fusb302b.h"
bool PolicyEngine::pdNegotiationComplete;
int PolicyEngine::current_voltage_mv;
int PolicyEngine::_requested_voltage;
bool PolicyEngine::_unconstrained_power;
union pd_msg PolicyEngine::currentMessage;
uint16_t PolicyEngine::hdr_template;
bool PolicyEngine::_explicit_contract;
int8_t PolicyEngine::_hard_reset_counter;
int8_t PolicyEngine::_old_tcc_match;
uint8_t PolicyEngine::_pps_index;
uint8_t PolicyEngine::_last_pps;
osThreadId PolicyEngine::TaskHandle = NULL;
uint32_t PolicyEngine::TaskBuffer[PolicyEngine::TaskStackSize];
osStaticThreadDef_t PolicyEngine::TaskControlBlock;
union pd_msg PolicyEngine::tempMessage;
union pd_msg PolicyEngine::_last_dpm_request;
PolicyEngine::policy_engine_state PolicyEngine::state = PESinkStartup;
StaticQueue_t PolicyEngine::xStaticQueue;
uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_SIZE
* sizeof(union pd_msg)];
QueueHandle_t PolicyEngine::messagesWaiting = NULL;
EventGroupHandle_t PolicyEngine::xEventGroupHandle = NULL;
StaticEventGroup_t PolicyEngine::xCreatedEventGroup;
void PolicyEngine::init() {
messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE,
sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
//Create static thread at PDB_PRIO_PE priority
osThreadStaticDef(PolEng, pe_task, PDB_PRIO_PE, 0, TaskStackSize,
TaskBuffer, &TaskControlBlock);
TaskHandle = osThreadCreate(osThread(PolEng), NULL);
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
}
void PolicyEngine::notify(uint32_t notification) {
if (xEventGroupHandle != NULL) {
xEventGroupSetBits(xEventGroupHandle, notification);
}
}
void PolicyEngine::pe_task(const void *arg) {
(void) arg;
//Internal thread loop
hdr_template = PD_DATAROLE_UFP | PD_POWERROLE_SINK;
/* Initialize the old_tcc_match */
_old_tcc_match = -1;
/* Initialize the pps_index */
_pps_index = 8;
/* Initialize the last_pps */
_last_pps = 8;
for (;;) {
//Loop based on state
switch (state) {
case PESinkStartup:
state = pe_sink_startup();
break;
case PESinkDiscovery:
state = pe_sink_discovery();
break;
case PESinkWaitCap:
state = pe_sink_wait_cap();
break;
case PESinkEvalCap:
state = pe_sink_eval_cap();
break;
case PESinkSelectCap:
state = pe_sink_select_cap();
break;
case PESinkTransitionSink:
state = pe_sink_transition_sink();
break;
case PESinkReady:
state = pe_sink_ready();
break;
case PESinkGetSourceCap:
state = pe_sink_get_source_cap();
break;
case PESinkGiveSinkCap:
state = pe_sink_give_sink_cap();
break;
case PESinkHardReset:
state = pe_sink_hard_reset();
break;
case PESinkTransitionDefault:
state = pe_sink_transition_default();
break;
case PESinkSoftReset:
state = pe_sink_soft_reset();
break;
case PESinkSendSoftReset:
state = pe_sink_send_soft_reset();
break;
case PESinkSendNotSupported:
state = pe_sink_send_not_supported();
break;
case PESinkChunkReceived:
state = pe_sink_chunk_received();
break;
case PESinkSourceUnresponsive:
state = pe_sink_source_unresponsive();
break;
case PESinkNotSupportedReceived:
state = pe_sink_not_supported_received();
break;
default:
state = PESinkStartup;
break;
}
}
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_startup() {
/* We don't have an explicit contract currently */
_explicit_contract = false;
//If desired could send an alert that PD is starting
/* No need to reset the protocol layer here. There are two ways into this
* state: startup and exiting hard reset. On startup, the protocol layer
* is reset by the startup procedure. When exiting hard reset, the
* protocol layer is reset by the hard reset state machine. Since it's
* already done somewhere else, there's no need to do it again here. */
return PESinkDiscovery;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_discovery() {
/* Wait for VBUS. Since it's our only power source, we already know that
* we have it, so just move on. */
return PESinkWaitCap;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() {
/* Fetch a message from the protocol layer */
eventmask_t evt = 0;
if (readMessage()) {
evt = PDB_EVT_PE_MSG_RX_PEND;
} else {
evt = waitForEvent(
PDB_EVT_PE_MSG_RX | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_RESET,
//Wait for cap timeout
PD_T_TYPEC_SINK_WAIT_CAP);
}
/* If we timed out waiting for Source_Capabilities, send a hard reset */
if (evt == 0) {
return PESinkHardReset;
}
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkWaitCap;
}
/* If we're too hot, we shouldn't negotiate power yet */
if (evt & PDB_EVT_PE_I_OVRTEMP) {
return PESinkWaitCap;
}
/* If we got a message */
if (evt & (PDB_EVT_PE_MSG_RX | PDB_EVT_PE_MSG_RX_PEND)) {
/* Get the message */
while ((evt & PDB_EVT_PE_MSG_RX_PEND) || readMessage() == true) {
/* If we got a Source_Capabilities message, read it. */
if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOURCE_CAPABILITIES
&& PD_NUMOBJ_GET(&tempMessage) > 0) {
/* First, determine what PD revision we're using */
if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) {
// /* If the other end is using at least version 3.0, we'll
// * use version 3.0. */
// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) {
// hdr_template |= PD_SPECREV_3_0;
// /* Otherwise, use 2.0. Don't worry about the 1.0 case
// * because we don't have hardware for PD 1.0 signaling. */
// } else {
hdr_template |= PD_SPECREV_2_0;
// }
}
return PESinkEvalCap;
/* If the message was a Soft_Reset, do the soft reset procedure */
}
evt = 0;
}
return PESinkWaitCap; //wait for more messages?
}
/* If we failed to get a message, send a hard reset */
return PESinkHardReset;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_eval_cap() {
/* If we have a Source_Capabilities message, remember the index of the
* first PPS APDO so we can check if the request is for a PPS APDO in
* PE_SNK_Select_Cap. */
/* Start by assuming we won't find a PPS APDO (set the index greater
* than the maximum possible) */
_pps_index = 8;
/* Search for the first PPS APDO */
for (int8_t i = 0; i < PD_NUMOBJ_GET(&tempMessage); i++) {
if ((tempMessage.obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED
&& (tempMessage.obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) {
_pps_index = i + 1;
break;
}
}
/* New capabilities also means we can't be making a request from the
* same PPS APDO */
_last_pps = 8;
/* Ask the DPM what to request */
if (pdbs_dpm_evaluate_capability(&tempMessage, &_last_dpm_request)) {
return PESinkSelectCap;
}
return PESinkWaitCap;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() {
/* Transmit the request */
waitForEvent(0xFFFF, 0); //clear pending
ProtocolTransmit::pushMessage(&_last_dpm_request);
//Send indication that there is a message pending
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
eventmask_t evt = waitForEvent(
PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET || evt == 0) {
return PESinkTransitionDefault;
}
/* If the message transmission failed, send a hard reset */
if ((evt & PDB_EVT_PE_TX_ERR) == PDB_EVT_PE_TX_ERR) {
return PESinkHardReset;
}
/* Wait for a response */
evt = waitForEvent(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET,
PD_T_SENDER_RESPONSE);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If we didn't get a response before the timeout, send a hard reset */
if (evt == 0) {
return PESinkHardReset;
}
/* Get the response message */
if (messageWaiting()) {
readMessage();
/* If the source accepted our request, wait for the new power */
if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_ACCEPT
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkTransitionSink;
/* If the message was a Soft_Reset, do the soft reset procedure */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkSoftReset;
/* If the message was Wait or Reject */
} else if ((PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_REJECT
|| PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_WAIT)
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
/* If we don't have an explicit contract, wait for capabilities */
if (!_explicit_contract) {
return PESinkWaitCap;
/* If we do have an explicit contract, go to the ready state */
} else {
return PESinkReady;
}
} else {
return PESinkSendSoftReset;
}
}
return PESinkHardReset;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_transition_sink() {
/* Wait for the PS_RDY message */
eventmask_t evt = waitForEvent(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET,
PD_T_PS_TRANSITION);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If no message was received, send a hard reset */
if (evt == 0) {
return PESinkHardReset;
}
/* If we received a message, read it */
if (messageWaiting()) {
readMessage();
/* If we got a PS_RDY, handle it */
if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_PS_RDY
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
/* We just finished negotiating an explicit contract */
_explicit_contract = true;
/* Set the output appropriately */
pdbs_dpm_transition_requested();
return PESinkReady;
/* If there was a protocol error, send a hard reset */
} else {
/* Turn off the power output before this hard reset to make sure we
* don't supply an incorrect voltage to the device we're powering.
*/
pdbs_dpm_transition_default();
return PESinkHardReset;
}
}
return PESinkHardReset;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_ready() {
eventmask_t evt;
/* Wait for an event */
evt = waitForEvent(
PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET | PDB_EVT_PE_I_OVRTEMP);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If we overheated, send a hard reset */
if (evt & PDB_EVT_PE_I_OVRTEMP) {
return PESinkHardReset;
}
/* If we received a message */
if (evt & PDB_EVT_PE_MSG_RX) {
if (messageWaiting()) {
readMessage();
/* Ignore vendor-defined messages */
if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_VENDOR_DEFINED
&& PD_NUMOBJ_GET(&tempMessage) > 0) {
return PESinkReady;
/* Ignore Ping messages */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_PING
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkReady;
/* DR_Swap messages are not supported */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_DR_SWAP
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkSendNotSupported;
/* Get_Source_Cap messages are not supported */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_GET_SOURCE_CAP
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkSendNotSupported;
/* PR_Swap messages are not supported */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_PR_SWAP
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkSendNotSupported;
/* VCONN_Swap messages are not supported */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_VCONN_SWAP
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkSendNotSupported;
/* Request messages are not supported */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_REQUEST
&& PD_NUMOBJ_GET(&tempMessage) > 0) {
return PESinkSendNotSupported;
/* Sink_Capabilities messages are not supported */
} else if (PD_MSGTYPE_GET(&tempMessage)
== PD_MSGTYPE_SINK_CAPABILITIES
&& PD_NUMOBJ_GET(&tempMessage) > 0) {
return PESinkSendNotSupported;
/* Handle GotoMin messages */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_GOTOMIN
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
/* GiveBack is not supported */
return PESinkSendNotSupported;
/* Evaluate new Source_Capabilities */
} else if (PD_MSGTYPE_GET(&tempMessage)
== PD_MSGTYPE_SOURCE_CAPABILITIES
&& PD_NUMOBJ_GET(&tempMessage) > 0) {
/* Don't free the message: we need to keep the
* Source_Capabilities message so we can evaluate it. */
return PESinkEvalCap;
/* Give sink capabilities when asked */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_GET_SINK_CAP
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkGiveSinkCap;
/* If the message was a Soft_Reset, do the soft reset procedure */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkSoftReset;
/* PD 3.0 messges */
} else if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) {
/* If the message is a multi-chunk extended message, let it
* time out. */
if ((tempMessage.hdr & PD_HDR_EXT)
&& (PD_DATA_SIZE_GET(&tempMessage)
> PD_MAX_EXT_MSG_LEGACY_LEN)) {
return PESinkChunkReceived;
/* Tell the DPM a message we sent got a response of
* Not_Supported. */
} else if (PD_MSGTYPE_GET(&tempMessage)
== PD_MSGTYPE_NOT_SUPPORTED
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkNotSupportedReceived;
/* If we got an unknown message, send a soft reset */
} else {
return PESinkSendSoftReset;
}
/* If we got an unknown message, send a soft reset ??? */
} else {
return PESinkSendSoftReset;
}
}
}
return PESinkReady;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_get_source_cap() {
/* Get a message object */
union pd_msg *get_source_cap = &tempMessage;
/* Make a Get_Source_Cap message */
get_source_cap->hdr = hdr_template | PD_MSGTYPE_GET_SOURCE_CAP
| PD_NUMOBJ(0);
/* Transmit the Get_Source_Cap */
ProtocolTransmit::pushMessage(get_source_cap);
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
eventmask_t evt = waitForEvent(
PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET);
/* Free the sent message */
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If the message transmission failed, send a hard reset */
if ((evt & PDB_EVT_PE_TX_DONE) == 0) {
return PESinkHardReset;
}
return PESinkReady;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_give_sink_cap() {
/* Get a message object */
union pd_msg *snk_cap = &tempMessage;
/* Get our capabilities from the DPM */
pdbs_dpm_get_sink_capability(snk_cap);
/* Transmit our capabilities */
ProtocolTransmit::pushMessage(snk_cap);
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
eventmask_t evt = waitForEvent(
PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET);
/* Free the Sink_Capabilities message */
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If the message transmission failed, send a hard reset */
if ((evt & PDB_EVT_PE_TX_DONE) == 0) {
return PESinkHardReset;
}
return PESinkReady;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_hard_reset() {
/* If we've already sent the maximum number of hard resets, assume the
* source is unresponsive. */
if (_hard_reset_counter > PD_N_HARD_RESET_COUNT) {
return PESinkSourceUnresponsive;
}
/* Generate a hard reset signal */
ResetHandler::notify(PDB_EVT_HARDRST_RESET);
waitForEvent(PDB_EVT_PE_HARD_SENT);
/* Increment HardResetCounter */
_hard_reset_counter++;
return PESinkTransitionDefault;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_transition_default() {
_explicit_contract = false;
/* Tell the DPM to transition to default power */
pdbs_dpm_transition_default();
/* There is no local hardware to reset. */
/* Since we never change our data role from UFP, there is no reason to set
* it here. */
/* Tell the protocol layer we're done with the reset */
ResetHandler::notify( PDB_EVT_HARDRST_DONE);
return PESinkStartup;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_soft_reset() {
/* No need to explicitly reset the protocol layer here. It resets itself
* when a Soft_Reset message is received. */
/* Get a message object */
union pd_msg accept;
/* Make an Accept message */
accept.hdr = hdr_template | PD_MSGTYPE_ACCEPT | PD_NUMOBJ(0);
/* Transmit the Accept */
ProtocolTransmit::pushMessage(&accept);
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
eventmask_t evt = waitForEvent(
PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET);
/* Free the sent message */
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If the message transmission failed, send a hard reset */
if ((evt & PDB_EVT_PE_TX_DONE) == 0) {
return PESinkHardReset;
}
return PESinkWaitCap;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_soft_reset() {
/* No need to explicitly reset the protocol layer here. It resets itself
* just before a Soft_Reset message is transmitted. */
/* Get a message object */
union pd_msg *softrst = &tempMessage;
/* Make a Soft_Reset message */
softrst->hdr = hdr_template | PD_MSGTYPE_SOFT_RESET | PD_NUMOBJ(0);
/* Transmit the soft reset */
ProtocolTransmit::pushMessage(softrst);
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
eventmask_t evt = waitForEvent(
PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If the message transmission failed, send a hard reset */
if ((evt & PDB_EVT_PE_TX_DONE) == 0) {
return PESinkHardReset;
}
/* Wait for a response */
evt = waitForEvent(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET,
PD_T_SENDER_RESPONSE);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If we didn't get a response before the timeout, send a hard reset */
if (evt == 0) {
return PESinkHardReset;
}
/* Get the response message */
if (messageWaiting()) {
readMessage();
/* If the source accepted our soft reset, wait for capabilities. */
if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_ACCEPT
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkWaitCap;
/* If the message was a Soft_Reset, do the soft reset procedure */
} else if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
return PESinkSoftReset;
/* Otherwise, send a hard reset */
} else {
return PESinkHardReset;
}
}
return PESinkHardReset;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_not_supported() {
/* Get a message object */
union pd_msg *not_supported = &tempMessage;
if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_2_0) {
/* Make a Reject message */
not_supported->hdr = hdr_template | PD_MSGTYPE_REJECT | PD_NUMOBJ(0);
} else if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) {
/* Make a Not_Supported message */
not_supported->hdr = hdr_template | PD_MSGTYPE_NOT_SUPPORTED
| PD_NUMOBJ(0);
}
/* Transmit the message */
ProtocolTransmit::pushMessage(not_supported);
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
eventmask_t evt = waitForEvent(
PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
/* If the message transmission failed, send a soft reset */
if ((evt & PDB_EVT_PE_TX_DONE) == 0) {
return PESinkSendSoftReset;
}
return PESinkReady;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_chunk_received() {
/* Wait for tChunkingNotSupported */
eventmask_t evt = waitForEvent(PDB_EVT_PE_RESET,
PD_T_CHUNKING_NOT_SUPPORTED);
/* If we got reset signaling, transition to default */
if (evt & PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
}
return PESinkSendNotSupported;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_not_supported_received() {
/* Inform the Device Policy Manager that we received a Not_Supported
* message. */
return PESinkReady;
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_source_unresponsive() {
//Sit and chill, as PD is not working
osDelay(PD_T_PD_DEBOUNCE);
return PESinkSourceUnresponsive;
}
uint32_t PolicyEngine::waitForEvent(uint32_t mask, uint32_t ticksToWait) {
return xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE,
ticksToWait);
}
bool PolicyEngine::isPD3_0() {
return (hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0;
}

View File

@@ -0,0 +1,198 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_POLICY_ENGINE_H
#define PDB_POLICY_ENGINE_H
#include <pd.h>
/*
* Events for the Policy Engine thread, used internally + sent by user code
*
*/
#define PDB_EVT_PE_RESET EVENT_MASK(0)
#define PDB_EVT_PE_MSG_RX EVENT_MASK(1)
#define PDB_EVT_PE_TX_DONE EVENT_MASK(2)
#define PDB_EVT_PE_TX_ERR EVENT_MASK(3)
#define PDB_EVT_PE_HARD_SENT EVENT_MASK(4)
#define PDB_EVT_PE_I_OVRTEMP EVENT_MASK(5)
#define PDB_EVT_PE_MSG_RX_PEND EVENT_MASK(7) /* Never SEND THIS DIRECTLY*/
class PolicyEngine {
public:
//Sets up internal state and registers the thread
static void init();
//Push an incoming message to the Policy Engine
static void handleMessage(union pd_msg *msg);
//Send a notification
static void notify(uint32_t notification);
//Returns true if headers indicate PD3.0 compliant
static bool isPD3_0();
static bool setupCompleteOrTimedOut() {
if (pdNegotiationComplete)
return true;
if (state == policy_engine_state::PESinkSourceUnresponsive)
return true;
if (state == policy_engine_state::PESinkReady)
return true;
return false;
}
//Has pd negotiation completed
static bool pdHasNegotiated() {
return pdNegotiationComplete;
}
private:
static bool pdNegotiationComplete;
static int current_voltage_mv; //The current voltage PD is expecting
static int _requested_voltage; //The voltage the unit wanted to requests
static bool _unconstrained_power; // If the source is unconstrained
//Current message being handled
static union pd_msg currentMessage;
/* PD message header template */
static uint16_t hdr_template;
/* Whether or not we have an explicit contract */
static bool _explicit_contract;
/* The number of hard resets we've sent */
static int8_t _hard_reset_counter;
/* The result of the last Type-C Current match comparison */
static int8_t _old_tcc_match;
/* The index of the first PPS APDO */
static uint8_t _pps_index;
/* The index of the just-requested PPS APDO */
static uint8_t _last_pps;
static void pe_task(const void *arg);
enum policy_engine_state {
PESinkStartup,
PESinkDiscovery,
PESinkWaitCap,
PESinkEvalCap,
PESinkSelectCap,
PESinkTransitionSink,
PESinkReady,
PESinkGetSourceCap,
PESinkGiveSinkCap,
PESinkHardReset,
PESinkTransitionDefault,
PESinkSoftReset,
PESinkSendSoftReset,
PESinkSendNotSupported,
PESinkChunkReceived,
PESinkNotSupportedReceived,
PESinkSourceUnresponsive
};
static enum policy_engine_state pe_sink_startup();
static enum policy_engine_state pe_sink_discovery();
static enum policy_engine_state pe_sink_wait_cap();
static enum policy_engine_state pe_sink_eval_cap();
static enum policy_engine_state pe_sink_select_cap();
static enum policy_engine_state pe_sink_transition_sink();
static enum policy_engine_state pe_sink_ready();
static enum policy_engine_state pe_sink_get_source_cap();
static enum policy_engine_state pe_sink_give_sink_cap();
static enum policy_engine_state pe_sink_hard_reset();
static enum policy_engine_state pe_sink_transition_default();
static enum policy_engine_state pe_sink_soft_reset();
static enum policy_engine_state pe_sink_send_soft_reset();
static enum policy_engine_state pe_sink_send_not_supported();
static enum policy_engine_state pe_sink_chunk_received();
static enum policy_engine_state pe_sink_not_supported_received();
static enum policy_engine_state pe_sink_source_unresponsive();
static EventGroupHandle_t xEventGroupHandle;
static StaticEventGroup_t xCreatedEventGroup;
static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait =
portMAX_DELAY);
//Task resources
static osThreadId TaskHandle;
static const size_t TaskStackSize = 2048 / 4;
static uint32_t TaskBuffer[TaskStackSize];
static osStaticThreadDef_t TaskControlBlock;
static union pd_msg tempMessage;
static union pd_msg _last_dpm_request;
static policy_engine_state state;
//queue of up to PDB_MSG_POOL_SIZE messages to send
static StaticQueue_t xStaticQueue;
/* The array to use as the queue's storage area. This must be at least
uxQueueLength * uxItemSize bytes. */
static uint8_t ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)];
static QueueHandle_t messagesWaiting;
static bool messageWaiting();
//Read a pending message into the temp message
static bool readMessage();
// These callbacks are called to implement the logic for the iron to select the desired voltage
/*
* Create a Request message based on the given Source_Capabilities message. If
* capabilities is NULL, the last non-null Source_Capabilities message passes
* is used. If none has been provided, the behavior is undefined.
*
* Returns true if sufficient power is available, false otherwise.
*/
static bool pdbs_dpm_evaluate_capability(const union pd_msg *capabilities,
union pd_msg *request);
/*
* Create a Sink_Capabilities message for our current capabilities.
*/
static void pdbs_dpm_get_sink_capability(union pd_msg *cap);
/*
* Return whether or not GiveBack support is enabled.
*/
static bool pdbs_dpm_giveback_enabled();
/*
* Evaluate whether or not the currently offered Type-C Current can fulfill our
* power needs.
*
* Returns true if sufficient power is available, false otherwise.
*/
static bool pdbs_dpm_evaluate_typec_current(enum fusb_typec_current tcc);
/*
* Indicate that power negotiations are starting.
*/
static void pdbs_dpm_pd_start();
/*
* Transition the sink to default power.
*/
static void pdbs_dpm_transition_default();
/*
* Transition to the requested minimum current.
*/
static void pdbs_dpm_transition_min();
/*
* Transition to Sink Standby if necessary.
*/
static void pdbs_dpm_transition_standby();
/*
* Transition to the requested power level
*/
static void pdbs_dpm_transition_requested();
/*
* Transition to the Type-C Current power level
*/
static void pdbs_dpm_transition_typec();
};
#endif /* PDB_POLICY_ENGINE_H */

View File

@@ -0,0 +1,227 @@
/*
* policy_engine_user.cpp
*
* Created on: 14 Jun 2020
* Author: Ralim
*/
#include "pd.h"
#include "policy_engine.h"
#include "BSP_PD.h"
/* The current draw when the output is disabled */
#define DPM_MIN_CURRENT PD_MA2PDI(50)
/*
* Find the index of the first PDO from capabilities in the voltage range,
* using the desired order.
*
* If there is no such PDO, returns -1 instead.
*/
static int8_t dpm_get_range_fixed_pdo_index(const union pd_msg *caps) {
/* Get the number of PDOs */
uint8_t numobj = PD_NUMOBJ_GET(caps);
/* Get ready to iterate over the PDOs */
int8_t i;
int8_t step;
i = numobj - 1;
step = -1;
uint16_t current = 100; // in centiamps
uint16_t voltagemin = 8000;
uint16_t voltagemax = 10000;
/* Look at the PDOs to see if one falls in our voltage range. */
while (0 <= i && i < numobj) {
/* If we have a fixed PDO, its V is within our range, and its I is at
* least our desired I */
uint16_t v = PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]);
if ((caps->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
if ( PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= current) {
if (v >= PD_MV2PDV(voltagemin) && v <= PD_MV2PDV(voltagemax)) {
return i;
}
}
}
i += step;
}
return -1;
}
bool PolicyEngine::pdbs_dpm_evaluate_capability(
const union pd_msg *capabilities, union pd_msg *request) {
/* Get the number of PDOs */
uint8_t numobj = PD_NUMOBJ_GET(capabilities);
/* Get whether or not the power supply is constrained */
_unconstrained_power =
capabilities->obj[0] & PD_PDO_SRC_FIXED_UNCONSTRAINED;
/* Make sure we have configuration */
/* Look at the PDOs to see if one matches our desires */
//Look against USB_PD_Desired_Levels to select in order of preference
for (uint8_t desiredLevel = 0; desiredLevel < USB_PD_Desired_Levels_Len;
desiredLevel++) {
for (uint8_t i = 0; i < numobj; i++) {
/* If we have a fixed PDO, its V equals our desired V, and its I is
* at least our desired I */
if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
//This is a fixed PDO entry
int voltage = PD_PDV2MV(
PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i]));
int current = PD_PDO_SRC_FIXED_CURRENT_GET(
capabilities->obj[i]);
uint16_t desiredVoltage = USB_PD_Desired_Levels[(desiredLevel
* 2) + 0];
uint16_t desiredminCurrent = USB_PD_Desired_Levels[(desiredLevel
* 2) + 1];
//As pd stores current in 10mA increments, divide by 10
desiredminCurrent /= 10;
if (voltage == desiredVoltage) {
if (current >= desiredminCurrent) {
/* We got what we wanted, so build a request for that */
request->hdr = hdr_template | PD_MSGTYPE_REQUEST
| PD_NUMOBJ(1);
/* GiveBack disabled */
request->obj[0] =
PD_RDO_FV_MAX_CURRENT_SET(
current) | PD_RDO_FV_CURRENT_SET(current)
| PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
//We support usb comms (ish)
request->obj[0] |= PD_RDO_USB_COMMS;
/* Update requested voltage */
_requested_voltage = voltage;
return true;
}
}
}
}
}
/* Nothing matched (or no configuration), so get 5 V at low current */
request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1);
request->obj[0] =
PD_RDO_FV_MAX_CURRENT_SET(
DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_NO_USB_SUSPEND
| PD_RDO_OBJPOS_SET(1);
/* If the output is enabled and we got here, it must be a capability
* mismatch. */
if (pdNegotiationComplete) {
request->obj[0] |= PD_RDO_CAP_MISMATCH;
}
request->obj[0] |= PD_RDO_USB_COMMS;
/* Update requested voltage */
_requested_voltage = 5000;
return false;
}
void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) {
/* Keep track of how many PDOs we've added */
int numobj = 0;
/* If we have no configuration or want something other than 5 V, add a PDO
* for vSafe5V */
/* Minimum current, 5 V, and higher capability. */
cap->obj[numobj++] =
PD_PDO_TYPE_FIXED
| PD_PDO_SNK_FIXED_VOLTAGE_SET(
PD_MV2PDV(5000)) | PD_PDO_SNK_FIXED_CURRENT_SET(DPM_MIN_CURRENT);
/* Get the current we want */
uint16_t current = USB_PD_Desired_Levels[1] / 10; // In centi-amps
uint16_t voltage = USB_PD_Desired_Levels[0]; // in mv
/* Add a PDO for the desired power. */
cap->obj[numobj++] = PD_PDO_TYPE_FIXED
| PD_PDO_SNK_FIXED_VOLTAGE_SET(
PD_MV2PDV(voltage)) | PD_PDO_SNK_FIXED_CURRENT_SET(current);
/* Get the PDO from the voltage range */
int8_t i = dpm_get_range_fixed_pdo_index(cap);
/* If it's vSafe5V, set our vSafe5V's current to what we want */
if (i == 0) {
cap->obj[0] &= ~PD_PDO_SNK_FIXED_CURRENT;
cap->obj[0] |= PD_PDO_SNK_FIXED_CURRENT_SET(current);
} else {
/* If we want more than 5 V, set the Higher Capability flag */
if (PD_MV2PDV(voltage) != PD_MV2PDV(5000)) {
cap->obj[0] |= PD_PDO_SNK_FIXED_HIGHER_CAP;
}
/* If the range PDO is a different voltage than the preferred
* voltage, add it to the array. */
if (i
> 0&& PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i]) != PD_MV2PDV(voltage)) {
cap->obj[numobj++] =
PD_PDO_TYPE_FIXED
| PD_PDO_SNK_FIXED_VOLTAGE_SET(
PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i])) | PD_PDO_SNK_FIXED_CURRENT_SET(
PD_PDO_SRC_FIXED_CURRENT_GET(cap->obj[i]));
}
/* If we have three PDOs at this point, make sure the last two are
* sorted by voltage. */
if (numobj == 3
&& (cap->obj[1] & PD_PDO_SNK_FIXED_VOLTAGE)
> (cap->obj[2] & PD_PDO_SNK_FIXED_VOLTAGE)) {
cap->obj[1] ^= cap->obj[2];
cap->obj[2] ^= cap->obj[1];
cap->obj[1] ^= cap->obj[2];
}
}
/* Set the unconstrained power flag. */
if (_unconstrained_power) {
cap->obj[0] |= PD_PDO_SNK_FIXED_UNCONSTRAINED;
}
/* Set the USB communications capable flag. */
cap->obj[0] |= PD_PDO_SNK_FIXED_USB_COMMS;
/* Set the Sink_Capabilities message header */
cap->hdr = hdr_template | PD_MSGTYPE_SINK_CAPABILITIES | PD_NUMOBJ(numobj);
}
bool PolicyEngine::pdbs_dpm_evaluate_typec_current(
enum fusb_typec_current tcc) {
(void) tcc;
//This is for evaluating 5V static current advertised by resistors
/* We don't control the voltage anymore; it will always be 5 V. */
current_voltage_mv = _requested_voltage = 5000;
//For the soldering iron we accept this as a fallback, but it sucks
pdNegotiationComplete = false;
return true;
}
void PolicyEngine::pdbs_dpm_transition_default() {
/* Cast the dpm_data to the right type */
/* Pretend we requested 5 V */
current_voltage_mv = 5000;
/* Turn the output off */
pdNegotiationComplete = false;
}
void PolicyEngine::pdbs_dpm_transition_requested() {
/* Cast the dpm_data to the right type */
pdNegotiationComplete = true;
}
void PolicyEngine::handleMessage(union pd_msg *msg) {
xQueueSend(messagesWaiting, msg, 100);
}
bool PolicyEngine::messageWaiting() {
return uxQueueMessagesWaiting(messagesWaiting) > 0;
}
bool PolicyEngine::readMessage() {
return xQueueReceive(messagesWaiting, &tempMessage, 0) == pdTRUE;
}
void PolicyEngine::pdbs_dpm_transition_typec() {
//This means PD failed, so we either have a dump 5V only type C or a QC charger
//For now; treat this as failed neg
pdNegotiationComplete = false;
}

View File

@@ -0,0 +1,189 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "protocol_rx.h"
#include <stdlib.h>
#include "string.h"
#include <pd.h>
#include "policy_engine.h"
#include "protocol_tx.h"
#include "fusb302b.h"
osThreadId ProtocolReceive::TaskHandle = NULL;
EventGroupHandle_t ProtocolReceive::xEventGroupHandle = NULL;
StaticEventGroup_t ProtocolReceive::xCreatedEventGroup;
uint32_t ProtocolReceive::TaskBuffer[ProtocolReceive::TaskStackSize];
osStaticThreadDef_t ProtocolReceive::TaskControlBlock;
union pd_msg ProtocolReceive::tempMessage;
uint8_t ProtocolReceive::_rx_messageid;
uint8_t ProtocolReceive::_tx_messageidcounter;
/*
* PRL_Rx_Wait_for_PHY_Message state
*/
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() {
/* Wait for an event */
_rx_messageid = 0;
eventmask_t evt = waitForEvent(
PDB_EVT_PRLRX_RESET | PDB_EVT_PRLRX_I_GCRCSENT | PDB_EVT_PRLRX_I_RXPEND);
/* If we got a reset event, reset */
if (evt & PDB_EVT_PRLRX_RESET) {
waitForEvent(PDB_EVT_PRLRX_RESET, 0);
return PRLRxWaitPHY;
}
/* If we got an I_GCRCSENT event, read the message and decide what to do */
if (evt & PDB_EVT_PRLRX_I_GCRCSENT) {
/* Get a buffer to read the message into. Guaranteed to not fail
* because we have a big enough pool and are careful. */
union pd_msg *_rx_message = &tempMessage;
memset(&tempMessage, 0, sizeof(tempMessage));
/* Read the message */
fusb_read_message(_rx_message);
/* If it's a Soft_Reset, go to the soft reset state */
if (PD_MSGTYPE_GET(_rx_message) == PD_MSGTYPE_SOFT_RESET
&& PD_NUMOBJ_GET(_rx_message) == 0) {
return PRLRxReset;
} else {
/* Otherwise, check the message ID */
return PRLRxCheckMessageID;
}
} else if (evt & PDB_EVT_PRLRX_I_RXPEND) {
//There is an RX message pending that is not a Good CRC
union pd_msg *_rx_message = &tempMessage;
/* Read the message */
fusb_read_message(_rx_message);
return PRLRxWaitPHY;
}
return PRLRxWaitPHY;
}
/*
* PRL_Rx_Layer_Reset_for_Receive state
*/
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_reset() {
/* Reset MessageIDCounter */
_tx_messageidcounter = 0;
/* Clear stored MessageID */
_rx_messageid = -1;
/* TX transitions to its reset state */
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET);
taskYIELD();
/* If we got a RESET signal, reset the machine */
if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) != 0) {
return PRLRxWaitPHY;
}
/* Go to the Check_MessageID state */
return PRLRxCheckMessageID;
}
volatile uint32_t rxCounter = 0;
/*
* PRL_Rx_Check_MessageID state
*/
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid() {
/* If we got a RESET signal, reset the machine */
// if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) == PDB_EVT_PRLRX_RESET) {
// return PRLRxWaitPHY;
// }
/* If the message has the stored ID, we've seen this message before. Free
* it and don't pass it to the policy engine. */
/* Otherwise, there's either no stored ID or this message has an ID we
* haven't just seen. Transition to the Store_MessageID state. */
// if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) {
// return PRLRxWaitPHY;
// } else
{
rxCounter++;
return PRLRxStoreMessageID;
}
}
/*
* PRL_Rx_Store_MessageID state
*/
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid() {
/* Tell ProtocolTX to discard the message being transmitted */
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_DISCARD);
/* Update the stored MessageID */
_rx_messageid = PD_MESSAGEID_GET(&tempMessage);
/* Pass the message to the policy engine. */
PolicyEngine::handleMessage(&tempMessage);
PolicyEngine::notify(PDB_EVT_PE_MSG_RX);
taskYIELD();
/* Don't check if we got a RESET because we'd do nothing different. */
return PRLRxWaitPHY;
}
void ProtocolReceive::init() {
osThreadStaticDef(protRX, thread, PDB_PRIO_PRL, 0, TaskStackSize,
TaskBuffer, &TaskControlBlock);
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
TaskHandle = osThreadCreate(osThread(protRX), NULL);
}
void ProtocolReceive::thread(const void *args) {
(void) args;
ProtocolReceive::protocol_rx_state state = PRLRxWaitPHY;
while (true) {
switch (state) {
case PRLRxWaitPHY:
state = protocol_rx_wait_phy();
break;
case PRLRxReset:
state = protocol_rx_reset();
break;
case PRLRxCheckMessageID:
state = protocol_rx_check_messageid();
break;
case PRLRxStoreMessageID:
state = protocol_rx_store_messageid();
break;
default:
/* This is an error. It really shouldn't happen. We might
* want to handle it anyway, though. */
state = PRLRxWaitPHY;
break;
}
}
}
void ProtocolReceive::notify(uint32_t notification) {
if (xEventGroupHandle != NULL) {
xEventGroupSetBits(xEventGroupHandle, notification);
}
}
uint32_t ProtocolReceive::waitForEvent(uint32_t mask, uint32_t ticksToWait) {
if (xEventGroupHandle != NULL) {
return xEventGroupWaitBits(xEventGroupHandle, mask, mask,
pdFALSE, ticksToWait);
}
return 0;
}

View File

@@ -0,0 +1,64 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_PROTOCOL_RX_H
#define PDB_PROTOCOL_RX_H
#include <stdint.h>
#include <pd.h>
/* Events for the Protocol RX thread */
#define PDB_EVT_PRLRX_RESET EVENT_MASK(0)
#define PDB_EVT_PRLRX_I_GCRCSENT EVENT_MASK(1)
#define PDB_EVT_PRLRX_I_RXPEND EVENT_MASK(2)
class ProtocolReceive {
public:
static void init();
static void notify(uint32_t notification);
private:
static void thread(const void *args);
static EventGroupHandle_t xEventGroupHandle;
static StaticEventGroup_t xCreatedEventGroup;
static osThreadId TaskHandle;
static const size_t TaskStackSize = 1024 / 4;
static uint32_t TaskBuffer[TaskStackSize];
static osStaticThreadDef_t TaskControlBlock;
/*
* Protocol RX machine states
*
* There is no Send_GoodCRC state because the PHY sends the GoodCRC for us.
* All transitions that would go to that state instead go to Check_MessageID.
*/
enum protocol_rx_state {
PRLRxWaitPHY, PRLRxReset, PRLRxCheckMessageID, PRLRxStoreMessageID
};
static protocol_rx_state protocol_rx_store_messageid();
static protocol_rx_state protocol_rx_check_messageid();
static protocol_rx_state protocol_rx_reset();
static protocol_rx_state protocol_rx_wait_phy();
static union pd_msg tempMessage;
static uint8_t _rx_messageid;
static uint8_t _tx_messageidcounter;
static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait =
portMAX_DELAY);
};
#endif /* PDB_PROTOCOL_RX_H */

View File

@@ -0,0 +1,298 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "protocol_tx.h"
#include <pd.h>
#include "policy_engine.h"
#include "protocol_rx.h"
#include "fusb302b.h"
#include "fusbpd.h"
osThreadId ProtocolTransmit::TaskHandle = NULL;
uint32_t ProtocolTransmit::TaskBuffer[ProtocolTransmit::TaskStackSize];
osStaticThreadDef_t ProtocolTransmit::TaskControlBlock;
StaticQueue_t ProtocolTransmit::xStaticQueue;
bool ProtocolTransmit::messageSending = false;
uint8_t ProtocolTransmit::ucQueueStorageArea[PDB_MSG_POOL_SIZE
* sizeof(union pd_msg)];
QueueHandle_t ProtocolTransmit::messagesWaiting = NULL;
uint8_t ProtocolTransmit::_tx_messageidcounter;
union pd_msg ProtocolTransmit::temp_msg;
EventGroupHandle_t ProtocolTransmit::xEventGroupHandle = NULL;
StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup;
/*
* PRL_Tx_PHY_Layer_Reset state
*/
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_phy_reset() {
/* Reset the PHY */
fusb_reset();
/* If a message was pending when we got here, tell the policy engine that
* we failed to send it */
if (messagePending()) {
/* Tell the policy engine that we failed */
PolicyEngine::notify( PDB_EVT_PE_TX_ERR);
/* Finish failing to send the message */
while (messagePending()) {
getMessage(); //Discard
}
}
/* Wait for a message request */
return PRLTxWaitMessage;
}
/*
* PRL_Tx_Wait_for_Message_Request state
*/
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() {
/* Wait for an event */
ProtocolTransmit::Notifications evt = waitForEvent(
(uint32_t) Notifications::PDB_EVT_PRLTX_RESET
| (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD
| (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX);
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
return PRLTxPHYReset;
}
/* If the policy engine is trying to send a message */
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) {
/* Get the message */
getMessage();
/* If it's a Soft_Reset, reset the TX layer first */
if (PD_MSGTYPE_GET(&temp_msg) == PD_MSGTYPE_SOFT_RESET
&& PD_NUMOBJ_GET(&(temp_msg)) == 0) {
return PRLTxReset;
/* Otherwise, just send the message */
} else {
return PRLTxConstructMessage;
}
}
/* Silence the compiler warning */
return PRLTxWaitMessage;
}
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() {
/* Clear MessageIDCounter */
_tx_messageidcounter = 0;
/* Tell the Protocol RX thread to reset */
ProtocolReceive::notify( PDB_EVT_PRLRX_RESET);
taskYIELD();
return PRLTxConstructMessage;
}
/*
* PRL_Tx_Construct_Message state
*/
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() {
/* Set the correct MessageID in the message */
temp_msg.hdr &= ~PD_HDR_MESSAGEID;
temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT;
/* PD 3.0 collision avoidance */
// if (PolicyEngine::isPD3_0()) {
// /* If we're starting an AMS, wait for permission to transmit */
// evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS,
// 0);
// if ((uint32_t) evt
// & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) {
// while (fusb_get_typec_current() != fusb_sink_tx_ok) {
// osDelay(1);
// }
// }
// }
messageSending = true;
/* Send the message to the PHY */
fusb_send_message(&temp_msg);
return PRLTxWaitResponse;
}
/*
* PRL_Tx_Wait_for_PHY_Response state
*/
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_response() {
/* Wait for an event. There is no need to run CRCReceiveTimer, since the
* FUSB302B handles that as part of its retry mechanism. */
ProtocolTransmit::Notifications evt = waitForEvent(
(uint32_t) Notifications::PDB_EVT_PRLTX_RESET
| (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD
| (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT
| (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
return PRLTxPHYReset;
}
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) {
return PRLTxDiscardMessage;
}
/* If the message was sent successfully */
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT) {
return PRLTxMatchMessageID;
}
/* If the message failed to be sent */
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) {
return PRLTxTransmissionError;
}
/* Silence the compiler warning */
return PRLTxDiscardMessage;
}
/*
* PRL_Tx_Match_MessageID state
*/
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_match_messageid() {
union pd_msg goodcrc;
/* Read the GoodCRC */
fusb_read_message(&goodcrc);
/* Check that the message is correct */
if (PD_MSGTYPE_GET(&goodcrc) == PD_MSGTYPE_GOODCRC
&& PD_NUMOBJ_GET(&goodcrc) == 0
&& PD_MESSAGEID_GET(&goodcrc) == _tx_messageidcounter) {
return PRLTxMessageSent;
} else {
return PRLTxTransmissionError;
}
}
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_transmission_error() {
/* Increment MessageIDCounter */
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
/* Tell the policy engine that we failed */
PolicyEngine::notify( PDB_EVT_PE_TX_ERR);
return PRLTxWaitMessage;
}
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_message_sent() {
messageSending = false;
/* Increment MessageIDCounter */
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
/* Tell the policy engine that we succeeded */
PolicyEngine::notify( PDB_EVT_PE_TX_DONE);
return PRLTxWaitMessage;
}
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_discard_message() {
/* If we were working on sending a message, increment MessageIDCounter */
if (messageSending) {
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
return PRLTxPHYReset;
} else {
return PRLTxWaitMessage;
}
}
void ProtocolTransmit::thread(const void *args) {
(void) args;
ProtocolTransmit::protocol_tx_state state = PRLTxPHYReset;
//Init the incoming message queue
while (true) {
switch (state) {
case PRLTxPHYReset:
state = protocol_tx_phy_reset();
break;
case PRLTxWaitMessage:
state = protocol_tx_wait_message();
break;
case PRLTxReset:
state = protocol_tx_reset();
break;
case PRLTxConstructMessage:
state = protocol_tx_construct_message();
break;
case PRLTxWaitResponse:
state = protocol_tx_wait_response();
break;
case PRLTxMatchMessageID:
state = protocol_tx_match_messageid();
break;
case PRLTxTransmissionError:
state = protocol_tx_transmission_error();
break;
case PRLTxMessageSent:
state = protocol_tx_message_sent();
break;
case PRLTxDiscardMessage:
state = protocol_tx_discard_message();
break;
default:
state = PRLTxPHYReset;
break;
}
}
}
void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) {
if (xEventGroupHandle != NULL) {
xEventGroupSetBits(xEventGroupHandle, (uint32_t) notification);
}
}
void ProtocolTransmit::init() {
messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE,
sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, TaskStackSize,
TaskBuffer, &TaskControlBlock);
TaskHandle = osThreadCreate(osThread(pd_txTask), NULL);
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
}
void ProtocolTransmit::pushMessage(union pd_msg *msg) {
if (messagesWaiting) {
xQueueSend(messagesWaiting, msg, 100);
}
}
bool ProtocolTransmit::messagePending() {
if (messagesWaiting) {
return uxQueueMessagesWaiting(messagesWaiting) > 0;
}
return false;
}
void ProtocolTransmit::getMessage() {
//Loads the pending message into the buffer
if (messagesWaiting) {
xQueueReceive(messagesWaiting, &temp_msg, 1);
}
}
ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask,
uint32_t ticksToWait) {
if (xEventGroupHandle) {
return (Notifications) xEventGroupWaitBits(xEventGroupHandle, mask,
mask,
pdFALSE, ticksToWait);
}
return (Notifications)0;
}

View File

@@ -0,0 +1,97 @@
/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_PROTOCOL_TX_H
#define PDB_PROTOCOL_TX_H
#include <stdint.h>
#include "policy_engine.h"
#include "protocol_rx.h"
#include <pd.h>
/* Events for the Protocol TX thread */
class ProtocolTransmit {
public:
static void init();
//Push a message to the queue to be sent out the pd comms bus
static void pushMessage(union pd_msg *msg);
enum class Notifications {
PDB_EVT_PRLTX_RESET = EVENT_MASK(0), //
PDB_EVT_PRLTX_I_TXSENT = EVENT_MASK(1), //
PDB_EVT_PRLTX_I_RETRYFAIL = EVENT_MASK(2), //
PDB_EVT_PRLTX_DISCARD = EVENT_MASK(3), //
PDB_EVT_PRLTX_MSG_TX = EVENT_MASK(4), //
PDB_EVT_PRLTX_START_AMS = EVENT_MASK(5), //
};
static void notify(Notifications notification);
private:
static void thread(const void *args);
static EventGroupHandle_t xEventGroupHandle;
static StaticEventGroup_t xCreatedEventGroup;
static osThreadId TaskHandle;
static const size_t TaskStackSize = 1024 / 4;
static uint32_t TaskBuffer[TaskStackSize];
static osStaticThreadDef_t TaskControlBlock;
static bool messageSending;
/*
* Protocol TX machine states
*
* Because the PHY can automatically send retries, the Check_RetryCounter state
* has been removed, transitions relating to it are modified appropriately, and
* we don't even keep a RetryCounter.
*/
enum protocol_tx_state {
PRLTxPHYReset,
PRLTxWaitMessage,
PRLTxReset,
PRLTxConstructMessage,
PRLTxWaitResponse,
PRLTxMatchMessageID,
PRLTxTransmissionError,
PRLTxMessageSent,
PRLTxDiscardMessage
};
//Internal states
static protocol_tx_state protocol_tx_discard_message();
static protocol_tx_state protocol_tx_message_sent();
static protocol_tx_state protocol_tx_transmission_error();
static protocol_tx_state protocol_tx_match_messageid();
static protocol_tx_state protocol_tx_wait_response();
static protocol_tx_state protocol_tx_construct_message();
static protocol_tx_state protocol_tx_reset();
static protocol_tx_state protocol_tx_wait_message();
static protocol_tx_state protocol_tx_phy_reset();
//queue of up to PDB_MSG_POOL_SIZE messages to send
static StaticQueue_t xStaticQueue;
/* The array to use as the queue's storage area. This must be at least
uxQueueLength * uxItemSize bytes. */
static uint8_t ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)];
static QueueHandle_t messagesWaiting;
static uint8_t _tx_messageidcounter;
static bool messagePending();
//Reads a message off the queue into the temp message
static void getMessage();
static union pd_msg temp_msg;
static Notifications waitForEvent(uint32_t mask, uint32_t ticksToWait =
portMAX_DELAY);
};
#endif /* PDB_PROTOCOL_TX_H */

View File

@@ -126,18 +126,6 @@ const uint8_t idleScreenBG[] = {
0x8A,0x84,0x82,0x81,0x80,0x80,0x80,0x40,0x40,0x20,0x18,0x07 0x8A,0x84,0x82,0x81,0x80,0x80,0x80,0x40,0x40,0x20,0x18,0x07
}; };
const uint8_t idleScreenBGF[] = {
//width = 84
//height = 16
0xE0,0x18,0x04,0x02,0x02,0x01,0x41,0x81,0x01,0x01,0x65,0x99,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x04,0x18,0xE0,0x00,0x00,0xE0,0x18,0x04,0x02,0x02,
0x01,0x01,0x41,0x61,0x61,0x61,0xE1,0xC1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xC1,
0xE1,0x61,0x61,0x61,0x41,0x01,0x02,0x02,0x04,0x18,0xE0,0x00,
0x07,0x18,0x20,0x40,0x40,0x80,0x80,0x80,0x81,0x82,0x84,0x8A,0x92,0x82,0x82,0x82,0x80,0x82,0x80,0x82,0x82,0x82,0x87,0x87,
0x85,0x87,0x85,0x87,0x87,0x85,0x85,0x85,0x85,0x87,0x82,0x80,0x40,0x40,0x20,0x18,0x07,0x00,0x00,0x07,0x18,0x20,0x40,0x40,
0x80,0x80,0x82,0x86,0x86,0x86,0x87,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,
0x87,0x86,0x86,0x86,0x82,0x80,0x40,0x40,0x20,0x18,0x07,0x00
};
/* /*
* 16x16 icons * 16x16 icons

View File

@@ -0,0 +1,310 @@
/*
* I2CBB.cpp
*
* Created on: 12 Jun 2020
* Author: Ralim
*/
#include "Model_Config.h"
#ifdef I2C_SOFT
#include <I2CBB.hpp>
#include "FreeRTOS.h"
SemaphoreHandle_t I2CBB::I2CSemaphore = NULL;
StaticSemaphore_t I2CBB::xSemaphoreBuffer;
SemaphoreHandle_t I2CBB::I2CSemaphore2 = NULL;
StaticSemaphore_t I2CBB::xSemaphoreBuffer2;
void I2CBB::init() {
//Set GPIO's to output open drain
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Pin = SDA2_Pin ;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(SDA2_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Pin = SCL2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(SCL2_GPIO_Port, &GPIO_InitStruct);
SOFT_SDA_HIGH();
SOFT_SCL_HIGH();
I2CSemaphore = xSemaphoreCreateMutexStatic (&xSemaphoreBuffer);
I2CSemaphore2 = xSemaphoreCreateMutexStatic (&xSemaphoreBuffer2);
unlock();
unlock2();
}
bool I2CBB::probe(uint8_t address) {
start();
bool ack = send(address);
stop();
return ack;
}
bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData,
uint16_t Size) {
if (!lock())
return false;
start();
bool ack = send(DevAddress);
if (!ack) {
stop();
unlock();
return false;
}
ack = send(MemAddress);
if (!ack) {
stop();
unlock();
return false;
}
SOFT_SCL_LOW();
SOFT_I2C_DELAY();
// stop();
start();
ack = send(DevAddress | 1);
if (!ack) {
stop();
unlock();
return false;
}
while (Size) {
pData[0] = read(Size > 1);
pData++;
Size--;
}
stop();
unlock();
return true;
}
bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
const uint8_t *pData, uint16_t Size) {
if (!lock())
return false;
start();
bool ack = send(DevAddress);
if (!ack) {
stop();
asm("bkpt");
unlock();
return false;
}
ack = send(MemAddress);
if (!ack) {
stop();
asm("bkpt");
unlock();
return false;
}
while (Size) {
resetWatchdog();
ack = send(pData[0]);
if (!ack) {
stop();
asm("bkpt");
unlock();
return false;
}
pData++;
Size--;
}
stop();
unlock();
return true;
}
void I2CBB::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
if (!lock())
return;
start();
bool ack = send(DevAddress);
if (!ack) {
stop();
unlock();
return;
}
while (Size) {
ack = send(pData[0]);
if (!ack) {
stop();
unlock();
return;
}
pData++;
Size--;
}
stop();
unlock();
}
void I2CBB::Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
if (!lock())
return;
start();
bool ack = send(DevAddress | 1);
if (!ack) {
stop();
unlock();
return;
}
while (Size) {
pData[0] = read(Size > 1);
pData++;
Size--;
}
stop();
unlock();
}
void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx) {
if (Size_tx == 0 && Size_rx == 0)
return;
if (lock() == false)
return;
if (Size_tx) {
start();
bool ack = send(DevAddress);
if (!ack) {
stop();
unlock();
return;
}
while (Size_tx) {
ack = send(pData_tx[0]);
if (!ack) {
stop();
unlock();
return;
}
pData_tx++;
Size_tx--;
}
}
if (Size_rx) {
start();
bool ack = send(DevAddress | 1);
if (!ack) {
stop();
unlock();
return;
}
while (Size_rx) {
pData_rx[0] = read(Size_rx > 1);
pData_rx++;
Size_rx--;
}
}
stop();
unlock();
}
void I2CBB::start() {
/* I2C Start condition, data line goes low when clock is high */
SOFT_SCL_HIGH();
SOFT_SDA_HIGH();
SOFT_I2C_DELAY();
SOFT_SDA_LOW();
SOFT_I2C_DELAY();
SOFT_SCL_LOW();
SOFT_I2C_DELAY();
SOFT_SDA_HIGH();
}
void I2CBB::stop() {
/* I2C Stop condition, clock goes high when data is low */
SOFT_SDA_LOW();
SOFT_I2C_DELAY();
SOFT_SCL_HIGH();
SOFT_I2C_DELAY();
SOFT_SDA_HIGH();
SOFT_I2C_DELAY();
}
bool I2CBB::send(uint8_t value) {
for (uint8_t i = 0; i < 8; i++) {
write_bit(value & 0x80); // write the most-significant bit
value <<= 1;
}
SOFT_SDA_HIGH();
bool ack = (read_bit() == 0);
return ack;
}
uint8_t I2CBB::read(bool ack) {
uint8_t B = 0;
uint8_t i;
for (i = 0; i < 8; i++) {
B <<= 1;
B |= read_bit();
}
SOFT_SDA_HIGH();
if (ack)
write_bit(0);
else
write_bit(1);
return B;
}
uint8_t I2CBB::read_bit() {
uint8_t b;
SOFT_SDA_HIGH();
SOFT_I2C_DELAY();
SOFT_SCL_HIGH();
SOFT_I2C_DELAY();
if (SOFT_SDA_READ())
b = 1;
else
b = 0;
SOFT_SCL_LOW();
return b;
}
void I2CBB::unlock() {
xSemaphoreGive(I2CSemaphore);
}
bool I2CBB::lock() {
if (I2CSemaphore == NULL) {
asm("bkpt");
}
bool a = xSemaphoreTake(I2CSemaphore, (TickType_t) 100) == pdTRUE;
return a;
}
void I2CBB::write_bit(uint8_t val) {
if (val) {
SOFT_SDA_HIGH();
} else {
SOFT_SDA_LOW();
}
SOFT_I2C_DELAY();
SOFT_SCL_HIGH();
SOFT_I2C_DELAY();
SOFT_SCL_LOW();
}
void I2CBB::unlock2() {
xSemaphoreGive(I2CSemaphore2);
}
bool I2CBB::lock2() {
if (I2CSemaphore2 == NULL) {
asm("bkpt");
}
bool a = xSemaphoreTake(I2CSemaphore2, (TickType_t) 500) == pdTRUE;
return a;
}
#endif

View File

@@ -0,0 +1,51 @@
/*
* I2CBB.hpp
*
* Created on: 12 Jun 2020
* Author: Ralim
*/
#ifndef BSP_MINIWARE_I2CBB_HPP_
#define BSP_MINIWARE_I2CBB_HPP_
#include "Model_Config.h"
#ifdef I2C_SOFT
#include "BSP.h"
#include "Setup.h"
#include "Pins.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "Software_I2C.h"
class I2CBB {
public:
static void init();
//Probe if device ACK's address or not
static bool probe(uint8_t address);
//Issues a complete 8bit register read
static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
uint8_t *pData, uint16_t Size);
//Implements a register write
static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
const uint8_t *pData, uint16_t Size);
static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx);
static void unlock2();
static bool lock2();
private:
static SemaphoreHandle_t I2CSemaphore;
static StaticSemaphore_t xSemaphoreBuffer;
static SemaphoreHandle_t I2CSemaphore2;
static StaticSemaphore_t xSemaphoreBuffer2;
static void unlock();
static bool lock();
static void start();
static void stop();
static bool send(uint8_t value);
static uint8_t read(bool ack);
static uint8_t read_bit();
static void write_bit(uint8_t val);
};
#endif
#endif /* BSP_MINIWARE_I2CBB_HPP_ */

View File

@@ -40,6 +40,9 @@ public:
static bool probe(uint16_t DevAddress); 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 Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx);
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);
static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg);

View File

@@ -171,7 +171,7 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
while (duration <= totalDuration) { while (duration <= totalDuration) {
duration = xTaskGetTickCount() - start; duration = xTaskGetTickCount() - start;
uint8_t progress = duration * 100 / totalDuration; uint8_t progress = duration * 1000 / totalDuration;
progress = easeInOutTiming(progress); progress = easeInOutTiming(progress);
progress = lerp(0, OLED_WIDTH, progress); progress = lerp(0, OLED_WIDTH, progress);
if (progress > OLED_WIDTH) { if (progress > OLED_WIDTH) {
@@ -191,9 +191,9 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
offset = progress; offset = progress;
memmove(&firstStripPtr[oldStart], &firstStripPtr[oldPrevious], memmove(&firstStripPtr[oldStart], &firstStripPtr[oldPrevious],
OLED_WIDTH - progress); OLED_WIDTH - progress);
memmove(&secondStripPtr[oldStart], &secondStripPtr[oldPrevious], memmove(&secondStripPtr[oldStart], &secondStripPtr[oldPrevious],
OLED_WIDTH - progress); OLED_WIDTH - progress);
memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress); memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress);
memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd],
@@ -213,7 +213,7 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) {
} }
void OLED::setRotation(bool leftHanded) { void OLED::setRotation(bool leftHanded) {
#ifdef MODEL_TS80 #ifdef OLED_FLIP
leftHanded = !leftHanded; leftHanded = !leftHanded;
#endif #endif
if (inLeftHandedMode == leftHanded) { if (inLeftHandedMode == leftHanded) {

View File

@@ -27,12 +27,11 @@
* This was bought to my attention by <Kuba Sztandera> * This was bought to my attention by <Kuba Sztandera>
*/ */
uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) { uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) {
// This takes the raw ADC samples, converts these to uV // This takes the raw ADC samples, converts these to uV
// Then divides this down by the gain to convert to the uV on the input to the op-amp (A+B terminals) // Then divides this down by the gain to convert to the uV on the input to the op-amp (A+B terminals)
// Then remove the calibration value that is stored as a tip offset // Then remove the calibration value that is stored as a tip offset
uint32_t vddRailmVX10 = 33000; //The vreg is +-2%, but we have no higher accuracy available uint32_t vddRailmVX10 = 33000;//The vreg is +-2%, but we have no higher accuracy available
// 4096 * 8 readings for full scale // 4096 * 8 readings for full scale
// Convert the input ADC reading back into mV times 10 format. // Convert the input ADC reading back into mV times 10 format.
uint32_t rawInputmVX10 = (rawADC * vddRailmVX10) / (4096 * 8); uint32_t rawInputmVX10 = (rawADC * vddRailmVX10) / (4096 * 8);
@@ -76,7 +75,7 @@ uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
tipuVDelta *= 10; tipuVDelta *= 10;
tipuVDelta /= systemSettings.TipGain; tipuVDelta /= systemSettings.TipGain;
#ifdef MODEL_TS80 #if defined( MODEL_TS80)+defined( MODEL_TS80P)>0
tipuVDelta /= OP_AMP_GAIN_STAGE_TS100 / OP_AMP_GAIN_STAGE_TS80; tipuVDelta /= OP_AMP_GAIN_STAGE_TS100 / OP_AMP_GAIN_STAGE_TS80;
#endif #endif

View File

@@ -1,173 +1,171 @@
/* /*
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution. This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*************************************************************************** ***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<< >>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<< >>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<< >>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<< >>! outside of the FreeRTOS kernel. !<<
*************************************************************************** ***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html link: http://www.freertos.org/a00114.html
*************************************************************************** ***************************************************************************
* * * *
* FreeRTOS provides completely free yet professionally developed, * * FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross * * robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it * * platform software that is more than just the market leader, it *
* is the industry's de facto standard. * * is the industry's de facto standard. *
* * * *
* Help yourself get started quickly while simultaneously helping * * Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS * * to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: * * tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation * * http://www.FreeRTOS.org/Documentation *
* * * *
*************************************************************************** ***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()? defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by embedded software for free we request you assist our global community by
participating in the support forum. participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS. Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack. compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware. licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability. mission critical applications that require provable dependability.
1 tab == 4 spaces! 1 tab == 4 spaces!
*/ */
#ifndef FREERTOS_CONFIG_H #ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Application specific definitions. * Application specific definitions.
* *
* These definitions should be adjusted for your particular hardware and * These definitions should be adjusted for your particular hardware and
* application requirements. * application requirements.
* *
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
* *
* See http://www.freertos.org/a00110.html. * See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
/* Section where include file can be added */ /* Section where include file can be added */
/* USER CODE END Includes */ /* USER CODE END Includes */
/* Ensure stdint is only used by the compiler, and not the assembler. */ /* Ensure stdint is only used by the compiler, and not the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h> #include <stdint.h>
extern uint32_t SystemCoreClock; extern uint32_t SystemCoreClock;
#endif #endif
#define configUSE_PREEMPTION 1 #define configUSE_PREEMPTION 1
#define configSUPPORT_STATIC_ALLOCATION 1 #define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 0 #define configSUPPORT_DYNAMIC_ALLOCATION 0
#define configUSE_IDLE_HOOK 1 #define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 0 #define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( SystemCoreClock ) #define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ((TickType_t)100) #define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES ( 4 ) #define configMAX_PRIORITIES ( 6 )
#define configMINIMAL_STACK_SIZE ((uint16_t)256) #define configMINIMAL_STACK_SIZE ((uint16_t)256)
#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ #define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/
#define configMAX_TASK_NAME_LEN ( 24 ) #define configMAX_TASK_NAME_LEN ( 32 )
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1 #define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8 #define configQUEUE_REGISTRY_SIZE 8
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_TIMERS 0
#define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/ #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/
/* Co-routine definitions. */ /* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0 #define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero /* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */ to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 0 #define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0 #define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 0 #define INCLUDE_vTaskSuspend 0
#define INCLUDE_vTaskDelayUntil 0 #define INCLUDE_vTaskDelayUntil 0
#define INCLUDE_vTaskDelay 1 #define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1 #define INCLUDE_uxTaskGetStackHighWaterMark 1
/* Cortex-M specific definitions. */ /* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS #ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS #define configPRIO_BITS __NVIC_PRIO_BITS
#else #else
#define configPRIO_BITS 4 #define configPRIO_BITS 4
#endif #endif
/* The lowest interrupt priority that can be used in a call to a "set priority" /* The lowest interrupt priority that can be used in a call to a "set priority"
function. */ function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
/* The highest interrupt priority that can be used by any interrupt service /* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */ PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic /* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */ to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Normal assert() semantics without relying on the provision of an assert.h /* Normal assert() semantics without relying on the provision of an assert.h
header file. */ header file. */
/* USER CODE BEGIN 1 */ /* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 */ /* USER CODE END 1 */
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */ standard names. */
#define vPortSVCHandler SVC_Handler #define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler #define xPortPendSVHandler PendSV_Handler
/* IMPORTANT: This define MUST be commented when used with STM32Cube firmware, #if configUSE_TIMERS
to prevent overwriting SysTick_Handler defined within STM32Cube HAL */ #define configTIMER_TASK_PRIORITY 2
/* #define xPortSysTickHandler SysTick_Handler */ #define configTIMER_QUEUE_LENGTH 8
#define configTIMER_TASK_STACK_DEPTH (512/4)
/* USER CODE BEGIN Defines */ #endif
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
/* USER CODE END Defines */ #endif /* FREERTOS_CONFIG_H */
#endif /* FREERTOS_CONFIG_H */

View File

@@ -12,8 +12,8 @@
#include "BSP.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 100
#define PRESS_ACCEL_INTERVAL_MAX 30 #define PRESS_ACCEL_INTERVAL_MAX 300
//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

View File

@@ -6,7 +6,7 @@
extern uint8_t PCBVersion; extern uint8_t PCBVersion;
extern uint32_t currentTempTargetDegC; extern uint32_t currentTempTargetDegC;
extern bool settingsWereReset; extern bool settingsWereReset;
extern bool usb_pd_available;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@@ -9,6 +9,7 @@
#include <history.hpp> #include <history.hpp>
#include "BSP.h" #include "BSP.h"
#include "expMovingAverage.h" #include "expMovingAverage.h"
#include "../../configuration.h"
#ifndef POWER_HPP_ #ifndef POWER_HPP_
#define POWER_HPP_ #define POWER_HPP_
@@ -18,16 +19,6 @@
// This is necessary because of the temp noise and thermal lag in the system. // This is necessary because of the temp noise and thermal lag in the system.
// Once we have feed-forward temp estimation we should be able to better tune this. // Once we have feed-forward temp estimation we should be able to better tune this.
#ifdef MODEL_TS100
const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second
const uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80
#endif
#ifdef MODEL_TS80
const uint32_t tipMass = 40;
const uint8_t tipResistance = 45; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80
#endif
const uint8_t wattHistoryFilter = 24; // I term look back weighting const uint8_t wattHistoryFilter = 24; // I term look back weighting
extern expMovingAverage<uint32_t, wattHistoryFilter> x10WattHistory; extern expMovingAverage<uint32_t, wattHistoryFilter> x10WattHistory;

View File

@@ -1,365 +1,364 @@
/** /**
****************************************************************************** ******************************************************************************
* @file stm32f1xx_hal_conf.h * @file stm32f1xx_hal_conf.h
* @brief HAL configuration file. * @brief HAL configuration file.
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2> * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met: * are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors * 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * 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 * 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. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
****************************************************************************** ******************************************************************************
*/ */
/* Define to prevent recursive inclusion -------------------------------------*/ /* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F1xx_HAL_CONF_H #ifndef __STM32F1xx_HAL_CONF_H
#define __STM32F1xx_HAL_CONF_H #define __STM32F1xx_HAL_CONF_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Exported types ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */ /* ########################## Module Selection ############################## */
/** /**
* @brief This is the list of modules to be used in the HAL driver * @brief This is the list of modules to be used in the HAL driver
*/ */
#define HAL_MODULE_ENABLED #define HAL_MODULE_ENABLED
#define HAL_ADC_MODULE_ENABLED #define HAL_ADC_MODULE_ENABLED
/*#define HAL_CRYP_MODULE_ENABLED */ /*#define HAL_CRYP_MODULE_ENABLED */
/*#define HAL_CAN_MODULE_ENABLED */ /*#define HAL_CAN_MODULE_ENABLED */
/*#define HAL_CEC_MODULE_ENABLED */ /*#define HAL_CEC_MODULE_ENABLED */
/*#define HAL_CORTEX_MODULE_ENABLED */ /*#define HAL_CORTEX_MODULE_ENABLED */
/*#define HAL_CRC_MODULE_ENABLED */ /*#define HAL_CRC_MODULE_ENABLED */
/*#define HAL_DAC_MODULE_ENABLED */ /*#define HAL_DAC_MODULE_ENABLED */
#define HAL_DMA_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED
/*#define HAL_ETH_MODULE_ENABLED */ /*#define HAL_ETH_MODULE_ENABLED */
/*#define HAL_FLASH_MODULE_ENABLED */ /*#define HAL_FLASH_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED
#define HAL_I2C_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED
/*#define HAL_I2S_MODULE_ENABLED */ /*#define HAL_I2S_MODULE_ENABLED */
/*#define HAL_IRDA_MODULE_ENABLED */ /*#define HAL_IRDA_MODULE_ENABLED */
#define HAL_IWDG_MODULE_ENABLED #define HAL_IWDG_MODULE_ENABLED
/*#define HAL_NOR_MODULE_ENABLED */ /*#define HAL_NOR_MODULE_ENABLED */
/*#define HAL_NAND_MODULE_ENABLED */ /*#define HAL_NAND_MODULE_ENABLED */
/*#define HAL_PCCARD_MODULE_ENABLED */ /*#define HAL_PCCARD_MODULE_ENABLED */
/*#define HAL_PCD_MODULE_ENABLED */ /*#define HAL_PCD_MODULE_ENABLED */
/*#define HAL_HCD_MODULE_ENABLED */ /*#define HAL_HCD_MODULE_ENABLED */
/*#define HAL_PWR_MODULE_ENABLED */ /*#define HAL_PWR_MODULE_ENABLED */
/*#define HAL_RCC_MODULE_ENABLED */ /*#define HAL_RCC_MODULE_ENABLED */
/*#define HAL_RTC_MODULE_ENABLED */ /*#define HAL_RTC_MODULE_ENABLED */
/*#define HAL_SD_MODULE_ENABLED */ /*#define HAL_SD_MODULE_ENABLED */
/*#define HAL_MMC_MODULE_ENABLED */ /*#define HAL_MMC_MODULE_ENABLED */
/*#define HAL_SDRAM_MODULE_ENABLED */ /*#define HAL_SDRAM_MODULE_ENABLED */
/*#define HAL_SMARTCARD_MODULE_ENABLED */ /*#define HAL_SMARTCARD_MODULE_ENABLED */
/*#define HAL_SPI_MODULE_ENABLED */ /*#define HAL_SPI_MODULE_ENABLED */
/*#define HAL_SRAM_MODULE_ENABLED */ /*#define HAL_SRAM_MODULE_ENABLED */
#define HAL_TIM_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED
/*#define HAL_UART_MODULE_ENABLED */ /*#define HAL_UART_MODULE_ENABLED */
/*#define HAL_USART_MODULE_ENABLED */ /*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_WWDG_MODULE_ENABLED */ /*#define HAL_WWDG_MODULE_ENABLED */
#define HAL_CORTEX_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED
#define HAL_GPIO_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED
/* ########################## Oscillator Values adaptation ####################*/ /* ########################## Oscillator Values adaptation ####################*/
/** /**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application. * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL). * (when HSE is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSE_VALUE) #if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */ #endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT) #if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */ #endif /* HSE_STARTUP_TIMEOUT */
/** /**
* @brief Internal High Speed oscillator (HSI) value. * @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL). * (when HSI is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSI_VALUE) #if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/ #define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */ #endif /* HSI_VALUE */
/** /**
* @brief Internal Low Speed oscillator (LSI) value. * @brief Internal Low Speed oscillator (LSI) value.
*/ */
#if !defined (LSI_VALUE) #if !defined (LSI_VALUE)
#define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ #define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations The real value may vary depending on the variations
in voltage and temperature. */ in voltage and temperature. */
/** /**
* @brief External Low Speed oscillator (LSE) value. * @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency * This value is used by the UART, RTC HAL module to compute the system frequency
*/ */
#if !defined (LSE_VALUE) #if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/
#endif /* LSE_VALUE */ #endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT) #if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */ #endif /* LSE_STARTUP_TIMEOUT */
/* Tip: To avoid modifying this file each time you need to use different HSE, /* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */ === you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */ /* ########################### System Configuration ######################### */
/** /**
* @brief This is the HAL system configuration section * @brief This is the HAL system configuration section
*/ */
#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ #define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority (lowest by default) */ #define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority (lowest by default) */
#define USE_RTOS 0 #define USE_RTOS 0
#define PREFETCH_ENABLE 1 #define PREFETCH_ENABLE 1
/* ########################## Assert Selection ############################## */ /* ########################## Assert Selection ############################## */
/** /**
* @brief Uncomment the line below to expanse the "assert_param" macro in the * @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code * HAL drivers code
*/ */
/* #define USE_FULL_ASSERT 1 */ /* #define USE_FULL_ASSERT 1 */
/* ################## Ethernet peripheral configuration ##################### */ /* ################## Ethernet peripheral configuration ##################### */
/* Section 1 : Ethernet peripheral configuration */ /* Section 1 : Ethernet peripheral configuration */
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ /* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
#define MAC_ADDR0 2 #define MAC_ADDR0 2
#define MAC_ADDR1 0 #define MAC_ADDR1 0
#define MAC_ADDR2 0 #define MAC_ADDR2 0
#define MAC_ADDR3 0 #define MAC_ADDR3 0
#define MAC_ADDR4 0 #define MAC_ADDR4 0
#define MAC_ADDR5 0 #define MAC_ADDR5 0
/* Definition of the Ethernet driver buffers size and count */ /* Definition of the Ethernet driver buffers size and count */
#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ #define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ #define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
#define ETH_RXBUFNB ((uint32_t)8) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ #define ETH_RXBUFNB ((uint32_t)8) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ #define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
/* Section 2: PHY configuration section */ /* Section 2: PHY configuration section */
/* DP83848_PHY_ADDRESS Address*/ /* DP83848_PHY_ADDRESS Address*/
#define DP83848_PHY_ADDRESS 0x01U #define DP83848_PHY_ADDRESS 0x01U
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ /* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY ((uint32_t)0x000000FF) #define PHY_RESET_DELAY ((uint32_t)0x000000FF)
/* PHY Configuration delay */ /* PHY Configuration delay */
#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) #define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF)
#define PHY_READ_TO ((uint32_t)0x0000FFFF) #define PHY_READ_TO ((uint32_t)0x0000FFFF)
#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) #define PHY_WRITE_TO ((uint32_t)0x0000FFFF)
/* Section 3: Common PHY Registers */ /* Section 3: Common PHY Registers */
#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ #define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */
#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ #define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */
#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ #define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */
#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ #define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ #define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ #define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ #define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ #define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ #define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ #define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */
#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ #define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */
#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ #define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ #define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */
#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ #define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */
#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ #define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */
/* Section 4: Extended PHY Registers */ /* Section 4: Extended PHY Registers */
#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ #define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ #define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ #define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
/** /**
* @brief Include module's header file * @brief Include module's header file
*/ */
#ifdef HAL_RCC_MODULE_ENABLED #ifdef HAL_RCC_MODULE_ENABLED
#include "stm32f1xx_hal_rcc.h" #include "stm32f1xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */ #endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED #ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32f1xx_hal_gpio.h" #include "stm32f1xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */ #endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED #ifdef HAL_DMA_MODULE_ENABLED
#include "stm32f1xx_hal_dma.h" #include "stm32f1xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */ #endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_ETH_MODULE_ENABLED #ifdef HAL_ETH_MODULE_ENABLED
#include "stm32f1xx_hal_eth.h" #include "stm32f1xx_hal_eth.h"
#endif /* HAL_ETH_MODULE_ENABLED */ #endif /* HAL_ETH_MODULE_ENABLED */
#ifdef HAL_CAN_MODULE_ENABLED #ifdef HAL_CAN_MODULE_ENABLED
#include "stm32f1xx_hal_can.h" #include "stm32f1xx_hal_can.h"
#endif /* HAL_CAN_MODULE_ENABLED */ #endif /* HAL_CAN_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED #ifdef HAL_CEC_MODULE_ENABLED
#include "stm32f1xx_hal_cec.h" #include "stm32f1xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */ #endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED #ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32f1xx_hal_cortex.h" #include "stm32f1xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */ #endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED #ifdef HAL_ADC_MODULE_ENABLED
#include "stm32f1xx_hal_adc.h" #include "stm32f1xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */ #endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED #ifdef HAL_CRC_MODULE_ENABLED
#include "stm32f1xx_hal_crc.h" #include "stm32f1xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */ #endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED #ifdef HAL_DAC_MODULE_ENABLED
#include "stm32f1xx_hal_dac.h" #include "stm32f1xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */ #endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED #ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32f1xx_hal_flash.h" #include "stm32f1xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */ #endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_SRAM_MODULE_ENABLED #ifdef HAL_SRAM_MODULE_ENABLED
#include "stm32f1xx_hal_sram.h" #include "stm32f1xx_hal_sram.h"
#endif /* HAL_SRAM_MODULE_ENABLED */ #endif /* HAL_SRAM_MODULE_ENABLED */
#ifdef HAL_NOR_MODULE_ENABLED #ifdef HAL_NOR_MODULE_ENABLED
#include "stm32f1xx_hal_nor.h" #include "stm32f1xx_hal_nor.h"
#endif /* HAL_NOR_MODULE_ENABLED */ #endif /* HAL_NOR_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED #ifdef HAL_I2C_MODULE_ENABLED
#include "stm32f1xx_hal_i2c.h" #include "stm32f1xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */ #endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED #ifdef HAL_I2S_MODULE_ENABLED
#include "stm32f1xx_hal_i2s.h" #include "stm32f1xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */ #endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED #ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32f1xx_hal_iwdg.h" #include "stm32f1xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */ #endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED #ifdef HAL_PWR_MODULE_ENABLED
#include "stm32f1xx_hal_pwr.h" #include "stm32f1xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */ #endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED #ifdef HAL_RTC_MODULE_ENABLED
#include "stm32f1xx_hal_rtc.h" #include "stm32f1xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */ #endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_PCCARD_MODULE_ENABLED #ifdef HAL_PCCARD_MODULE_ENABLED
#include "stm32f1xx_hal_pccard.h" #include "stm32f1xx_hal_pccard.h"
#endif /* HAL_PCCARD_MODULE_ENABLED */ #endif /* HAL_PCCARD_MODULE_ENABLED */
#ifdef HAL_SD_MODULE_ENABLED #ifdef HAL_SD_MODULE_ENABLED
#include "stm32f1xx_hal_sd.h" #include "stm32f1xx_hal_sd.h"
#endif /* HAL_SD_MODULE_ENABLED */ #endif /* HAL_SD_MODULE_ENABLED */
#ifdef HAL_MMC_MODULE_ENABLED #ifdef HAL_MMC_MODULE_ENABLED
#include "stm32f1xx_hal_mmc.h" #include "stm32f1xx_hal_mmc.h"
#endif /* HAL_MMC_MODULE_ENABLED */ #endif /* HAL_MMC_MODULE_ENABLED */
#ifdef HAL_NAND_MODULE_ENABLED #ifdef HAL_NAND_MODULE_ENABLED
#include "stm32f1xx_hal_nand.h" #include "stm32f1xx_hal_nand.h"
#endif /* HAL_NAND_MODULE_ENABLED */ #endif /* HAL_NAND_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED #ifdef HAL_SPI_MODULE_ENABLED
#include "stm32f1xx_hal_spi.h" #include "stm32f1xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */ #endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED #ifdef HAL_TIM_MODULE_ENABLED
#include "stm32f1xx_hal_tim.h" #include "stm32f1xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */ #endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED #ifdef HAL_UART_MODULE_ENABLED
#include "stm32f1xx_hal_uart.h" #include "stm32f1xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */ #endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED #ifdef HAL_USART_MODULE_ENABLED
#include "stm32f1xx_hal_usart.h" #include "stm32f1xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */ #endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED #ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32f1xx_hal_irda.h" #include "stm32f1xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */ #endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED #ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32f1xx_hal_smartcard.h" #include "stm32f1xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */ #endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED #ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32f1xx_hal_wwdg.h" #include "stm32f1xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */ #endif /* HAL_WWDG_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED #ifdef HAL_PCD_MODULE_ENABLED
#include "stm32f1xx_hal_pcd.h" #include "stm32f1xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */ #endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_HCD_MODULE_ENABLED #ifdef HAL_HCD_MODULE_ENABLED
#include "stm32f1xx_hal_hcd.h" #include "stm32f1xx_hal_hcd.h"
#endif /* HAL_HCD_MODULE_ENABLED */ #endif /* HAL_HCD_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT
#ifdef USE_FULL_ASSERT /**
/** * @brief The assert_param macro is used for function's parameters check.
* @brief The assert_param macro is used for function's parameters check. * @param expr: If expr is false, it calls assert_failed function
* @param expr: If expr is false, it calls assert_failed function * which reports the name of the source file and the source
* which reports the name of the source file and the source * line number of the call that failed.
* line number of the call that failed. * If expr is true, it returns no value.
* If expr is true, it returns no value. * @retval None
* @retval None */
*/ #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) /* Exported functions ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */ void assert_failed(uint8_t* file, uint32_t line);
void assert_failed(uint8_t* file, uint32_t line); #else
#else #define assert_param(expr) ((void)0U)
#define assert_param(expr) ((void)0U) #endif /* USE_FULL_ASSERT */
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
#ifdef __cplusplus }
} #endif
#endif
#endif /* __STM32F1xx_HAL_CONF_H */
#endif /* __STM32F1xx_HAL_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -23,10 +23,12 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
/* place for user code */ /* place for user code */
} }
void vApplicationStackOverflowHook(xTaskHandle *pxTask, void vApplicationStackOverflowHook(xTaskHandle *pxTask,
signed portCHAR *pcTaskName) { signed portCHAR *pcTaskName) {
(void) pxTask; (void) pxTask;
(void) pcTaskName; (void) pcTaskName;
asm("bkpt");
// We dont have a good way to handle a stack overflow at this point in time // We dont have a good way to handle a stack overflow at this point in time
reboot(); reboot();
} }

View File

@@ -13,68 +13,72 @@
#include "stdint.h" #include "stdint.h"
void QC_Seek9V() { void QC_Seek9V() {
QC_DNegZero_Six(); QC_DNegZero_Six();
QC_DPlusThree_Three(); QC_DPlusThree_Three();
} }
void QC_Seek12V() { void QC_Seek12V() {
QC_DNegZero_Six(); QC_DNegZero_Six();
QC_DPlusZero_Six(); QC_DPlusZero_Six();
} }
void QC_Seek20V() { void QC_Seek20V() {
QC_DNegThree_Three(); QC_DNegThree_Three();
QC_DPlusThree_Three(); QC_DPlusThree_Three();
} }
void QC_SeekContMode() { void QC_SeekContMode() {
QC_DNegThree_Three(); QC_DNegThree_Three();
QC_DPlusZero_Six(); QC_DPlusZero_Six();
} }
void QC_SeekContPlus() { void QC_SeekContPlus() {
QC_SeekContMode(); QC_SeekContMode();
vTaskDelay(3); osDelay(30);
QC_Seek20V(); QC_Seek20V();
vTaskDelay(1); osDelay(10);
QC_SeekContMode(); QC_SeekContMode();
} }
void QC_SeekContNeg() { void QC_SeekContNeg() {
QC_SeekContMode(); QC_SeekContMode();
vTaskDelay(3); osDelay(30);
QC_Seek12V(); QC_Seek12V();
vTaskDelay(1); osDelay(10);
QC_SeekContMode(); QC_SeekContMode();
} }
uint8_t QCMode = 0; uint8_t QCMode = 0;
uint8_t QCTries = 0; uint8_t QCTries = 0;
void seekQC(int16_t Vx10, uint16_t divisor) { void seekQC(int16_t Vx10, uint16_t divisor) {
if (QCMode == 5) startQC(divisor); if (QCMode == 0)
if (QCMode == 0) return; // NOT connected to a QC Charger startQC(divisor);
if (Vx10 < 45) return; if (Vx10 < 45)
if (xTaskGetTickCount() < 100) return; return;
if (Vx10 > 130) Vx10 = 130; // Cap max value at 13V if (xTaskGetTickCount() < 1000)
// Seek the QC to the Voltage given if this adapter supports continuous mode return;
// try and step towards the wanted value 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 // 1. Measure current voltage
int16_t vStart = getInputVoltageX10(divisor, 1); int16_t vStart = getInputVoltageX10(divisor, 1);
int difference = Vx10 - vStart; int difference = Vx10 - vStart;
// 2. calculate ideal steps (0.2V changes) // 2. calculate ideal steps (0.2V changes)
int steps = difference / 2; int steps = difference / 2;
if (QCMode == 3) { if (QCMode == 3) {
if (steps > -2 && steps < 2) return; // dont bother with small steps if (steps > -2 && steps < 2)
while (steps < 0) { return; // dont bother with small steps
QC_SeekContNeg(); while (steps < 0) {
vTaskDelay(3); QC_SeekContNeg();
steps++; osDelay(30);
} steps++;
while (steps > 0) { }
QC_SeekContPlus(); while (steps > 0) {
vTaskDelay(3); QC_SeekContPlus();
steps--; osDelay(30);
} steps--;
vTaskDelay(10); }
} osDelay(100);
}
#ifdef ENABLE_QC2 #ifdef ENABLE_QC2
// Re-measure // Re-measure
/* Disabled due to nothing to test and code space of around 1k*/ /* Disabled due to nothing to test and code space of around 1k*/
@@ -99,59 +103,61 @@ void seekQC(int16_t Vx10, uint16_t divisor) {
} }
// Must be called after FreeRToS Starts // Must be called after FreeRToS Starts
void startQC(uint16_t divisor) { void startQC(uint16_t divisor) {
// Pre check that the input could be >5V already, and if so, dont both // Pre check that the input could be >5V already, and if so, dont both
// negotiating as someone is feeding in hv // negotiating as someone is feeding in hv
uint16_t vin = getInputVoltageX10(divisor, 1); uint16_t vin = getInputVoltageX10(divisor, 1);
if (vin > 100) { if (vin > 100) {
QCMode = 1; // Already at 12V, user has probably over-ridden this QCMode = 1; // Already at 12V, user has probably over-ridden this
return; return;
} }
QC_Init_GPIO(); if (QCTries > 10) {
return;
}
QC_Init_GPIO();
// Tries to negotiate QC for 9V // Tries to negotiate QC for 9V
// This is a multiple step process. // This is a multiple step process.
// 1. Set around 0.6V on D+ for 1.25 Seconds or so // 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 // 2. After this It should un-short D+->D- and instead add a 20k pulldown on
// D- // D-
QC_DPlusZero_Six(); QC_DPlusZero_Six();
// Delay 1.25 seconds
uint8_t enteredQC = 0;
for (uint16_t i = 0; i < 200 && enteredQC == 0; i++) {
osDelay(10); // 10mS pause
if (i > 130) {
if (QC_DM_PulledDown()) {
enteredQC = 1;
}
if (i == 140) {
// For some marginal QC chargers, we try adding a pulldown
QC_DM_PullDown();
}
}
}
QC_DM_No_PullDown();
if (enteredQC) {
// We have a QC capable charger
QC_Seek9V();
QC_Post_Probe_En();
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;
}
osDelay(100); // 100mS
}
QCMode = 0;
QCTries++;
} else {
// no QC
QCMode = 0;
}
// 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 (QC_DM_PulledDown()) {
enteredQC = 1;
}
if (i == 140) {
// For some marginal QC chargers, we try adding a pulldown
QC_DM_PullDown();
}
}
}
QC_DM_No_PullDown();
if (enteredQC) {
// We have a QC capable charger
QC_Seek9V();
QC_Post_Probe_En();
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;
} }

View File

@@ -120,14 +120,14 @@ static void settings_enterAdvancedMenu(void);
* *
*/ */
const menuitem rootSettingsMenu[] { const menuitem rootSettingsMenu[] {
/* /*
* Power Source * Power Source
* Soldering Menu * Soldering Menu
* Power Saving Menu * Power Saving Menu
* UI Menu * UI Menu
* Advanced Menu * Advanced Menu
* Exit * Exit
*/ */
#ifdef MODEL_TS100 #ifdef MODEL_TS100
{ (const char*) SettingsDescriptions[0], { settings_setInputVRange }, { { (const char*) SettingsDescriptions[0], { settings_setInputVRange }, {
settings_displayInputVRange } }, /*Voltage input*/ settings_displayInputVRange } }, /*Voltage input*/
@@ -291,7 +291,7 @@ static int userConfirmation(const char *message) {
for (;;) { for (;;) {
int16_t messageOffset = ((xTaskGetTickCount() - messageStart) int16_t messageOffset = ((xTaskGetTickCount() - messageStart)
/ (systemSettings.descriptionScrollSpeed == 1 ? 1 : 2)); / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20));
messageOffset %= messageWidth; // Roll around at the end messageOffset %= messageWidth; // Roll around at the end
if (lastOffset != messageOffset) { if (lastOffset != messageOffset) {
@@ -353,8 +353,7 @@ static void settings_setInputPRange(void) {
static void settings_displayInputPRange(void) { static void settings_displayInputPRange(void) {
printShortDescription(0, 5); printShortDescription(0, 5);
//0 = 9V, 1=12V (Fixed Voltages, these imply 1.5A limits) //0 = 9V, 1=12V (Fixed Voltages, these imply 1.5A limits)
//2 = 18W, 2=24W (Auto Adjusting V, estimated from the tip resistance???) # TODO /// TODO TS80P
// Need to come back and look at these ^ as there were issues with voltage hunting
switch (systemSettings.cutoutSetting) { switch (systemSettings.cutoutSetting) {
case 0: case 0:
OLED::printNumber(9, 2); OLED::printNumber(9, 2);
@@ -647,7 +646,7 @@ static void settings_setResetSettings(void) {
OLED::print(ResetOKMessage); OLED::print(ResetOKMessage);
OLED::refresh(); OLED::refresh();
waitForButtonPressOrTimeout(200); // 2 second timeout waitForButtonPressOrTimeout(2000); // 2 second timeout
} }
} }
@@ -729,6 +728,10 @@ static void settings_setCalibrateVIN(void) {
case BUTTON_F_LONG: case BUTTON_F_LONG:
case BUTTON_B_LONG: case BUTTON_B_LONG:
saveSettings(); saveSettings();
OLED::setCursor(0, 0);
OLED::printNumber(systemSettings.voltageDiv, 3);
OLED::refresh();
waitForButtonPressOrTimeout(1000);
return; return;
break; break;
case BUTTON_NONE: case BUTTON_NONE:
@@ -740,7 +743,7 @@ static void settings_setCalibrateVIN(void) {
osDelay(40); osDelay(40);
// Cap to sensible values // Cap to sensible values
#ifdef MODEL_TS80 #if defined(MODEL_TS80)+defined(MODEL_TS80P)>0
if (systemSettings.voltageDiv < 500) { if (systemSettings.voltageDiv < 500) {
systemSettings.voltageDiv = 500; systemSettings.voltageDiv = 500;
} else if (systemSettings.voltageDiv > 900) { } else if (systemSettings.voltageDiv > 900) {
@@ -930,7 +933,7 @@ void gui_Menu(const menuitem *menu) {
OLED::setCursor(0, 0); OLED::setCursor(0, 0);
// If the user has hesitated for >=3 seconds, show the long text // If the user has hesitated for >=3 seconds, show the long text
// Otherwise "draw" the option // Otherwise "draw" the option
if ((xTaskGetTickCount() - lastButtonTime < 300) if ((xTaskGetTickCount() - lastButtonTime < 3000)
|| menu[currentScreen].description == NULL) { || menu[currentScreen].description == NULL) {
OLED::clearScreen(); OLED::clearScreen();
menu[currentScreen].draw.func(); menu[currentScreen].draw.func();
@@ -949,7 +952,7 @@ void gui_Menu(const menuitem *menu) {
int16_t descriptionOffset = int16_t descriptionOffset =
((xTaskGetTickCount() - descriptionStart) ((xTaskGetTickCount() - descriptionStart)
/ (systemSettings.descriptionScrollSpeed == 1 ? / (systemSettings.descriptionScrollSpeed == 1 ?
1 : 2)); 10 : 20));
descriptionOffset %= descriptionWidth; // Roll around at the end descriptionOffset %= descriptionWidth; // Roll around at the end
if (lastOffset != descriptionOffset) { if (lastOffset != descriptionOffset) {
OLED::clearScreen(); OLED::clearScreen();
@@ -1037,7 +1040,7 @@ void gui_Menu(const menuitem *menu) {
osDelay(40); osDelay(40);
lcdRefresh = false; lcdRefresh = false;
} }
if ((xTaskGetTickCount() - lastButtonTime) > (100 * 30)) { if ((xTaskGetTickCount() - lastButtonTime) > (1000 * 30)) {
// If user has not pressed any buttons in 30 seconds, exit back a menu layer // 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 // This will trickle the user back to the main screen eventually
earlyExit = true; earlyExit = true;

View File

@@ -13,7 +13,7 @@
#include "cmsis_os.h" #include "cmsis_os.h"
uint8_t PCBVersion = 0; uint8_t PCBVersion = 0;
// File local variables // File local variables
bool usb_pd_available = false;
bool settingsWereReset = false; bool settingsWereReset = false;
// FreeRTOS variables // FreeRTOS variables
@@ -43,21 +43,28 @@ int main(void) {
OLED::setFont(0); // default to bigger font OLED::setFont(0); // default to bigger font
// Testing for which accelerometer is mounted // Testing for which accelerometer is mounted
resetWatchdog(); resetWatchdog();
usb_pd_available = usb_pd_detect();
resetWatchdog();
settingsWereReset = restoreSettings(); // load the settings from flash settingsWereReset = restoreSettings(); // load the settings from flash
#ifdef ACCEL_MMA
if (MMA8652FC::detect()) { if (MMA8652FC::detect()) {
PCBVersion = 1; PCBVersion = 1;
MMA8652FC::initalize(); // this sets up the I2C registers MMA8652FC::initalize(); // this sets up the I2C registers
} else if (LIS2DH12::detect()) { } else
#endif
#ifdef ACCEL_LIS
if (LIS2DH12::detect()) {
PCBVersion = 2; PCBVersion = 2;
// Setup the ST Accelerometer // Setup the ST Accelerometer
LIS2DH12::initalize(); // startup the accelerometer LIS2DH12::initalize(); // startup the accelerometer
} else { } else
#endif
{
PCBVersion = 3; PCBVersion = 3;
systemSettings.SleepTime = 0; systemSettings.SleepTime = 0;
systemSettings.ShutdownTime = 0; // No accel -> disable sleep systemSettings.ShutdownTime = 0; // No accel -> disable sleep
systemSettings.sensitivity = 0; systemSettings.sensitivity = 0;
} }
resetWatchdog(); resetWatchdog();
/* Create the thread(s) */ /* Create the thread(s) */

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,6 @@ uint32_t lastMovementTime = 0;
void startMOVTask(void const *argument __unused) { void startMOVTask(void const *argument __unused) {
OLED::setRotation(systemSettings.OrientationMode & 1); OLED::setRotation(systemSettings.OrientationMode & 1);
postRToSInit(); postRToSInit();
power_probe();
lastMovementTime = 0; lastMovementTime = 0;
int16_t datax[MOVFilter] = { 0 }; int16_t datax[MOVFilter] = { 0 };
int16_t datay[MOVFilter] = { 0 }; int16_t datay[MOVFilter] = { 0 };
@@ -39,13 +38,20 @@ void startMOVTask(void const *argument __unused) {
for (;;) { for (;;) {
int32_t threshold = 1500 + (9 * 200); int32_t threshold = 1500 + (9 * 200);
threshold -= systemSettings.sensitivity * 200; // 200 is the step size threshold -= systemSettings.sensitivity * 200; // 200 is the step size
#ifdef ACCEL_LIS
if (PCBVersion == 2) { if (PCBVersion == 2) {
LIS2DH12::getAxisReadings(tx, ty, tz); LIS2DH12::getAxisReadings(tx, ty, tz);
rotation = LIS2DH12::getOrientation(); rotation = LIS2DH12::getOrientation();
} else if (PCBVersion == 1) { } else
#endif
#ifdef ACCEL_MMA
if (PCBVersion == 1) {
MMA8652FC::getAxisReadings(tx, ty, tz); MMA8652FC::getAxisReadings(tx, ty, tz);
rotation = MMA8652FC::getOrientation(); rotation = MMA8652FC::getOrientation();
}else
#endif
{
//do nothing :(
} }
if (systemSettings.OrientationMode == 2) { if (systemSettings.OrientationMode == 2) {
if (rotation != ORIENTATION_FLAT) { if (rotation != ORIENTATION_FLAT) {

View File

@@ -14,8 +14,8 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "Settings.h" #include "Settings.h"
static TickType_t powerPulseRate = 1000; static TickType_t powerPulseRate = 10000;
static TickType_t powerPulseDuration = 50; static TickType_t powerPulseDuration = 250;
TaskHandle_t pidTaskNotification = NULL; TaskHandle_t pidTaskNotification = NULL;
uint32_t currentTempTargetDegC = 0; // Current temperature target in C uint32_t currentTempTargetDegC = 0; // Current temperature target in C

View File

@@ -14,9 +14,9 @@ MEMORY
{ {
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
/* LOCAL_BUILD*/ /* LOCAL_BUILD*/
/*ROM (rx) : ORIGIN = 0x08000000, LENGTH = 46K*/ /*ROM (rx) : ORIGIN = 0x08000000, LENGTH = 48K*/
/* production*/ /* production*/
ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K

View File

@@ -22,6 +22,7 @@ FRTOS_CMIS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
FRTOS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/include FRTOS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/include
FRTOS_GCC_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 FRTOS_GCC_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3
DRIVER_INC_DIR =./Core/Drivers DRIVER_INC_DIR =./Core/Drivers
FUSB_DRIVERS_INC_DIR = ./Core/Drivers/FUSB302
BSP_INC_DIR = ./Core/BSP BSP_INC_DIR = ./Core/BSP
MINIWARE_INC_DIR = ./Core/BSP/Miniware MINIWARE_INC_DIR = ./Core/BSP/Miniware
THREADS_INC_DIR = ./Core/Threads THREADS_INC_DIR = ./Core/Threads
@@ -37,7 +38,8 @@ INCLUDES = -I$(APP_INC_DIR) \
-I$(DRIVER_INC_DIR) \ -I$(DRIVER_INC_DIR) \
-I$(BSP_INC_DIR) \ -I$(BSP_INC_DIR) \
-I$(MINIWARE_INC_DIR) \ -I$(MINIWARE_INC_DIR) \
-I$(THREADS_INC_DIR) -I$(THREADS_INC_DIR) \
-I$(FUSB_DRIVERS_INC_DIR)
# output folder # output folder
HEXFILE_DIR=Hexfile HEXFILE_DIR=Hexfile

View File

@@ -6,7 +6,7 @@ TRANSLATION_SCRIPT="make_translation.py"
# AVAILABLE_LANGUAGES will be calculating according to json files in $TRANSLATION_DIR # AVAILABLE_LANGUAGES will be calculating according to json files in $TRANSLATION_DIR
AVAILABLE_LANGUAGES=() AVAILABLE_LANGUAGES=()
BUILD_LANGUAGES=() BUILD_LANGUAGES=()
AVAILABLE_MODELS=("TS100" "TS80") AVAILABLE_MODELS=("TS100" "TS80" "TS80P")
BUILD_MODELS=() BUILD_MODELS=()
usage() { usage() {

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Model_Config.h"
/** /**
* Configuration.h * Configuration.h
* Define here your default pre settings for TS80 or TS100 * Define here your default pre settings for TS80 or TS100
@@ -76,7 +77,6 @@
#define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0 #define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0
#define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0 #define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0
#define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80) #define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80)
#define TEMPERATURE_INF 0 // default to 0 #define TEMPERATURE_INF 0 // default to 0
#define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow #define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow
@@ -94,6 +94,10 @@
#define OP_AMP_GAIN_STAGE_TS80 (1+(OP_AMP_Rf_TS80/OP_AMP_Rin_TS80)) #define OP_AMP_GAIN_STAGE_TS80 (1+(OP_AMP_Rf_TS80/OP_AMP_Rin_TS80))
//Deriving the Voltage div:
// Vin_max = (3.3*(r1+r2))/(r2)
//vdiv = (32768*4)/(vin_max*10)
#ifdef MODEL_TS100 #ifdef MODEL_TS100
#define VOLTAGE_DIV 467 // 467 - Default divider from schematic #define VOLTAGE_DIV 467 // 467 - Default divider from schematic
#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV #define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV
@@ -105,11 +109,38 @@
#endif #endif
#ifdef MODEL_TS80 #ifdef MODEL_TS80
#define VOLTAGE_DIV 780 // Default divider from schematic #define VOLTAGE_DIV 780 // Default divider from schematic
#define PID_POWER_LIMIT 24 // Sets the max pwm power limit #define PID_POWER_LIMIT 24 // Sets the max pwm power limit
#define CALIBRATION_OFFSET 900 // the adc offset in uV #define CALIBRATION_OFFSET 900 // the adc offset in uV
#define POWER_LIMIT 24 // 24 watts default power limit #define POWER_LIMIT 24 // 24 watts default power limit
#define MAX_POWER_LIMIT 30 // #define MAX_POWER_LIMIT 30 //
#define POWER_LIMIT_STEPS 2 #define POWER_LIMIT_STEPS 2
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80
#endif
#ifdef MODEL_TS80P
#define VOLTAGE_DIV 650 // Default for TS80P with slightly different resistors
#define PID_POWER_LIMIT 35 // Sets the max pwm power limit
#define CALIBRATION_OFFSET 900 // the adc offset in uV
#define POWER_LIMIT 30 // 30 watts default power limit
#define MAX_POWER_LIMIT 35 //
#define POWER_LIMIT_STEPS 2
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80
#endif
#ifdef MODEL_TS100
const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second
const uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80
#endif
#ifdef MODEL_TS80
const uint32_t tipMass = 40;
const uint8_t tipResistance = 45; //x10 ohms, 4.5 typical for ts80 tips
#endif
#ifdef MODEL_TS80P
const uint32_t tipMass = 40;
const uint8_t tipResistance = 45; //x10 ohms, 4.5 typical for ts80 tips
#endif #endif