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
	 あく
						あく