Power: bq25896 and bq27220 drivers, portable power api. (#224)
* Power: add portability layer, port to F3. * F3: bq25896 driver stab * GUI: new primary and secondary fonts * F3: bq25896 register map, basic functions * F3: move bq27220 command descritpion to separate file. Code format. * Power: OTG enable/disable * Power: choose more correct profile * F3: pet bq25896 watchdog sometimes
This commit is contained in:
parent
49fdb28871
commit
f05ffddbde
@ -120,9 +120,9 @@ void canvas_font_set(CanvasApi* api, Font font) {
|
|||||||
Canvas* canvas = (Canvas*)api;
|
Canvas* canvas = (Canvas*)api;
|
||||||
u8g2_SetFontMode(&canvas->fb, 1);
|
u8g2_SetFontMode(&canvas->fb, 1);
|
||||||
if(font == FontPrimary) {
|
if(font == FontPrimary) {
|
||||||
u8g2_SetFont(&canvas->fb, u8g2_font_Born2bSportyV2_tr);
|
u8g2_SetFont(&canvas->fb, u8g2_font_helvB08_tf);
|
||||||
} else if(font == FontSecondary) {
|
} else if(font == FontSecondary) {
|
||||||
u8g2_SetFont(&canvas->fb, u8g2_font_HelvetiPixel_tr);
|
u8g2_SetFont(&canvas->fb, u8g2_font_haxrcorp4089_tr);
|
||||||
} else {
|
} else {
|
||||||
furi_check(0);
|
furi_check(0);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
#include <flipper_v2.h>
|
#include <flipper_v2.h>
|
||||||
|
|
||||||
|
#include <menu/menu.h>
|
||||||
|
#include <menu/menu_item.h>
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <gui/widget.h>
|
#include <gui/widget.h>
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
#include <api-hal-power.h>
|
||||||
#define BATTERY_MIN_VOLTAGE 3.2f
|
|
||||||
#define BATTERY_MAX_VOLTAGE 4.0f
|
|
||||||
#define BATTERY_INIT 0xFFAACCEE
|
|
||||||
|
|
||||||
extern ADC_HandleTypeDef hadc1;
|
|
||||||
|
|
||||||
struct Power {
|
struct Power {
|
||||||
Icon* usb_icon;
|
Icon* usb_icon;
|
||||||
@ -18,7 +16,10 @@ struct Power {
|
|||||||
Icon* battery_icon;
|
Icon* battery_icon;
|
||||||
Widget* battery_widget;
|
Widget* battery_widget;
|
||||||
|
|
||||||
uint32_t charge;
|
ValueMutex* menu_vm;
|
||||||
|
MenuItem* menu;
|
||||||
|
|
||||||
|
uint8_t charge;
|
||||||
};
|
};
|
||||||
|
|
||||||
void power_draw_usb_callback(CanvasApi* canvas, void* context) {
|
void power_draw_usb_callback(CanvasApi* canvas, void* context) {
|
||||||
@ -32,40 +33,40 @@ void power_draw_battery_callback(CanvasApi* canvas, void* context) {
|
|||||||
Power* power = context;
|
Power* power = context;
|
||||||
|
|
||||||
canvas->draw_icon(canvas, 0, 0, power->battery_icon);
|
canvas->draw_icon(canvas, 0, 0, power->battery_icon);
|
||||||
|
canvas->draw_box(canvas, 2, 2, (float)power->charge / 100 * 14, 4);
|
||||||
if(power->charge != BATTERY_INIT) {
|
|
||||||
float charge = ((float)power->charge / 1000 * 2 - BATTERY_MIN_VOLTAGE) /
|
|
||||||
(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE);
|
|
||||||
if(charge > 1) {
|
|
||||||
charge = 1;
|
|
||||||
}
|
|
||||||
canvas->draw_box(canvas, 2, 2, charge * 14, 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void power_input_events_callback(const void* value, void* ctx) {
|
void power_off_callback(void* context) {
|
||||||
assert(ctx);
|
api_hal_power_off();
|
||||||
Power* power = ctx;
|
}
|
||||||
const InputEvent* event = value;
|
|
||||||
|
|
||||||
if(event->input != InputCharging) return;
|
void power_enable_otg_callback(void* context) {
|
||||||
|
api_hal_power_enable_otg();
|
||||||
|
}
|
||||||
|
|
||||||
widget_enabled_set(power->usb_widget, event->state);
|
void power_disable_otg_callback(void* context) {
|
||||||
widget_update(power->usb_widget);
|
api_hal_power_disable_otg();
|
||||||
}
|
}
|
||||||
|
|
||||||
Power* power_alloc() {
|
Power* power_alloc() {
|
||||||
Power* power = furi_alloc(sizeof(Power));
|
Power* power = furi_alloc(sizeof(Power));
|
||||||
|
|
||||||
|
power->menu_vm = furi_open("menu");
|
||||||
|
furi_check(power->menu_vm);
|
||||||
|
|
||||||
|
power->menu = menu_item_alloc_menu("Power", NULL);
|
||||||
|
menu_item_subitem_add(
|
||||||
|
power->menu, menu_item_alloc_function("Poweroff", NULL, power_off_callback, power));
|
||||||
|
menu_item_subitem_add(
|
||||||
|
power->menu,
|
||||||
|
menu_item_alloc_function("Enable OTG", NULL, power_enable_otg_callback, power));
|
||||||
|
menu_item_subitem_add(
|
||||||
|
power->menu,
|
||||||
|
menu_item_alloc_function("Disable OTG", NULL, power_disable_otg_callback, power));
|
||||||
|
|
||||||
power->usb_icon = assets_icons_get(I_USBConnected_15x8);
|
power->usb_icon = assets_icons_get(I_USBConnected_15x8);
|
||||||
power->usb_widget = widget_alloc();
|
power->usb_widget = widget_alloc();
|
||||||
widget_set_width(power->usb_widget, icon_get_width(power->usb_icon));
|
widget_set_width(power->usb_widget, icon_get_width(power->usb_icon));
|
||||||
|
|
||||||
ValueManager* input_state_manager = furi_open("input_state");
|
|
||||||
InputState input_state;
|
|
||||||
read_mutex_block(&input_state_manager->value, &input_state, sizeof(input_state));
|
|
||||||
widget_enabled_set(power->usb_widget, input_state.charging);
|
|
||||||
|
|
||||||
widget_draw_callback_set(power->usb_widget, power_draw_usb_callback, power);
|
widget_draw_callback_set(power->usb_widget, power_draw_usb_callback, power);
|
||||||
|
|
||||||
power->battery_icon = assets_icons_get(I_Battery_19x8);
|
power->battery_icon = assets_icons_get(I_Battery_19x8);
|
||||||
@ -73,12 +74,6 @@ Power* power_alloc() {
|
|||||||
widget_set_width(power->battery_widget, icon_get_width(power->battery_icon));
|
widget_set_width(power->battery_widget, icon_get_width(power->battery_icon));
|
||||||
widget_draw_callback_set(power->battery_widget, power_draw_battery_callback, power);
|
widget_draw_callback_set(power->battery_widget, power_draw_battery_callback, power);
|
||||||
|
|
||||||
PubSub* input_event_record = furi_open("input_events");
|
|
||||||
assert(input_event_record);
|
|
||||||
subscribe_pubsub(input_event_record, power_input_events_callback, power);
|
|
||||||
|
|
||||||
power->charge = BATTERY_INIT;
|
|
||||||
|
|
||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,19 +94,21 @@ void power_task(void* p) {
|
|||||||
gui->add_widget(gui, power->battery_widget, GuiLayerStatusBarRight);
|
gui->add_widget(gui, power->battery_widget, GuiLayerStatusBarRight);
|
||||||
furi_commit(gui_record);
|
furi_commit(gui_record);
|
||||||
|
|
||||||
|
with_value_mutex(
|
||||||
|
power->menu_vm, (Menu * menu) { menu_item_add(menu, power->menu); });
|
||||||
|
|
||||||
if(!furi_create("power", power)) {
|
if(!furi_create("power", power)) {
|
||||||
printf("[power_task] unable to create power record\n");
|
printf("[power_task] unable to create power record\n");
|
||||||
furiac_exit(NULL);
|
furiac_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api_hal_power_init();
|
||||||
|
|
||||||
furiac_ready();
|
furiac_ready();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
HAL_ADC_Start(&hadc1);
|
power->charge = api_hal_power_get_pct();
|
||||||
if(HAL_ADC_PollForConversion(&hadc1, 1000) != HAL_TIMEOUT) {
|
widget_enabled_set(power->usb_widget, api_hal_power_is_charging());
|
||||||
power->charge = HAL_ADC_GetValue(&hadc1);
|
|
||||||
widget_update(power->battery_widget);
|
|
||||||
}
|
|
||||||
osDelay(1000);
|
osDelay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ include $(PROJECT_ROOT)/lib/lib.mk
|
|||||||
TARGET ?= f2
|
TARGET ?= f2
|
||||||
TARGET_DIR = targets/$(TARGET)
|
TARGET_DIR = targets/$(TARGET)
|
||||||
include $(TARGET_DIR)/target.mk
|
include $(TARGET_DIR)/target.mk
|
||||||
|
CFLAGS += -Itargets/Inc
|
||||||
|
|
||||||
include $(PROJECT_ROOT)/make/git.mk
|
include $(PROJECT_ROOT)/make/git.mk
|
||||||
include $(PROJECT_ROOT)/make/toolchain.mk
|
include $(PROJECT_ROOT)/make/toolchain.mk
|
||||||
|
22
firmware/targets/Inc/api-hal-power.h
Normal file
22
firmware/targets/Inc/api-hal-power.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/* Initialize drivers */
|
||||||
|
void api_hal_power_init();
|
||||||
|
|
||||||
|
/* Get predicted remaining battery capacity in percents */
|
||||||
|
uint8_t api_hal_power_get_pct();
|
||||||
|
|
||||||
|
/* Get charging status */
|
||||||
|
bool api_hal_power_is_charging();
|
||||||
|
|
||||||
|
/* Poweroff system */
|
||||||
|
void api_hal_power_off();
|
||||||
|
|
||||||
|
/* OTG enable */
|
||||||
|
void api_hal_power_enable_otg();
|
||||||
|
|
||||||
|
/* OTG disable */
|
||||||
|
void api_hal_power_disable_otg();
|
34
firmware/targets/f2/api-hal/api-hal-power.c
Normal file
34
firmware/targets/f2/api-hal/api-hal-power.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <api-hal-power.h>
|
||||||
|
#include <adc.h>
|
||||||
|
|
||||||
|
#define BATTERY_MIN_VOLTAGE 3.2f
|
||||||
|
#define BATTERY_MAX_VOLTAGE 4.0f
|
||||||
|
|
||||||
|
void api_hal_power_init() {}
|
||||||
|
|
||||||
|
uint8_t api_hal_power_get_pct() {
|
||||||
|
float value;
|
||||||
|
HAL_ADC_Start(&hadc1);
|
||||||
|
if(HAL_ADC_PollForConversion(&hadc1, 1000) != HAL_TIMEOUT) {
|
||||||
|
value = HAL_ADC_GetValue(&hadc1);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = ((float)value / 10 * 2 - BATTERY_MIN_VOLTAGE) /
|
||||||
|
(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE);
|
||||||
|
|
||||||
|
if(value > 100) {
|
||||||
|
value = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool api_hal_power_is_charging() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void api_hal_power_off() {}
|
||||||
|
|
||||||
|
void api_hal_power_enable_otg() {}
|
||||||
|
|
||||||
|
void api_hal_power_disable_otg() {}
|
18
firmware/targets/f3/Inc/bq25896.h
Normal file
18
firmware/targets/f3/Inc/bq25896.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/* Initialize Driver */
|
||||||
|
void bq25896_init();
|
||||||
|
|
||||||
|
/* Send device into shipping mode */
|
||||||
|
void bq25896_poweroff();
|
||||||
|
|
||||||
|
/* Is currently charging */
|
||||||
|
bool bq25896_is_charging();
|
||||||
|
|
||||||
|
/* Enable otg */
|
||||||
|
void bq25896_enable_otg();
|
||||||
|
|
||||||
|
/* Disable otg */
|
||||||
|
void bq25896_disable_otg();
|
263
firmware/targets/f3/Inc/bq25896_reg.h
Normal file
263
firmware/targets/f3/Inc/bq25896_reg.h
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if BITS_BIG_ENDIAN == 1
|
||||||
|
#error Bit structures defined in this file is not portable to BE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BQ25896_ADDRESS 0xD6
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t IINLIM:6; // Input Current Limit, mA, offset: +100mA
|
||||||
|
bool EN_ILIM:1; // Enable ILIM Pin
|
||||||
|
bool EN_HIZ:1; // Enable HIZ Mode
|
||||||
|
} REG00;
|
||||||
|
|
||||||
|
#define IILIM_1600 (1<<5)
|
||||||
|
#define IILIM_800 (1<<4)
|
||||||
|
#define IILIM_400 (1<<3)
|
||||||
|
#define IILIM_200 (1<<2)
|
||||||
|
#define IILIM_100 (1<<1)
|
||||||
|
#define IILIM_50 (1<<0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t VINDPM_OS:5; // Input Voltage Limit Offset, mV
|
||||||
|
bool BCOLD:1; // Boost Mode Cold Temperature Monitor Threshold
|
||||||
|
uint8_t BHOT:2; // Boost Mode Hot Temperature Monitor Threshold
|
||||||
|
} REG01;
|
||||||
|
|
||||||
|
#define VINDPM_OS_1600 (1<<4)
|
||||||
|
#define VINDPM_OS_800 (1<<3)
|
||||||
|
#define VINDPM_OS_400 (1<<2)
|
||||||
|
#define VINDPM_OS_200 (1<<1)
|
||||||
|
#define VINDPM_OS_100 (1<<0)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool AUTO_DPDM_EN:1; // Automatic Input Detection Enable
|
||||||
|
bool FORCE_DPDM:1; // Force Input Detection
|
||||||
|
uint8_t RES:2; // Reserved
|
||||||
|
bool ICO_EN:1; // Input Current Optimizer (ICO) Enable
|
||||||
|
bool BOOST_FREQ:1; // Boost Mode Frequency Selection
|
||||||
|
bool CONV_RATE:1; // ADC Conversion Rate Selection
|
||||||
|
bool CONV_START:1; // ADC Conversion Start Control
|
||||||
|
} REG02;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool MIN_VBAT_SEL:1; // Minimum Battery Voltage (falling) to exit boost mode
|
||||||
|
uint8_t SYS_MIN:3; // Minimum System Voltage Limit, mV, offset: +3000mV
|
||||||
|
bool CHG_CONFIG:1; // Charge Enable Configuration
|
||||||
|
bool OTG_CONFIG:1; // Boost (OTG) Mode Configuration
|
||||||
|
bool WD_RST:1; // I2C Watchdog Timer Reset
|
||||||
|
bool BAT_LOADEN:1; // Battery Load (IBATLOAD) Enable
|
||||||
|
} REG03;
|
||||||
|
|
||||||
|
#define SYS_MIN_400 (1<<2)
|
||||||
|
#define SYS_MIN_200 (1<<1)
|
||||||
|
#define SYS_MIN_100 (1<<0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ICHG:7; // Fast Charge Current Limit, mA
|
||||||
|
bool EN_PUMPX:1; // Current pulse control Enable
|
||||||
|
} REG04;
|
||||||
|
|
||||||
|
#define ICHG_4096 (1<<6)
|
||||||
|
#define ICHG_2048 (1<<5)
|
||||||
|
#define ICHG_1024 (1<<4)
|
||||||
|
#define ICHG_512 (1<<3)
|
||||||
|
#define ICHG_256 (1<<2)
|
||||||
|
#define ICHG_128 (1<<1)
|
||||||
|
#define ICHG_64 (1<<0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ITERM:4; // Termination Current Limit, offset: +64mA
|
||||||
|
uint8_t IPRECHG:4; // Precharge Current Limit, offset: +64mA
|
||||||
|
} REG05;
|
||||||
|
|
||||||
|
#define IPRETERM_512 (1<<3)
|
||||||
|
#define IPRETERM_256 (1<<2)
|
||||||
|
#define IPRETERM_128 (1<<1)
|
||||||
|
#define IPRETERM_64 (1<<0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool VRECHG:1; // Battery Recharge Threshold Offset
|
||||||
|
bool BATLOWV:1; // Battery Precharge to Fast Charge Threshold
|
||||||
|
uint8_t VREG:6; // Charge Voltage Limit, offset: +3840mV
|
||||||
|
} REG06;
|
||||||
|
|
||||||
|
#define VREG_512 (1<<5)
|
||||||
|
#define VREG_256 (1<<4)
|
||||||
|
#define VREG_128 (1<<3)
|
||||||
|
#define VREG_64 (1<<2)
|
||||||
|
#define VREG_32 (1<<1)
|
||||||
|
#define VREG_16 (1<<0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool JEITA_ISET:1; // JEITA Low Temperature Current Setting
|
||||||
|
uint8_t CHG_TIMER:2; // Fast Charge Timer Setting
|
||||||
|
bool EN_TIMER:1; // Charging Safety Timer Enable
|
||||||
|
uint8_t WATCHDOG:2; // I2C Watchdog Timer Setting
|
||||||
|
bool STAT_DIS:1; // STAT Pin Disable
|
||||||
|
bool EN_TERM:1; // Charging Termination Enable
|
||||||
|
} REG07;
|
||||||
|
|
||||||
|
#define WATCHDOG_DIS (0b00)
|
||||||
|
#define WATCHDOG_40 (0b01)
|
||||||
|
#define WATCHDOG_80 (0b10)
|
||||||
|
#define WATCHDOG_160 (0b11)
|
||||||
|
|
||||||
|
#define CHG_TIMER_5 (0b00)
|
||||||
|
#define CHG_TIMER_8 (0b01)
|
||||||
|
#define CHG_TIMER_12 (0b10)
|
||||||
|
#define CHG_TIMER_20 (0b11)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t TREG:2; // Thermal Regulation Threshold
|
||||||
|
uint8_t VCLAMP:3; // IR Compensation Voltage Clamp
|
||||||
|
uint8_t BAT_COMP:3; // IR Compensation Resistor Setting
|
||||||
|
} REG08;
|
||||||
|
|
||||||
|
#define BAT_COMP_80 (1<<2)
|
||||||
|
#define BAT_COMP_40 (1<<1)
|
||||||
|
#define BAT_COMP_20 (1<<0)
|
||||||
|
|
||||||
|
#define VCLAMP_128 (1<<2)
|
||||||
|
#define VCLAMP_64 (1<<1)
|
||||||
|
#define VCLAMP_32 (1<<0)
|
||||||
|
|
||||||
|
#define TREG_60 (0b00)
|
||||||
|
#define TREG_80 (0b01)
|
||||||
|
#define TREG_100 (0b10)
|
||||||
|
#define TREG_120 (0b11)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool PUMPX_DN:1; // Current pulse control voltage down enable
|
||||||
|
bool PUMPX_UP:1; // Current pulse control voltage up enable
|
||||||
|
bool BATFET_RST_EN:1; // BATFET full system reset enable
|
||||||
|
bool BATFET_DLY:1; // BATFET turn off delay control
|
||||||
|
bool JEITA_VSET:1; // JEITA High Temperature Voltage Setting
|
||||||
|
bool BATFET_DIS:1; // Force BATFET off to enable ship mode
|
||||||
|
bool TMR2X_EN:1; // Safety Timer Setting during DPM or Thermal Regulation
|
||||||
|
bool FORCE_ICO:1; // Force Start Input Current Optimizer
|
||||||
|
} REG09;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t BOOST_LIM:3; // Boost Mode Current Limit
|
||||||
|
bool PFM_OTG_DIS:1; // PFM mode allowed in boost mode
|
||||||
|
uint8_t BOOSTV:4; // Boost Mode Voltage Regulation, offset: +4550mV
|
||||||
|
} REG0A;
|
||||||
|
|
||||||
|
#define BOOSTV_512 (1<<3)
|
||||||
|
#define BOOSTV_256 (1<<2)
|
||||||
|
#define BOOSTV_128 (1<<1)
|
||||||
|
#define BOOSTV_64 (1<<0)
|
||||||
|
|
||||||
|
#define BOOST_LIM_500 (0b000)
|
||||||
|
#define BOOST_LIM_750 (0b001)
|
||||||
|
#define BOOST_LIM_1200 (0b010)
|
||||||
|
#define BOOST_LIM_1400 (0b011)
|
||||||
|
#define BOOST_LIM_1650 (0b100)
|
||||||
|
#define BOOST_LIM_1875 (0b101)
|
||||||
|
#define BOOST_LIM_2150 (0b110)
|
||||||
|
#define BOOST_LIM_RSVD (0b111)
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VBusStatNo = 0b000,
|
||||||
|
VBusStatUSB = 0b001,
|
||||||
|
VBusStatExternal = 0b010,
|
||||||
|
VBusStatOTG = 0b111,
|
||||||
|
} VBusStat;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ChrgStatNo = 0b00,
|
||||||
|
ChrgStatPre = 0b01,
|
||||||
|
ChrgStatFast = 0b10,
|
||||||
|
ChrgStatDone = 0b11,
|
||||||
|
} ChrgStat;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool VSYS_STAT:1; // VSYS Regulation Status
|
||||||
|
bool RES:1; // Reserved: Always reads 1
|
||||||
|
bool PG_STAT:1; // Power Good Status
|
||||||
|
ChrgStat CHRG_STAT:2; // Charging Status
|
||||||
|
VBusStat VBUS_STAT:3; // VBUS Status register
|
||||||
|
} REG0B;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ChrgFaultNO = 0b00,
|
||||||
|
ChrgFaultIN = 0b01,
|
||||||
|
ChrgFaultTH = 0b10,
|
||||||
|
ChrgFaultTIM = 0b11,
|
||||||
|
} ChrgFault;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NtcFaultNo = 0b000,
|
||||||
|
NtcFaultWarm = 0b010,
|
||||||
|
NtcFaultCool = 0b011,
|
||||||
|
NtcFaultCold = 0b101,
|
||||||
|
NtcFaultHot = 0b110,
|
||||||
|
} NtcFault;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NtcFault NTC_FAULT:3; // NTC Fault Status
|
||||||
|
bool BAT_FAULT:1; // Battery Fault Status
|
||||||
|
ChrgFault CHRG_FAULT:2; // Charge Fault Status
|
||||||
|
bool BOOST_FAULT:1; // Boost Mode Fault Status
|
||||||
|
bool WATCHDOG_FAULT:1; // Watchdog Fault Status
|
||||||
|
} REG0C;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t VINDPM:7; // Absolute VINDPM Threshold, offset: +2600mV
|
||||||
|
bool FORCE_VINDPM:1; // VINDPM Threshold Setting Method
|
||||||
|
} REG0D;
|
||||||
|
|
||||||
|
#define VINDPM_6400 (1<<6)
|
||||||
|
#define VINDPM_3200 (1<<5)
|
||||||
|
#define VINDPM_1600 (1<<4)
|
||||||
|
#define VINDPM_800 (1<<3)
|
||||||
|
#define VINDPM_400 (1<<2)
|
||||||
|
#define VINDPM_200 (1<<1)
|
||||||
|
#define VINDPM_100 (1<<0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t BATV:7; // ADC conversion of Battery Voltage (VBAT), offset: +2304mV
|
||||||
|
bool THERM_STAT:1; // Thermal Regulation Status
|
||||||
|
} REG0E;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t SYSV:7; // ADDC conversion of System Voltage (VSYS), offset: +2304mV
|
||||||
|
uint8_t RES:1; // Reserved: Always reads 0
|
||||||
|
} REG0F;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t TSPCT:7; // ADC conversion of TS Voltage (TS) as percentage of REGN, offset: +21%
|
||||||
|
uint8_t RES:1; // Reserved: Always reads 0
|
||||||
|
} REG10;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t VBUSV:7; // ADC conversion of VBUS voltage (VBUS), offset: +2600mV
|
||||||
|
bool VBUS_GD:1; // VBUS Good Status
|
||||||
|
} REG11;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ICHGR:7; // ADC conversion of Charge Current (IBAT) when VBAT > VBATSHORT
|
||||||
|
uint8_t RES:1; // Reserved: Always reads 0
|
||||||
|
} REG12;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t IDPM_LIM:6; // Input Current Limit in effect while Input Current Optimizer (ICO) is enabled, offset: 100mA (default)
|
||||||
|
bool IDPM_STAT:1; // IINDPM Status
|
||||||
|
bool VDPM_STAT:1; // VINDPM Status
|
||||||
|
} REG13;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t DEV_REV:2; // Device Revision
|
||||||
|
bool TS_PROFILE:1; // Temperature Profile
|
||||||
|
uint8_t PN:3; // Device Configuration
|
||||||
|
bool ICO_OPTIMIZED:1; // Input Current Optimizer (ICO) Status
|
||||||
|
bool REG_RST:1; // Register Reset
|
||||||
|
} REG14;
|
21
firmware/targets/f3/Inc/bq27220.h
Normal file
21
firmware/targets/f3/Inc/bq27220.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Initialize Driver */
|
||||||
|
void bq27220_init();
|
||||||
|
|
||||||
|
/* Get battery voltage in mV */
|
||||||
|
uint16_t bq27220_get_voltage();
|
||||||
|
|
||||||
|
/* Get current in mA */
|
||||||
|
int16_t bq27220_get_current();
|
||||||
|
|
||||||
|
/* Get compensated full charge capacity in in mAh */
|
||||||
|
uint16_t bq27220_get_full_charge_capacity();
|
||||||
|
|
||||||
|
/* Get remaining capacity in in mAh */
|
||||||
|
uint16_t bq27220_get_remaining_capacity();
|
||||||
|
|
||||||
|
/* Get predicted remaining battery capacity in percents */
|
||||||
|
uint16_t bq27220_get_state_of_charge();
|
66
firmware/targets/f3/Inc/bq27220_reg.h
Normal file
66
firmware/targets/f3/Inc/bq27220_reg.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define BQ27220_ADDRESS 0xAA
|
||||||
|
|
||||||
|
#define CommandControl 0x00
|
||||||
|
#define CommandAtRate 0x02
|
||||||
|
#define CommandAtRateTimeToEmpty 0x04
|
||||||
|
#define CommandTemperature 0x06
|
||||||
|
#define CommandVoltage 0x08
|
||||||
|
#define CommandBatteryStatus 0x0A
|
||||||
|
#define CommandCurrent 0x0C
|
||||||
|
#define CommandRemainingCapacity 0x10
|
||||||
|
#define CommandFullChargeCapacity 0x12
|
||||||
|
#define CommandAverageCurrent 0x14
|
||||||
|
#define CommandTimeToEmpty 0x16
|
||||||
|
#define CommandTimeToFull 0x18
|
||||||
|
#define CommandStandbyCurrent 0x1A
|
||||||
|
#define CommandStandbyTimeToEmpty 0x1C
|
||||||
|
#define CommandMaxLoadCurrent 0x1E
|
||||||
|
#define CommandMaxLoadTimeToEmpty 0x20
|
||||||
|
#define CommandRawCoulombCount 0x22
|
||||||
|
#define CommandAveragePower 0x24
|
||||||
|
#define CommandInternalTemperature 0x28
|
||||||
|
#define CommandCycleCount 0x2A
|
||||||
|
#define CommandStateOfCharge 0x2C
|
||||||
|
#define CommandStateOfHealth 0x2E
|
||||||
|
#define CommandChargeVoltage 0x30
|
||||||
|
#define CommandChargeCurrent 0x32
|
||||||
|
#define CommandBTPDischargeSet 0x34
|
||||||
|
#define CommandBTPChargeSet 0x36
|
||||||
|
#define CommandOperationStatus 0x3A
|
||||||
|
#define CommandDesignCapacity 0x3C
|
||||||
|
#define CommandMACData 0x40
|
||||||
|
#define CommandMACDataSum 0x60
|
||||||
|
#define CommandMACDataLen 0x61
|
||||||
|
#define CommandAnalogCount 0x79
|
||||||
|
#define CommandRawCurrent 0x7A
|
||||||
|
#define CommandRawVoltage 0x7C
|
||||||
|
#define CommandRawIntTemp 0x7E
|
||||||
|
|
||||||
|
#define Control_CONTROL_STATUS 0x0000
|
||||||
|
#define Control_DEVICE_NUMBER 0x0001
|
||||||
|
#define Control_FW_VERSION 0x0002
|
||||||
|
#define Control_BOARD_OFFSET 0x0009
|
||||||
|
#define Control_CC_OFFSET 0x000A
|
||||||
|
#define Control_CC_OFFSET_SAVE 0x000B
|
||||||
|
#define Control_OCV_CMD 0x000C
|
||||||
|
#define Control_BAT_INSERT 0x000D
|
||||||
|
#define Control_BAT_REMOVE 0x000E
|
||||||
|
#define Control_SET_SNOOZE 0x0013
|
||||||
|
#define Control_CLEAR_SNOOZE 0x0014
|
||||||
|
#define Control_SET_PROFILE_1 0x0015
|
||||||
|
#define Control_SET_PROFILE_2 0x0016
|
||||||
|
#define Control_SET_PROFILE_3 0x0017
|
||||||
|
#define Control_SET_PROFILE_4 0x0018
|
||||||
|
#define Control_SET_PROFILE_5 0x0019
|
||||||
|
#define Control_SET_PROFILE_6 0x001A
|
||||||
|
#define Control_CAL_TOGGLE 0x002D
|
||||||
|
#define Control_SEALED 0x0030
|
||||||
|
#define Control_RESET 0x0041
|
||||||
|
#define Control_EXIT_CAL 0x0080
|
||||||
|
#define Control_ENTER_CAL 0x0081
|
||||||
|
#define Control_ENTER_CFG_UPDATE 0x0090
|
||||||
|
#define Control_EXIT_CFG_UPDATE_REINIT 0x0091
|
||||||
|
#define Control_EXIT_CFG_UPDATE 0x0092
|
||||||
|
#define Control_RETURN_TO_ROM 0x0F00
|
@ -34,6 +34,8 @@ extern I2C_HandleTypeDef hi2c1;
|
|||||||
|
|
||||||
/* USER CODE BEGIN Private defines */
|
/* USER CODE BEGIN Private defines */
|
||||||
|
|
||||||
|
#define POWER_I2C hi2c1
|
||||||
|
|
||||||
/* USER CODE END Private defines */
|
/* USER CODE END Private defines */
|
||||||
|
|
||||||
void MX_I2C1_Init(void);
|
void MX_I2C1_Init(void);
|
||||||
|
99
firmware/targets/f3/Src/bq25896.c
Normal file
99
firmware/targets/f3/Src/bq25896.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
|
||||||
|
#include <bq25896.h>
|
||||||
|
#include <bq25896_reg.h>
|
||||||
|
#include <i2c.h>
|
||||||
|
|
||||||
|
uint8_t bit_reverse(uint8_t b) {
|
||||||
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||||
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||||
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bq25896_read(uint8_t address, uint8_t* data, size_t size) {
|
||||||
|
if (HAL_I2C_Master_Transmit(&POWER_I2C, BQ25896_ADDRESS, &address, 1, 2000) != HAL_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (HAL_I2C_Master_Receive(&POWER_I2C, BQ25896_ADDRESS, data, size, 2000) != HAL_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bq25896_read_reg(uint8_t address, uint8_t* data) {
|
||||||
|
bq25896_read(address, data, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bq25896_write_reg(uint8_t address, uint8_t* data) {
|
||||||
|
uint8_t buffer[2] = { address, *data };
|
||||||
|
|
||||||
|
if (HAL_I2C_Master_Transmit(&POWER_I2C, BQ25896_ADDRESS, buffer, 2, 2000) != HAL_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
REG00 r00;
|
||||||
|
REG01 r01;
|
||||||
|
REG02 r02;
|
||||||
|
REG03 r03;
|
||||||
|
REG04 r04;
|
||||||
|
REG05 r05;
|
||||||
|
REG06 r06;
|
||||||
|
REG07 r07;
|
||||||
|
REG08 r08;
|
||||||
|
REG09 r09;
|
||||||
|
REG0A r0A;
|
||||||
|
REG0B r0B;
|
||||||
|
REG0C r0C;
|
||||||
|
REG0D r0D;
|
||||||
|
REG0E r0E;
|
||||||
|
REG0F r0F;
|
||||||
|
REG10 r10;
|
||||||
|
REG11 r11;
|
||||||
|
REG12 r12;
|
||||||
|
REG13 r13;
|
||||||
|
REG14 r14;
|
||||||
|
} bq25896_regs_t;
|
||||||
|
|
||||||
|
static bq25896_regs_t bq25896_regs;
|
||||||
|
|
||||||
|
void bq25896_init() {
|
||||||
|
bq25896_read(0x00, (uint8_t*)&bq25896_regs, sizeof(bq25896_regs));
|
||||||
|
|
||||||
|
bq25896_regs.r09.BATFET_DIS = 0;
|
||||||
|
bq25896_write_reg(0x09, (uint8_t*)&bq25896_regs.r09);
|
||||||
|
|
||||||
|
bq25896_regs.r14.REG_RST = 1;
|
||||||
|
bq25896_write_reg(0x14, (uint8_t*)&bq25896_regs.r14);
|
||||||
|
|
||||||
|
// bq25896_regs.r07.WATCHDOG = 0b00;
|
||||||
|
// bq25896_write_reg(0x07, (uint8_t*)&bq25896_regs.r07);
|
||||||
|
|
||||||
|
bq25896_read(0x00, (uint8_t*)&bq25896_regs, sizeof(bq25896_regs));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bq25896_poweroff() {
|
||||||
|
bq25896_regs.r09.BATFET_DIS=1;
|
||||||
|
bq25896_write_reg(0x09, (uint8_t*)&bq25896_regs.r09);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bq25896_is_charging() {
|
||||||
|
bq25896_regs.r03.WD_RST = 1;
|
||||||
|
bq25896_write_reg(0x03, (uint8_t*)&bq25896_regs.r03);
|
||||||
|
|
||||||
|
bq25896_read_reg(0x0B, (uint8_t*)&bq25896_regs.r0B);
|
||||||
|
return bq25896_regs.r0B.CHRG_STAT != ChrgStatNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bq25896_enable_otg() {
|
||||||
|
bq25896_regs.r03.OTG_CONFIG = 1;
|
||||||
|
bq25896_write_reg(0x09, (uint8_t*)&bq25896_regs.r03);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bq25896_disable_otg() {
|
||||||
|
bq25896_regs.r03.OTG_CONFIG = 0;
|
||||||
|
bq25896_write_reg(0x09, (uint8_t*)&bq25896_regs.r03);
|
||||||
|
}
|
53
firmware/targets/f3/Src/bq27220.c
Normal file
53
firmware/targets/f3/Src/bq27220.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#include <bq27220.h>
|
||||||
|
#include <bq27220_reg.h>
|
||||||
|
#include <i2c.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
uint16_t bq27220_read_word(uint8_t address) {
|
||||||
|
uint8_t data[2] = { address };
|
||||||
|
if (HAL_I2C_Master_Transmit(&POWER_I2C, BQ27220_ADDRESS, data, 1, 2000) != HAL_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HAL_I2C_Master_Receive(&POWER_I2C, BQ27220_ADDRESS, data, 2, 2000) != HAL_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *(uint16_t*)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bq27220_control(uint16_t control) {
|
||||||
|
uint8_t data[3] = { CommandControl };
|
||||||
|
data[1] = (control>>8) & 0xFF;
|
||||||
|
data[2] = control & 0xFF;
|
||||||
|
if (HAL_I2C_Master_Transmit(&POWER_I2C, BQ27220_ADDRESS, data, 3, 2000) != HAL_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bq27220_init() {
|
||||||
|
bq27220_control(Control_ENTER_CFG_UPDATE);
|
||||||
|
bq27220_control(Control_SET_PROFILE_2);
|
||||||
|
bq27220_control(Control_EXIT_CFG_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bq27220_get_voltage() {
|
||||||
|
return bq27220_read_word(CommandVoltage);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t bq27220_get_current() {
|
||||||
|
return (int16_t)bq27220_read_word(CommandCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bq27220_get_full_charge_capacity() {
|
||||||
|
return bq27220_read_word(CommandFullChargeCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bq27220_get_remaining_capacity() {
|
||||||
|
return bq27220_read_word(CommandRemainingCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bq27220_get_state_of_charge() {
|
||||||
|
return bq27220_read_word(CommandStateOfCharge);
|
||||||
|
}
|
28
firmware/targets/f3/api-hal/api-hal-power.c
Normal file
28
firmware/targets/f3/api-hal/api-hal-power.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <api-hal-power.h>
|
||||||
|
#include <bq27220.h>
|
||||||
|
#include <bq25896.h>
|
||||||
|
|
||||||
|
void api_hal_power_init() {
|
||||||
|
bq27220_init();
|
||||||
|
bq25896_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t api_hal_power_get_pct() {
|
||||||
|
return bq27220_get_state_of_charge();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool api_hal_power_is_charging() {
|
||||||
|
return bq25896_is_charging();
|
||||||
|
}
|
||||||
|
|
||||||
|
void api_hal_power_off() {
|
||||||
|
bq25896_poweroff();
|
||||||
|
}
|
||||||
|
|
||||||
|
void api_hal_power_enable_otg() {
|
||||||
|
bq25896_enable_otg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void api_hal_power_disable_otg() {
|
||||||
|
bq25896_disable_otg();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user