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; | ||||
|     u8g2_SetFontMode(&canvas->fb, 1); | ||||
|     if(font == FontPrimary) { | ||||
|         u8g2_SetFont(&canvas->fb, u8g2_font_Born2bSportyV2_tr); | ||||
|         u8g2_SetFont(&canvas->fb, u8g2_font_helvB08_tf); | ||||
|     } else if(font == FontSecondary) { | ||||
|         u8g2_SetFont(&canvas->fb, u8g2_font_HelvetiPixel_tr); | ||||
|         u8g2_SetFont(&canvas->fb, u8g2_font_haxrcorp4089_tr); | ||||
|     } else { | ||||
|         furi_check(0); | ||||
|     } | ||||
|  | ||||
| @ -1,15 +1,13 @@ | ||||
| #include "power.h" | ||||
| 
 | ||||
| #include <flipper_v2.h> | ||||
| 
 | ||||
| #include <menu/menu.h> | ||||
| #include <menu/menu_item.h> | ||||
| #include <gui/gui.h> | ||||
| #include <gui/widget.h> | ||||
| #include <assets_icons.h> | ||||
| 
 | ||||
| #define BATTERY_MIN_VOLTAGE 3.2f | ||||
| #define BATTERY_MAX_VOLTAGE 4.0f | ||||
| #define BATTERY_INIT 0xFFAACCEE | ||||
| 
 | ||||
| extern ADC_HandleTypeDef hadc1; | ||||
| #include <api-hal-power.h> | ||||
| 
 | ||||
| struct Power { | ||||
|     Icon* usb_icon; | ||||
| @ -18,7 +16,10 @@ struct Power { | ||||
|     Icon* battery_icon; | ||||
|     Widget* battery_widget; | ||||
| 
 | ||||
|     uint32_t charge; | ||||
|     ValueMutex* menu_vm; | ||||
|     MenuItem* menu; | ||||
| 
 | ||||
|     uint8_t charge; | ||||
| }; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
|     canvas->draw_icon(canvas, 0, 0, power->battery_icon); | ||||
| 
 | ||||
|     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); | ||||
|     } | ||||
|     canvas->draw_box(canvas, 2, 2, (float)power->charge / 100 * 14, 4); | ||||
| } | ||||
| 
 | ||||
| void power_input_events_callback(const void* value, void* ctx) { | ||||
|     assert(ctx); | ||||
|     Power* power = ctx; | ||||
|     const InputEvent* event = value; | ||||
| void power_off_callback(void* context) { | ||||
|     api_hal_power_off(); | ||||
| } | ||||
| 
 | ||||
|     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); | ||||
|     widget_update(power->usb_widget); | ||||
| void power_disable_otg_callback(void* context) { | ||||
|     api_hal_power_disable_otg(); | ||||
| } | ||||
| 
 | ||||
| Power* power_alloc() { | ||||
|     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_widget = widget_alloc(); | ||||
|     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); | ||||
| 
 | ||||
|     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_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; | ||||
| } | ||||
| 
 | ||||
| @ -99,19 +94,21 @@ void power_task(void* p) { | ||||
|     gui->add_widget(gui, power->battery_widget, GuiLayerStatusBarRight); | ||||
|     furi_commit(gui_record); | ||||
| 
 | ||||
|     with_value_mutex( | ||||
|         power->menu_vm, (Menu * menu) { menu_item_add(menu, power->menu); }); | ||||
| 
 | ||||
|     if(!furi_create("power", power)) { | ||||
|         printf("[power_task] unable to create power record\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|     api_hal_power_init(); | ||||
| 
 | ||||
|     furiac_ready(); | ||||
| 
 | ||||
|     while(1) { | ||||
|         HAL_ADC_Start(&hadc1); | ||||
|         if(HAL_ADC_PollForConversion(&hadc1, 1000) != HAL_TIMEOUT) { | ||||
|             power->charge = HAL_ADC_GetValue(&hadc1); | ||||
|             widget_update(power->battery_widget); | ||||
|         } | ||||
|         power->charge = api_hal_power_get_pct(); | ||||
|         widget_enabled_set(power->usb_widget, api_hal_power_is_charging()); | ||||
|         osDelay(1000); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -14,6 +14,7 @@ include			$(PROJECT_ROOT)/lib/lib.mk | ||||
| TARGET			?= f2 | ||||
| TARGET_DIR		= targets/$(TARGET) | ||||
| include			$(TARGET_DIR)/target.mk | ||||
| CFLAGS			+= -Itargets/Inc | ||||
| 
 | ||||
| include			$(PROJECT_ROOT)/make/git.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 */ | ||||
| 
 | ||||
| #define POWER_I2C hi2c1 | ||||
| 
 | ||||
| /* USER CODE END Private defines */ | ||||
| 
 | ||||
| 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
	 あく
						あく