diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index a558baad..f1765c0f 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -2,7 +2,7 @@ #include "BSP_Power.h" #include "BSP_QC.h" #include "Defines.h" -#include "UnitSettings.h" +#include "Model_Config.h" #include "stdint.h" /* * 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 // Returns 1 if the logo was printed so that the unit waits for the timeout or button 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 } #endif diff --git a/workspace/TS100/Core/BSP/BSP_PD.h b/workspace/TS100/Core/BSP/BSP_PD.h new file mode 100644 index 00000000..c38f13c9 --- /dev/null +++ b/workspace/TS100/Core/BSP/BSP_PD.h @@ -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_ */ diff --git a/workspace/TS100/Core/BSP/BSP_Power.h b/workspace/TS100/Core/BSP/BSP_Power.h index 1ce7f2bf..5b277a21 100644 --- a/workspace/TS100/Core/BSP/BSP_Power.h +++ b/workspace/TS100/Core/BSP/BSP_Power.h @@ -12,9 +12,6 @@ extern "C" { #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 // Can be used to check any details for the power system diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index da79b46f..a2afb4f3 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -7,6 +7,7 @@ #include "Pins.h" #include "main.hpp" #include "history.hpp" +#include "Model_Config.h" #include "I2C_Wrapper.hpp" volatile uint16_t PWMSafetyTimer = 0; volatile uint8_t pendingPWM = 0; @@ -16,8 +17,89 @@ history rawTempFilter = { { 0 }, 0, 0 }; void resetWatchdog() { 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() { +#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 // 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) = @@ -32,14 +114,15 @@ uint16_t getHandleTemperature() { result *= 100; result /= 993; return result; +#endif } uint16_t getTipInstantTemperature() { uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits uint16_t readings[8]; - //Looking to reject the highest outlier readings. - //As on some hardware these samples can run into the op-amp recovery time - //Once this time is up the signal stabilises quickly, so no need to reject minimums +//Looking to reject the highest outlier readings. +//As on some hardware these samples can run into the op-amp recovery time +//Once this time is up the signal stabilises quickly, so no need to reject minimums readings[0] = hadc1.Instance->JDR1; readings[1] = hadc1.Instance->JDR2; readings[2] = hadc1.Instance->JDR3; @@ -66,10 +149,10 @@ uint16_t getTipRawTemp(uint8_t refresh) { } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { - // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN - // Therefore we can divide down from there - // Multiplying ADC max by 4 for additional calibration options, - // ideal term is 467 +// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN +// Therefore we can divide down from there +// Multiplying ADC max by 4 for additional calibration options, +// ideal term is 467 #ifdef MODEL_TS100 #define BATTFILTERDEPTH 32 #else @@ -94,6 +177,9 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { sum += samples[i]; sum /= BATTFILTERDEPTH; + if (divisor == 0) { + divisor = 1; + } return sum * 4 / divisor; } @@ -140,13 +226,13 @@ void unstick_I2C() { int timeout = 100; int timeout_cnt = 0; - // 1. Clear PE bit. +// 1. Clear PE bit. hi2c1.Instance->CR1 &= ~(0x0001); /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL PB7 ------> I2C1_SDA */ - // 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). +// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; @@ -173,7 +259,7 @@ void unstick_I2C() { 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.Pull = GPIO_PULLUP; 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(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; asm("nop"); - // 14. Clear SWRST bit in I2Cx_CR1 register. +// 14. Clear SWRST bit in I2Cx_CR1 register. hi2c1.Instance->CR1 &= ~0x8000; asm("nop"); - // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register +// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register hi2c1.Instance->CR1 |= 0x0001; - // Call initialization function. +// Call initialization function. HAL_I2C_Init(&hi2c1); } @@ -214,6 +300,7 @@ uint8_t getButtonB() { } void reboot() { + NVIC_SystemReset(); } diff --git a/workspace/TS100/Core/BSP/Miniware/BSP_PD.c b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c new file mode 100644 index 00000000..0b3c2af9 --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/BSP_PD.c @@ -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 diff --git a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp index eac8cdbc..fe7b4b15 100644 --- a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp @@ -6,6 +6,7 @@ */ #include "IRQ.h" +#include "int_n.h" /* * 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 @@ -41,3 +42,8 @@ void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c __unused) { void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); } + +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + (void)GPIO_Pin; + InterruptHandler::irqCallback(); +} diff --git a/workspace/TS100/Core/BSP/Miniware/IRQ.h b/workspace/TS100/Core/BSP/Miniware/IRQ.h index 09d79c36..bcd42d04 100644 --- a/workspace/TS100/Core/BSP/Miniware/IRQ.h +++ b/workspace/TS100/Core/BSP/Miniware/IRQ.h @@ -24,6 +24,7 @@ void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_GPIO_EXTI_Callback(uint16_t); #ifdef __cplusplus } diff --git a/workspace/TS100/Core/BSP/Miniware/Model_Config.h b/workspace/TS100/Core/BSP/Miniware/Model_Config.h new file mode 100644 index 00000000..6cb69a94 --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/Model_Config.h @@ -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_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/Pins.h b/workspace/TS100/Core/BSP/Miniware/Pins.h index 1f0ddfa9..59d26a07 100644 --- a/workspace/TS100/Core/BSP/Miniware/Pins.h +++ b/workspace/TS100/Core/BSP/Miniware/Pins.h @@ -7,12 +7,7 @@ #ifndef BSP_MINIWARE_PINS_H_ #define BSP_MINIWARE_PINS_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 +#include "Model_Config.h" #ifdef MODEL_TS100 @@ -45,8 +40,8 @@ #define SCL_GPIO_Port GPIOB #define SDA_Pin GPIO_PIN_7 #define SDA_GPIO_Port GPIOB - -#else +#endif +#ifdef MODEL_TS80 // TS80 pin map #define KEY_B_Pin GPIO_PIN_0 #define KEY_B_GPIO_Port GPIOB @@ -77,6 +72,51 @@ #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 +#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 diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index 30386c83..23b02783 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -2,20 +2,35 @@ #include "BSP_Power.h" #include "QC3.h" #include "Settings.h" -void power_probe() { -// If TS80 probe for QC -// If TS100 - noop -#ifdef MODEL_TS80 - startQC(systemSettings.voltageDiv); - - seekQC((systemSettings.cutoutSetting) ? 120 : 90, - systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with - -#endif -} +#include "Pins.h" +#include "fusbpd.h" +#include "Model_Config.h" +#include "policy_engine.h" +#include "int_n.h" +bool FUSB302_present = false; void power_check() { -#ifdef MODEL_TS80 - QC_resync(); +#ifdef POW_PD + if (FUSB302_present) { + //Cant start QC until either PD works or fails + if (PolicyEngine::setupCompleteOrTimedOut() == false) { + return; + } + if (PolicyEngine::pdHasNegotiated()) { + return; + } + } #endif -} \ No newline at end of file +#ifdef POW_QC + QC_resync(); +#endif +} +uint8_t usb_pd_detect() { +#ifdef POW_PD + FUSB302_present = fusb302_detect(); + + return FUSB302_present; +#endif + return false; +} + diff --git a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp index bd3841c3..a4bba7db 100644 --- a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp +++ b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp @@ -9,6 +9,8 @@ #include "QC3.h" #include "Settings.h" #include "stm32f1xx_hal.h" +#include "Model_Config.h" +#ifdef POW_QC void QC_DPlusZero_Six() { 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; } - +#endif void QC_resync() { -#ifdef MODEL_TS80 +#ifdef POW_QC seekQC((systemSettings.cutoutSetting) ? 120 : 90, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much #endif -} \ No newline at end of file +} diff --git a/workspace/TS100/Core/BSP/Miniware/Setup.c b/workspace/TS100/Core/BSP/Miniware/Setup.c index 4b3d1f5b..2d7f2c15 100644 --- a/workspace/TS100/Core/BSP/Miniware/Setup.c +++ b/workspace/TS100/Core/BSP/Miniware/Setup.c @@ -35,7 +35,7 @@ void Setup_HAL() { SystemClock_Config(); __HAL_AFIO_REMAP_SWJ_DISABLE() ; - +// __HAL_AFIO_REMAP_SWJ_NOJTAG(); MX_GPIO_Init(); MX_DMA_Init(); MX_I2C1_Init(); @@ -458,3 +458,8 @@ static void MX_GPIO_Init(void) { HAL_Delay(30); 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 diff --git a/workspace/TS100/Core/BSP/Miniware/Software_I2C.h b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h new file mode 100644 index 00000000..9fc62d5d --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h @@ -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_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/UnitSettings.h b/workspace/TS100/Core/BSP/Miniware/UnitSettings.h deleted file mode 100644 index f3588b8b..00000000 --- a/workspace/TS100/Core/BSP/Miniware/UnitSettings.h +++ /dev/null @@ -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_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h index 0e3bdfc5..10c507ba 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h @@ -291,7 +291,7 @@ typedef struct /** @defgroup RCC_Flag Flags * Elements values convention: XXXYYYYYb * - YYYYY : Flag position in the register - * - XXX : Register index + * - X XX : Register index * - 001: CR register * - 010: BDCR register * - 011: CSR register diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c index 2d539a22..5619d38a 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c @@ -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. */ /* - if scan mode is enabled, injected channels sequence length is set to */ /* parameter "InjectedNbrOfConversion". */ - if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) - { - if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1) - { - /* Clear the old SQx bits for all injected ranks */ - MODIFY_REG(hadc->Instance->JSQR , - ADC_JSQR_JL | - ADC_JSQR_JSQ4 | - ADC_JSQR_JSQ3 | - ADC_JSQR_JSQ2 | - ADC_JSQR_JSQ1 , - ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel, - ADC_INJECTED_RANK_1, - 0x01U)); - } - /* If another injected rank than rank1 was intended to be set, and could */ - /* not due to ScanConvMode disabled, error is reported. */ - else - { - /* Update ADC state machine to error */ - SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); - - tmp_hal_status = HAL_ERROR; - } - } - else +// if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) +// { +// if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1) +// { +// /* Clear the old SQx bits for all injected ranks */ +// MODIFY_REG(hadc->Instance->JSQR , +// ADC_JSQR_JL | +// ADC_JSQR_JSQ4 | +// ADC_JSQR_JSQ3 | +// ADC_JSQR_JSQ2 | +// ADC_JSQR_JSQ1 , +// ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel, +// ADC_INJECTED_RANK_1, +// 0x01U)); +// } +// /* If another injected rank than rank1 was intended to be set, and could */ +// /* not due to ScanConvMode disabled, error is reported. */ +// else +// { +// /* Update ADC state machine to error */ +// SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); +// +// tmp_hal_status = HAL_ERROR; +// } +// } +// else { /* Since injected channels rank conv. order depends on total number of */ /* injected conversions, selected rank must be below or equal to total */ diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c index 09846a44..4f839a3f 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c @@ -3479,6 +3479,7 @@ void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) } } /* Slave mode selected */ +#if 0 else { /* ADDR set --------------------------------------------------------------*/ @@ -3520,6 +3521,7 @@ void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) } } } +#endif } /** diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c index e146d9b6..240c5d11 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c @@ -369,57 +369,6 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); /*------------------------------- 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 --------------------------*/ 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 -------------------------*/ - 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 -------------------------*/ - 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) /*-------------------------------- PLL2 Configuration -----------------------*/ diff --git a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c index 9a42f0ed..89c7f948 100644 --- a/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c +++ b/workspace/TS100/Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c @@ -3968,129 +3968,129 @@ HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockCo } break; - case TIM_CLOCKSOURCE_ETRMODE1: - { - /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/ - assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); - - /* Check ETR input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - /* Configure the ETR Clock source */ - TIM_ETR_SetConfig(htim->Instance, - sClockSourceConfig->ClockPrescaler, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - /* Get the TIMx SMCR register value */ - tmpsmcr = htim->Instance->SMCR; - /* Reset the SMS and TS Bits */ - tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); - /* Select the External clock mode1 and the ETRF trigger */ - tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1); - /* Write to TIMx SMCR */ - htim->Instance->SMCR = tmpsmcr; - } - break; - - case TIM_CLOCKSOURCE_ETRMODE2: - { - /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/ - assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance)); - - /* Check ETR input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - /* Configure the ETR Clock source */ - TIM_ETR_SetConfig(htim->Instance, - sClockSourceConfig->ClockPrescaler, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - /* Enable the External clock mode2 */ - htim->Instance->SMCR |= TIM_SMCR_ECE; - } - break; - - case TIM_CLOCKSOURCE_TI1: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); - - /* Check TI1 input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - TIM_TI1_ConfigInputStage(htim->Instance, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1); - } - break; - case TIM_CLOCKSOURCE_TI2: - { - /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/ - assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); - - /* Check TI2 input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - TIM_TI2_ConfigInputStage(htim->Instance, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2); - } - break; - case TIM_CLOCKSOURCE_TI1ED: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); - - /* Check TI1 input conditioning related parameters */ - assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); - assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); - - TIM_TI1_ConfigInputStage(htim->Instance, - sClockSourceConfig->ClockPolarity, - sClockSourceConfig->ClockFilter); - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED); - } - break; - case TIM_CLOCKSOURCE_ITR0: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0); - } - break; - case TIM_CLOCKSOURCE_ITR1: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1); - } - break; - case TIM_CLOCKSOURCE_ITR2: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2); - } - break; - case TIM_CLOCKSOURCE_ITR3: - { - /* Check whether or not the timer instance supports external clock mode 1 */ - assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); - - TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3); - } - break; +// case TIM_CLOCKSOURCE_ETRMODE1: +// { +// /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/ +// assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); +// +// /* Check ETR input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// /* Configure the ETR Clock source */ +// TIM_ETR_SetConfig(htim->Instance, +// sClockSourceConfig->ClockPrescaler, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// /* Get the TIMx SMCR register value */ +// tmpsmcr = htim->Instance->SMCR; +// /* Reset the SMS and TS Bits */ +// tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); +// /* Select the External clock mode1 and the ETRF trigger */ +// tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1); +// /* Write to TIMx SMCR */ +// htim->Instance->SMCR = tmpsmcr; +// } +// break; +// +// case TIM_CLOCKSOURCE_ETRMODE2: +// { +// /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/ +// assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance)); +// +// /* Check ETR input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// /* Configure the ETR Clock source */ +// TIM_ETR_SetConfig(htim->Instance, +// sClockSourceConfig->ClockPrescaler, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// /* Enable the External clock mode2 */ +// htim->Instance->SMCR |= TIM_SMCR_ECE; +// } +// break; +// +// case TIM_CLOCKSOURCE_TI1: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); +// +// /* Check TI1 input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// TIM_TI1_ConfigInputStage(htim->Instance, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1); +// } +// break; +// case TIM_CLOCKSOURCE_TI2: +// { +// /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/ +// assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); +// +// /* Check TI2 input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// TIM_TI2_ConfigInputStage(htim->Instance, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2); +// } +// break; +// case TIM_CLOCKSOURCE_TI1ED: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); +// +// /* Check TI1 input conditioning related parameters */ +// assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); +// assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); +// +// TIM_TI1_ConfigInputStage(htim->Instance, +// sClockSourceConfig->ClockPolarity, +// sClockSourceConfig->ClockFilter); +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED); +// } +// break; +// case TIM_CLOCKSOURCE_ITR0: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0); +// } +// break; +// case TIM_CLOCKSOURCE_ITR1: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1); +// } +// break; +// case TIM_CLOCKSOURCE_ITR2: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2); +// } +// break; +// case TIM_CLOCKSOURCE_ITR3: +// { +// /* Check whether or not the timer instance supports external clock mode 1 */ +// assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); +// +// TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3); +// } +// break; default: break; diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp new file mode 100644 index 00000000..9deb8c2f --- /dev/null +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -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 +#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 diff --git a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp index deb78e5d..fa55ab11 100644 --- a/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/postRTOS.cpp @@ -8,7 +8,12 @@ #include "stdlib.h" #include "task.h" #include "I2C_Wrapper.hpp" +#include "fusbpd.h" void postRToSInit() { - // Any after RTos setup + // Any after RTos setup FRToSI2C::FRToSInit(); +#ifdef POW_PD + //Spawn all of the USB-C processors + fusb302_start_processing(); +#endif } diff --git a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp index 6a16c44f..6b0614b9 100644 --- a/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Miniware/preRTOS.cpp @@ -9,6 +9,9 @@ #include "BSP.h" #include "Setup.h" #include "Pins.h" +#include "I2CBB.hpp" +#include "fusbpd.h" +#include "Model_Config.h" void preRToSInit() { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ @@ -18,5 +21,9 @@ void preRToSInit() { HAL_Delay(50); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_Delay(50); +#ifdef I2C_SOFT + I2CBB::init(); + +#endif } diff --git a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c index b411c980..b9ee5c51 100644 --- a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c +++ b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c @@ -82,3 +82,6 @@ void DMA1_Channel6_IRQHandler(void) { void DMA1_Channel7_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_rx); } +void EXTI9_5_IRQHandler(void){ + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); +} diff --git a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c index dfff3485..fabf4234 100644 --- a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c +++ b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c @@ -11,6 +11,7 @@ #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) /* #define DATA_IN_ExtSRAM */ #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ +//#define LOCAL_BUILD #ifndef LOCAL_BUILD #define VECT_TAB_OFFSET 0x00004000U /*!< Vector Table base offset field. This value must be a multiple of 0x200. */ diff --git a/workspace/TS100/Core/Drivers/Buttons.cpp b/workspace/TS100/Core/Drivers/Buttons.cpp index beca08b1..8aa47833 100644 --- a/workspace/TS100/Core/Drivers/Buttons.cpp +++ b/workspace/TS100/Core/Drivers/Buttons.cpp @@ -24,7 +24,7 @@ ButtonState getButtonState() { */ static uint8_t previousState = 0; static uint32_t previousStateChange = 0; - const uint16_t timeout = 40; + const uint16_t timeout = 400; uint8_t currentState; currentState = (getButtonA()) << 0; currentState |= (getButtonB()) << 1; diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h new file mode 100644 index 00000000..bcd66407 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h @@ -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 + +#include "pd.h" +#include + +/* 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 */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp new file mode 100644 index 00000000..f6bb58e1 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -0,0 +1,38 @@ +/* + * fusbpd.cpp + * + * Created on: 13 Jun 2020 + * Author: Ralim + */ +#include "Model_Config.h" +#ifdef POW_PD +#include +#include +#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 diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.h b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.h new file mode 100644 index 00000000..b48dfc4e --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.h @@ -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 + +//returns 1 if the FUSB302 is on the I2C bus +uint8_t fusb302_detect(); + +void fusb302_start_processing(); +#endif /* DRIVERS_FUSB302_FUSBPD_H_ */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp new file mode 100644 index 00000000..97ffdd71 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.cpp @@ -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 +#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; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h new file mode 100644 index 00000000..9466b33c --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/hard_reset.h @@ -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 + +/* 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 */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp new file mode 100644 index 00000000..52d7701b --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -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 +#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); + } +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.h b/workspace/TS100/Core/Drivers/FUSB302/int_n.h new file mode 100644 index 00000000..69c460f7 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.h @@ -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 + +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 */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/pd.h b/workspace/TS100/Core/Drivers/FUSB302/pd.h new file mode 100644 index 00000000..60cbd26a --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/pd.h @@ -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 +#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 */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h b/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h new file mode 100644 index 00000000..c2ca0f3f --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/pdb_conf.h @@ -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< + + + +/* + * 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 */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp new file mode 100644 index 00000000..0e8464fc --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -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 +#include "int_n.h" +#include +#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; +} + diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h new file mode 100644 index 00000000..4aef4b0e --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.h @@ -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 + +/* + * 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 */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp new file mode 100644 index 00000000..4e65cf85 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -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; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp new file mode 100644 index 00000000..132cd6a3 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.cpp @@ -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 +#include "string.h" +#include +#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; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h new file mode 100644 index 00000000..cdfce1f0 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_rx.h @@ -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 + +#include + +/* 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 */ diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp new file mode 100644 index 00000000..6caeeac3 --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.cpp @@ -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 +#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; +} diff --git a/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h new file mode 100644 index 00000000..b593feae --- /dev/null +++ b/workspace/TS100/Core/Drivers/FUSB302/protocol_tx.h @@ -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 +#include "policy_engine.h" +#include "protocol_rx.h" +#include + +/* 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 */ diff --git a/workspace/TS100/Core/Drivers/Font.h b/workspace/TS100/Core/Drivers/Font.h index 761b2723..50932504 100644 --- a/workspace/TS100/Core/Drivers/Font.h +++ b/workspace/TS100/Core/Drivers/Font.h @@ -126,18 +126,6 @@ const uint8_t idleScreenBG[] = { 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 diff --git a/workspace/TS100/Core/Drivers/I2CBB.cpp b/workspace/TS100/Core/Drivers/I2CBB.cpp new file mode 100644 index 00000000..c21a3a97 --- /dev/null +++ b/workspace/TS100/Core/Drivers/I2CBB.cpp @@ -0,0 +1,310 @@ +/* + * I2CBB.cpp + * + * Created on: 12 Jun 2020 + * Author: Ralim + */ +#include "Model_Config.h" +#ifdef I2C_SOFT +#include +#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 diff --git a/workspace/TS100/Core/Drivers/I2CBB.hpp b/workspace/TS100/Core/Drivers/I2CBB.hpp new file mode 100644 index 00000000..6d733c90 --- /dev/null +++ b/workspace/TS100/Core/Drivers/I2CBB.hpp @@ -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_ */ diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index 3753a481..779ddc20 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -40,6 +40,9 @@ public: static bool probe(uint16_t DevAddress); 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 uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); diff --git a/workspace/TS100/Core/Drivers/OLED.cpp b/workspace/TS100/Core/Drivers/OLED.cpp index fc9867eb..7d5eb0b2 100644 --- a/workspace/TS100/Core/Drivers/OLED.cpp +++ b/workspace/TS100/Core/Drivers/OLED.cpp @@ -171,7 +171,7 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { while (duration <= totalDuration) { duration = xTaskGetTickCount() - start; - uint8_t progress = duration * 100 / totalDuration; + uint8_t progress = duration * 1000 / totalDuration; progress = easeInOutTiming(progress); progress = lerp(0, OLED_WIDTH, progress); if (progress > OLED_WIDTH) { @@ -191,9 +191,9 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { offset = progress; memmove(&firstStripPtr[oldStart], &firstStripPtr[oldPrevious], - OLED_WIDTH - progress); + OLED_WIDTH - progress); memmove(&secondStripPtr[oldStart], &secondStripPtr[oldPrevious], - OLED_WIDTH - progress); + OLED_WIDTH - progress); memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress); memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], @@ -213,7 +213,7 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) { } void OLED::setRotation(bool leftHanded) { -#ifdef MODEL_TS80 +#ifdef OLED_FLIP leftHanded = !leftHanded; #endif if (inLeftHandedMode == leftHanded) { diff --git a/workspace/TS100/Core/Drivers/TipThermoModel.cpp b/workspace/TS100/Core/Drivers/TipThermoModel.cpp index ac1c9389..c94e6284 100644 --- a/workspace/TS100/Core/Drivers/TipThermoModel.cpp +++ b/workspace/TS100/Core/Drivers/TipThermoModel.cpp @@ -27,12 +27,11 @@ * This was bought to my attention by */ - uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) { // 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 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 // Convert the input ADC reading back into mV times 10 format. uint32_t rawInputmVX10 = (rawADC * vddRailmVX10) / (4096 * 8); @@ -76,7 +75,7 @@ uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { tipuVDelta *= 10; 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; #endif diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h index 8989a8d8..e2c1c4c7 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSConfig.h +++ b/workspace/TS100/Core/Inc/FreeRTOSConfig.h @@ -1,173 +1,171 @@ -/* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. - All rights reserved - - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - This file is part of the FreeRTOS distribution. - - 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 - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - *************************************************************************** - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - *************************************************************************** - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available on the following - link: http://www.freertos.org/a00114.html - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that is more than just the market leader, it * - * is the industry's de facto standard. * - * * - * Help yourself get started quickly while simultaneously helping * - * to support the FreeRTOS project by purchasing a FreeRTOS * - * tutorial book, reference manual, or both: * - * http://www.FreeRTOS.org/Documentation * - * * - *************************************************************************** - - 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 - defined configASSERT()? - - http://www.FreeRTOS.org/support - In return for receiving this top quality - embedded software for free we request you assist our global community by - participating in the support forum. - - 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 - FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers - Ltd, and the world's leading authority on the world's leading RTOS. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - 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. - - http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High - Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and commercial middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! -*/ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -/* USER CODE BEGIN Includes */ -/* Section where include file can be added */ -/* USER CODE END Includes */ - -/* Ensure stdint is only used by the compiler, and not the assembler. */ -#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) - #include - extern uint32_t SystemCoreClock; -#endif - -#define configUSE_PREEMPTION 1 -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 -#define configUSE_IDLE_HOOK 1 -#define configUSE_TICK_HOOK 0 -#define configCPU_CLOCK_HZ ( SystemCoreClock ) -#define configTICK_RATE_HZ ((TickType_t)100) -#define configMAX_PRIORITIES ( 4 ) -#define configMINIMAL_STACK_SIZE ((uint16_t)256) -#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ -#define configMAX_TASK_NAME_LEN ( 24 ) -#define configUSE_16_BIT_TICKS 0 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#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. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) - -/* Set the following definitions to 1 to include the API function, or zero -to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskCleanUpResources 0 -#define INCLUDE_vTaskSuspend 0 -#define INCLUDE_vTaskDelayUntil 0 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 1 - -/* Cortex-M specific definitions. */ -#ifdef __NVIC_PRIO_BITS - /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ - #define configPRIO_BITS __NVIC_PRIO_BITS -#else - #define configPRIO_BITS 4 -#endif - -/* The lowest interrupt priority that can be used in a call to a "set priority" -function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 - -/* 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 -INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER -PRIORITY THAN THIS! (higher priorities are lower numeric values. */ -#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 - -/* 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. */ -#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! -See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ -#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 -header file. */ -/* USER CODE BEGIN 1 */ -#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} -/* USER CODE END 1 */ - -/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS -standard names. */ -#define vPortSVCHandler SVC_Handler -#define xPortPendSVHandler PendSV_Handler - -/* IMPORTANT: This define MUST be commented when used with STM32Cube firmware, - to prevent overwriting SysTick_Handler defined within STM32Cube HAL */ -/* #define xPortSysTickHandler SysTick_Handler */ - -/* USER CODE BEGIN Defines */ -/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */ -/* USER CODE END Defines */ - -#endif /* FREERTOS_CONFIG_H */ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + 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 + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + 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 + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + 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 + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + 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. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +/* USER CODE BEGIN Includes */ +/* Section where include file can be added */ +/* USER CODE END Includes */ + +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +#define configUSE_PREEMPTION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( SystemCoreClock ) +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMAX_PRIORITIES ( 6 ) +#define configMINIMAL_STACK_SIZE ((uint16_t)256) +#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ +#define configMAX_TASK_NAME_LEN ( 32 ) +#define configUSE_16_BIT_TICKS 0 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_TIMERS 0 +#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. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Set the following definitions to 1 to include the API function, or zero + to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 0 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS + /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" + function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 + +/* 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 + INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER + PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* 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. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#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 + header file. */ +/* USER CODE BEGIN 1 */ +#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} +/* USER CODE END 1 */ + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS + standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +#if configUSE_TIMERS +#define configTIMER_TASK_PRIORITY 2 +#define configTIMER_QUEUE_LENGTH 8 +#define configTIMER_TASK_STACK_DEPTH (512/4) +#endif + +#endif /* FREERTOS_CONFIG_H */ diff --git a/workspace/TS100/Core/Inc/gui.hpp b/workspace/TS100/Core/Inc/gui.hpp index f05d59fb..1b7827d3 100644 --- a/workspace/TS100/Core/Inc/gui.hpp +++ b/workspace/TS100/Core/Inc/gui.hpp @@ -12,8 +12,8 @@ #include "BSP.h" #define PRESS_ACCEL_STEP 3 -#define PRESS_ACCEL_INTERVAL_MIN 10 -#define PRESS_ACCEL_INTERVAL_MAX 30 +#define PRESS_ACCEL_INTERVAL_MIN 100 +#define PRESS_ACCEL_INTERVAL_MAX 300 //GUI holds the menu structure and all its methods for the menu itself diff --git a/workspace/TS100/Core/Inc/main.hpp b/workspace/TS100/Core/Inc/main.hpp index 606d920b..edfde783 100644 --- a/workspace/TS100/Core/Inc/main.hpp +++ b/workspace/TS100/Core/Inc/main.hpp @@ -6,7 +6,7 @@ extern uint8_t PCBVersion; extern uint32_t currentTempTargetDegC; extern bool settingsWereReset; - +extern bool usb_pd_available; #ifdef __cplusplus extern "C" { #endif diff --git a/workspace/TS100/Core/Inc/power.hpp b/workspace/TS100/Core/Inc/power.hpp index c882a99a..31fddd33 100644 --- a/workspace/TS100/Core/Inc/power.hpp +++ b/workspace/TS100/Core/Inc/power.hpp @@ -9,6 +9,7 @@ #include #include "BSP.h" #include "expMovingAverage.h" +#include "../../configuration.h" #ifndef POWER_HPP_ #define POWER_HPP_ @@ -18,16 +19,6 @@ // 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. -#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 extern expMovingAverage x10WattHistory; diff --git a/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h b/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h index e1df8b6f..b3e68d1a 100644 --- a/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h +++ b/workspace/TS100/Core/Inc/stm32f1xx_hal_conf.h @@ -1,365 +1,364 @@ -/** - ****************************************************************************** - * @file stm32f1xx_hal_conf.h - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

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

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_HAL_CONF_H +#define __STM32F1xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_CAN_MODULE_ENABLED */ +/*#define HAL_CEC_MODULE_ENABLED */ +/*#define HAL_CORTEX_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_DAC_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/*#define HAL_ETH_MODULE_ENABLED */ +/*#define HAL_FLASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +#define HAL_IWDG_MODULE_ENABLED +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_PCCARD_MODULE_ENABLED */ +/*#define HAL_PCD_MODULE_ENABLED */ +/*#define HAL_HCD_MODULE_ENABLED */ +/*#define HAL_PWR_MODULE_ENABLED */ +/*#define HAL_RCC_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +/*#define HAL_SD_MODULE_ENABLED */ +/*#define HAL_MMC_MODULE_ENABLED */ +/*#define HAL_SDRAM_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED +/*#define HAL_UART_MODULE_ENABLED */ +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ + +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @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 + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * 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). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* 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. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#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 USE_RTOS 0 +#define PREFETCH_ENABLE 1 + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1 */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2 +#define MAC_ADDR1 0 +#define MAC_ADDR2 0 +#define MAC_ADDR3 0 +#define MAC_ADDR4 0 +#define MAC_ADDR5 0 + +/* Definition of the Ethernet driver buffers size and count */ +#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_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 */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FF) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) + +#define PHY_READ_TO ((uint32_t)0x0000FFFF) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#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_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_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_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f1xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f1xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f1xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f1xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f1xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f1xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f1xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f1xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f1xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f1xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f1xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f1xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f1xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f1xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f1xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f1xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f1xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f1xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f1xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f1xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f1xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f1xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f1xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f1xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f1xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f1xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f1xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f1xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f1xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f1xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f1xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/workspace/TS100/Core/Src/FreeRTOSHooks.c b/workspace/TS100/Core/Src/FreeRTOSHooks.c index 1e9c3dc6..f7c56c6a 100644 --- a/workspace/TS100/Core/Src/FreeRTOSHooks.c +++ b/workspace/TS100/Core/Src/FreeRTOSHooks.c @@ -23,10 +23,12 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, /* place for user code */ } + void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName) { (void) pxTask; (void) pcTaskName; + asm("bkpt"); // We dont have a good way to handle a stack overflow at this point in time reboot(); } diff --git a/workspace/TS100/Core/Src/QC3.c b/workspace/TS100/Core/Src/QC3.c index 43cff776..473c14b2 100644 --- a/workspace/TS100/Core/Src/QC3.c +++ b/workspace/TS100/Core/Src/QC3.c @@ -13,68 +13,72 @@ #include "stdint.h" void QC_Seek9V() { - QC_DNegZero_Six(); - QC_DPlusThree_Three(); + QC_DNegZero_Six(); + QC_DPlusThree_Three(); } void QC_Seek12V() { - QC_DNegZero_Six(); - QC_DPlusZero_Six(); + QC_DNegZero_Six(); + QC_DPlusZero_Six(); } void QC_Seek20V() { - QC_DNegThree_Three(); - QC_DPlusThree_Three(); + QC_DNegThree_Three(); + QC_DPlusThree_Three(); } void QC_SeekContMode() { - QC_DNegThree_Three(); - QC_DPlusZero_Six(); + QC_DNegThree_Three(); + QC_DPlusZero_Six(); } void QC_SeekContPlus() { - QC_SeekContMode(); - vTaskDelay(3); - QC_Seek20V(); - vTaskDelay(1); - QC_SeekContMode(); + QC_SeekContMode(); + osDelay(30); + QC_Seek20V(); + osDelay(10); + QC_SeekContMode(); } void QC_SeekContNeg() { - QC_SeekContMode(); - vTaskDelay(3); - QC_Seek12V(); - vTaskDelay(1); - QC_SeekContMode(); + QC_SeekContMode(); + osDelay(30); + QC_Seek12V(); + osDelay(10); + QC_SeekContMode(); } uint8_t QCMode = 0; uint8_t QCTries = 0; void seekQC(int16_t Vx10, uint16_t divisor) { - if (QCMode == 5) startQC(divisor); - if (QCMode == 0) return; // NOT connected to a QC Charger + if (QCMode == 0) + startQC(divisor); - if (Vx10 < 45) return; - if (xTaskGetTickCount() < 100) return; - if (Vx10 > 130) Vx10 = 130; // Cap max value at 13V - // Seek the QC to the Voltage given if this adapter supports continuous mode - // try and step towards the wanted value + if (Vx10 < 45) + return; + if (xTaskGetTickCount() < 1000) + return; + if (Vx10 > 130) + Vx10 = 130; // Cap max value at 13V + // Seek the QC to the Voltage given if this adapter supports continuous mode + // try and step towards the wanted value - // 1. Measure current voltage - int16_t vStart = getInputVoltageX10(divisor, 1); - int difference = Vx10 - vStart; + // 1. Measure current voltage + int16_t vStart = getInputVoltageX10(divisor, 1); + int difference = Vx10 - vStart; - // 2. calculate ideal steps (0.2V changes) + // 2. calculate ideal steps (0.2V changes) - int steps = difference / 2; - if (QCMode == 3) { - if (steps > -2 && steps < 2) return; // dont bother with small steps - while (steps < 0) { - QC_SeekContNeg(); - vTaskDelay(3); - steps++; - } - while (steps > 0) { - QC_SeekContPlus(); - vTaskDelay(3); - steps--; - } - vTaskDelay(10); - } + int steps = difference / 2; + if (QCMode == 3) { + if (steps > -2 && steps < 2) + return; // dont bother with small steps + while (steps < 0) { + QC_SeekContNeg(); + osDelay(30); + steps++; + } + while (steps > 0) { + QC_SeekContPlus(); + osDelay(30); + steps--; + } + osDelay(100); + } #ifdef ENABLE_QC2 // Re-measure /* 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 void startQC(uint16_t divisor) { - // Pre check that the input could be >5V already, and if so, dont both - // negotiating as someone is feeding in hv - uint16_t vin = getInputVoltageX10(divisor, 1); - if (vin > 100) { - QCMode = 1; // Already at 12V, user has probably over-ridden this - return; - } - QC_Init_GPIO(); + // Pre check that the input could be >5V already, and if so, dont both + // negotiating as someone is feeding in hv + uint16_t vin = getInputVoltageX10(divisor, 1); + if (vin > 100) { + QCMode = 1; // Already at 12V, user has probably over-ridden this + return; + } + if (QCTries > 10) { + return; + } + QC_Init_GPIO(); - // Tries to negotiate QC for 9V - // This is a multiple step process. - // 1. Set around 0.6V on D+ for 1.25 Seconds or so - // 2. After this It should un-short D+->D- and instead add a 20k pulldown on - // D- - QC_DPlusZero_Six(); + // Tries to negotiate QC for 9V + // This is a multiple step process. + // 1. Set around 0.6V on D+ for 1.25 Seconds or so + // 2. After this It should un-short D+->D- and instead add a 20k pulldown on + // D- + 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; } diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index 0bd0b13d..eaf71811 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -120,14 +120,14 @@ static void settings_enterAdvancedMenu(void); * */ const menuitem rootSettingsMenu[] { -/* - * Power Source - * Soldering Menu - * Power Saving Menu - * UI Menu - * Advanced Menu - * Exit - */ + /* + * Power Source + * Soldering Menu + * Power Saving Menu + * UI Menu + * Advanced Menu + * Exit + */ #ifdef MODEL_TS100 { (const char*) SettingsDescriptions[0], { settings_setInputVRange }, { settings_displayInputVRange } }, /*Voltage input*/ @@ -291,7 +291,7 @@ static int userConfirmation(const char *message) { for (;;) { int16_t messageOffset = ((xTaskGetTickCount() - messageStart) - / (systemSettings.descriptionScrollSpeed == 1 ? 1 : 2)); + / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20)); messageOffset %= messageWidth; // Roll around at the end if (lastOffset != messageOffset) { @@ -353,8 +353,7 @@ static void settings_setInputPRange(void) { static void settings_displayInputPRange(void) { printShortDescription(0, 5); //0 = 9V, 1=12V (Fixed Voltages, these imply 1.5A limits) - //2 = 18W, 2=24W (Auto Adjusting V, estimated from the tip resistance???) # TODO - // Need to come back and look at these ^ as there were issues with voltage hunting + /// TODO TS80P switch (systemSettings.cutoutSetting) { case 0: OLED::printNumber(9, 2); @@ -647,7 +646,7 @@ static void settings_setResetSettings(void) { OLED::print(ResetOKMessage); 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_B_LONG: saveSettings(); + OLED::setCursor(0, 0); + OLED::printNumber(systemSettings.voltageDiv, 3); + OLED::refresh(); + waitForButtonPressOrTimeout(1000); return; break; case BUTTON_NONE: @@ -740,7 +743,7 @@ static void settings_setCalibrateVIN(void) { osDelay(40); // Cap to sensible values -#ifdef MODEL_TS80 +#if defined(MODEL_TS80)+defined(MODEL_TS80P)>0 if (systemSettings.voltageDiv < 500) { systemSettings.voltageDiv = 500; } else if (systemSettings.voltageDiv > 900) { @@ -930,7 +933,7 @@ void gui_Menu(const menuitem *menu) { OLED::setCursor(0, 0); // If the user has hesitated for >=3 seconds, show the long text // Otherwise "draw" the option - if ((xTaskGetTickCount() - lastButtonTime < 300) + if ((xTaskGetTickCount() - lastButtonTime < 3000) || menu[currentScreen].description == NULL) { OLED::clearScreen(); menu[currentScreen].draw.func(); @@ -949,7 +952,7 @@ void gui_Menu(const menuitem *menu) { int16_t descriptionOffset = ((xTaskGetTickCount() - descriptionStart) / (systemSettings.descriptionScrollSpeed == 1 ? - 1 : 2)); + 10 : 20)); descriptionOffset %= descriptionWidth; // Roll around at the end if (lastOffset != descriptionOffset) { OLED::clearScreen(); @@ -1037,7 +1040,7 @@ void gui_Menu(const menuitem *menu) { osDelay(40); 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 // This will trickle the user back to the main screen eventually earlyExit = true; diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 3141a5d2..89d2bc45 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -13,7 +13,7 @@ #include "cmsis_os.h" uint8_t PCBVersion = 0; // File local variables - +bool usb_pd_available = false; bool settingsWereReset = false; // FreeRTOS variables @@ -43,21 +43,28 @@ int main(void) { OLED::setFont(0); // default to bigger font // Testing for which accelerometer is mounted resetWatchdog(); + usb_pd_available = usb_pd_detect(); + resetWatchdog(); settingsWereReset = restoreSettings(); // load the settings from flash +#ifdef ACCEL_MMA if (MMA8652FC::detect()) { PCBVersion = 1; MMA8652FC::initalize(); // this sets up the I2C registers - } else if (LIS2DH12::detect()) { + } else +#endif +#ifdef ACCEL_LIS + if (LIS2DH12::detect()) { PCBVersion = 2; // Setup the ST Accelerometer LIS2DH12::initalize(); // startup the accelerometer - } else { + } else +#endif + { PCBVersion = 3; systemSettings.SleepTime = 0; systemSettings.ShutdownTime = 0; // No accel -> disable sleep systemSettings.sensitivity = 0; } - resetWatchdog(); /* Create the thread(s) */ diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 13e94ea0..afeceeeb 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -22,7 +22,7 @@ extern "C" { #include "stdlib.h" #include "string.h" #include "unit.h" - +#include "I2CBB.hpp" // File local variables extern uint32_t currentTempTargetDegC; extern uint8_t accelInit; @@ -36,720 +36,774 @@ extern osThreadId PIDTaskHandle; #define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ) static uint16_t min(uint16_t a, uint16_t b) { - if (a > b) - return b; - else - return a; + if (a > b) + return b; + else + return a; } void printVoltage() { - uint32_t volt = getInputVoltageX10(systemSettings.voltageDiv, 0); - OLED::printNumber(volt / 10, 2); - OLED::print(SymbolDot); - OLED::printNumber(volt % 10, 1); + uint32_t volt = getInputVoltageX10(systemSettings.voltageDiv, 0); + OLED::printNumber(volt / 10, 2); + OLED::print(SymbolDot); + OLED::printNumber(volt % 10, 1); } void GUIDelay() { - // Called in all UI looping tasks, - // This limits the re-draw rate to the LCD and also lets the DMA run - // As the gui task can very easily fill this bus with transactions, which will - // prevent the movement detection from running - osDelay(50); + // Called in all UI looping tasks, + // This limits the re-draw rate to the LCD and also lets the DMA run + // As the gui task can very easily fill this bus with transactions, which will + // prevent the movement detection from running + osDelay(50); } void gui_drawTipTemp(bool symbol) { - // Draw tip temp handling unit conversion & tolerance near setpoint - uint16_t Temp = 0; + // Draw tip temp handling unit conversion & tolerance near setpoint + uint16_t Temp = 0; #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) + if (systemSettings.temperatureInF){ Temp = TipThermoModel::getTipInF(); - else + }else #endif - Temp = TipThermoModel::getTipInC(); + { + Temp = TipThermoModel::getTipInC(); + } - OLED::printNumber(Temp, 3); // Draw the tip temp out finally - if (symbol) { - if (OLED::getFont() == 0) { - // Big font, can draw nice symbols + OLED::printNumber(Temp, 3); // Draw the tip temp out finally + if (symbol) { + if (OLED::getFont() == 0) { + // Big font, can draw nice symbols #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::drawSymbol(0); else #endif - OLED::drawSymbol(1); - } else { - // Otherwise fall back to chars + OLED::drawSymbol(1); + } else { + // Otherwise fall back to chars #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::print(SymbolDegF); else #endif - OLED::print(SymbolDegC); - } - } + OLED::print(SymbolDegC); + } + } } #ifdef MODEL_TS100 // returns true if undervoltage has occured static bool checkVoltageForExit() { - uint16_t v = getInputVoltageX10(systemSettings.voltageDiv, 0); + uint16_t v = getInputVoltageX10(systemSettings.voltageDiv, 0); - // Dont check for first 1.5 seconds while the ADC stabilizes and the DMA fills the buffer - if (xTaskGetTickCount() > 150) { - if ((v < lookupVoltageLevel(systemSettings.cutoutSetting))) { - GUIDelay(); - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedSoldering) { - OLED::setFont(1); - OLED::print(UndervoltageString); - OLED::setCursor(0, 8); - OLED::print(InputVoltageString); - printVoltage(); - OLED::print(SymbolVolts); + // Dont check for first 1.5 seconds while the ADC stabilizes and the DMA fills the buffer + if (xTaskGetTickCount() > 150) { + if ((v < lookupVoltageLevel(systemSettings.cutoutSetting))) { + GUIDelay(); + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedSoldering) { + OLED::setFont(1); + OLED::print(UndervoltageString); + OLED::setCursor(0, 8); + OLED::print(InputVoltageString); + printVoltage(); + OLED::print(SymbolVolts); - } else { - OLED::setFont(0); - OLED::print(UVLOWarningString); - } + } else { + OLED::setFont(0); + OLED::print(UVLOWarningString); + } - OLED::refresh(); - currentTempTargetDegC = 0; - waitForButtonPress(); - return true; - } - } - return false; + OLED::refresh(); + currentTempTargetDegC = 0; + waitForButtonPress(); + return true; + } + } + return false; } #endif static void gui_drawBatteryIcon() { #ifdef MODEL_TS100 - if (systemSettings.cutoutSetting) { - // User is on a lithium battery - // we need to calculate which of the 10 levels they are on - uint8_t cellCount = systemSettings.cutoutSetting + 2; - uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) / cellCount; - // Should give us approx cell voltage X10 - // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 - if (cellV < 33) cellV = 33; - cellV -= 33; // Should leave us a number of 0-9 - if (cellV > 9) cellV = 9; - OLED::drawBattery(cellV + 1); - } else - OLED::drawSymbol(15); // Draw the DC Logo + if (systemSettings.cutoutSetting) { + // User is on a lithium battery + // we need to calculate which of the 10 levels they are on + uint8_t cellCount = systemSettings.cutoutSetting + 2; + uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) + / cellCount; + // Should give us approx cell voltage X10 + // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 + if (cellV < 33) + cellV = 33; + cellV -= 33; // Should leave us a number of 0-9 + if (cellV > 9) + cellV = 9; + OLED::drawBattery(cellV + 1); + } else + OLED::drawSymbol(15); // Draw the DC Logo #else - // On TS80 we replace this symbol with the voltage we are operating on - // If <9V then show single digit, if not show duals - uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); - if (V % 10 >= 5) - V = V / 10 + 1; // round up - else - V = V / 10; - if (V >= 10) { - int16_t xPos = OLED::getCursorX(); - OLED::setFont(1); - OLED::printNumber(1, 1); - OLED::setCursor(xPos, 8); - OLED::printNumber(V % 10, 1); - OLED::setFont(0); - OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char - } else { - OLED::printNumber(V, 1); - } + // On TS80 we replace this symbol with the voltage we are operating on + // If <9V then show single digit, if not show duals + uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); + if (V % 10 >= 5) + V = V / 10 + 1; // round up + else + V = V / 10; + if (V >= 10) { + int16_t xPos = OLED::getCursorX(); + OLED::setFont(1); + OLED::printNumber(1, 1); + OLED::setCursor(xPos, 8); + OLED::printNumber(V % 10, 1); + OLED::setFont(0); + OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char + } else { + OLED::printNumber(V, 1); + } #endif } static void gui_solderingTempAdjust() { - uint32_t lastChange = xTaskGetTickCount(); - currentTempTargetDegC = 0; - uint32_t autoRepeatTimer = 0; - uint8_t autoRepeatAcceleration = 0; - for (;;) { - OLED::setCursor(0, 0); - OLED::clearScreen(); - OLED::setFont(0); - ButtonState buttons = getButtonState(); - if (buttons) lastChange = xTaskGetTickCount(); - switch (buttons) { - case BUTTON_NONE: - // stay - break; - case BUTTON_BOTH: - // exit - return; - break; - case BUTTON_B_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; - } else - systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; + uint32_t lastChange = xTaskGetTickCount(); + currentTempTargetDegC = 0; + uint32_t autoRepeatTimer = 0; + uint8_t autoRepeatAcceleration = 0; + for (;;) { + OLED::setCursor(0, 0); + OLED::clearScreen(); + OLED::setFont(0); + ButtonState buttons = getButtonState(); + if (buttons) + lastChange = xTaskGetTickCount(); + switch (buttons) { + case BUTTON_NONE: + // stay + break; + case BUTTON_BOTH: + // exit + return; + break; + case BUTTON_B_LONG: + if (xTaskGetTickCount() - autoRepeatTimer + + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp += + systemSettings.TempChangeLongStep; + } else + systemSettings.SolderingTemp -= + systemSettings.TempChangeLongStep; - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_B_SHORT: - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; - } else - systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; - break; - case BUTTON_F_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; - } else - systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; - autoRepeatTimer = xTaskGetTickCount(); - autoRepeatAcceleration += PRESS_ACCEL_STEP; - } - break; - case BUTTON_F_SHORT: - if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; // add 10 - } else - systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; // add 10 - break; - default: - break; - } - if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) { - autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; - } - // constrain between 10-450 C + autoRepeatTimer = xTaskGetTickCount(); + autoRepeatAcceleration += PRESS_ACCEL_STEP; + } + break; + case BUTTON_B_SHORT: + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp += + systemSettings.TempChangeShortStep; + } else + systemSettings.SolderingTemp -= + systemSettings.TempChangeShortStep; + break; + case BUTTON_F_LONG: + if (xTaskGetTickCount() - autoRepeatTimer + + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp -= + systemSettings.TempChangeLongStep; + } else + systemSettings.SolderingTemp += + systemSettings.TempChangeLongStep; + autoRepeatTimer = xTaskGetTickCount(); + autoRepeatAcceleration += PRESS_ACCEL_STEP; + } + break; + case BUTTON_F_SHORT: + if (systemSettings.ReverseButtonTempChangeEnabled) { + systemSettings.SolderingTemp -= + systemSettings.TempChangeShortStep; // add 10 + } else + systemSettings.SolderingTemp += + systemSettings.TempChangeShortStep; // add 10 + break; + default: + break; + } + if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) + < PRESS_ACCEL_INTERVAL_MIN) { + autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX + - PRESS_ACCEL_INTERVAL_MIN; + } + // constrain between 10-450 C #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { if (systemSettings.SolderingTemp > 850) systemSettings.SolderingTemp = 850; if (systemSettings.SolderingTemp < 60) systemSettings.SolderingTemp = 60; } else #endif - { - if (systemSettings.SolderingTemp > 450) systemSettings.SolderingTemp = 450; - if (systemSettings.SolderingTemp < 10) systemSettings.SolderingTemp = 10; - } + { + if (systemSettings.SolderingTemp > 450) + systemSettings.SolderingTemp = 450; + if (systemSettings.SolderingTemp < 10) + systemSettings.SolderingTemp = 10; + } - if (xTaskGetTickCount() - lastChange > 200) return; // exit if user just doesn't press anything for a bit + if (xTaskGetTickCount() - lastChange > 2000) + return; // exit if user just doesn't press anything for a bit -#ifdef MODEL_TS80 - if (!OLED::getRotation()) { +#ifdef OLED_FLIP + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus); - } else { - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus); - } + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolPlus : SymbolMinus); + } else { + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolMinus : SymbolPlus); + } - OLED::print(SymbolSpace); - OLED::printNumber(systemSettings.SolderingTemp, 3); + OLED::print(SymbolSpace); + OLED::printNumber(systemSettings.SolderingTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::drawSymbol(0); else #endif - { - OLED::drawSymbol(1); - } - OLED::print(SymbolSpace); -#ifdef MODEL_TS80 - if (!OLED::getRotation()) { + { + OLED::drawSymbol(1); + } + OLED::print(SymbolSpace); +#ifdef OLED_FLIP + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus); - } else { - OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus); - } - OLED::refresh(); - GUIDelay(); - } + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolMinus : SymbolPlus); + } else { + OLED::print( + systemSettings.ReverseButtonTempChangeEnabled ? + SymbolPlus : SymbolMinus); + } + OLED::refresh(); + GUIDelay(); + } } static int gui_SolderingSleepingMode(bool stayOff) { - // Drop to sleep temperature and display until movement or button press + // Drop to sleep temperature and display until movement or button press - for (;;) { - ButtonState buttons = getButtonState(); - if (buttons) return 0; - if ((xTaskGetTickCount() > 100) && ((accelInit && (xTaskGetTickCount() - lastMovementTime < 100)) || (xTaskGetTickCount() - lastButtonTime < 100))) return 0; // user moved or pressed a button, go back to soldering + for (;;) { + ButtonState buttons = getButtonState(); + if (buttons) + return 0; + if ((xTaskGetTickCount() > 1000) + && ((accelInit + && (xTaskGetTickCount() - lastMovementTime < 1000)) + || (xTaskGetTickCount() - lastButtonTime < 1000))) + return 0; // user moved or pressed a button, go back to soldering #ifdef MODEL_TS100 - if (checkVoltageForExit()) return 1; // return non-zero on error + if (checkVoltageForExit()) + return 1; // return non-zero on error #endif #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(systemSettings.SleepTemp, systemSettings.SolderingTemp)); } else #endif - { - currentTempTargetDegC = stayOff ? 0 : min(systemSettings.SleepTemp, systemSettings.SolderingTemp); - } - // draw the lcd - uint16_t tipTemp; + { + currentTempTargetDegC = + stayOff ? + 0 : + min(systemSettings.SleepTemp, + systemSettings.SolderingTemp); + } + // draw the lcd + uint16_t tipTemp; #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) tipTemp = TipThermoModel::getTipInF(); else #endif - { - tipTemp = TipThermoModel::getTipInC(); - } + { + tipTemp = TipThermoModel::getTipInC(); + } - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedSoldering) { - OLED::setFont(1); - OLED::print(SleepingAdvancedString); - OLED::setCursor(0, 8); - OLED::print(SleepingTipAdvancedString); - OLED::printNumber(tipTemp, 3); + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedSoldering) { + OLED::setFont(1); + OLED::print(SleepingAdvancedString); + OLED::setCursor(0, 8); + OLED::print(SleepingTipAdvancedString); + OLED::printNumber(tipTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::print(SymbolDegF); else #endif - { - OLED::print(SymbolDegC); - } + { + OLED::print(SymbolDegC); + } - OLED::print(SymbolSpace); - printVoltage(); - OLED::print(SymbolVolts); - } else { - OLED::setFont(0); - OLED::print(SleepingSimpleString); - OLED::printNumber(tipTemp, 3); + OLED::print(SymbolSpace); + printVoltage(); + OLED::print(SymbolVolts); + } else { + OLED::setFont(0); + OLED::print(SleepingSimpleString); + OLED::printNumber(tipTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) OLED::drawSymbol(0); else #endif - { - OLED::drawSymbol(1); - } - } - if (systemSettings.ShutdownTime) // only allow shutdown exit if time > 0 - if (lastMovementTime) - if (((uint32_t)(xTaskGetTickCount() - lastMovementTime)) > (uint32_t)(systemSettings.ShutdownTime * 60 * 100)) { - // shutdown - currentTempTargetDegC = 0; - return 1; // we want to exit soldering mode - } - OLED::refresh(); - GUIDelay(); - } - return 0; + { + OLED::drawSymbol(1); + } + } + if (systemSettings.ShutdownTime) // only allow shutdown exit if time > 0 + if (lastMovementTime) + if (((uint32_t) (xTaskGetTickCount() - lastMovementTime)) + > (uint32_t) (systemSettings.ShutdownTime * 60 * 1000)) { + // shutdown + currentTempTargetDegC = 0; + return 1; // we want to exit soldering mode + } + OLED::refresh(); + GUIDelay(); + } + return 0; } static void display_countdown(int sleepThres) { - /* - * Print seconds or minutes (if > 99 seconds) until sleep - * mode is triggered. - */ - int lastEventTime = lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime; - int downCount = sleepThres - xTaskGetTickCount() + lastEventTime; - if (downCount > 9900) { - OLED::printNumber(downCount / 6000 + 1, 2); - OLED::print(SymbolMinutes); - } else { - OLED::printNumber(downCount / 100 + 1, 2); - OLED::print(SymbolSeconds); - } + /* + * Print seconds or minutes (if > 99 seconds) until sleep + * mode is triggered. + */ + int lastEventTime = + lastButtonTime < lastMovementTime ? + lastMovementTime : lastButtonTime; + int downCount = sleepThres - xTaskGetTickCount() + lastEventTime; + if (downCount > 99000) { + OLED::printNumber(downCount / 60000 + 1, 2); + OLED::print(SymbolMinutes); + } else { + OLED::printNumber(downCount / 1000 + 1, 2); + OLED::print(SymbolSeconds); + } } static void gui_solderingMode(uint8_t jumpToSleep) { - /* - * * Soldering (gui_solderingMode) - * -> Main loop where we draw temp, and animations - * --> User presses buttons and they goto the temperature adjust screen - * ---> Display the current setpoint temperature - * ---> Use buttons to change forward and back on temperature - * ---> Both buttons or timeout for exiting - * --> Long hold front button to enter boost mode - * ---> Just temporarily sets the system into the alternate temperature for - * PID control - * --> Long hold back button to exit - * --> Double button to exit - */ - bool boostModeOn = false; + /* + * * Soldering (gui_solderingMode) + * -> Main loop where we draw temp, and animations + * --> User presses buttons and they goto the temperature adjust screen + * ---> Display the current setpoint temperature + * ---> Use buttons to change forward and back on temperature + * ---> Both buttons or timeout for exiting + * --> Long hold front button to enter boost mode + * ---> Just temporarily sets the system into the alternate temperature for + * PID control + * --> Long hold back button to exit + * --> Double button to exit + */ + bool boostModeOn = false; - uint32_t sleepThres = 0; - if (systemSettings.SleepTime < 6) - sleepThres = systemSettings.SleepTime * 10 * 100; - else - sleepThres = (systemSettings.SleepTime - 5) * 60 * 100; - if (jumpToSleep) { - if (gui_SolderingSleepingMode(jumpToSleep == 2)) { - lastButtonTime = xTaskGetTickCount(); - return; // If the function returns non-0 then exit - } - } - for (;;) { - ButtonState buttons = getButtonState(); - switch (buttons) { - case BUTTON_NONE: - // stay - boostModeOn = false; - break; - case BUTTON_BOTH: - // exit - return; - break; - case BUTTON_B_LONG: - return; // exit on back long hold - break; - case BUTTON_F_LONG: - // if boost mode is enabled turn it on - if (systemSettings.boostModeEnabled) boostModeOn = true; - break; - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: { - uint16_t oldTemp = systemSettings.SolderingTemp; - gui_solderingTempAdjust(); // goto adjust temp mode - if (oldTemp != systemSettings.SolderingTemp) { - saveSettings(); // only save on change - } - } break; - default: - break; - } - // else we update the screen information - OLED::setCursor(0, 0); - OLED::clearScreen(); - OLED::setFont(0); - // Draw in the screen details - if (systemSettings.detailedSoldering) { - OLED::setFont(1); - OLED::print(SolderingAdvancedPowerPrompt); // Power: - OLED::printNumber(x10WattHistory.average() / 10, 2); - OLED::print(SymbolDot); - OLED::printNumber(x10WattHistory.average() % 10, 1); - OLED::print(SymbolWatts); + uint32_t sleepThres = 0; + if (systemSettings.SleepTime < 6) + sleepThres = systemSettings.SleepTime * 10 * 1000; + else + sleepThres = (systemSettings.SleepTime - 5) * 60 * 1000; + if (jumpToSleep) { + if (gui_SolderingSleepingMode(jumpToSleep == 2)) { + lastButtonTime = xTaskGetTickCount(); + return; // If the function returns non-0 then exit + } + } + for (;;) { + ButtonState buttons = getButtonState(); + switch (buttons) { + case BUTTON_NONE: + // stay + boostModeOn = false; + break; + case BUTTON_BOTH: + // exit + return; + break; + case BUTTON_B_LONG: + return; // exit on back long hold + break; + case BUTTON_F_LONG: + // if boost mode is enabled turn it on + if (systemSettings.boostModeEnabled) + boostModeOn = true; + break; + case BUTTON_F_SHORT: + case BUTTON_B_SHORT: { + uint16_t oldTemp = systemSettings.SolderingTemp; + gui_solderingTempAdjust(); // goto adjust temp mode + if (oldTemp != systemSettings.SolderingTemp) { + saveSettings(); // only save on change + } + } + break; + default: + break; + } + // else we update the screen information + OLED::setCursor(0, 0); + OLED::clearScreen(); + OLED::setFont(0); + // Draw in the screen details + if (systemSettings.detailedSoldering) { + OLED::setFont(1); + OLED::print(SolderingAdvancedPowerPrompt); // Power: + OLED::printNumber(x10WattHistory.average() / 10, 2); + OLED::print(SymbolDot); + OLED::printNumber(x10WattHistory.average() % 10, 1); + OLED::print(SymbolWatts); - if (systemSettings.sensitivity && systemSettings.SleepTime) { - OLED::print(SymbolSpace); - display_countdown(sleepThres); - } + if (systemSettings.sensitivity && systemSettings.SleepTime) { + OLED::print(SymbolSpace); + display_countdown(sleepThres); + } - OLED::setCursor(0, 8); - OLED::print(SleepingTipAdvancedString); - // OLED::printNumber( - // TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 5); // Draw the tip temp out finally + OLED::setCursor(0, 8); + OLED::print(SleepingTipAdvancedString); + gui_drawTipTemp(true); + OLED::print(SymbolSpace); + printVoltage(); + OLED::print(SymbolVolts); + } else { + // We switch the layout direction depending on the orientation of the + // OLED:: + if (OLED::getRotation()) { + // battery + gui_drawBatteryIcon(); + OLED::print(SymbolSpace); // Space out gap between battery <-> temp + gui_drawTipTemp(true); // Draw current tip temp - gui_drawTipTemp(true); - OLED::print(SymbolSpace); - printVoltage(); - OLED::print(SymbolVolts); - } else { - // We switch the layout direction depending on the orientation of the - // OLED:: - if (OLED::getRotation()) { - // battery - gui_drawBatteryIcon(); - OLED::print(SymbolSpace); // Space out gap between battery <-> temp - gui_drawTipTemp(true); // Draw current tip temp + // We draw boost arrow if boosting, or else gap temp <-> heat + // indicator + if (boostModeOn) + OLED::drawSymbol(2); + else + OLED::print(SymbolSpace); - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace); + // Draw heating/cooling symbols + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); + } else { + // Draw heating/cooling symbols + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); + // We draw boost arrow if boosting, or else gap temp <-> heat + // indicator + if (boostModeOn) + OLED::drawSymbol(2); + else + OLED::print(SymbolSpace); + gui_drawTipTemp(true); // Draw current tip temp - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - } else { - // Draw heating/cooling symbols - OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average())); - // We draw boost arrow if boosting, or else gap temp <-> heat - // indicator - if (boostModeOn) - OLED::drawSymbol(2); - else - OLED::print(SymbolSpace); - gui_drawTipTemp(true); // Draw current tip temp + OLED::print(SymbolSpace); // Space out gap between battery <-> temp - OLED::print(SymbolSpace); // Space out gap between battery <-> temp + gui_drawBatteryIcon(); + } + } + OLED::refresh(); - gui_drawBatteryIcon(); - } - } - OLED::refresh(); - - // Update the setpoints for the temperature - if (boostModeOn) { + // Update the setpoints for the temperature + if (boostModeOn) { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.BoostTemp); else #endif - { - currentTempTargetDegC = (systemSettings.BoostTemp); - } - } else { + { + currentTempTargetDegC = (systemSettings.BoostTemp); + } + } else { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.SolderingTemp); else #endif - { - currentTempTargetDegC = (systemSettings.SolderingTemp); - } - } + { + currentTempTargetDegC = (systemSettings.SolderingTemp); + } + } #ifdef MODEL_TS100 - // Undervoltage test - if (checkVoltageForExit()) { - lastButtonTime = xTaskGetTickCount(); - return; - } -#else - // on the TS80 we only want to check for over voltage to prevent tip damage - /*if (getInputVoltageX10(systemSettings.voltageDiv, 1) > 150) { - lastButtonTime = xTaskGetTickCount(); - currentlyActiveTemperatureTarget = 0; - return; // Over voltage - }*/ + // Undervoltage test + if (checkVoltageForExit()) { + lastButtonTime = xTaskGetTickCount(); + return; + } #endif - if (systemSettings.sensitivity && systemSettings.SleepTime) - if (xTaskGetTickCount() - lastMovementTime > sleepThres && xTaskGetTickCount() - lastButtonTime > sleepThres) { - if (gui_SolderingSleepingMode(false)) { - return; // If the function returns non-0 then exit - } - } - // slow down ui update rate - GUIDelay(); - } + if (systemSettings.sensitivity && systemSettings.SleepTime) + if (xTaskGetTickCount() - lastMovementTime > sleepThres + && xTaskGetTickCount() - lastButtonTime > sleepThres) { + if (gui_SolderingSleepingMode(false)) { + return; // If the function returns non-0 then exit + } + } + // slow down ui update rate + GUIDelay(); + } } void showDebugMenu(void) { - uint8_t screen = 0; - ButtonState b; - for (;;) { - OLED::clearScreen(); // Ensure the buffer starts clean - OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) - OLED::setFont(1); // small font - OLED::print(SymbolVersionNumber); // Print version number - OLED::setCursor(0, 8); // second line - OLED::print(DebugMenu[screen]); - switch (screen) { - case 0: // Just prints date - break; - case 1: - // High water mark for GUI - OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 5); - break; - case 2: - // High water mark for the Movement task - OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 5); - break; - case 3: - // High water mark for the PID task - OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 5); - break; - case 4: - // system up time stamp - OLED::printNumber(xTaskGetTickCount() / 100, 5); - break; - case 5: - // Movement time stamp - OLED::printNumber(lastMovementTime / 100, 5); - break; - case 6: - // Raw Tip - { - uint32_t temp = systemSettings.CalibrationOffset; - systemSettings.CalibrationOffset = 0; - OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); - systemSettings.CalibrationOffset = temp; - } - break; - case 7: - // Temp in C - OLED::printNumber(TipThermoModel::getTipInC(1), 5); - break; - case 8: - // Handle Temp - OLED::printNumber(getHandleTemperature(), 3); - break; - case 9: - // Voltage input - printVoltage(); - break; - case 10: - // Print PCB ID number - OLED::printNumber(PCBVersion, 1); - break; - default: - break; - } + uint8_t screen = 0; + ButtonState b; + for (;;) { + OLED::clearScreen(); // Ensure the buffer starts clean + OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) + OLED::setFont(1); // small font + OLED::print(SymbolVersionNumber); // Print version number + OLED::setCursor(0, 8); // second line + OLED::print(DebugMenu[screen]); + switch (screen) { + case 0: // Just prints date + break; + case 1: + // High water mark for GUI + OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 5); + break; + case 2: + // High water mark for the Movement task + OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 5); + break; + case 3: + // High water mark for the PID task + OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 5); + break; + case 4: + // system up time stamp + OLED::printNumber(xTaskGetTickCount() / 100, 5); + break; + case 5: + // Movement time stamp + OLED::printNumber(lastMovementTime / 100, 5); + break; + case 6: + // Raw Tip + { + uint32_t temp = systemSettings.CalibrationOffset; + systemSettings.CalibrationOffset = 0; + OLED::printNumber( + TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); + systemSettings.CalibrationOffset = temp; + } + break; + case 7: + // Temp in C + OLED::printNumber(TipThermoModel::getTipInC(1), 5); + break; + case 8: + // Handle Temp + OLED::printNumber(getHandleTemperature(), 3); + break; + case 9: + // Voltage input + printVoltage(); + break; + case 10: + // Print PCB ID number + OLED::printNumber(PCBVersion, 1); + break; + default: + break; + } - OLED::refresh(); - b = getButtonState(); - if (b == BUTTON_B_SHORT) - return; - else if (b == BUTTON_F_SHORT) { - screen++; - screen = screen % 11; - } - GUIDelay(); - } + OLED::refresh(); + b = getButtonState(); + if (b == BUTTON_B_SHORT) + return; + else if (b == BUTTON_F_SHORT) { + screen++; + screen = screen % 11; + } + GUIDelay(); + } } - +uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { - uint8_t tempWarningState = 0; - bool buttonLockout = false; - bool tempOnDisplay = false; - getTipRawTemp(1); // reset filter - OLED::setRotation(systemSettings.OrientationMode & 1); - uint32_t ticks = xTaskGetTickCount(); - ticks += 400; // 4 seconds from now - while (xTaskGetTickCount() < ticks) { - if (showBootLogoIfavailable() == false) ticks = xTaskGetTickCount(); - ButtonState buttons = getButtonState(); - if (buttons) ticks = xTaskGetTickCount(); // make timeout now so we will exit - GUIDelay(); - } + uint8_t tempWarningState = 0; + bool buttonLockout = false; + bool tempOnDisplay = false; + { + //Generate the flipped screen into ram for later use +//flipped is generated by flipping each row + for (int row = 0; row < 2; row++) { + for (int x = 0; x < 84; x++) { + idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) + + (83 - x)]; + } + } + } + getTipRawTemp(1); // reset filter + OLED::setRotation(systemSettings.OrientationMode & 1); + uint32_t ticks = xTaskGetTickCount(); + ticks += 4000; // 4 seconds from now + while (xTaskGetTickCount() < ticks) { + if (showBootLogoIfavailable() == false) + ticks = xTaskGetTickCount(); + ButtonState buttons = getButtonState(); + if (buttons) + ticks = xTaskGetTickCount(); // make timeout now so we will exit + GUIDelay(); + } - if (settingsWereReset) { - // Display alert settings were reset - OLED::clearScreen(); - OLED::setFont(1); - OLED::setCursor(0, 0); - OLED::print(SettingsResetMessage); - OLED::refresh(); - waitForButtonPressOrTimeout(1000); - } + if (settingsWereReset) { + // Display alert settings were reset + OLED::clearScreen(); + OLED::setFont(1); + OLED::setCursor(0, 0); + OLED::print(SettingsResetMessage); + OLED::refresh(); + waitForButtonPressOrTimeout(10000); + } + if (systemSettings.autoStartMode) { + // jump directly to the autostart mode + if (systemSettings.autoStartMode == 1) { + gui_solderingMode(0); + buttonLockout = true; + } else if (systemSettings.autoStartMode == 2) { + gui_solderingMode(1); + buttonLockout = true; + } else if (systemSettings.autoStartMode == 3) { + gui_solderingMode(2); + buttonLockout = true; + } + } - if (systemSettings.autoStartMode) { - // jump directly to the autostart mode - if (systemSettings.autoStartMode == 1) { - gui_solderingMode(0); - buttonLockout = true; - } else if (systemSettings.autoStartMode == 2) { - gui_solderingMode(1); - buttonLockout = true; - } else if (systemSettings.autoStartMode == 3) { - gui_solderingMode(2); - buttonLockout = true; - } - } + for (;;) { + ButtonState buttons = getButtonState(); + if (buttons != BUTTON_NONE) { + OLED::setDisplayState(OLED::DisplayState::ON); + OLED::setFont(0); + } + if (tempWarningState == 2) + buttons = BUTTON_F_SHORT; + if (buttons != BUTTON_NONE && buttonLockout) + buttons = BUTTON_NONE; + else + buttonLockout = false; - for (;;) { - ButtonState buttons = getButtonState(); - if (buttons != BUTTON_NONE) { - OLED::setDisplayState(OLED::DisplayState::ON); - OLED::setFont(0); - } - if (tempWarningState == 2) buttons = BUTTON_F_SHORT; - if (buttons != BUTTON_NONE && buttonLockout) - buttons = BUTTON_NONE; - else - buttonLockout = false; + switch (buttons) { + case BUTTON_NONE: + // Do nothing + break; + case BUTTON_BOTH: + // Not used yet + // In multi-language this might be used to reset language on a long hold + // or some such + break; - switch (buttons) { - case BUTTON_NONE: - // Do nothing - break; - case BUTTON_BOTH: - // Not used yet - // In multi-language this might be used to reset language on a long hold - // or some such - break; + case BUTTON_B_LONG: + // Show the version information + showDebugMenu(); + break; + case BUTTON_F_LONG: + gui_solderingTempAdjust(); + saveSettings(); + break; + case BUTTON_F_SHORT: + gui_solderingMode(0); // enter soldering mode + buttonLockout = true; + break; + case BUTTON_B_SHORT: + enterSettingsMenu(); // enter the settings menu + buttonLockout = true; + break; + default: + break; + } - case BUTTON_B_LONG: - // Show the version information - showDebugMenu(); - break; - case BUTTON_F_LONG: - gui_solderingTempAdjust(); - saveSettings(); - break; - case BUTTON_F_SHORT: - gui_solderingMode(0); // enter soldering mode - buttonLockout = true; - break; - case BUTTON_B_SHORT: - enterSettingsMenu(); // enter the settings menu - buttonLockout = true; - break; - default: - break; - } + currentTempTargetDegC = 0; // ensure tip is off + getInputVoltageX10(systemSettings.voltageDiv, 0); + uint16_t tipTemp = TipThermoModel::getTipInC(); - currentTempTargetDegC = 0; // ensure tip is off - getInputVoltageX10(systemSettings.voltageDiv, 0); - uint16_t tipTemp = TipThermoModel::getTipInC(); + // Preemptively turn the display on. Turn it off if and only if + // the tip temperature is below 50 degrees C *and* motion sleep + // detection is enabled *and* there has been no activity (movement or + // button presses) in a while. + OLED::setDisplayState(OLED::DisplayState::ON); - // Preemptively turn the display on. Turn it off if and only if - // the tip temperature is below 50 degrees C *and* motion sleep - // detection is enabled *and* there has been no activity (movement or - // button presses) in a while. - OLED::setDisplayState(OLED::DisplayState::ON); + if ((tipTemp < 50) && systemSettings.sensitivity + && (((xTaskGetTickCount() - lastMovementTime) + > MOVEMENT_INACTIVITY_TIME) + && ((xTaskGetTickCount() - lastButtonTime) + > BUTTON_INACTIVITY_TIME))) { + OLED::setDisplayState(OLED::DisplayState::OFF); + } - if ((tipTemp < 50) && systemSettings.sensitivity && (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { - OLED::setDisplayState(OLED::DisplayState::OFF); - } + // Clear the lcd buffer + OLED::clearScreen(); + OLED::setCursor(0, 0); + if (systemSettings.detailedIDLE) { + OLED::setFont(1); + if (tipTemp > 470) { + OLED::print(TipDisconnectedString); + } else { + OLED::print(IdleTipString); + gui_drawTipTemp(false); + OLED::print(IdleSetString); + OLED::printNumber(systemSettings.SolderingTemp, 3); + } + OLED::setCursor(0, 8); - // Clear the lcd buffer - OLED::clearScreen(); - OLED::setCursor(0, 0); - if (systemSettings.detailedIDLE) { - OLED::setFont(1); - if (tipTemp > 470) { - OLED::print(TipDisconnectedString); - } else { - OLED::print(IdleTipString); - gui_drawTipTemp(false); - OLED::print(IdleSetString); - OLED::printNumber(systemSettings.SolderingTemp, 3); - } - OLED::setCursor(0, 8); + OLED::print(InputVoltageString); + printVoltage(); - OLED::print(InputVoltageString); - printVoltage(); - - } else { - OLED::setFont(0); -#ifdef MODEL_TS80 - if (!OLED::getRotation()) { + } else { + OLED::setFont(0); +#ifdef OLED_FLIP + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - OLED::drawArea(12, 0, 84, 16, idleScreenBG); - OLED::setCursor(0, 0); - gui_drawBatteryIcon(); - } else { - OLED::drawArea(0, 0, 84, 16, idleScreenBGF); // Needs to be flipped so button ends up - // on right side of screen - OLED::setCursor(84, 0); - gui_drawBatteryIcon(); - } - if (tipTemp > 55) - tempOnDisplay = true; - else if (tipTemp < 45) - tempOnDisplay = false; - if (tempOnDisplay) { - // draw temp over the start soldering button - // Location changes on screen rotation -#ifdef MODEL_TS80 - if (!OLED::getRotation()) { + OLED::drawArea(12, 0, 84, 16, idleScreenBG); + OLED::setCursor(0, 0); + gui_drawBatteryIcon(); + } else { + OLED::drawArea(0, 0, 84, 16, idleScreenBGF); // Needs to be flipped so button ends up + // on right side of screen + OLED::setCursor(84, 0); + gui_drawBatteryIcon(); + } + if (tipTemp > 55) + tempOnDisplay = true; + else if (tipTemp < 45) + tempOnDisplay = false; + if (tempOnDisplay) { + // draw temp over the start soldering button + // Location changes on screen rotation +#ifdef OLED_FLIP + if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif - // in right handed mode we want to draw over the first part - OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp - OLED::setCursor(56, 0); + // in right handed mode we want to draw over the first part + OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp + OLED::setCursor(56, 0); - } else { - OLED::fillArea(0, 0, 41, 16, 0); // clear the area - OLED::setCursor(0, 0); - } - // draw in the temp - if (!(systemSettings.coolingTempBlink && (xTaskGetTickCount() % 25 < 16))) gui_drawTipTemp(false); // draw in the temp - } - } - OLED::refresh(); - GUIDelay(); - } + } else { + OLED::fillArea(0, 0, 41, 16, 0); // clear the area + OLED::setCursor(0, 0); + } + // draw in the temp + if (!(systemSettings.coolingTempBlink + && (xTaskGetTickCount() % 25 < 16))) + gui_drawTipTemp(false); // draw in the temp + } + } + OLED::refresh(); + GUIDelay(); + } } diff --git a/workspace/TS100/Core/Threads/MOVThread.cpp b/workspace/TS100/Core/Threads/MOVThread.cpp index 5d236ba1..4ca5e54b 100644 --- a/workspace/TS100/Core/Threads/MOVThread.cpp +++ b/workspace/TS100/Core/Threads/MOVThread.cpp @@ -25,7 +25,6 @@ uint32_t lastMovementTime = 0; void startMOVTask(void const *argument __unused) { OLED::setRotation(systemSettings.OrientationMode & 1); postRToSInit(); - power_probe(); lastMovementTime = 0; int16_t datax[MOVFilter] = { 0 }; int16_t datay[MOVFilter] = { 0 }; @@ -39,13 +38,20 @@ void startMOVTask(void const *argument __unused) { for (;;) { int32_t threshold = 1500 + (9 * 200); threshold -= systemSettings.sensitivity * 200; // 200 is the step size - +#ifdef ACCEL_LIS if (PCBVersion == 2) { LIS2DH12::getAxisReadings(tx, ty, tz); rotation = LIS2DH12::getOrientation(); - } else if (PCBVersion == 1) { + } else +#endif +#ifdef ACCEL_MMA + if (PCBVersion == 1) { MMA8652FC::getAxisReadings(tx, ty, tz); rotation = MMA8652FC::getOrientation(); + }else +#endif + { + //do nothing :( } if (systemSettings.OrientationMode == 2) { if (rotation != ORIENTATION_FLAT) { diff --git a/workspace/TS100/Core/Threads/PIDThread.cpp b/workspace/TS100/Core/Threads/PIDThread.cpp index 844e3617..b0e523dc 100644 --- a/workspace/TS100/Core/Threads/PIDThread.cpp +++ b/workspace/TS100/Core/Threads/PIDThread.cpp @@ -14,8 +14,8 @@ #include "FreeRTOS.h" #include "task.h" #include "Settings.h" -static TickType_t powerPulseRate = 1000; -static TickType_t powerPulseDuration = 50; +static TickType_t powerPulseRate = 10000; +static TickType_t powerPulseDuration = 250; TaskHandle_t pidTaskNotification = NULL; uint32_t currentTempTargetDegC = 0; // Current temperature target in C diff --git a/workspace/TS100/LinkerScript.ld b/workspace/TS100/LinkerScript.ld index 8ca171b5..75be14f8 100644 --- a/workspace/TS100/LinkerScript.ld +++ b/workspace/TS100/LinkerScript.ld @@ -14,9 +14,9 @@ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K /* LOCAL_BUILD*/ -/*ROM (rx) : ORIGIN = 0x08000000, LENGTH = 46K*/ +/*ROM (rx) : ORIGIN = 0x08000000, LENGTH = 48K*/ /* production*/ -ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K + ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index a9868318..ba6ba490 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -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_GCC_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 DRIVER_INC_DIR =./Core/Drivers +FUSB_DRIVERS_INC_DIR = ./Core/Drivers/FUSB302 BSP_INC_DIR = ./Core/BSP MINIWARE_INC_DIR = ./Core/BSP/Miniware THREADS_INC_DIR = ./Core/Threads @@ -37,7 +38,8 @@ INCLUDES = -I$(APP_INC_DIR) \ -I$(DRIVER_INC_DIR) \ -I$(BSP_INC_DIR) \ -I$(MINIWARE_INC_DIR) \ - -I$(THREADS_INC_DIR) + -I$(THREADS_INC_DIR) \ + -I$(FUSB_DRIVERS_INC_DIR) # output folder HEXFILE_DIR=Hexfile diff --git a/workspace/TS100/build.sh b/workspace/TS100/build.sh index 2fd28523..068d7f20 100755 --- a/workspace/TS100/build.sh +++ b/workspace/TS100/build.sh @@ -6,7 +6,7 @@ TRANSLATION_SCRIPT="make_translation.py" # AVAILABLE_LANGUAGES will be calculating according to json files in $TRANSLATION_DIR AVAILABLE_LANGUAGES=() BUILD_LANGUAGES=() -AVAILABLE_MODELS=("TS100" "TS80") +AVAILABLE_MODELS=("TS100" "TS80" "TS80P") BUILD_MODELS=() usage() { diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index 1bdc13d0..57bdc23e 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -1,4 +1,5 @@ #pragma once +#include "Model_Config.h" /** * Configuration.h * 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_IDLE 0 // 0: Disable 1: Enable - Default 0 - #define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80) #define TEMPERATURE_INF 0 // default to 0 #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)) +//Deriving the Voltage div: +// Vin_max = (3.3*(r1+r2))/(r2) +//vdiv = (32768*4)/(vin_max*10) + #ifdef MODEL_TS100 #define VOLTAGE_DIV 467 // 467 - Default divider from schematic #define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV @@ -105,11 +109,38 @@ #endif #ifdef MODEL_TS80 - #define VOLTAGE_DIV 780 // Default divider from schematic - #define PID_POWER_LIMIT 24 // Sets the max pwm power limit - #define CALIBRATION_OFFSET 900 // the adc offset in uV - #define POWER_LIMIT 24 // 24 watts default power limit - #define MAX_POWER_LIMIT 30 // - #define POWER_LIMIT_STEPS 2 - #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 +#define VOLTAGE_DIV 780 // Default divider from schematic +#define PID_POWER_LIMIT 24 // Sets the max pwm power limit +#define CALIBRATION_OFFSET 900 // the adc offset in uV +#define POWER_LIMIT 24 // 24 watts default power limit +#define MAX_POWER_LIMIT 30 // +#define POWER_LIMIT_STEPS 2 +#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