코드 정리

- 주석 영문으로 변경
- Allman 스타일로 통일
This commit is contained in:
2026-04-16 12:01:51 +09:00
parent c98d9ae14e
commit 2861cb9815
35 changed files with 2406 additions and 2557 deletions

View File

@@ -1,32 +1,32 @@
// file: debug_print.h
/*******************************************************************************
* [한국어 설명] 디버그 출력 매크로 (조건부 컴파일)
* Debug print macros (conditional compilation)
*
* SEGGER RTT(Real Time Transfer)를 이용한 디버그 출력 매크로.
* J-Link 디버거를 통해 실시간으로 로그를 PC에 전송한다.
* UART를 사용하지 않으므로 시스템 타이밍에 미치는 영향이 적다.
* Debug output macros using SEGGER RTT (Real Time Transfer).
* Sends logs to the PC in real time via J-Link debugger.
* Minimal impact on system timing since UART is not used.
*
* === 조건부 컴파일 ===
* ENABLE_PRINTF = 1: DBG_PRINTF SEGGER_RTT_printf(채널0)로 치환됨
* -> 실제 로그 출력 (디버깅 시 사용)
* ENABLE_PRINTF = 0: DBG_PRINTF가 빈 매크로로 치환됨
* -> 코드에서 완전히 제거 (릴리스 빌드 시 사용)
* === Conditional compilation ===
* ENABLE_PRINTF = 1: DBG_PRINTF maps to SEGGER_RTT_printf (channel 0)
* -> Actual log output (for debugging)
* ENABLE_PRINTF = 0: DBG_PRINTF maps to an empty macro
* -> Completely removed from code (for release builds)
*
* === 사용법 ===
* DBG_PRINTF(": %d\r\n", value); // printf와 동일한 포맷 문자열
* 출력은 SEGGER RTT Viewer 또는 J-Link RTT Client에서 확인.
* === Usage ===
* DBG_PRINTF("val: %d\r\n", value); // Same format string as printf
* View output in SEGGER RTT Viewer or J-Link RTT Client.
******************************************************************************/
#ifndef DEBUG_PRINT_H
#define DEBUG_PRINT_H
#define ENABLE_PRINTF 1 /* 1=디버그 출력 활성화, 0=전역 비활성화 */
#define ENABLE_PRINTF 1 /* 1=Enable debug output, 0=Disable globally */
#if ENABLE_PRINTF
#include "SEGGER_RTT.h"
/* SEGGER RTT 채널 0으로 포맷 문자열 출력 */
/* Print formatted string to SEGGER RTT channel 0 */
#define DBG_PRINTF(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#else
/* 빈 매크로: 컴파일러가 호출 코드를 완전히 제거 */
/* Empty macro: compiler removes all call-site code */
#define DBG_PRINTF(...) // Do nothing
#endif

View File

