diff --git a/bootloader/targets/f5/target.mk b/bootloader/targets/f5/target.mk index c2aef017..4e23c951 100644 --- a/bootloader/targets/f5/target.mk +++ b/bootloader/targets/f5/target.mk @@ -31,7 +31,7 @@ LDFLAGS += -T$(TARGET_DIR)/stm32wb55xx_flash_cm4.ld # Drivers DRIVERS_DIR = ../lib/drivers CFLAGS += -I$(DRIVERS_DIR) -C_SOURCES += $(wildcard $(DRIVERS_DIR)/*.c) +C_SOURCES += $(DRIVERS_DIR)/lp5562.c # API-HAL CFLAGS += -I$(TARGET_DIR)/api-hal diff --git a/firmware/targets/f4/Src/main.c b/firmware/targets/f4/Src/main.c index 8c766611..72dcebaa 100644 --- a/firmware/targets/f4/Src/main.c +++ b/firmware/targets/f4/Src/main.c @@ -46,9 +46,9 @@ int main(void) MX_AES2_Init(); MX_CRC_Init(); + delay_us_init_DWT(); api_hal_init(); MX_FATFS_Init(); - delay_us_init_DWT(); furi_init(); // CMSIS initialization diff --git a/firmware/targets/f4/api-hal/api-hal-power.c b/firmware/targets/f4/api-hal/api-hal-power.c index 44222246..7eb930e6 100644 --- a/firmware/targets/f4/api-hal/api-hal-power.c +++ b/firmware/targets/f4/api-hal/api-hal-power.c @@ -13,6 +13,28 @@ #include volatile uint32_t api_hal_power_insomnia = 1; +const ParamCEDV cedv = { + .full_charge_cap = 2100, + .design_cap = 2100, + .EMF = 3739, + .C0 = 776, + .C1 = 0, + .R1 = 193, + .R0 = 1, + .T0 = 1, + .TC = 11, + .DOD0 = 4044, + .DOD10 = 3899, + .DOD20 = 3796, + .DOD30 = 3704, + .DOD40 = 3627, + .DOD50 = 3573, + .DOD60 = 3535, + .DOD70 = 3501, + .DOD80 = 3453, + .DOD90 = 3366, + .DOD100 = 2419, +}; void HAL_RCC_CSSCallback(void) { // TODO: notify user about issue with HSE @@ -21,7 +43,7 @@ void HAL_RCC_CSSCallback(void) { void api_hal_power_init() { LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); - bq27220_init(); + bq27220_init(&cedv); bq25896_init(); } @@ -195,8 +217,8 @@ void api_hal_power_dump_state(string_t buffer) { ); // Voltage and current info string_cat_printf(buffer, - "bq27220: Full capacity: %dmAh, Remaining capacity: %dmAh, State of Charge: %d%%, State of health: %d%%\r\n", - bq27220_get_full_charge_capacity(), bq27220_get_remaining_capacity(), + "bq27220: Full capacity: %dmAh, Design capacity: %dmAh, Remaining capacity: %dmAh, State of Charge: %d%%, State of health: %d%%\r\n", + bq27220_get_full_charge_capacity(), bq27220_get_design_capacity(), bq27220_get_remaining_capacity(), bq27220_get_state_of_charge(), bq27220_get_state_of_health() ); string_cat_printf(buffer, diff --git a/firmware/targets/f5/Src/main.c b/firmware/targets/f5/Src/main.c index fcd98aac..47e0ead0 100644 --- a/firmware/targets/f5/Src/main.c +++ b/firmware/targets/f5/Src/main.c @@ -46,9 +46,9 @@ int main(void) MX_AES2_Init(); MX_CRC_Init(); + delay_us_init_DWT(); api_hal_init(); MX_FATFS_Init(); - delay_us_init_DWT(); furi_init(); // CMSIS initialization diff --git a/firmware/targets/f5/api-hal/api-hal-power.c b/firmware/targets/f5/api-hal/api-hal-power.c index d5c46a49..fda81dce 100644 --- a/firmware/targets/f5/api-hal/api-hal-power.c +++ b/firmware/targets/f5/api-hal/api-hal-power.c @@ -14,6 +14,28 @@ #include volatile uint32_t api_hal_power_insomnia = 1; +const ParamCEDV cedv = { + .full_charge_cap = 2100, + .design_cap = 2100, + .EMF = 3739, + .C0 = 776, + .C1 = 0, + .R1 = 193, + .R0 = 1, + .T0 = 1, + .TC = 11, + .DOD0 = 4044, + .DOD10 = 3899, + .DOD20 = 3796, + .DOD30 = 3704, + .DOD40 = 3627, + .DOD50 = 3573, + .DOD60 = 3535, + .DOD70 = 3501, + .DOD80 = 3453, + .DOD90 = 3366, + .DOD100 = 2419, +}; void HAL_RCC_CSSCallback(void) { // TODO: notify user about issue with HSE @@ -22,7 +44,7 @@ void HAL_RCC_CSSCallback(void) { void api_hal_power_init() { LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); - bq27220_init(); + bq27220_init(&cedv); bq25896_init(); } @@ -196,8 +218,8 @@ void api_hal_power_dump_state(string_t buffer) { ); // Voltage and current info string_cat_printf(buffer, - "bq27220: Full capacity: %dmAh, Remaining capacity: %dmAh, State of Charge: %d%%, State of health: %d%%\r\n", - bq27220_get_full_charge_capacity(), bq27220_get_remaining_capacity(), + "bq27220: Full capacity: %dmAh, Design capacity: %dmAh, Remaining capacity: %dmAh, State of Charge: %d%%, State of health: %d%%\r\n", + bq27220_get_full_charge_capacity(), bq27220_get_design_capacity(), bq27220_get_remaining_capacity(), bq27220_get_state_of_charge(), bq27220_get_state_of_health() ); string_cat_printf(buffer, diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index 487560bf..ab242e4c 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -2,6 +2,7 @@ #include "bq27220_reg.h" #include +#include #include uint16_t bq27220_read_word(uint8_t address) { @@ -25,16 +26,90 @@ bool bq27220_control(uint16_t control) { bool, &ret, () { uint8_t buffer[3]; buffer[0] = CommandControl; - buffer[1] = (control >> 8) & 0xFF; - buffer[2] = control & 0xFF; + buffer[1] = control & 0xFF; + buffer[2] = (control >> 8) & 0xFF; return api_hal_i2c_tx(POWER_I2C, BQ27220_ADDRESS, buffer, 3, BQ27220_I2C_TIMEOUT); }); return ret; } -void bq27220_init() { +uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) { + uint8_t ret = 0; + for(uint16_t i = 0; i < len; i++) { + ret += data[i]; + } + return 0xFF - ret; +} + +bool bq27220_set_parameter_u16(uint16_t address, uint16_t value) { + bool ret; + uint8_t buffer[5]; + with_api_hal_i2c( + bool, &ret, () { + buffer[0] = CommandSelectSubclass; + buffer[1] = address & 0xFF; + buffer[2] = (address >> 8) & 0xFF; + buffer[3] = (value >> 8) & 0xFF; + buffer[4] = value & 0xFF; + return api_hal_i2c_tx(POWER_I2C, BQ27220_ADDRESS, buffer, 5, BQ27220_I2C_TIMEOUT); + }); + uint8_t checksum = bq27220_get_checksum(&buffer[1], 4); + with_api_hal_i2c( + bool, &ret, () { + buffer[0] = CommandMACDataSum; + buffer[1] = checksum; + buffer[2] = 6; + return api_hal_i2c_tx(POWER_I2C, BQ27220_ADDRESS, buffer, 3, BQ27220_I2C_TIMEOUT); + }); + return ret; +} + +void bq27220_init(const ParamCEDV* cedv) { + uint32_t timeout = 100; + OperationStatus status = {}; bq27220_control(Control_ENTER_CFG_UPDATE); - bq27220_control(Control_SET_PROFILE_2); + while((status.CFGUPDATE != 1) && (timeout-- > 0)) { + bq27220_get_operation_status(&status); + } + bq27220_set_parameter_u16(AddressFullChargeCapacity, cedv->full_charge_cap); + delay_us(15000); + bq27220_set_parameter_u16(AddressDesignCapacity, cedv->design_cap); + delay_us(15000); + bq27220_set_parameter_u16(AddressEMF, cedv->EMF); + delay_us(15000); + bq27220_set_parameter_u16(AddressC0, cedv->C0); + delay_us(15000); + bq27220_set_parameter_u16(AddressR0, cedv->R0); + delay_us(15000); + bq27220_set_parameter_u16(AddressT0, cedv->T0); + delay_us(15000); + bq27220_set_parameter_u16(AddressR1, cedv->R1); + delay_us(15000); + bq27220_set_parameter_u16(AddressTC, (cedv->TC) << 8 | cedv->C1); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD0, cedv->DOD0); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD10, cedv->DOD10); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD20, cedv->DOD20); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD30, cedv->DOD30); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD40, cedv->DOD40); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD50, cedv->DOD40); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD60, cedv->DOD60); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD70, cedv->DOD70); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD80, cedv->DOD80); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD90, cedv->DOD90); + delay_us(15000); + bq27220_set_parameter_u16(AddressStartDOD100, cedv->DOD100); + delay_us(15000); + bq27220_control(Control_EXIT_CFG_UPDATE); } @@ -74,6 +149,10 @@ uint16_t bq27220_get_full_charge_capacity() { return bq27220_read_word(CommandFullChargeCapacity); } +uint16_t bq27220_get_design_capacity() { + return bq27220_read_word(CommandDesignCapacity); +} + uint16_t bq27220_get_remaining_capacity() { return bq27220_read_word(CommandRemainingCapacity); } diff --git a/lib/drivers/bq27220.h b/lib/drivers/bq27220.h index 4512db46..7e50942d 100644 --- a/lib/drivers/bq27220.h +++ b/lib/drivers/bq27220.h @@ -43,8 +43,31 @@ typedef struct { uint8_t RSVD0 : 5; } OperationStatus; +typedef struct { + uint16_t full_charge_cap; + uint16_t design_cap; + uint16_t EMF; + uint16_t C0; + uint16_t R0; + uint16_t T0; + uint16_t R1; + uint8_t TC; + uint8_t C1; + uint16_t DOD0; + uint16_t DOD10; + uint16_t DOD20; + uint16_t DOD30; + uint16_t DOD40; + uint16_t DOD50; + uint16_t DOD60; + uint16_t DOD70; + uint16_t DOD80; + uint16_t DOD90; + uint16_t DOD100; +} ParamCEDV; + /** Initialize Driver */ -void bq27220_init(); +void bq27220_init(const ParamCEDV* cedv); /** Get battery voltage in mV or error */ uint16_t bq27220_get_voltage(); @@ -64,6 +87,9 @@ uint16_t bq27220_get_temperature(); /** Get compensated full charge capacity in in mAh */ uint16_t bq27220_get_full_charge_capacity(); +/** Get design capacity in mAh */ +uint16_t bq27220_get_design_capacity(); + /** Get remaining capacity in in mAh */ uint16_t bq27220_get_remaining_capacity(); @@ -72,3 +98,5 @@ uint16_t bq27220_get_state_of_charge(); /** Get ratio of full charge capacity over design capacity in percents */ uint16_t bq27220_get_state_of_health(); + +void bq27220_change_design_capacity(uint16_t capacity); diff --git a/lib/drivers/bq27220_reg.h b/lib/drivers/bq27220_reg.h index 0ed35301..20effd68 100644 --- a/lib/drivers/bq27220_reg.h +++ b/lib/drivers/bq27220_reg.h @@ -31,6 +31,7 @@ #define CommandBTPChargeSet 0x36 #define CommandOperationStatus 0x3A #define CommandDesignCapacity 0x3C +#define CommandSelectSubclass 0x3E #define CommandMACData 0x40 #define CommandMACDataSum 0x60 #define CommandMACDataLen 0x61 @@ -65,3 +66,24 @@ #define Control_EXIT_CFG_UPDATE_REINIT 0x0091 #define Control_EXIT_CFG_UPDATE 0x0092 #define Control_RETURN_TO_ROM 0x0F00 + +#define AddressFullChargeCapacity 0x929D +#define AddressDesignCapacity 0x929F +#define AddressEMF 0x92A3 +#define AddressC0 0x92A9 +#define AddressR0 0x92AB +#define AddressT0 0x92AD +#define AddressR1 0x92AF +#define AddressTC 0x92B1 +#define AddressC1 0x92B1 +#define AddressStartDOD0 0x92BD +#define AddressStartDOD10 0x92BF +#define AddressStartDOD20 0x92C1 +#define AddressStartDOD30 0x92C3 +#define AddressStartDOD40 0x92C5 +#define AddressStartDOD50 0x92C7 +#define AddressStartDOD60 0x92C9 +#define AddressStartDOD70 0x92CB +#define AddressStartDOD80 0x92CD +#define AddressStartDOD90 0x92CF +#define AddressStartDOD100 0x92D1