Implemented the logic to detect and read the charge controller status pins using two different policies :
- the first one (also used right now) is using interrupts on the two lines - the second one was doing some polling using a timer interrupt to check the controller status
This commit is contained in:
parent
9f574f0486
commit
214e174ffc
@ -6,19 +6,107 @@
|
|||||||
#include "wm_timer.h"
|
#include "wm_timer.h"
|
||||||
#include "wm_pwm.h"
|
#include "wm_pwm.h"
|
||||||
|
|
||||||
|
#define INTERRUPT_POLICY (0)
|
||||||
|
#define POLL_POLICY (1)
|
||||||
|
|
||||||
|
#define BATTERY_CONTROLLER_STATUS_DETECTION_POLICY INTERRUPT_POLICY
|
||||||
|
|
||||||
|
/* Battery voltage and ADC */
|
||||||
static int8_t _adc_offset = 0;
|
static int8_t _adc_offset = 0;
|
||||||
|
|
||||||
|
/* Vibration motor timer */
|
||||||
static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
|
static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
|
||||||
|
|
||||||
|
/* Battery charge controller status */
|
||||||
|
static battery_controller_status_e _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
static BatteryControllerStatusChangeCb_t _BatteryControllerStatusChangeCb = NULL;
|
||||||
|
|
||||||
static void vibration_motor_timer_irq_cb(void *p)
|
static void vibration_motor_timer_irq_cb(void *p)
|
||||||
{
|
{
|
||||||
(void)p;
|
(void)p;
|
||||||
tls_pwm_stop(VIBRATION_MOTOR_PWM_CHANNEL);
|
tls_pwm_stop(VIBRATION_MOTOR_PWM_CHANNEL);
|
||||||
tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
||||||
APP_LOG_DEBUG("Vibration stopped");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY
|
||||||
|
static uint8_t _battery_status_timer_id = WM_TIMER_ID_INVALID;
|
||||||
|
|
||||||
|
static void battery_status_timer_irq_cb(void *p)
|
||||||
|
{
|
||||||
|
bool charging = tls_gpio_read(BATTERY_CONTROLLER_CHARGING_STATUS) == 0;
|
||||||
|
bool charged = tls_gpio_read(BATTERY_CONTROLLER_CHARGED_STATUS) == 0;
|
||||||
|
|
||||||
|
battery_controller_status_e old_battery_status = _battery_fsm;
|
||||||
|
|
||||||
|
if(charging && !charged)
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGING;
|
||||||
|
else if(!charging && charged)
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGED;
|
||||||
|
else if (!charging && !charged)
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
else
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_ERROR;
|
||||||
|
|
||||||
|
if(old_battery_status != _battery_fsm)
|
||||||
|
{
|
||||||
|
// Let's call a user registered callback here
|
||||||
|
APP_LOG_INFO("Battery status changed from %s to %s",
|
||||||
|
battery_controller_status_2_str(old_battery_status),
|
||||||
|
battery_controller_status_2_str(_battery_fsm));
|
||||||
|
|
||||||
|
if(_BatteryControllerStatusChangeCb) _BatteryControllerStatusChangeCb(old_battery_status, _battery_fsm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY
|
||||||
|
static void battery_controller_irq_cb(void *p)
|
||||||
|
{
|
||||||
|
enum tls_io_name gpio_pin = (enum tls_io_name)p;
|
||||||
|
|
||||||
|
if(BATTERY_CONTROLLER_CHARGING_STATUS == gpio_pin)
|
||||||
|
{
|
||||||
|
tls_clr_gpio_irq_status(BATTERY_CONTROLLER_CHARGING_STATUS);
|
||||||
|
}
|
||||||
|
if(BATTERY_CONTROLLER_CHARGED_STATUS == gpio_pin)
|
||||||
|
{
|
||||||
|
tls_clr_gpio_irq_status(BATTERY_CONTROLLER_CHARGED_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool charging = tls_gpio_read(BATTERY_CONTROLLER_CHARGING_STATUS) == 0;
|
||||||
|
bool charged = tls_gpio_read(BATTERY_CONTROLLER_CHARGED_STATUS) == 0;
|
||||||
|
|
||||||
|
battery_controller_status_e old_battery_status = _battery_fsm;
|
||||||
|
|
||||||
|
switch(old_battery_status)
|
||||||
|
{
|
||||||
|
case BATTERY_CONTROLLER_STATUS_CHARGING:
|
||||||
|
if(charged) _battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGED;
|
||||||
|
else if(!charged && !charging) _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
break;
|
||||||
|
case BATTERY_CONTROLLER_STATUS_CHARGED:
|
||||||
|
if(!charged && !charging) _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
break;
|
||||||
|
case BATTERY_CONTROLLER_STATUS_DISCHARGING:
|
||||||
|
if(charging) _battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(old_battery_status != _battery_fsm)
|
||||||
|
{
|
||||||
|
// Let's call a user registered callback here
|
||||||
|
APP_LOG_INFO("Battery status changed from %s to : %s, IRQ : %u",
|
||||||
|
battery_controller_status_2_str(old_battery_status),
|
||||||
|
battery_controller_status_2_str(_battery_fsm),
|
||||||
|
gpio_pin);
|
||||||
|
|
||||||
|
if(_BatteryControllerStatusChangeCb) _BatteryControllerStatusChangeCb(old_battery_status, _battery_fsm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void watch_peripherals_io_init(void)
|
static void watch_peripherals_io_init(void)
|
||||||
{
|
{
|
||||||
/* We initialize the ADC input as well as the gpio used to enabled the voltage divider bridge */
|
/* We initialize the ADC input as well as the gpio used to enabled the voltage divider bridge */
|
||||||
@ -31,8 +119,34 @@ static void watch_peripherals_io_init(void)
|
|||||||
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
||||||
|
|
||||||
/* We initialize the pins used to read the battery controller IC charging and charged statuses */
|
/* We initialize the pins used to read the battery controller IC charging and charged statuses */
|
||||||
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGING_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
|
||||||
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
|
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGING_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
|
|
||||||
|
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY
|
||||||
|
tls_gpio_isr_register(BATTERY_CONTROLLER_CHARGED_STATUS, &(battery_controller_irq_cb), (int*) BATTERY_CONTROLLER_CHARGED_STATUS);
|
||||||
|
tls_gpio_irq_enable(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_IRQ_TRIG_DOUBLE_EDGE); // Enabled when level is changing edge
|
||||||
|
|
||||||
|
tls_gpio_isr_register(BATTERY_CONTROLLER_CHARGING_STATUS, &(battery_controller_irq_cb), (int*) BATTERY_CONTROLLER_CHARGING_STATUS);
|
||||||
|
tls_gpio_irq_enable(BATTERY_CONTROLLER_CHARGING_STATUS, WM_GPIO_IRQ_TRIG_DOUBLE_EDGE); // Enabled when level is changing edge
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CASE_RETURN_STR
|
||||||
|
#define CASE_RETURN_STR(const) case const: return #const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *battery_controller_status_2_str(battery_controller_status_e status)
|
||||||
|
{
|
||||||
|
switch(status)
|
||||||
|
{
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_CHARGING)
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_DISCHARGING)
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_CHARGED)
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_ERROR)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "Unknown Battery Status";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_peripherals_init(int8_t adcOffset)
|
void watch_peripherals_init(int8_t adcOffset)
|
||||||
@ -43,7 +157,7 @@ void watch_peripherals_init(int8_t adcOffset)
|
|||||||
/* Prevent multiple init call !*/
|
/* Prevent multiple init call !*/
|
||||||
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
||||||
{
|
{
|
||||||
/* Let's initialize the timer w'll use to stop the vibration motor */
|
/* Let's initialize the timer we'll use to stop the vibration motor */
|
||||||
struct tls_timer_cfg vibration_motor_timer_cfg =
|
struct tls_timer_cfg vibration_motor_timer_cfg =
|
||||||
{
|
{
|
||||||
.arg = NULL,
|
.arg = NULL,
|
||||||
@ -55,8 +169,32 @@ void watch_peripherals_init(int8_t adcOffset)
|
|||||||
_vibration_motor_timer_id = tls_timer_create(&vibration_motor_timer_cfg);
|
_vibration_motor_timer_id = tls_timer_create(&vibration_motor_timer_cfg);
|
||||||
|
|
||||||
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
||||||
APP_LOG_ERROR("Failed to create timer");
|
APP_LOG_ERROR("Failed to create vibration motor timer");
|
||||||
}
|
}
|
||||||
|
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY
|
||||||
|
if(WM_TIMER_ID_INVALID == _battery_status_timer_id)
|
||||||
|
{
|
||||||
|
struct tls_timer_cfg battery_status_timer_cfg =
|
||||||
|
{
|
||||||
|
.arg = NULL,
|
||||||
|
.callback = &(battery_status_timer_irq_cb),
|
||||||
|
.unit = TLS_TIMER_UNIT_MS,
|
||||||
|
.is_repeat = true,
|
||||||
|
.timeout = 200
|
||||||
|
};
|
||||||
|
_battery_status_timer_id = tls_timer_create(&battery_status_timer_cfg);
|
||||||
|
|
||||||
|
if(WM_TIMER_ID_INVALID == _battery_status_timer_id)
|
||||||
|
APP_LOG_ERROR("Failed to create battery status timer");
|
||||||
|
else
|
||||||
|
tls_timer_start(_battery_status_timer_id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void watch_peripherals_register_battery_controller_status_change_cb(BatteryControllerStatusChangeCb_t BatteryControllerStatusChangeCb)
|
||||||
|
{
|
||||||
|
_BatteryControllerStatusChangeCb = BatteryControllerStatusChangeCb;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t watch_peripherals_get_battery_voltage(battery_unit_e unit)
|
uint16_t watch_peripherals_get_battery_voltage(battery_unit_e unit)
|
||||||
@ -100,22 +238,11 @@ uint8_t battery_voltage_to_percentage(uint16_t voltage_in_mV)
|
|||||||
|
|
||||||
battery_controller_status_e watch_peripherals_get_battery_controller_status(void)
|
battery_controller_status_e watch_peripherals_get_battery_controller_status(void)
|
||||||
{
|
{
|
||||||
bool charging = tls_gpio_read(BATTERY_CONTROLLER_CHARGING_STATUS) == 0;
|
return _battery_fsm;
|
||||||
bool charged = tls_gpio_read(BATTERY_CONTROLLER_CHARGED_STATUS) == 0;
|
|
||||||
|
|
||||||
if(charging && !charged)
|
|
||||||
return BATTERY_CHARGING;
|
|
||||||
else if(!charging && charged)
|
|
||||||
return BATTERY_CHARGED;
|
|
||||||
else if (!charging && !charged)
|
|
||||||
return BATTERY_DISCHARGING;
|
|
||||||
else
|
|
||||||
return BATTERY_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs)
|
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs)
|
||||||
{
|
{
|
||||||
APP_LOG_DEBUG("Vibration started");
|
|
||||||
/* No need to do anything if the duration is 0 or if the strength is 0 */
|
/* No need to do anything if the duration is 0 or if the strength is 0 */
|
||||||
if(!strength || !durationMs) return;
|
if(!strength || !durationMs) return;
|
||||||
/* We start the timer which will stop the vibration after durationMs time */
|
/* We start the timer which will stop the vibration after durationMs time */
|
||||||
|
@ -15,12 +15,22 @@ typedef enum battery_unit
|
|||||||
|
|
||||||
typedef enum battery_controller_status
|
typedef enum battery_controller_status
|
||||||
{
|
{
|
||||||
BATTERY_CHARGING = 0,
|
BATTERY_CONTROLLER_STATUS_DISCHARGING = 0,
|
||||||
BATTERY_CHARGED,
|
BATTERY_CONTROLLER_STATUS_CHARGING,
|
||||||
BATTERY_DISCHARGING,
|
BATTERY_CONTROLLER_STATUS_CHARGED,
|
||||||
BATTERY_ERROR
|
BATTERY_CONTROLLER_STATUS_ERROR
|
||||||
} battery_controller_status_e;
|
} battery_controller_status_e;
|
||||||
|
|
||||||
|
typedef void (*BatteryControllerStatusChangeCb_t)(battery_controller_status_e old, battery_controller_status_e new);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function to easily print the battery status enumeration name
|
||||||
|
*
|
||||||
|
* @param status the enumeration value for which to get the name
|
||||||
|
* @return const char* a string representing the enumeration value
|
||||||
|
*/
|
||||||
|
const char *battery_controller_status_2_str(battery_controller_status_e status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Inits the watch peripherals driver.
|
* @brief Inits the watch peripherals driver.
|
||||||
* This must be called before using the API.
|
* This must be called before using the API.
|
||||||
@ -29,6 +39,14 @@ typedef enum battery_controller_status
|
|||||||
*/
|
*/
|
||||||
void watch_peripherals_init(int8_t adcOffset);
|
void watch_peripherals_init(int8_t adcOffset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers the user provided callback function to notify the battery controller status change event
|
||||||
|
* @note This function should be as short as possible, do not call LVGL functions in it.
|
||||||
|
*
|
||||||
|
* @param BatteryStatusChangeCb a pointer to the function having the right definition.
|
||||||
|
*/
|
||||||
|
void watch_peripherals_register_battery_controller_status_change_cb(BatteryControllerStatusChangeCb_t BatteryStatusChangeCb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads and returns the current battery voltage in mV or it's corresponding capacity in percentage.
|
* @brief Reads and returns the current battery voltage in mV or it's corresponding capacity in percentage.
|
||||||
* This function takes into account the adcOffset parameter provided in the @ref watch_peripherals_init
|
* This function takes into account the adcOffset parameter provided in the @ref watch_peripherals_init
|
||||||
@ -50,9 +68,9 @@ uint8_t battery_voltage_to_percentage(uint16_t voltage_in_mV);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the current battery controller IC status.
|
* @brief Returns the current battery controller IC status.
|
||||||
* It can be one of the following
|
* It can be one of the following :
|
||||||
*
|
*
|
||||||
* @return battery_controller_status_e
|
* @return battery_controller_status_e BATTERY_CHARGING, BATTERY_CHARGED, BATTERY_DISCHARGING and BATTERY_ERROR.
|
||||||
*/
|
*/
|
||||||
battery_controller_status_e watch_peripherals_get_battery_controller_status(void);
|
battery_controller_status_e watch_peripherals_get_battery_controller_status(void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user