diff --git a/workspace/TS100/Core/BSP/BSP_Common.c b/workspace/TS100/Core/BSP/BSP_Common.c new file mode 100644 index 00000000..67a76d18 --- /dev/null +++ b/workspace/TS100/Core/BSP/BSP_Common.c @@ -0,0 +1 @@ +#include "BSP.h" diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index a2afb4f3..1b5ed75f 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -13,87 +13,92 @@ volatile uint16_t PWMSafetyTimer = 0; volatile uint8_t pendingPWM = 0; //2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = { { 0 }, 0, 0 }; -void resetWatchdog() { +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, // - }; + //ADC Reading , Temp in C + 29189, 0, // + 29014, 1, // + 28832, 2, // + 28644, 3, // + 28450, 4, // + 28249, 5, // + 28042, 6, // + 27828, 7, // + 27607, 8, // + 27380, 9, // + 27146, 10, // + 26906, 11, // + 26660, 12, // + 26407, 13, // + 26147, 14, // + 25882, 15, // + 25610, 16, // + 25332, 17, // + 25049, 18, // + 24759, 19, // + 24465, 20, // + 24164, 21, // + 23859, 22, // + 23549, 23, // + 23234, 24, // + 22915, 25, // + 22591, 26, // + 22264, 27, // + 21933, 28, // + 21599, 29, // + // 21261, 30, // + // 20921, 31, // + // 20579, 32, // + // 20234, 33, // + // 19888, 34, // + // 19541, 35, // + // 19192, 36, // + // 18843, 37, // + // 18493, 38, // + // 18143, 39, // + // 17793, 40, // + // 17444, 41, // + // 17096, 42, // + // 16750, 43, // + // 16404, 44, // + // 16061, 45, // + // 15719, 46, // + // 15380, 47, // + // 15044, 48, // + // 14710, 49, // + // 14380, 50, // + // 14053, 51, // + // 13729, 52, // + // 13410, 53, // + // 13094, 54, // + // 12782, 55, // + // 12475, 56, // + // 12172, 57, // + // 11874, 58, // + // 11580, 59, // + // 11292, 60, // +}; #endif -uint16_t getHandleTemperature() { + +uint16_t getHandleTemperature() +{ #ifdef TEMP_NTC //TS80P uses 100k NTC resistors instead //NTCG104EF104FT1X from TDK //For now not doing interpolation int32_t result = getADC(0); for (uint32_t i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); - i++) { - if (result > NTCHandleLookup[(i * 2) + 0]) { + i++) + { + if (result > NTCHandleLookup[(i * 2) + 0]) + { return NTCHandleLookup[(i * 2) + 1] * 10; } } @@ -108,7 +113,7 @@ uint16_t getHandleTemperature() { // (4964.8 counts) // int32_t result = getADC(0); - result -= 4965; // remove 0.5V offset + result -= 4965; // remove 0.5V offset // 10mV per C // 99.29 counts per Deg C above 0C result *= 100; @@ -117,12 +122,13 @@ uint16_t getHandleTemperature() { #endif } -uint16_t getTipInstantTemperature() { - uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits +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; @@ -132,23 +138,29 @@ uint16_t getTipInstantTemperature() { readings[6] = hadc2.Instance->JDR3; readings[7] = hadc2.Instance->JDR4; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) + { sum += readings[i]; } - return sum; // 8x over sample + return sum; // 8x over sample } -uint16_t getTipRawTemp(uint8_t refresh) { - if (refresh) { +uint16_t getTipRawTemp(uint8_t refresh) +{ + if (refresh) + { uint16_t lastSample = getTipInstantTemperature(); rawTempFilter.update(lastSample); return lastSample; - } else { + } + else + { return rawTempFilter.average(); } } -uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { +uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) +{ // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN // Therefore we can divide down from there // Multiplying ADC max by 4 for additional calibration options, @@ -162,12 +174,14 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { static uint8_t preFillneeded = 10; static uint32_t samples[BATTFILTERDEPTH]; static uint8_t index = 0; - if (preFillneeded) { + if (preFillneeded) + { for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) samples[i] = getADC(1); preFillneeded--; } - if (sample) { + if (sample) + { samples[index] = getADC(1); index = (index + 1) % BATTFILTERDEPTH; } @@ -177,13 +191,15 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { sum += samples[i]; sum /= BATTFILTERDEPTH; - if (divisor == 0) { + if (divisor == 0) + { divisor = 1; } return sum * 4 / divisor; } -void setTipPWM(uint8_t pulse) { +void setTipPWM(uint8_t pulse) +{ PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is // disabled if the PID task is not scheduled often enough. @@ -193,9 +209,11 @@ void setTipPWM(uint8_t pulse) { // These are called by the HAL after the corresponding events from the system // timers. -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { -// Period has elapsed - if (htim->Instance == TIM2) { +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + // Period has elapsed + if (htim->Instance == TIM2) + { // we want to turn on the output again PWMSafetyTimer--; // We decrement this safety value so that lockups in the @@ -204,35 +222,43 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { // While we could assume this could never happen, its a small price for // increased safety htim2.Instance->CCR4 = pendingPWM; - if (htim2.Instance->CCR4 && PWMSafetyTimer) { + if (htim2.Instance->CCR4 && PWMSafetyTimer) + { HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); - } else { + } + else + { HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1); } - } else if (htim->Instance == TIM1) { + } + else if (htim->Instance == TIM1) + { // STM uses this for internal functions as a counter for timeouts HAL_IncTick(); } } -void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { -// This was a when the PWM for the output has timed out - if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) { +void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) +{ + // This was a when the PWM for the output has timed out + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) + { HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1); } } -void unstick_I2C() { +void unstick_I2C() +{ GPIO_InitTypeDef GPIO_InitStruct; 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; @@ -245,7 +271,8 @@ void unstick_I2C() { HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); - while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) { + while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) + { //Move clock to release I2C HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET); asm("nop"); @@ -259,7 +286,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; @@ -273,37 +300,39 @@ 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); } -uint8_t getButtonA() { - return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? - 1 : 0; +uint8_t getButtonA() +{ + return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? 1 : 0; } -uint8_t getButtonB() { - return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? - 1 : 0; +uint8_t getButtonB() +{ + return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? 1 : 0; } -void reboot() { +void reboot() +{ NVIC_SystemReset(); } -void delay_ms(uint16_t count) { +void delay_ms(uint16_t count) +{ HAL_Delay(count); } diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 0a31b154..9517a596 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -10,14 +10,20 @@ #include "systick.h" #include -void resetWatchdog() { +//2 second filter (ADC is PID_TIM_HZ Hz) +history rawTempFilter = {{0}, 0, 0}; + +void resetWatchdog() +{ //TODO } -uint16_t getTipInstantTemperature() { +uint16_t getTipInstantTemperature() +{ uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { sum += adc_inserted_data_read(ADC0, i); sum += adc_inserted_data_read(ADC1, i); } @@ -28,23 +34,113 @@ uint16_t getTipInstantTemperature() { // TODO // Handle callback of the PWM modulator to enable / disable the output PWM -void unstick_I2C() { +uint16_t getTipRawTemp(uint8_t refresh) +{ + if (refresh) + { + uint16_t lastSample = getTipInstantTemperature(); + rawTempFilter.update(lastSample); + return lastSample; + } + else + { + return rawTempFilter.average(); + } +} +void unstick_I2C() +{ // TODO } -uint8_t getButtonA() { - // TODO +uint8_t getButtonA() +{ return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == RESET) ? 1 : 0; } -uint8_t getButtonB() { - // TODO +uint8_t getButtonB() +{ return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == RESET) ? 1 : 0; } -void reboot() { +void reboot() +{ // TODO - for (;;) { + for (;;) + { } } void delay_ms(uint16_t count) { delay_1ms(count); } + +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) = + // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 + // mV per count So we need to subtract an offset of 0.5V to center on 0C + // (4964.8 counts) + // + int32_t result = getADC(0); + result -= 4965; // remove 0.5V offset + // 10mV per C + // 99.29 counts per Deg C above 0C + result *= 100; + result /= 993; + return result; +#endif +} + +uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) +{ +// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN +// Therefore we can divide down from there +// Multiplying ADC max by 4 for additional calibration options, +// ideal term is 467 +#ifdef MODEL_TS100 +#define BATTFILTERDEPTH 32 +#else +#define BATTFILTERDEPTH 8 + +#endif + static uint8_t preFillneeded = 10; + static uint32_t samples[BATTFILTERDEPTH]; + static uint8_t index = 0; + if (preFillneeded) + { + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + samples[i] = getADC(1); + preFillneeded--; + } + if (sample) + { + samples[index] = getADC(1); + index = (index + 1) % BATTFILTERDEPTH; + } + uint32_t sum = 0; + + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + sum += samples[i]; + + sum /= BATTFILTERDEPTH; + if (divisor == 0) + { + divisor = 1; + } + return sum * 4 / divisor; +} \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 6d274997..3424b60f 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -21,7 +21,7 @@ #define ACCEL_LIS #define TEMP_TMP36 #define POW_QC -#define POW_PD +// #define POW_PD #endif #endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/Power.cpp b/workspace/TS100/Core/BSP/Pine64/Power.cpp index 522802a3..ae6d8520 100644 --- a/workspace/TS100/Core/BSP/Pine64/Power.cpp +++ b/workspace/TS100/Core/BSP/Pine64/Power.cpp @@ -2,10 +2,39 @@ #include "BSP_Power.h" #include "QC3.h" #include "Settings.h" -void power_probe() { - //TODO -- Check for PD -} +#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() { - //TODO -- Checks for PD? -} \ No newline at end of file +void power_check() +{ +#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 +#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/Pine64/fusb302b.cpp b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp new file mode 100644 index 00000000..2304ecf2 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp @@ -0,0 +1,303 @@ +/* + * 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 "I2C_Wrapper.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 (!FRToSI2C::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 FRToSI2C::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 FRToSI2C::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 FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, buf, size); +} + +void fusb_send_message(const union pd_msg *msg) +{ + if (!FRToSI2C::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); + + FRToSI2C::unlock2(); +} + +uint8_t fusb_read_message(union pd_msg *msg) +{ + if (!FRToSI2C::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); + + FRToSI2C::unlock2(); + return 0; +} + +void fusb_send_hardrst() +{ + + if (!FRToSI2C::lock2()) + { + return; + } + /* Send a hard reset */ + fusb_write_byte(FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); + + FRToSI2C::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 (!FRToSI2C::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) + { + FRToSI2C::unlock2(); + } + fusb_reset(); +} + +void fusb_get_status(union fusb_status *status) +{ + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + if (!FRToSI2C::lock2()) + { + return; + } + } + + /* Read the interrupt and status flags into status */ + fusb_read_buf(FUSB_STATUS0A, 7, status->bytes); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + FRToSI2C::unlock2(); + } +} + +enum fusb_typec_current fusb_get_typec_current() +{ + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + if (!FRToSI2C::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) + { + FRToSI2C::unlock2(); + } + return bc_lvl; +} + +void fusb_reset() +{ + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + if (!FRToSI2C::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) + { + FRToSI2C::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 FRToSI2C::probe(FUSB302B_ADDR); +} + +#endif diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index 224b7d41..caf51e19 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -48,6 +48,10 @@ public: static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); + //These are public locks that let code lock the bus for back-to-back operations + static bool lock2(); + static void unlock2(); + private: static bool lock(); static void unlock(); diff --git a/workspace/TS100/build.sh b/workspace/TS100/build.sh index 068d7f20..29260de8 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" "TS80P") +AVAILABLE_MODELS=("TS100" "TS80" "TS80P" "Pinecil") BUILD_MODELS=() usage() {