292 lines
9.3 KiB
C
292 lines
9.3 KiB
C
/*******************************************************************************
|
|
* @file power_ctrl.c
|
|
* @brief Power Management and Control Functions
|
|
* @author Charles KWON <charleskwon@medithings.co.kr>
|
|
* @date 2025-01-30
|
|
* @copyright (c) 2025 Medithings Inc. All rights reserved.
|
|
*
|
|
* @details Power on/off control, sleep mode, button state machine.
|
|
******************************************************************************/
|
|
|
|
#include "sdk_config.h"
|
|
#include "power_ctrl.h"
|
|
#include "ble_core.h"
|
|
#include "nrf_gpio.h"
|
|
#include "nrf_delay.h"
|
|
#include "app_timer.h"
|
|
#include "app_error.h"
|
|
#include "bsp.h"
|
|
#include "bsp_btn_ble.h"
|
|
#include "ble_advertising.h"
|
|
#include "debug_print.h"
|
|
#include "main.h"
|
|
#include "main_timer.h"
|
|
#include "battery_saadc.h"
|
|
#include "power_control.h"
|
|
#include "measurements.h"
|
|
#include "cat_interface.h"
|
|
#include <cmd_parse.h>
|
|
#include "app_raw_main.h"
|
|
#include "ada2200_spi.h"
|
|
#include "mcp4725_i2c.h"
|
|
#include "storage/dr_mem.h"
|
|
#include "fstorage.h"
|
|
|
|
/*==============================================================================
|
|
* EXTERNAL DECLARATIONS
|
|
*============================================================================*/
|
|
|
|
extern uint16_t m_conn_handle;
|
|
extern bool bond_data_delete;
|
|
extern bool erase_bonds;
|
|
extern volatile bool ble_connection_st;
|
|
|
|
/* Functions from ble_core module - declared in ble_core.h */
|
|
|
|
/*==============================================================================
|
|
* GLOBAL VARIABLES
|
|
*============================================================================*/
|
|
|
|
volatile bool processing = false;
|
|
volatile bool power_state = false;
|
|
bool power_off_duble_prohibit = false;
|
|
bool device_status = false;
|
|
bool device_reset = true;
|
|
uint16_t cnt_s = 0;
|
|
uint8_t m_reset_status = 0;
|
|
|
|
bool go_device_power_off = false;
|
|
bool go_sleep_mode_enter = false;
|
|
bool go_NVIC_SystemReset = false;
|
|
|
|
/*==============================================================================
|
|
* TIMER INSTANCES
|
|
*============================================================================*/
|
|
|
|
APP_TIMER_DEF(m_power_on_delay_timer_id);
|
|
APP_TIMER_DEF(m_power_off_delay_timer_id);
|
|
APP_TIMER_DEF(m_PM_timer_id);
|
|
|
|
/*==============================================================================
|
|
* TIMER INITIALIZATION
|
|
*============================================================================*/
|
|
|
|
void power_ctrl_timers_init(void)
|
|
{
|
|
APP_ERROR_CHECK(app_timer_create(&m_power_on_delay_timer_id,
|
|
APP_TIMER_MODE_SINGLE_SHOT,
|
|
power_button_handler));
|
|
APP_ERROR_CHECK(app_timer_create(&m_power_off_delay_timer_id,
|
|
APP_TIMER_MODE_SINGLE_SHOT,
|
|
power_off_timeout_handler));
|
|
APP_ERROR_CHECK(app_timer_create(&m_PM_timer_id,
|
|
APP_TIMER_MODE_SINGLE_SHOT,
|
|
pm_timeout_handler));
|
|
}
|
|
|
|
void power_ctrl_timers_start(void)
|
|
{
|
|
ret_code_t err_code;
|
|
err_code = app_timer_start(m_power_on_delay_timer_id,
|
|
APP_TIMER_TICKS(POWER_ON_DELAY), NULL);
|
|
APP_ERROR_CHECK(err_code);
|
|
}
|
|
|
|
/*==============================================================================
|
|
* POWER CONTROL FUNCTIONS
|
|
*============================================================================*/
|
|
|
|
void power_control_set(on_off_cont_t device_power_st)
|
|
{
|
|
if (device_power_st == OFF) {
|
|
nrf_gpio_pin_clear(POWER_HOLD);
|
|
DBG_PRINTF("Main Power OFF\r\n");
|
|
} else if (device_power_st == ON) {
|
|
nrf_gpio_pin_set(POWER_HOLD);
|
|
DBG_PRINTF("Main Power ON\r\n");
|
|
}
|
|
}
|
|
|
|
void device_power_off(void)
|
|
{
|
|
uint32_t err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_ON);
|
|
APP_ERROR_CHECK(err_code);
|
|
APP_ERROR_CHECK(app_timer_start(m_power_off_delay_timer_id,
|
|
APP_TIMER_TICKS(POWER_OFF_DELAY), NULL));
|
|
}
|
|
|
|
void sleep_mode_enter(void)
|
|
{
|
|
uint32_t err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_ON);
|
|
APP_ERROR_CHECK(err_code);
|
|
DBG_PRINTF("go Sleep!\r\n");
|
|
|
|
APP_ERROR_CHECK(app_timer_start(m_power_off_delay_timer_id,
|
|
APP_TIMER_TICKS(POWER_OFF_DELAY), NULL));
|
|
}
|
|
|
|
/*==============================================================================
|
|
* TIMER CALLBACKS
|
|
*============================================================================*/
|
|
|
|
void power_off_timeout_handler(void * p_context)
|
|
{
|
|
UNUSED_PARAMETER(p_context);
|
|
APP_ERROR_CHECK(app_timer_stop(m_power_off_delay_timer_id));
|
|
DBG_PRINTF("Off stop\r\n");
|
|
|
|
uint32_t err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_OFF);
|
|
APP_ERROR_CHECK(err_code);
|
|
power_control_set(OFF);
|
|
}
|
|
|
|
void pm_timeout_handler(void * p_context)
|
|
{
|
|
UNUSED_PARAMETER(p_context);
|
|
APP_ERROR_CHECK(app_timer_stop(m_PM_timer_id));
|
|
|
|
if (m_reset_status == 5) {
|
|
DBG_PRINTF("kill\r\n");
|
|
disconnect(m_conn_handle, NULL);
|
|
}
|
|
}
|
|
|
|
/*==============================================================================
|
|
* POWER BUTTON STATE MACHINE
|
|
*============================================================================*/
|
|
|
|
void power_button_handler(void * p_context)
|
|
{
|
|
UNUSED_PARAMETER(p_context);
|
|
APP_ERROR_CHECK(app_timer_stop(m_power_on_delay_timer_id));
|
|
|
|
if (nrf_gpio_pin_read(POWER_BUTTON)) {
|
|
/* Button released - determine action based on press duration */
|
|
if ((cnt_s < 150) && (m_reset_status != 2)) {
|
|
/* Short press - power off */
|
|
uint32_t err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_OFF);
|
|
(void)err_code;
|
|
power_control_set(OFF);
|
|
cnt_s = 0;
|
|
}
|
|
else if (cnt_s > 1000) {
|
|
/* Very long press - factory reset */
|
|
power_control_set(ON);
|
|
nrf_delay_ms(100);
|
|
bond_data_delete = true;
|
|
/* Factory reset: save defaults to FDS */
|
|
{
|
|
uint8_t bd = (uint8_t)bond_data_delete;
|
|
dr_memWrite("bond_delete", &bd, 1);
|
|
|
|
const char pass_init[6] = "123456";
|
|
dr_memWrite("passkey", (uint8_t *)pass_init, 6);
|
|
}
|
|
nrf_delay_ms(1000);
|
|
|
|
go_device_power_off = true;
|
|
main_timer_start();
|
|
}
|
|
else if (cnt_s > 150 || (m_reset_status == 2)) {
|
|
/* Long press - normal startup */
|
|
device_reset = false;
|
|
DBG_PRINTF("\r\n\r\n/////////////////////////////////\r\n");
|
|
DBG_PRINTF("MEDiThings VivaMayo Started 1.12C\r\n");
|
|
DBG_PRINTF("/////////////////////////////////\r\n");
|
|
|
|
power_control_set(ON);
|
|
battery_timer_start();
|
|
|
|
icm42670_init();
|
|
nrf_delay_ms(2);
|
|
|
|
DBG_PRINTF("ADV_START\r\n");
|
|
#if FEATURE_SECURE_CONNECTION
|
|
advertising_start(erase_bonds);
|
|
#else
|
|
advertising_start();
|
|
#endif
|
|
DBG_PRINTF("ADV_DONE\r\n");
|
|
|
|
ada2200_init();
|
|
nrf_delay_ms(1);
|
|
mcp4725_init();
|
|
nrf_delay_ms(1);
|
|
|
|
/* Set reset status in RAM only (no FDS write during boot) */
|
|
m_reset_status = 1;
|
|
m_config.reset_status = 1;
|
|
LOG_PRINTF("START\r\n");
|
|
|
|
/* W25Q32 Flash test - disabled, use cmd?99,0,0 manually */
|
|
// w25q_test_timer_start();
|
|
}
|
|
} else {
|
|
/* Button still pressed - increment counter and continue polling */
|
|
cnt_s++;
|
|
device_reset = false;
|
|
|
|
if (cnt_s == 150) {
|
|
/* Indicate long press threshold reached */
|
|
uint32_t err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_ON);
|
|
(void)err_code;
|
|
}
|
|
power_ctrl_timers_start();
|
|
}
|
|
}
|
|
|
|
/*==============================================================================
|
|
* BSP EVENT HANDLER
|
|
*============================================================================*/
|
|
|
|
void power_bsp_event_handler(bsp_event_t event)
|
|
{
|
|
uint32_t err_code;
|
|
|
|
switch (event)
|
|
{
|
|
case BSP_EVENT_SLEEP:
|
|
go_sleep_mode_enter = true;
|
|
DBG_PRINTF("BSP_EVENT_sleep\r\n");
|
|
main_timer_start();
|
|
break;
|
|
|
|
case BSP_EVENT_DISCONNECT:
|
|
err_code = sd_ble_gap_disconnect(m_conn_handle,
|
|
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
|
if (err_code != NRF_SUCCESS) {
|
|
m_reset_status = 2;
|
|
} else {
|
|
DBG_PRINTF("Disconnected connection handle %d\r\n", m_conn_handle);
|
|
}
|
|
break;
|
|
|
|
case BSP_EVENT_WHITELIST_OFF:
|
|
if (m_conn_handle == BLE_CONN_HANDLE_INVALID) {
|
|
err_code = ble_advertising_restart_without_whitelist_wrapper();
|
|
if (err_code != NRF_ERROR_INVALID_STATE) {
|
|
APP_ERROR_CHECK(err_code);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BSP_EVENT_KEY_2:
|
|
break;
|
|
|
|
case BSP_EVENT_POWER_CONTROL:
|
|
if (processing == false) {
|
|
DBG_PRINTF("SYSTEM OFF\r\n");
|
|
err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_ON);
|
|
APP_ERROR_CHECK(err_code);
|
|
go_device_power_off = true;
|
|
main_timer_start();
|
|
} else {
|
|
DBG_PRINTF("SYSTEM OFF FAIL\r\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|