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