mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
USB-PD Support for Sequre S60P (#1883)
* Basic Init * Rought implementation of fs2711 usb pd interface * Rought implementation of fs2711 usb pd interface * Still needs work overcurrent protection keeps getting tripped * New pdo selection logic * Update push.yml * Update push.yml * Update push.yml * Update Makefile * Adds PPS * Removed unused define * Adds PPS * Apply suggestions from code review Co-authored-by: Ben V. Brown <5425387+Ralim@users.noreply.github.com> * Code review changes * Added osDelay include * New line alignment for S60 softwarei2c * Code review * Fixes code review stuff * code review changes * Change voltage limit to 20 as that's what the device is rated for * Shortened wait time for usb pd * Fixed issues that cuase S60P to restart constantly * fixing minimal OLED brightness With the current settings, the OLED turns off if the first level is selected. * Adds protocol to s60p debug menu * loosened fs2711 protocol selection timing * Adds PDO register reading to negotiation logic * Fixes FS2711 timeout issue and cleans up driver * Adds FS2711 protocol negotiation to power loop * Removed uneeded define * Reverts changes to Font.h and adds clang-format comments --------- Co-authored-by: Ben V. Brown <Ralim@Ralimtek.com> Co-authored-by: discip <53649486+discip@users.noreply.github.com> Co-authored-by: Ben V. Brown <5425387+Ralim@users.noreply.github.com>
This commit is contained in:
239
source/Core/Drivers/FS2711.cpp
Normal file
239
source/Core/Drivers/FS2711.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include "FS2711.hpp"
|
||||
#include "FS2711_defines.h"
|
||||
#include "I2CBB2.hpp"
|
||||
#include "configuration.h"
|
||||
#if POW_PD_EXT == 2
|
||||
#include "BSP.h"
|
||||
#include "cmsis_os.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef USB_PD_VMAX
|
||||
#error Max PD Voltage must be defined
|
||||
#endif
|
||||
|
||||
#define PROTOCOL_TIMEOUT 100 // ms
|
||||
|
||||
extern int32_t powerSupplyWattageLimit;
|
||||
|
||||
fs2711_state_t FS2711::state;
|
||||
|
||||
inline void i2c_write(uint8_t addr, uint8_t data) { I2CBB2::Mem_Write(FS2711_ADDR, addr, &data, 1); }
|
||||
|
||||
inline uint8_t i2c_read(uint8_t addr) {
|
||||
uint8_t data = 0;
|
||||
I2CBB2::Mem_Read(FS2711_ADDR, addr, &data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
inline bool i2c_probe(uint8_t addr) { return I2CBB2::probe(addr); }
|
||||
|
||||
void FS2711::start() {
|
||||
memset(&state, 0, sizeof(fs2711_state_t));
|
||||
state.req_pdo_num = 0xFF;
|
||||
|
||||
enable_protocol(false);
|
||||
osDelay(PROTOCOL_TIMEOUT);
|
||||
select_protocol(FS2711_PROTOCOL_PD);
|
||||
enable_protocol(true);
|
||||
osDelay(PROTOCOL_TIMEOUT);
|
||||
}
|
||||
|
||||
uint8_t FS2711::selected_protocol() { return i2c_read(FS2711_REG_SELECT_PROTOCOL); }
|
||||
|
||||
void FS2711::enable_protocol(bool enable) { i2c_write(FS2711_REG_ENABLE_PROTOCOL, enable ? FS2711_ENABLE : FS2711_DISABLE); }
|
||||
|
||||
void FS2711::select_protocol(uint8_t protocol) { i2c_write(FS2711_REG_SELECT_PROTOCOL, protocol); }
|
||||
|
||||
void FS2711::enable_voltage() { i2c_write(FS2711_REG_ENABLE_VOLTAGE, FS2711_ENABLE); }
|
||||
|
||||
bool FS2711::probe() { return i2c_probe(FS2711_ADDR); }
|
||||
|
||||
void FS2711::pdo_update() {
|
||||
uint8_t pdo_b0 = 0, pdo_b1 = 0, pdo_b2 = 0, pdo_b3 = 0;
|
||||
|
||||
state.pdo_num = 0;
|
||||
memset(state.pdo_type, 0, 7);
|
||||
memset(state.pdo_min_volt, 0, 7);
|
||||
memset(state.pdo_max_volt, 0, 7);
|
||||
memset(state.pdo_max_curr, 0, 7);
|
||||
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
pdo_b0 = i2c_read(FS2711_REG_PDO_B0 + i * 4);
|
||||
pdo_b1 = i2c_read(FS2711_REG_PDO_B1 + i * 4);
|
||||
pdo_b2 = i2c_read(FS2711_REG_PDO_B2 + i * 4);
|
||||
pdo_b3 = i2c_read(FS2711_REG_PDO_B3 + i * 4);
|
||||
|
||||
if (pdo_b0) {
|
||||
if ((pdo_b3 & FS2711_REG_PDO_B0) == FS2711_REG_PDO_B0) {
|
||||
state.pdo_type[i] = FS2711_PDO_PPS;
|
||||
state.pdo_min_volt[i] = pdo_b1 * 100;
|
||||
state.pdo_max_volt[i] = ((pdo_b2 >> 1) + ((pdo_b3 & 0x1) << 7)) * 100;
|
||||
state.pdo_max_curr[i] = (pdo_b0 & 0x7F) * 50;
|
||||
} else {
|
||||
state.pdo_type[i] = FS2711_PDO_FIX;
|
||||
state.pdo_min_volt[i] = ((pdo_b1 >> 2) + ((pdo_b2 & 0xF) << 6)) * 50;
|
||||
state.pdo_max_volt[i] = state.pdo_min_volt[i];
|
||||
state.pdo_max_curr[i] = (pdo_b0 + ((pdo_b1 & 0x3) << 8)) * 10;
|
||||
}
|
||||
state.pdo_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FS2711::open_pps(uint8_t pdoid, uint16_t volt, uint16_t max_curr) {
|
||||
uint16_t wr;
|
||||
|
||||
if (pdoid > state.pdo_num)
|
||||
return false;
|
||||
if ((volt > state.pdo_max_volt[pdoid]) || (volt < state.pdo_min_volt[pdoid]))
|
||||
return false;
|
||||
if ((volt > state.pdo_max_volt[pdoid]) || (volt < state.pdo_min_volt[pdoid]))
|
||||
return false;
|
||||
if (max_curr > state.pdo_max_curr[pdoid])
|
||||
return false;
|
||||
if (state.pdo_type[pdoid] != FS2711_PDO_PPS)
|
||||
return false;
|
||||
|
||||
if (FS2711::selected_protocol() == FS2711_PROTOCOL_PD) {
|
||||
select_protocol(FS2711_PROTOCOL_PPS);
|
||||
enable_protocol(true);
|
||||
}
|
||||
|
||||
if (FS2711::selected_protocol() != FS2711_PROTOCOL_PPS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i2c_write(FS2711_REG_PDO_IDX, pdoid + (pdoid << 4));
|
||||
wr = (volt - state.pdo_min_volt[pdoid]) / 20;
|
||||
i2c_write(FS2711_PROTOCOL_PPS_CURRENT, max_curr / 50);
|
||||
|
||||
i2c_write(FS2711_REG_VOLT_CFG_B0, wr & 0xFF);
|
||||
i2c_write(FS2711_REG_VOLT_CFG_B1, (wr >> 8) & 0xFF);
|
||||
i2c_write(FS2711_REG_VOLT_CFG_B2, wr & 0xFF);
|
||||
i2c_write(FS2711_REG_VOLT_CFG_B3, (wr >> 8) & 0xFF);
|
||||
|
||||
enable_voltage();
|
||||
|
||||
state.source_voltage = volt;
|
||||
state.source_current = max_curr;
|
||||
state.req_pdo_num = pdoid;
|
||||
powerSupplyWattageLimit = ((volt * max_curr) / 1000000) - 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FS2711::open_pd(uint8_t pdoid) {
|
||||
if (pdoid >= state.pdo_num) {
|
||||
return false;
|
||||
}
|
||||
if (state.pdo_type[pdoid] != FS2711_PDO_FIX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FS2711::selected_protocol() != FS2711_PROTOCOL_PD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i2c_write(FS2711_REG_PDO_IDX, pdoid + (pdoid << 4));
|
||||
|
||||
enable_voltage();
|
||||
|
||||
state.source_voltage = state.pdo_max_volt[pdoid];
|
||||
state.source_current = state.pdo_max_curr[pdoid];
|
||||
state.req_pdo_num = pdoid;
|
||||
|
||||
powerSupplyWattageLimit = ((state.source_voltage * state.source_current) / 1000000) - 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FS2711::negotiate() {
|
||||
uint16_t best_voltage = 0;
|
||||
uint16_t best_current = 0;
|
||||
uint8_t best_pdoid = 0xFF;
|
||||
bool pps = false;
|
||||
|
||||
int min_resistance_omhsx10 = 0;
|
||||
|
||||
// FS2711 uses mV instead of V
|
||||
const uint16_t vmax = USB_PD_VMAX * 1000;
|
||||
const uint8_t tip_resistance = getTipResistanceX10() + 5;
|
||||
|
||||
uint16_t pdo_min_mv = 0, pdo_max_mv = 0, pdo_max_curr = 0, pdo_type = 0;
|
||||
|
||||
FS2711::pdo_update();
|
||||
|
||||
for (int i = 0; state.pdo_num > i; i++) {
|
||||
pdo_min_mv = state.pdo_min_volt[i];
|
||||
pdo_max_mv = state.pdo_max_volt[i];
|
||||
pdo_max_curr = state.pdo_max_curr[i];
|
||||
pdo_type = state.pdo_type[i];
|
||||
|
||||
min_resistance_omhsx10 = (pdo_max_mv / pdo_max_curr) * 10;
|
||||
|
||||
switch (pdo_type) {
|
||||
case FS2711_PDO_FIX:
|
||||
if (pdo_max_mv > 0 && vmax >= pdo_max_mv) {
|
||||
if (min_resistance_omhsx10 <= tip_resistance) {
|
||||
if (pdo_max_mv > best_voltage) {
|
||||
pps = false;
|
||||
best_pdoid = i;
|
||||
best_voltage = pdo_max_mv;
|
||||
best_current = pdo_max_curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FS2711_PDO_PPS: {
|
||||
int ideal_mv = tip_resistance * (pdo_max_curr / 10);
|
||||
if (ideal_mv > pdo_max_mv) {
|
||||
ideal_mv = pdo_max_mv;
|
||||
}
|
||||
|
||||
if (ideal_mv > vmax) {
|
||||
ideal_mv = vmax;
|
||||
}
|
||||
|
||||
if (ideal_mv > best_voltage) {
|
||||
best_pdoid = i;
|
||||
best_voltage = ideal_mv;
|
||||
best_current = pdo_max_curr;
|
||||
pps = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_pdoid != 0xFF && best_pdoid != state.req_pdo_num) {
|
||||
if (pps) {
|
||||
FS2711::open_pps(best_pdoid, best_voltage, best_current);
|
||||
} else {
|
||||
FS2711::open_pd(best_pdoid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FS2711::has_run_selection() { return state.req_pdo_num != 0xFF; }
|
||||
|
||||
uint16_t FS2711::source_voltage() { return state.source_voltage / 1000; }
|
||||
|
||||
// FS2711 does current in mV so it needs to be converted to x100 intead of x1000
|
||||
uint16_t FS2711::source_currentx100() { return state.source_current / 10; }
|
||||
|
||||
uint16_t FS2711::debug_pdo_max_voltage(uint8_t pdoid) { return state.pdo_max_volt[pdoid]; }
|
||||
|
||||
uint16_t FS2711::debug_pdo_min_voltage(uint8_t pdoid) { return state.pdo_min_volt[pdoid]; }
|
||||
|
||||
uint16_t FS2711::debug_pdo_source_current(uint8_t pdoid) { return state.pdo_max_curr[pdoid]; }
|
||||
|
||||
uint16_t FS2711::debug_pdo_type(uint8_t pdoid) { return state.pdo_type[pdoid]; }
|
||||
|
||||
fs2711_state_t FS2711::debug_get_state() { return state; }
|
||||
|
||||
#endif
|
||||
61
source/Core/Drivers/FS2711.hpp
Normal file
61
source/Core/Drivers/FS2711.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "configuration.h"
|
||||
#ifndef _DRIVERS_FS2711_HPP_
|
||||
#define _DRIVERS_FS2711_HPP_
|
||||
// #define POW_PD_EXT 2
|
||||
#if POW_PD_EXT == 2
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t pdo_num; // Nums of USB-PD Objects max of 7
|
||||
uint16_t source_current;
|
||||
uint16_t source_voltage;
|
||||
uint16_t req_pdo_num;
|
||||
uint16_t pdo_type[7];
|
||||
uint16_t pdo_min_volt[7];
|
||||
uint16_t pdo_max_volt[7];
|
||||
uint16_t pdo_max_curr[7];
|
||||
} fs2711_state_t;
|
||||
|
||||
class FS2711 {
|
||||
public:
|
||||
static bool probe();
|
||||
|
||||
static void start();
|
||||
|
||||
static bool open_pps(uint8_t PDOID, uint16_t volt, uint16_t max_curr);
|
||||
|
||||
static bool open_pd(uint8_t PDOID);
|
||||
|
||||
static void negotiate();
|
||||
|
||||
static bool has_run_selection();
|
||||
|
||||
static uint16_t source_voltage();
|
||||
|
||||
static uint16_t source_currentx100();
|
||||
|
||||
static uint8_t selected_protocol();
|
||||
|
||||
static void pdo_update();
|
||||
|
||||
static uint8_t debug_protocol();
|
||||
static uint16_t debug_pdo_max_voltage(uint8_t pdoid);
|
||||
static uint16_t debug_pdo_min_voltage(uint8_t pdoid);
|
||||
static uint16_t debug_pdo_source_current(uint8_t pdoid);
|
||||
static uint16_t debug_pdo_type(uint8_t pdoid);
|
||||
static fs2711_state_t debug_get_state();
|
||||
|
||||
private:
|
||||
// Internal state of IC
|
||||
static fs2711_state_t state;
|
||||
|
||||
static void enable_protocol(bool enable);
|
||||
|
||||
static void select_protocol(uint8_t protocol);
|
||||
|
||||
static void enable_voltage();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
73
source/Core/Drivers/FS2711_defines.h
Normal file
73
source/Core/Drivers/FS2711_defines.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef _FS2711_DEFINE_HPP_
|
||||
#define _FS2711_DEFINE_HPP_
|
||||
|
||||
#define FS2711_WRITE_ADDR 0x5A
|
||||
#define FS2711_READ_ADDR 0x5B
|
||||
|
||||
#define FS2711_ADDR 0x5A
|
||||
|
||||
#define FS2711_PDO_FIX 0
|
||||
#define FS2711_PDO_PPS 1
|
||||
|
||||
#define FS2711_MAX_5V 1
|
||||
#define FS2711_MAX_9V 3
|
||||
#define FS2711_MAX_12V 7
|
||||
#define FS2711_MAX_20V 15
|
||||
|
||||
#define FS2711_ENABLE 0x1
|
||||
#define FS2711_DISABLE 0x2
|
||||
|
||||
// Protocol Selection
|
||||
#define FS2711_PROTOCOL_QC2A 4
|
||||
#define FS2711_PROTOCOL_QC2B 5
|
||||
#define FS2711_PROTOCOL_QC3A 6
|
||||
#define FS2711_PROTOCOL_QC3B 7
|
||||
#define FS2711_PROTOCOL_PPS 20
|
||||
#define FS2711_PROTOCOL_PD 21
|
||||
|
||||
#define FS2711_PROTOCOL_PPS_CURRENT 0xDE
|
||||
|
||||
#define FS2711_PROTOCOL_QC_MAX_VOLT 0xC0
|
||||
|
||||
#define FS2711_REG_SCAN_START 0x40 // Protocol Scan
|
||||
#define FS2711_REG_ENABLE_PROTOCOL 0x41 // Enable Protocol
|
||||
#define FS2711_REG_SELECT_PROTOCOL 0x42 // Select Protocol
|
||||
#define FS2711_REG_ENABLE_VOLTAGE 0x43 // Enable Voltage
|
||||
#define FS2711_REG_PDO_IDX 0x46 // Requests Protocol Index
|
||||
#define FS2711_REG_SWEEP 0x47 // Requests a voltage sweep?
|
||||
#define FS2711_REG_PORT_RESET 0x49 // Port Reset
|
||||
#define FS2711_REG_SYSTEM_RESET 0x4A // System Reset
|
||||
#define FS2711_REG_DPDM 0x51 // DPDM
|
||||
#define FS2711_REG_MODE_SET 0xA0 // Mode set
|
||||
#define FS2711_REG_STATE0 0xB1 // PD:A_SNK PD:A_SRC (PD:pe_ready POM:crc_success) (PD:soft_reset POM:crc_fail) (PD:hard_rest POM:resp_fail) PD:hardreset_found VIVO
|
||||
#define FS2711_REG_STATE1 0xB2 // scan_done pdo_updated vooc_recv_cmd vivo_pom_tx_finish vivo_pom_rx_finish huawei_comm_fail huawei_op_finish
|
||||
|
||||
// Used to calculate PDO Objects
|
||||
#define FS2711_REG_PDO_B0 0xC0
|
||||
#define FS2711_REG_PDO_B1 0xC1
|
||||
#define FS2711_REG_PDO_B2 0xC2
|
||||
#define FS2711_REG_PDO_B3 0xC3
|
||||
|
||||
#define FS2711_REG_VOLT_CFG_B0 0xF4
|
||||
#define FS2711_REG_VOLT_CFG_B1 0xF5
|
||||
#define FS2711_REG_VOLT_CFG_B2 0xF6
|
||||
#define FS2711_REG_VOLT_CFG_B3 0xF7
|
||||
|
||||
// 0xF0 ~ 0xF1 16 bits
|
||||
#define FS2711_REG_MASK 0xF0
|
||||
// 0xF4 ~ 0xF7 32 bits
|
||||
#define FS2711_REG_PROTOCOL_VOLT 0xF4
|
||||
// 0xF8 ~ 0xFB 24 bits
|
||||
#define FS2711_REG_PROTOCOL_EXISTS 0xF8
|
||||
|
||||
#define FS2711_SWEEP_SAW 0
|
||||
#define FS2711_SWEEP_TRI 1
|
||||
#define FS2711_SWEEP_STEP 2
|
||||
|
||||
#define FS2711_STATE_SCAN_DONE 0x01
|
||||
#define FS2711_STATE_PDO_UPDATE 0x02
|
||||
#define FS2711_STATE_PD_SNK 0x40
|
||||
#define FS2711_STATE_PD_SRC 0x80
|
||||
#define FS2711_STATE_PD_PE_READY 0x100
|
||||
#define FS2711_STATE_DISABLE 0x800
|
||||
#endif
|
||||
@@ -14,7 +14,7 @@
|
||||
#define FONT_12_WIDTH 12
|
||||
// THE MAIN FONTS ARE NO LONGER HERE, MOVED TO PYTHON AUTO GEN
|
||||
// THESE ARE ONLY THE SYMBOL FONTS
|
||||
|
||||
// clang-format off
|
||||
const uint8_t ExtraFontChars[] = {
|
||||
// width = 12
|
||||
// height = 16
|
||||
@@ -872,5 +872,6 @@ const uint8_t SettingsMenuIcons[][32 * 3] = {
|
||||
}
|
||||
#endif
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#endif /* FONT_H_ */
|
||||
|
||||
Reference in New Issue
Block a user