Files
game-and-watch-retro-go/Core/Src/bq24072.c
2021-01-11 02:30:22 +01:00

187 lines
3.7 KiB
C

#include <stdio.h>
#include <stdbool.h>
#include <stm32h7xx_hal.h>
#include "bq24072.h"
#include "utils.h"
#define BQ24072_BATTERY_FULL 13000
#define BQ24072_BATTERY_LOWBAT 11000
#define BQ24072_PROFILING 0
typedef enum {
BQ24072_PIN_CHG,
BQ24072_PIN_PGOOD,
BQ24072_PIN_COUNT // Keep this last
} bq24072_pin_t;
// PE7 - CHG
// PE8 - CE
// PA2 - PGOOD
// PC4 - Battery voltage
static const struct {
uint32_t pin;
GPIO_TypeDef* bank;
} bq_pins[BQ24072_PIN_COUNT] = {
[BQ24072_PIN_CHG] = { .pin = GPIO_PIN_7, .bank = GPIOE},
[BQ24072_PIN_PGOOD] = { .pin = GPIO_PIN_2, .bank = GPIOA},
};
extern ADC_HandleTypeDef hadc1;
extern TIM_HandleTypeDef htim1;
#if BQ24072_PROFILING
static volatile uint32_t bq24072_battery_value;
#endif // BQ24072_PROFILING
static struct {
uint16_t value;
bool charging;
bool power_good;
struct {
int percent;
bq24072_state_t state;
} last;
} bq24072_data;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
bq24072_data.value = HAL_ADC_GetValue(hadc);
#if BQ24072_PROFILING == 1
bq24072_battery_value = bq24072_data.value;
#endif
HAL_ADC_Stop_IT(hadc);
}
int32_t bq24072_init(void)
{
// Read initial states
bq24072_handle_power_good();
bq24072_handle_charging();
bq24072_poll();
// Start timer for voltage poll
HAL_TIM_Base_Start_IT(&htim1);
return 0;
}
void bq24072_handle_power_good(void)
{
bq24072_data.power_good = !(HAL_GPIO_ReadPin(bq_pins[BQ24072_PIN_PGOOD].bank, bq_pins[BQ24072_PIN_PGOOD].pin) == GPIO_PIN_SET);
}
void bq24072_handle_charging(void)
{
bq24072_data.charging = !(HAL_GPIO_ReadPin(bq_pins[BQ24072_PIN_CHG].bank, bq_pins[BQ24072_PIN_CHG].pin) == GPIO_PIN_SET);
}
bq24072_state_t bq24072_get_state(void)
{
if (bq24072_data.power_good)
{
if (bq24072_data.charging)
{
return BQ24072_STATE_CHARGING;
}
else
{
return BQ24072_STATE_FULL;
}
}
else
{
if (!bq24072_data.charging)
{
return BQ24072_STATE_DISCHARGING;
}
else
{
return BQ24072_STATE_MISSING;
}
}
}
int bq24072_get_percent(void)
{
int span = BQ24072_BATTERY_FULL - BQ24072_BATTERY_LOWBAT;
if (bq24072_get_state() == BQ24072_STATE_MISSING)
{
return 0;
}
if (bq24072_data.value - BQ24072_BATTERY_LOWBAT <= 0)
{
return 0;
}
else if (bq24072_data.value >= BQ24072_BATTERY_FULL)
{
return 100;
}
else
{
return (bq24072_data.value - BQ24072_BATTERY_LOWBAT)*100 / span;
}
}
int bq24072_get_percent_filtered(void)
{
int percent;
bq24072_state_t state;
if (bq24072_data.value == 0)
{
// No value read from ADC yet
return 0;
}
state = bq24072_get_state();
percent = bq24072_get_percent();
if (state != bq24072_data.last.state)
{
bq24072_data.last.state = state;
bq24072_data.last.percent = percent;
return percent;
}
switch (state)
{
case BQ24072_STATE_MISSING:
case BQ24072_STATE_FULL:
return percent;
case BQ24072_STATE_CHARGING:
if (percent > bq24072_data.last.percent)
{
bq24072_data.last.percent = percent;
}
return bq24072_data.last.percent;
case BQ24072_STATE_DISCHARGING:
if (percent < bq24072_data.last.percent)
{
bq24072_data.last.percent = percent;
}
return bq24072_data.last.percent;
}
return percent;
}
void bq24072_poll(void)
{
HAL_ADC_Start_IT(&hadc1);
}