@@ -1,11 +1,11 @@
/*******************************************************************************
* @file led_control.c
* @brief LED 직접 제어 드라이버 (BSP 미사용)
* @brief Direct LED control driver (no BSP)
* @date 2026-03-30
*
* app_timer 1개로 2색 LED(녹색/주황)의 복합 blink 패턴 구현
* 단순 on/off 상태는 타이머 없이 즉시 GPIO 제어
* 복합 패턴(에러 등)은 phase 기반 state machine으로 처리
* Implements dual-color LED (green/orange) blink patterns with a single app_timer.
* Simple on/off states use immediate GPIO control without a timer.
* Complex patterns (e.g. error) are handled by a phase-based state machine.
******************************************************************************/
#include "led_control.h"
@@ -13,20 +13,20 @@
#include "app_timer.h"
/*==============================================================================
* 내부 상수
* Internal constants
*============================================================================*/
#define MS_TO_TICKS(ms) APP_TIMER_TICKS(ms)
/*==============================================================================
* 색상
* Colors
*============================================================================*/
#define COLOR_NONE 0
#define COLOR_GREEN 1
#define COLOR_ORANGE 2
/*==============================================================================
* 에러 패턴 상수 (No.7)
* 3Hz 깜빡 3회 = 166ms on + 166ms off × 3 = ~1, 이후 꺼짐 1
* Error pattern constants (No.7)
* 3Hz blink x3 = 166ms on + 166ms off x 3 = ~1s, then off for 1s
*============================================================================*/
#define ERROR_BLINK_ON_MS 166
#define ERROR_BLINK_OFF_MS 166
@@ -34,42 +34,42 @@
#define ERROR_PAUSE_MS 1000
/*==============================================================================
* 패턴 테이블 (단순 blink)
* Pattern table (for simple blink)
*============================================================================*/
typedef struct
{
uint32_t on_ms; /* LED 켜짐 시간 (ms) */
uint32_t off_ms; /* LED 꺼짐 시간 (ms) */
uint8_t color; /* COLOR_GREEN 또는 COLOR_ORANGE */
bool repeat; /* true: 무한 반복, false: 1회 후 OFF */
uint32_t on_ms; /* LED on duration (ms) */
uint32_t off_ms; /* LED off duration (ms) */
uint8_t color; /* COLOR_GREEN or COLOR_ORANGE */
bool repeat; /* true: repeat forever, false: once then OFF */
} led_pattern_t;
static const led_pattern_t m_patterns[LED_STATE_COUNT] =
{
[LED_STATE_OFF] = { 0, 0, COLOR_NONE, false },
[LED_STATE_POWER_ON] = { 2000, 0, COLOR_GREEN, false }, /* 초록 점등 2초 → 유지 */
[LED_STATE_POWER_OFF] = { 2000, 0, COLOR_GREEN, false }, /* 초록 점등 2초 → OFF */
[LED_STATE_ADVERTISING] = { 500, 500, COLOR_GREEN, true }, /* 초록 점멸 1초 */
[LED_STATE_DETACH_WARNING] = { 1000, 3000, COLOR_GREEN, true }, /* 초록 1 on / 3 off */
[LED_STATE_ALIGN_SEARCHING] = { 1000, 1000, COLOR_ORANGE, true }, /* 주황 점멸 1초 */
[LED_STATE_ALIGN_COMPLETE] = { 3000, 1000, COLOR_GREEN, true }, /* 초록 3 on / 1 off */
[LED_STATE_ERROR] = { 0, 0, COLOR_ORANGE, true } /* 별도 state machine */
[LED_STATE_POWER_ON] = { 2000, 0, COLOR_GREEN, false }, /* Green on 2s, stay on */
[LED_STATE_POWER_OFF] = { 2000, 0, COLOR_GREEN, false }, /* Green on 2s, then OFF */
[LED_STATE_ADVERTISING] = { 500, 500, COLOR_GREEN, true }, /* Green blink 1s interval */
[LED_STATE_DETACH_WARNING] = { 1000, 3000, COLOR_GREEN, true }, /* Green 1s on / 3s off */
[LED_STATE_ALIGN_SEARCHING] = { 1000, 1000, COLOR_ORANGE, true }, /* Orange blink 1s interval */
[LED_STATE_ALIGN_COMPLETE] = { 3000, 1000, COLOR_GREEN, true }, /* Green 3s on / 1s off */
[LED_STATE_ERROR] = { 0, 0, COLOR_ORANGE, true } /* Separate state machine */
};
/*==============================================================================
* 모듈 변수
* Module variables
*============================================================================*/
APP_TIMER_DEF(m_led_timer);
static led_state_t m_current_state = LED_STATE_OFF;
static bool m_phase_on; /* true: LED 켜진 구간, false: 꺼진 구간 */
static bool m_phase_on; /* true: LED on phase, false: off phase */
/* 에러 패턴 전용 */
static uint8_t m_error_blink_cnt; /* 현재까지 깜빡인 횟수 */
/* Error pattern only */
static uint8_t m_error_blink_cnt; /* Blink count so far */
static uint8_t m_error_phase; /* 0: blink-on, 1: blink-off, 2: pause */
/*==============================================================================
* GPIO 헬퍼
* GPIO helpers
*============================================================================*/
static inline void led_green_on(void)
@@ -122,7 +122,7 @@ static void led_color_on(uint8_t color)
}
/*==============================================================================
* 타이머 시작 헬퍼
* Timer start helper
*============================================================================*/
static void timer_start_ms(uint32_t ms)
{
@@ -131,7 +131,7 @@ static void timer_start_ms(uint32_t ms)
}
/*==============================================================================
* 에러 패턴 state machine (No.7)
* Error pattern state machine (No.7)
* phase 0: LED ON (166ms) → phase 1
* phase 1: LED OFF (166ms) → cnt++ → cnt<3 ? phase 0 : phase 2
* phase 2: PAUSE (1000ms) → cnt=0, phase 0
@@ -148,30 +148,30 @@ static void error_pattern_tick(void)
{
switch (m_error_phase)
{
case 0: /* ON 구간 끝 → OFF */
case 0: /* ON phase done -> OFF */
led_all_off();
m_error_phase = 1;
timer_start_ms(ERROR_BLINK_OFF_MS);
break;
case 1: /* OFF 구간 끝 */
case 1: /* OFF phase done */
m_error_blink_cnt++;
if (m_error_blink_cnt < ERROR_BLINK_COUNT)
{
/* 다시 ON */
/* Back to ON */
m_error_phase = 0;
led_color_on(COLOR_ORANGE);
timer_start_ms(ERROR_BLINK_ON_MS);
}
else
{
/* 3회 완료 → pause */
/* 3 blinks done -> pause */
m_error_phase = 2;
timer_start_ms(ERROR_PAUSE_MS);
}
break;
case 2: /* pause 끝 → 처음부터 */
case 2: /* Pause done -> restart */
m_error_blink_cnt = 0;
m_error_phase = 0;
led_color_on(COLOR_ORANGE);
@@ -184,13 +184,13 @@ static void error_pattern_tick(void)
}
/*==============================================================================
* 타이머 콜백
* Timer callback
*============================================================================*/
static void led_timer_handler(void * p_context)
{
(void)p_context;
/* 에러 상태는 별도 처리 */
/* Error state handled separately */
if (m_current_state == LED_STATE_ERROR)
{
error_pattern_tick();
@@ -201,7 +201,7 @@ static void led_timer_handler(void * p_context)
if (m_phase_on)
{
/* ON→OFF 전환 */
/* ON -> OFF transition */
led_all_off();
m_phase_on = false;
@@ -211,40 +211,40 @@ static void led_timer_handler(void * p_context)
}
else if (!p->repeat)
{
/* 1회성: off_ms == 0 이면 그냥 유지 (POWER_ON) 또는 끄기 (POWER_OFF) */
/* One-shot: if off_ms == 0, stay on (POWER_ON) or turn off (POWER_OFF) */
if (m_current_state == LED_STATE_POWER_OFF)
{
led_all_off();
m_current_state = LED_STATE_OFF;
}
/* POWER_ON: 점등 유지 상태 → 타이머 x */
/* POWER_ON: stay lit, no timer */
}
}
else
{
/* OFF ON 전환 */
/* OFF -> ON transition */
if (p->repeat)
{
led_color_on(p->color);
m_phase_on = true;
timer_start_ms(p->on_ms);
}
/* repeat == false && off_ms > 0 인 경우는 현재 없음 */
/* No current case where repeat == false && off_ms > 0 */
}
}
/*==============================================================================
* 공개 함수
* Public functions
*============================================================================*/
void led_init(void)
{
/* GPIO 출력 설정 */
/* Configure GPIO outputs */
nrf_gpio_cfg_output(LED_PIN_GREEN);
nrf_gpio_cfg_output(LED_PIN_ORANGE);
led_all_off();
/* 타이머 생성 (single-shot) */
/* Create timer (single-shot) */
app_timer_create(&m_led_timer, APP_TIMER_MODE_SINGLE_SHOT, led_timer_handler);
m_current_state = LED_STATE_OFF;
@@ -254,7 +254,7 @@ void led_set_state(led_state_t state)
{
if (state >= LED_STATE_COUNT) return;
/* 이전 패턴 중단 */
/* Stop previous pattern */
app_timer_stop(m_led_timer);
led_all_off();
@@ -266,15 +266,15 @@ void led_set_state(led_state_t state)
switch (state)
{
case LED_STATE_OFF:
/* 이미 all off */
/* Already all off */
break;
/* 에러 패턴: 별도 state machine */
/* Error pattern: separate state machine */
case LED_STATE_ERROR:
error_pattern_start();
break;
/* 그 외: on 구간부터 시작 */
/* All others: start from ON phase */
default:
led_color_on(p->color);
m_phase_on = true;

View File

@@ -1,10 +1,10 @@
/*******************************************************************************
* @file led_control.h
* @brief LED 직접 제어 드라이버 (BSP 미사용)
* @brief Direct LED control driver (no BSP)
* @date 2026-03-30
*
* 녹색(P0.12) + 주황(P0.29) 2색 LED를 app_timer 기반으로 제어
* 각 상태별 on/off 시간, 색상, 반복 패턴을 테이블로 관리
* Controls dual-color LED green(P0.12) + orange(P0.29) via app_timer.
* On/off timing, color, and repeat pattern managed per state in a table.
******************************************************************************/
#ifndef LED_CONTROL_H__
@@ -14,39 +14,39 @@
#include <stdbool.h>
/*==============================================================================
* LED 핀 정의
* LED pin definitions
*============================================================================*/
#define LED_PIN_GREEN NRF_GPIO_PIN_MAP(0, 12) /* 녹색 LED */
#define LED_PIN_ORANGE NRF_GPIO_PIN_MAP(0, 29) /* 주황 LED */
#define LED_ACTIVE_LOW 1 /* 1 = Active Low (GPIO LOW에서 LED 켜짐) */
#define LED_PIN_GREEN NRF_GPIO_PIN_MAP(0, 12) /* Green LED */
#define LED_PIN_ORANGE NRF_GPIO_PIN_MAP(0, 29) /* Orange LED */
#define LED_ACTIVE_LOW 1 /* 1 = Active Low (LED on when GPIO LOW) */
/*==============================================================================
* LED 상태 열거형
* LED state enumeration
*============================================================================*/
typedef enum
{
LED_STATE_OFF = 0, /* 모든 LED 소등 */
LED_STATE_POWER_ON, /* 1: 전원 ON - 초록 소등 → 녹색 점등 2 */
LED_STATE_POWER_OFF, /* 2: 전원 OFF - 초록 점등 2초 → 소등 */
LED_STATE_ADVERTISING, /* 3: 블루투스 스캐닝 - 초록 점멸 1초 간격(반복) */
LED_STATE_DETACH_WARNING, /* 4: 정상 작동중(미부착 시) - 초록 점등 1초 / 소등 3초 (반복) */
LED_STATE_ALIGN_SEARCHING, /* 5: 정렬모드(탐지중) - 주황 점멸 1초 간격 (반복) */
LED_STATE_ALIGN_COMPLETE, /* 6: 정렬모드(탐지 완료) - 초록 점등 3초 / 소등 1초 */
LED_STATE_ERROR, /* 7: 오류 발생 - 주황 3Hz 깜빡 3회 / 꺼짐 1 (반복) */
LED_STATE_COUNT /* 배열 크기 */
LED_STATE_OFF = 0, /* All LEDs off */
LED_STATE_POWER_ON, /* 1: Power ON - green on 2s */
LED_STATE_POWER_OFF, /* 2: Power OFF - green on 2s then off */
LED_STATE_ADVERTISING, /* 3: BLE advertising - green blink 1s interval (repeat) */
LED_STATE_DETACH_WARNING, /* 4: Normal operation (detached) - green 1s on / 3s off (repeat) */
LED_STATE_ALIGN_SEARCHING, /* 5: Alignment mode (searching) - orange blink 1s interval (repeat) */
LED_STATE_ALIGN_COMPLETE, /* 6: Alignment mode (complete) - green 3s on / 1s off */
LED_STATE_ERROR, /* 7: Error - orange 3Hz blink x3 / off 1s (repeat) */
LED_STATE_COUNT /* Array size */
} led_state_t;
/*==============================================================================
* 공개 함수
* Public functions
*============================================================================*/
/** @brief LED GPIO 초기화 + 타이머 생성 - main()에서 1회 호출 */
/** @brief Initialize LED GPIO + create timer - call once from main() */
void led_init(void);
/** @brief LED 상태 변경 - 이전 패턴을 즉시 중단하고 새 패턴 시작 */
/** @brief Change LED state - immediately stops previous pattern and starts new one */
void led_set_state(led_state_t state);
/** @brief 현재 LED 상태 조회 */
/** @brief Get current LED state */
led_state_t led_get_state(void);
#endif /* LED_CONTROL_H__ */

View File

@@ -2,30 +2,30 @@
TEST medi50 Dec 23
*******************************************************************************
*
* [모듈 개요]
* 메인 이벤트 루프 타이머 모듈 (10ms 간격, 싱글샷 모드).
* [Module overview]
* Main event loop timer module (10ms interval, single-shot mode).
*
* 센서 데이터 수집 및 시스템 제어 이벤트를 플래그 기반으로 디스패치한다.
* app_timer 싱글샷 모드를 사용하므로, 이벤트 처리 완료 후
* 필요 시 main_timer_start()로 수동 재시작해야 한다.
* Dispatches sensor data collection and system control events via flags.
* Uses app_timer single-shot mode; after processing, call main_timer_start()
* manually to restart if needed.
*
* [이벤트 플래그 및 처리 순서]
* motion_raw_data_enabled IMU 데이터 읽기 (icm42670_main 호출)
* - motion_data_once == true: 단발성 읽기 (HW I2C 초기화 후 1회)
* - motion_data_once == false: 연속 읽기 (BLE 전송 대기 중이 아닐 때)
* go_batt → 배터리 전압 측정 (battery_level_meas)
* go_temp → 온도 측정 (tmp235_voltage_level_meas)
* go_device_power_off → 디바이스 전원 OFF (device_power_off)
* go_sleep_mode_enter → 슬립 모드 진입 (sleep_mode_enter)
* go_NVIC_SystemReset NVIC 시스템 리셋
* [Event flags and processing order]
* motion_raw_data_enabled -> IMU data read (calls icm42670_main)
* - motion_data_once == true: one-shot read (after HW I2C init)
* - motion_data_once == false: continuous read (when not waiting for BLE TX)
* go_batt -> Battery voltage measurement (battery_level_meas)
* go_temp -> Temperature measurement (tmp235_voltage_level_meas)
* go_device_power_off -> Device power OFF (device_power_off)
* go_sleep_mode_enter -> Enter sleep mode (sleep_mode_enter)
* go_NVIC_SystemReset -> NVIC system reset
*
* [info4 모드 측정 순서]
* IMU 연속 읽기 → go_batt(배터리) → go_temp(온도) → motion_data_once(IMU 단발)
* 온도 측정 완료 시 motion_data_once=true로 설정하여 다시 IMU로 돌아간다.
* [info4 mode measurement order]
* IMU continuous read -> go_batt (battery) -> go_temp (temp) -> motion_data_once (IMU one-shot)
* After temperature measurement, motion_data_once=true to return to IMU.
*
* [타이머 설정]
* - 일반 모드: 10ms 간격 (MAIN_LOOP_INTERVAL)
* - FEATURE_DETAIL_VALUE_FULL 모드: 80ms 간격 (디테일 프린트아웃용)
* [Timer settings]
* - Normal mode: 10ms interval (MAIN_LOOP_INTERVAL)
* - FEATURE_DETAIL_VALUE_FULL mode: 80ms interval (for detail printout)
*
******************************************************************************/
@@ -56,16 +56,16 @@
#include "tmp235_q1.h"
//#include "fstorage.h"
#include "power_control.h"
#include "main.h" /* 2026-03-17: cmd_parse.h 삭제 → main.h */
#include "main.h" /* 2026-03-17: cmd_parse.h removed, use main.h */
#include "debug_print.h"
#include "i2c_manager.h" //add cj
/* 메인 루프 싱글샷 타이머 인스턴스 */
/* Main loop single-shot timer instance */
APP_TIMER_DEF(m_main_loop_timer_id);
#if FEATURE_DETAIL_VALUE_FULL
/* 디테일 프린트아웃 모드: 80ms 간격으로 메인 루프 실행 */
#define MAIN_LOOP_INTERVAL 80 /* 디테일 프린트아웃이 있을경우 Full_Mode Main Prosessing 수행하는 타이머 */
/* Detail printout mode: run main loop at 80ms interval */
#define MAIN_LOOP_INTERVAL 80 /* Timer for Full_Mode main processing when detail printout is enabled */
//extern bool pd_adc_full_a_start;
//extern bool pd_adc_full_b_start;
@@ -75,36 +75,36 @@ APP_TIMER_DEF(m_main_loop_timer_id);
extern which_cmd_t cmd_type_t;
#else
/* 일반 모드: 10ms 간격으로 메인 루프 실행 */
/* Normal mode: run main loop at 10ms interval */
#define MAIN_LOOP_INTERVAL 10
#endif
/* ========================================================================== */
/* 이벤트 플래그 (외부 모듈에서 설정, main_loop에서 처리) */
/* Event flags (set by external modules, processed in main_loop) */
/* ========================================================================== */
bool go_batt= false; /* 배터리 측정 요청 플래그 */
bool go_temp= false; /* 온도 측정 요청 플래그 */
bool go_device_power_off = false; /* 디바이스 전원 OFF 요청 플래그 */
bool go_sleep_mode_enter = false; /* 슬립 모드 진입 요청 플래그 */
bool go_NVIC_SystemReset = false; /* 시스템 리셋 요청 플래그 */
bool motion_raw_data_enabled = false; /* IMU 모션 데이터 읽기 활성화 플래그 */
bool ble_got_new_data = false; /* BLE로 새 데이터 전송 완료 여부 */
bool motion_data_once = false; /* IMU 단발성 읽기 모드 (true: 1회만 읽기) */
bool go_batt= false; /* Battery measurement request flag */
bool go_temp= false; /* Temperature measurement request flag */
bool go_device_power_off = false; /* Device power OFF request flag */
bool go_sleep_mode_enter = false; /* Sleep mode entry request flag */
bool go_NVIC_SystemReset = false; /* System reset request flag */
bool motion_raw_data_enabled = false; /* IMU motion data read enable flag */
bool ble_got_new_data = false; /* BLE new data transmission complete */
bool motion_data_once = false; /* IMU one-shot read mode (true: read once) */
/**
* @brief 메인 이벤트 루프 (싱글샷 타이머 콜백)
* @brief Main event loop (single-shot timer callback)
*
* 플래그 기반 이벤트 디스패처로, 설정된 플래그에 따라 해당 처리를 수행한다.
* 싱글샷 타이머이므로 연속 실행이 필요한 경우 처리 내부에서 main_timer_start()
* 다시 호출하여 타이머를 재시작해야 한다.
* Flag-based event dispatcher; processes actions based on set flags.
* Since the timer is single-shot, call main_timer_start() again from
* within the handler to continue execution.
*
* [처리 우선순위] (코드 순서대로 검사)
* 1. IMU 모션 데이터 (motion_raw_data_enabled)
* 2. 배터리 측정 (go_batt)
* 3. 온도 측정 (go_temp)
* 4. 전원 OFF (go_device_power_off)
* 5. 슬립 모드 (go_sleep_mode_enter)
* 6. 시스템 리셋 (go_NVIC_SystemReset)
* [Processing priority] (checked in code order)
* 1. IMU motion data (motion_raw_data_enabled)
* 2. Battery measurement (go_batt)
* 3. Temperature measurement (go_temp)
* 4. Power OFF (go_device_power_off)
* 5. Sleep mode (go_sleep_mode_enter)
* 6. System reset (go_NVIC_SystemReset)
*/
void main_loop(void * p_context) /* For x ms */
{
@@ -140,36 +140,36 @@ void main_loop(void * p_context) /* For x ms */
// For Motion Data Sampling
/* ---- IMU 모션 데이터 읽기 ---- */
/* ---- IMU motion data read ---- */
/*
* motion_raw_data_enabled true이면 IMU(ICM42670P) 데이터를 읽는다.
* If motion_raw_data_enabled is true, read IMU (ICM42670P) data.
*
* motion_data_once == true:
* 단발성 읽기 모드. HW I2C를 초기화한 후 icm42670_main()을 1회 호출.
* info4 모드에서 배터리/온도 측정 후 다시 IMU로 돌아올 때 사용.
* One-shot read mode. Initialize HW I2C then call icm42670_main() once.
* Used in info4 mode to return to IMU after battery/temp measurement.
*
* motion_data_once == false:
* 연속 읽기 모드. BLE 전송 대기 중(ble_got_new_data==false)이면
* icm42670_main()을 호출하고 10ms 후 타이머를 재시작하여 반복 실행.
* Continuous read mode. If not waiting for BLE TX (ble_got_new_data==false),
* call icm42670_main() and restart timer after 10ms for repeated execution.
*/
if(motion_raw_data_enabled == true) {
main_timer_stop(); /* 타이머 정지 (재진입 방지) */
main_timer_stop(); /* Stop timer (prevent re-entry) */
if(motion_data_once == true)
{
/* 단발성 모드: HW I2C 초기화 후 IMU 데이터 1회 읽기 */
hw_i2c_init_once(); /* HW TWI 모드로 전환 (400kHz) */
icm42670_main(); /* IMU 데이터 읽기 및 처리 */
/* One-shot mode: init HW I2C then read IMU data once */
hw_i2c_init_once(); /* Switch to HW TWI mode (400kHz) */
icm42670_main(); /* Read and process IMU data */
}
else{
/* 연속 모드: BLE 전송 대기 중이 아니면 반복 읽기 */
/* Continuous mode: repeat read if not waiting for BLE TX */
if(ble_got_new_data==false){
//for(uint16_t i=0 ; i<60 ;i++)
//{
DBG_PRINTF("IMU \r\n");
icm42670_main(); /* IMU 데이터 읽기 */
motion_raw_data_enabled = true; /* 플래그 유지 (연속 읽기) */
main_timer_start_ms(1000); /* 1초 후 다음 IMU 읽기 */
icm42670_main(); /* Read IMU data */
motion_raw_data_enabled = true; /* Keep flag set (continuous read) */
main_timer_start_ms(1000); /* Next IMU read after 1s */
}
// else if(ble_got_new_data==true){
// motion_data_once = true;
@@ -178,71 +178,71 @@ void main_loop(void * p_context) /* For x ms */
}
/* ---- 배터리 전압 측정 ---- */
/* ---- Battery voltage measurement ---- */
/*
* go_batt 플래그가 true이면 배터리 레벨을 측정한다.
* info4 모드에서 IMU 연속 읽기 이후 호출되는 단계.
* 측정 완료 후 타이머가 정지된 상태로 유지된다.
* If go_batt is true, measure battery level.
* Called after IMU continuous read in info4 mode.
* Timer remains stopped after measurement.
*/
if(go_batt == true) {
DBG_PRINTF("IMU BATT\r\n");
main_timer_stop(); /* 타이머 정지 */
go_batt = false; /* 플래그 소비 (1회 실행) */
main_timer_stop(); /* Stop timer */
go_batt = false; /* Consume flag (one-shot) */
// go_temp = true;
battery_level_meas(); /* SAADC를 이용한 배터리 전압 측정 */
battery_level_meas(); /* Measure battery voltage via SAADC */
// nrf_delay_ms(20);
// m48_adc_start_init();
// main_timer_start();
}
/* ---- 온도 측정 ---- */
/* ---- Temperature measurement ---- */
/*
* go_temp 플래그가 true이면 TMP235-Q1 센서로 온도를 측정한다.
* info4 모드에서 배터리 측정 이후 호출되는 단계.
* 측정 완료 후 motion_data_once=true로 설정하여
* 다음 IMU 읽기는 단발성 모드(HW I2C 재초기화)로 전환된다.
* If go_temp is true, measure temperature via TMP235-Q1 sensor.
* Called after battery measurement in info4 mode.
* After completion, sets motion_data_once=true so the next IMU read
* uses one-shot mode (with HW I2C re-init).
*/
if(go_temp == true) {
DBG_PRINTF("IMU Temp\r\n");
main_timer_stop(); /* 타이머 정지 */
main_timer_stop(); /* Stop timer */
// go_batt = false;
go_temp = false; /* 플래그 소비 (1회 실행) */
motion_data_once = true; /* 다음 IMU 읽기를 단발성 모드로 전환 */
tmp235_voltage_level_meas(); /* TMP235-Q1 온도 센서 전압 측정 */
go_temp = false; /* Consume flag (one-shot) */
motion_data_once = true; /* Switch next IMU read to one-shot mode */
tmp235_voltage_level_meas(); /* Measure TMP235-Q1 temperature sensor voltage */
// motion_raw_data_enabled = true;
// main_timer_start();
}
/* ---- 시스템 제어 이벤트 처리 ---- */
/* ---- System control event handling ---- */
/* 디바이스 전원 OFF 처리 */
/* Device power OFF handling */
if(go_device_power_off == true){
main_timer_stop(); /* 타이머 정지 */
main_timer_stop(); /* Stop timer */
DBG_PRINTF("Off main_timer\r\n");
device_power_off(); /* 디바이스 전원 OFF 실행 */
device_power_off(); /* Execute device power OFF */
}
/* 슬립 모드 진입 처리 */
/* Sleep mode entry handling */
if(go_sleep_mode_enter == true){
main_timer_stop(); /* 타이머 정지 */
main_timer_stop(); /* Stop timer */
DBG_PRINTF("sleep main timer\r\n");
sleep_mode_enter(); /* 슬립 모드 진입 실행 */
sleep_mode_enter(); /* Execute sleep mode entry */
}
/* NVIC 시스템 리셋 처리 */
/* NVIC system reset handling */
if(go_NVIC_SystemReset == true) {
main_timer_stop(); /* 타이머 정지 */
NVIC_SystemReset(); /* ARM Cortex-M4 시스템 리셋 */
main_timer_stop(); /* Stop timer */
NVIC_SystemReset(); /* ARM Cortex-M4 system reset */
}
}
/**
* @brief 메인 루프 타이머 시작
* @brief Start main loop timer
*
* 싱글샷 모드로 MAIN_LOOP_INTERVAL(10ms 또는 80ms) 후 main_loop()를 호출
* Single-shot mode; calls main_loop() after MAIN_LOOP_INTERVAL (10ms or 80ms)
*/
void main_timer_start(void)
{
@@ -250,9 +250,9 @@ void main_timer_start(void)
}
/**
* @brief 지정된 간격(ms)으로 메인 루프 타이머 시작
* @brief Start main loop timer with specified interval (ms)
*
* IMU 연속 스트리밍 등 기본 간격과 다른 주기가 필요할 때 사용
* Used when a different period than the default is needed (e.g. IMU streaming)
*/
void main_timer_start_ms(uint32_t interval_ms)
{
@@ -260,7 +260,7 @@ void main_timer_start_ms(uint32_t interval_ms)
}
/**
* @brief 메인 루프 타이머 정지
* @brief Stop main loop timer
*/
void main_timer_stop(void)
{
@@ -268,10 +268,10 @@ void main_timer_stop(void)
}
/**
* @brief 메인 루프 타이머 초기화 (앱 시작 시 1회 호출)
* @brief Initialize main loop timer (call once at app startup)
*
* 싱글샷 모드 타이머를 생성하고, 콜백으로 main_loop()를 등록
* 싱글샷이므로 매 호출마다 main_timer_start()로 수동 재시작해야 함
* Creates a single-shot timer with main_loop() as callback.
* Must manually restart via main_timer_start() after each firing.
*/
void main_timer_init(void)
{

View File

@@ -6,32 +6,32 @@
* @brief
*******************************************************************************
*
* [헤더 개요]
* 메인 이벤트 루프 타이머의 공용 인터페이스 헤더.
* [Header overview]
* Public interface header for the main event loop timer.
*
* 10ms(일반) 또는 80ms(디테일) 간격의 싱글샷 타이머를 사용하여
* main_loop() 콜백에서 센서 데이터 수집 및 시스템 제어를 수행한다.
* Uses a single-shot timer at 10ms (normal) or 80ms (detail) interval.
* The main_loop() callback handles sensor data collection and system control.
*
* [주요 함수]
* main_timer_start() : 타이머 시작 (싱글샷, 수동 재시작 필요)
* main_timer_stop() : 타이머 정지
* main_timer_init() : 타이머 초기화 (앱 시작 시 1회 호출)
* [Key functions]
* main_timer_start() : Start timer (single-shot, manual restart required)
* main_timer_stop() : Stop timer
* main_timer_init() : Initialize timer (call once at app startup)
*
******************************************************************************/
#ifndef TIMER_ROUTINE_H__
#define TIMER_ROUTINE_H__
/** @brief 메인 루프 타이머 시작 (싱글샷, MAIN_LOOP_INTERVAL 후 main_loop 호출) */
/** @brief Start main loop timer (single-shot, calls main_loop after MAIN_LOOP_INTERVAL) */
void main_timer_start(void);
/** @brief 지정된 간격(ms)으로 메인 루프 타이머 시작 */
/** @brief Start main loop timer with specified interval (ms) */
void main_timer_start_ms(uint32_t interval_ms);
/** @brief 메인 루프 타이머 정지 */
/** @brief Stop main loop timer */
void main_timer_stop(void);
/** @brief 메인 루프 타이머 초기화 (앱 시작 시 1회, 싱글샷 모드로 생성) */
/** @brief Initialize main loop timer (call once at startup, creates single-shot timer) */
void main_timer_init(void);
#endif //TIMER_ROUTINE_H__

View File

@@ -3,24 +3,24 @@
//=========power_control.c====================
*******************************************************************************
*
* [모듈 개요]
* 디바이스 전원 시퀀스를 관리하는 모듈 (전원 켜기 / 끄기 / 슬립).
* [Module overview]
* Device power sequence manager (power on / off / sleep).
*
* [전원 켜기 흐름]
* [Power-on flow]
* device_activated()
* power_loop 타이머 시작 → 즉시 완료 (센서 초기화 불필요)
* → 센서(IMU)는 측정 명령 시 imu_read_direct()가 자체 처리
* -> Start power_loop timer -> completes immediately (no sensor init needed)
* -> Sensor (IMU) is handled by imu_read_direct() at measurement time
*
* [슬립 모드]
* [Sleep mode]
* device_sleep_mode()
* processing 플래그 해제
* -> Clear processing flag
*
* [재활성화]
* [Reactivation]
* device_reactivated()
* → I2C 재초기화 후 전원 시퀀스를 처음부터 다시 시작
* -> Re-init I2C then restart power sequence from the beginning
*
* [타이머]
* 싱글샷 모드 app_timer, 20ms 간격으로 power_loop 호출
* [Timer]
* Single-shot app_timer, calls power_loop at 20ms interval
*
******************************************************************************/
#include <stdbool.h>
@@ -38,53 +38,53 @@
#include "i2c_manager.h"
/* 전원 시퀀스용 싱글샷 타이머 인스턴스 */
/* Single-shot timer instance for power sequence */
APP_TIMER_DEF(m_power_timer_id);
/* 전원 시퀀스 상태머신의 타이머 간격 (20ms) */
/* Power sequence state machine timer interval (20ms) */
// 2025-12-08 change to #define POWER_LOOP_INTERVAL 30 -> 20
#define POWER_LOOP_INTERVAL 20
/* 전원 시퀀스 현재 단계 (0: I2C 초기화, 1: 예약, 2: 완료) */
/* Power sequence current step (0: I2C init, 1: reserved, 2: complete) */
static uint8_t p_order;
/* 데이터 처리 중 플래그 (외부 모듈에서 선언) */
/* Data processing flag (declared in external module) */
extern volatile bool processing;
/* 전원 시퀀스 잠금 플래그 (true = 전원 시퀀스 진행 중) */
/* Power sequence lock flag (true = sequence in progress) */
bool lock_check = false;
/**
* @brief 디바이스 슬립 모드 진입
* @brief Enter device sleep mode
*
* 데이터 처리 플래그(processing)를 해제하여
* 메인 루프가 더 이상 센서 데이터를 처리하지 않도록 한다.
* Clears the processing flag so the main loop stops
* processing sensor data.
*
* @return 0 (항상 성공)
* @return 0 (always succeeds)
*/
int device_sleep_mode(void){
int rc = 0;
nrf_delay_ms(2);
DBG_PRINTF("Device_Sleep_Mode OK!\r\n");
nrf_delay_ms(10);
processing = false; /* 데이터 처리 플래그 해제 → 센서 처리 중단 */
processing = false; /* Clear processing flag -> stop sensor handling */
return rc;
}
/**
* @brief 디바이스 전원 켜기 (전원 시퀀스 시작)
* @brief Power on device (start power sequence)
*
* 전원 시퀀스 단계를 0으로 초기화하고, 잠금 플래그를 설정한 뒤
* 타이머를 시작하여 power_loop() 상태머신을 구동한다.
* Resets the sequence step to 0, sets the lock flag, and starts
* the timer to drive the power_loop() state machine.
*
* @return 0 (항상 성공)
* @return 0 (always succeeds)
*/
int device_activated(void){
int rc = 0;
p_order = 0; /* 상태머신 시작 단계 (Step 0: I2C 초기화) */
lock_check =true; /* 전원 시퀀스 진행 중 잠금 */
power_timer_start(); /* 20ms 후 power_loop() 첫 호출 */
p_order = 0; /* State machine start step (Step 0: I2C init) */
lock_check =true; /* Lock: power sequence in progress */
power_timer_start(); /* First power_loop() call after 20ms */
return rc;
}
@@ -101,60 +101,60 @@ int device_activated(void){
* 2: Complete
*/
/*
* 전원 시퀀스 상태머신 (20ms 싱글샷 타이머 콜백).
* Power sequence state machine (20ms single-shot timer callback).
*
* [실행 흐름]
* 1) 타이머 콜백 진입 → 타이머 정지 (싱글샷이므로)
* 2) 현재 p_order에 해당하는 초기화 단계 실행
* 3) p_order < 2이면 다음 단계로 진행하고 타이머 재시작
* 4) p_order == 2이면 전원 시퀀스 완료
* [Execution flow]
* 1) Timer callback entry -> stop timer (single-shot)
* 2) Execute init step for current p_order
* 3) If p_order < 2, advance to next step and restart timer
* 4) If p_order == 2, power sequence complete
*
* 센서 초기화 불필요 — imu_read_direct()가 매 측정 시 자체 처리
* No sensor init needed -- imu_read_direct() handles it per measurement.
*/
void power_loop(void *p_context)
{
UNUSED_PARAMETER(p_context);
power_timer_stop(); /* 현재 타이머 정지 (싱글샷 → 수동 재시작 필요) */
power_timer_stop(); /* Stop current timer (single-shot, manual restart needed) */
/* 센서 초기화 불필요 — imu_read_direct()가 매 측정 시 자체 처리 */
/* 추후 전원 시퀀스 단계가 필요하면 여기에 switch(p_order) 추가 */
/* No sensor init needed -- imu_read_direct() handles it per measurement */
/* Add switch(p_order) here if future power sequence steps are needed */
p_order = 2;
/* Advance to next step or finish */
/* 다음 단계로 진행하거나, 시퀀스 완료 처리 */
/* Advance to next step or finish sequence */
if (p_order < 2) {
p_order++; /* 다음 단계로 이동 */
power_timer_start(); /* 20ms 후 다음 단계 실행 */
p_order++; /* Move to next step */
power_timer_start(); /* Execute next step after 20ms */
} else {
/* 전원 시퀀스 전체 완료 */
/* Power sequence fully complete */
DBG_PRINTF("[PWR] Device Activated OK!\r\n");
}
}
/**
* @brief 디바이스 재활성화 (슬립 복귀 시)
* @brief Reactivate device (on wake from sleep)
*
* I2C를 재초기화하고, 전원 시퀀스를 처음부터 다시 시작한다.
* 슬립 모드에서 깨어날 때 호출된다.
* Re-initializes I2C and restarts the power sequence from the beginning.
* Called when waking from sleep mode.
*
* @return 0 (항상 성공)
* @return 0 (always succeeds)
*/
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() 시작 */
sw_i2c_init_once(); /* Re-initialize I2C bus */
nrf_delay_ms(10); /* Stabilization delay */
lock_check = true; /* Lock: power sequence in progress */
p_order = 0; /* Restart state machine from Step 0 */
power_timer_start(); /* Start power_loop() after 20ms */
return rc;
}
/**
* @brief 전원 시퀀스 타이머 시작
* @brief Start power sequence timer
*
* 싱글샷 모드로 POWER_LOOP_INTERVAL(20ms) 후 power_loop()를 호출한다.
* Single-shot mode; calls power_loop() after POWER_LOOP_INTERVAL (20ms).
*/
void power_timer_start(void)
{
@@ -163,7 +163,7 @@ void power_timer_start(void)
/**
* @brief 전원 시퀀스 타이머 정지
* @brief Stop power sequence timer
*/
void power_timer_stop(void)
{
@@ -173,10 +173,10 @@ void power_timer_stop(void)
/**
* @brief 전원 시퀀스 타이머 초기화 (앱 시작 시 1회 호출)
* @brief Initialize power sequence timer (call once at app startup)
*
* 싱글샷 모드 타이머를 생성하고, 콜백으로 power_loop()를 등록한다.
* 싱글샷이므로 매 단계마다 power_timer_start()로 수동 재시작해야 한다.
* Creates a single-shot timer with power_loop() as callback.
* Must manually restart via power_timer_start() after each step.
*/
void power_timer_init(void) //active start
{

View File

@@ -6,16 +6,16 @@
* @brief
*******************************************************************************
*
* [헤더 개요]
* 디바이스 전원 시퀀스 관리 모듈의 공용 인터페이스 헤더.
* [Header overview]
* Public interface header for the device power sequence manager.
*
* [주요 함수 요약]
* device_activated() : 전원 켜기 → power_loop 상태머신 시작
* device_sleep_mode() : 슬립 모드 진입 (처리 중단)
* device_reactivated() : 슬립 복귀 → 전원 시퀀스 재시작
* power_loop() : 20ms 간격 전원 시퀀스 상태머신 콜백
* power_timer_start/stop : 전원 시퀀스 타이머 제어
* power_timer_init() : 전원 시퀀스 타이머 초기화 (앱 시작 시 1회)
* [Key functions]
* device_activated() : Power on -> start power_loop state machine
* device_sleep_mode() : Enter sleep mode (stop processing)
* device_reactivated() : Wake from sleep -> restart power sequence
* power_loop() : 20ms power sequence state machine callback
* power_timer_start/stop : Power sequence timer control
* power_timer_init() : Initialize power sequence timer (call once at startup)
*
******************************************************************************/
@@ -24,25 +24,25 @@
#include "main.h"
/** @brief 디바이스 슬립 모드 진입 (processing 해제) */
/** @brief Enter device sleep mode (clears processing flag) */
int device_sleep_mode(void);
/** @brief 디바이스 전원 켜기 (전원 시퀀스 상태머신 시작) */
/** @brief Power on device (start power sequence state machine) */
int device_activated(void);
/** @brief 디바이스 재활성화 (슬립 복귀 시 I2C 재초기화 후 시퀀스 재시작) */
/** @brief Reactivate device (re-init I2C and restart sequence on wake from sleep) */
int device_reactivated(void);
/** @brief 전원 시퀀스 상태머신 (20ms 타이머 콜백, Step 0→1→2) */
/** @brief Power sequence state machine (20ms timer callback, Step 0->1->2) */
void power_loop(void * p_context); /* For x ms */
/** @brief 전원 시퀀스 타이머 시작 (20ms 싱글샷) */
/** @brief Start power sequence timer (20ms single-shot) */
void power_timer_start(void);
/** @brief 전원 시퀀스 타이머 정지 */
/** @brief Stop power sequence timer */
void power_timer_stop(void);;
/** @brief 전원 시퀀스 타이머 초기화 (앱 시작 시 1회 호출) */
/** @brief Initialize power sequence timer (call once at app startup) */
void power_timer_init(void);
#endif //_POWER_CONTROL_H_

View File

@@ -100,7 +100,7 @@ void ble_security_quick_pm_handler(pm_evt_t const *p_evt)
{
ret_code_t err_code;
// DEV 모드: 보안 실패 이벤트는 SDK 핸들러에 전달하지 않음 (disconnect 방지)
// DEV mode: do not forward security failure events to SDK handler (prevent disconnect)
if (m_state.dev_mode && p_evt->evt_id == PM_EVT_CONN_SEC_FAILED) {
DBG_PRINTF("Security failed: error=%d\r\n",
p_evt->params.conn_sec_failed.error);
@@ -133,13 +133,13 @@ void ble_security_quick_pm_handler(pm_evt_t const *p_evt)
p_evt->params.conn_sec_failed.error);
if (m_state.dev_mode) {
// DEV 모드: 보안 실패 무시 — 연결 유지
// DEV mode: ignore security failure, keep connection
DBG_PRINTF("DEV: Ignoring sec failure, keeping connection\r\n");
break;
}
if (p_evt->params.conn_sec_failed.error == PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING) {
// Key missing: 재페어링 시도, 실패 시 disconnect로 폴백
// Key missing: attempt re-pairing, fall back to disconnect on failure
err_code = pm_conn_secure(p_evt->conn_handle, true);
if (err_code != NRF_ERROR_INVALID_STATE &&
err_code != NRF_ERROR_BUSY &&
@@ -147,11 +147,11 @@ void ble_security_quick_pm_handler(pm_evt_t const *p_evt)
APP_ERROR_CHECK(err_code);
}
if (err_code != NRF_SUCCESS) {
// 재페어링 불가 → disconnect
// Re-pairing not possible -> disconnect
pm_handler_disconnect_on_sec_failure(p_evt);
}
} else {
// 기타 보안 실패 → bond 삭제 후 재페어링 시도
// Other security failure -> delete bond then attempt re-pairing
pm_peer_id_t peer_id;
if (pm_peer_id_get(p_evt->conn_handle, &peer_id) == NRF_SUCCESS
&& peer_id != PM_PEER_ID_INVALID) {