Files
VesiScan-Basic-firmware-test/project/ble_peripheral/ble_app_bladder_patch/power_control.c
jhChun a0c96c6677 maa samples 140->100 변경, mec/maa 수신 시 Piezo 자동 Active/Sleep
- MAA_NUM_SAMPLES 140에서 100으로 변경 (DR_ADC_ECHO_SAMPLES_MAX 제한)
- 단일(mec) 및 모든 채널(maa) 에코 캡처 명령 수신 시 Piezo 자동 Active, 응답 송신 후 Sleep
- Cmd_mpa 중복 호출 정리 (dr_piezo_system_init 내부에 power_on 포함)
- 채널별 디버그 로그 추가
- 코드 리뷰 주석 정리 및 기타 파일 업데이트

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:03:04 +09:00

261 lines
8.1 KiB
C

/*******************************************************************************
TEST medi50 Dec 23
//=========power_control.c====================
*******************************************************************************
*
* [모듈 개요]
* 디바이스 전원 시퀀스를 관리하는 모듈 (전원 켜기 / 끄기 / 슬립).
*
* [전원 켜기 흐름]
* device_activated()
* → p_order=0으로 초기화, power_loop 타이머 시작
* → power_loop() 상태머신이 20ms 간격으로 Step 0→1→2 순서대로 실행
* - Step 0: I2C 초기화 (sw_i2c_init_once)
* - Step 1: 예약 (현재 미사용)
* - Step 2: 전원 시퀀스 완료
*
* [슬립 모드]
* device_sleep_mode()
* → EEPROM OFF → processing 플래그 해제
*
* [재활성화]
* device_reactivated()
* → I2C 재초기화 후 전원 시퀀스를 처음부터 다시 시작
*
* [EEPROM 쓰기 보호 핀]
* EEP_WP = P0.24 (레거시, 현재는 FDS를 사용하므로 실질적으로 미사용)
*
* [타이머]
* 싱글샷 모드 app_timer, 20ms 간격으로 power_loop 호출
*
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "power_control.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "app_timer.h"
#include "debug_print.h"
#include "i2c_manager.h"
/* EEPROM 쓰기 보호 핀 (P0.24) - 레거시, 현재는 FDS 사용 */
#define EEP_WP NRF_GPIO_PIN_MAP(0, 24)
/* 전원 시퀀스용 싱글샷 타이머 인스턴스 */
APP_TIMER_DEF(m_power_timer_id);
/* 전원 시퀀스 상태머신의 타이머 간격 (20ms) */
// 2025-12-08 change to #define POWER_LOOP_INTERVAL 30 -> 20
#define POWER_LOOP_INTERVAL 20
/* 전원 시퀀스 현재 단계 (0: I2C 초기화, 1: 예약, 2: 완료) */
static uint8_t p_order;
/* 데이터 처리 중 플래그 (외부 모듈에서 선언) */
extern volatile bool processing;
/* 전원 시퀀스 잠금 플래그 (true = 전원 시퀀스 진행 중) */
bool lock_check = false;
/**
* @brief 전원 관련 GPIO 핀 초기화
*
* EEP_WP 핀을 출력 모드로 설정한다.
*/
void power_gpio_init(void)
{
nrf_gpio_cfg_output(EEP_WP);
}
/**
* @brief EEPROM 전원 제어 (ON/OFF)
*
* @param eeprom_st ON: EEP_WP 핀 HIGH (쓰기 허용), OFF: LOW (쓰기 보호)
* 레거시 기능으로, 현재는 FDS(Flash Data Storage)를 사용하여 실질적으로 미사용.
*/
void eeprom_control(on_off_cont_t eeprom_st)
{
if(eeprom_st == OFF) {
nrf_gpio_pin_clear(EEP_WP); /* LOW: EEPROM 쓰기 보호 활성화 */
}else if(eeprom_st == ON){
nrf_gpio_pin_set(EEP_WP); /* HIGH: EEPROM 쓰기 허용 */
}
}
/**
* @brief 디바이스 슬립 모드 진입
*
* EEPROM을 OFF하고, 데이터 처리 플래그(processing)를 해제하여
* 메인 루프가 더 이상 센서 데이터를 처리하지 않도록 한다.
*
* @return 0 (항상 성공)
*/
int device_sleep_mode(void){
int rc = 0;
eeprom_control(OFF); /* EEPROM 쓰기 보호 활성화 */
nrf_delay_ms(2);
DBG_PRINTF("Device_Sleep_Mode OK!\r\n");
nrf_delay_ms(10);
processing = false; /* 데이터 처리 플래그 해제 → 센서 처리 중단 */
return rc;
}
/**
* @brief 디바이스 전원 켜기 (전원 시퀀스 시작)
*
* 전원 시퀀스 단계를 0으로 초기화하고, 잠금 플래그를 설정한 뒤
* 타이머를 시작하여 power_loop() 상태머신을 구동한다.
* EEPROM은 OFF 상태로 시작한다.
*
* @return 0 (항상 성공)
*/
int device_activated(void){
int rc = 0;
p_order = 0; /* 상태머신 시작 단계 (Step 0: I2C 초기화) */
lock_check =true; /* 전원 시퀀스 진행 중 잠금 */
power_timer_start(); /* 20ms 후 power_loop() 첫 호출 */
eeprom_control(OFF); /* EEPROM OFF 상태로 시작 */
return rc;
}
/**
* @brief Power-up sequence state machine
*
* Executes hardware initialization steps
* Called by app_timer at POWER_LOOP_INTERVAL (20ms)
*
* Sequence:
* 0: I2C init
* 1: (reserved)
* 2: Complete
*/
/*
* 전원 시퀀스 상태머신 (20ms 싱글샷 타이머 콜백).
*
* [실행 흐름]
* 1) 타이머 콜백 진입 → 타이머 정지 (싱글샷이므로)
* 2) 현재 p_order에 해당하는 초기화 단계 실행
* 3) p_order < 2이면 다음 단계로 진행하고 타이머 재시작
* 4) p_order == 2이면 전원 시퀀스 완료
*
* [DEBUG_MINIMAL_BOOT 모드]
* 센서 초기화를 건너뛰고 즉시 완료 단계(Step 2)로 점프
*/
void power_loop(void *p_context)
{
UNUSED_PARAMETER(p_context);
power_timer_stop(); /* 현재 타이머 정지 (싱글샷 → 수동 재시작 필요) */
#if DEBUG_MINIMAL_BOOT
/* Minimal Boot: Skip sensor initialization */
/* 미니멀 부트 모드: 센서 초기화 생략하고 바로 완료 */
DBG_PRINTF("[PWR] Minimal mode - skipping sensor init\r\n");
p_order = 2; // Jump to complete
#else
/* Full Boot: Execute power sequence */
/* 풀 부트 모드: 전원 시퀀스 단계별 실행 */
switch (p_order) {
/* Step 0: I2C Initialize */
/* 단계 0: I2C 버스를 SW 모드로 초기화 (레거시 흐름) */
case 0:
sw_i2c_init_once(); /* SW I2C 초기화 (TWI 해제 → 비트뱅 모드) */
nrf_delay_ms(10); /* I2C 버스 안정화 대기 */
DBG_PRINTF("[PWR] Step %d: I2C Init\r\n", p_order);
break;
/* Step 1: Reserved */
/* 단계 1: 예약 (추후 센서 초기화 등 추가 가능) */
case 1:
DBG_PRINTF("[PWR] Step %d: (reserved)\r\n", p_order);
break;
/* Step 2: Complete */
/* 단계 2: 전원 시퀀스 완료 → 디바이스 사용 준비 완료 */
case 2:
DBG_PRINTF("[PWR] Step %d: Sequence Complete\r\n", p_order);
break;
default:
break;
}
#endif
/* Advance to next step or finish */
/* 다음 단계로 진행하거나, 시퀀스 완료 처리 */
if (p_order < 2) {
p_order++; /* 다음 단계로 이동 */
power_timer_start(); /* 20ms 후 다음 단계 실행 */
} else {
/* 전원 시퀀스 전체 완료 */
DBG_PRINTF("[PWR] Device Activated OK!\r\n");
}
}
/**
* @brief 디바이스 재활성화 (슬립 복귀 시)
*
* I2C를 재초기화하고, 전원 시퀀스를 처음부터 다시 시작한다.
* 슬립 모드에서 깨어날 때 호출된다.
*
* @return 0 (항상 성공)
*/
int device_reactivated(void){
int rc = 0;
sw_i2c_init_once(); /* I2C 버스 재초기화 */
nrf_delay_ms(10); /* 안정화 대기 */
lock_check = true; /* 전원 시퀀스 진행 중 잠금 */
p_order = 0; /* 상태머신을 Step 0부터 재시작 */
power_timer_start(); /* 20ms 후 power_loop() 시작 */
return rc;
}
/**
* @brief 전원 시퀀스 타이머 시작
*
* 싱글샷 모드로 POWER_LOOP_INTERVAL(20ms) 후 power_loop()를 호출한다.
*/
void power_timer_start(void)
{
APP_ERROR_CHECK(app_timer_start(m_power_timer_id, APP_TIMER_TICKS(POWER_LOOP_INTERVAL), NULL));
}
/**
* @brief 전원 시퀀스 타이머 정지
*/
void power_timer_stop(void)
{
APP_ERROR_CHECK(app_timer_stop(m_power_timer_id));
}
/**
* @brief 전원 시퀀스 타이머 초기화 (앱 시작 시 1회 호출)
*
* 싱글샷 모드 타이머를 생성하고, 콜백으로 power_loop()를 등록한다.
* 싱글샷이므로 매 단계마다 power_timer_start()로 수동 재시작해야 한다.
*/
void power_timer_init(void) //active start
{
APP_ERROR_CHECK(app_timer_create(&m_power_timer_id, APP_TIMER_MODE_SINGLE_SHOT, power_loop));
// 2025-12-08 change to APP_TIMER_MODE_REPEATED mode
//APP_ERROR_CHECK(app_timer_create(&m_power_timer_id, APP_TIMER_MODE_REPEATED, power_loop));
}