initial commit
This commit is contained in:
@@ -0,0 +1,589 @@
|
||||
# VivaMyo BLE Application - 프로그램 아키텍처 문서
|
||||
|
||||
## 1. 프로젝트 개요
|
||||
|
||||
VivaMyo는 nRF52840 기반 BLE 의료 기기 펌웨어로, 방광 모니터링을 위한 NIRS(Near-Infrared Spectroscopy) 장치입니다.
|
||||
|
||||
### 1.1 주요 특징
|
||||
- **MCU**: Nordic nRF52840
|
||||
- **통신**: BLE (Nordic UART Service)
|
||||
- **보안**: LESC 페어링, Static Passkey
|
||||
- **센서**: LED 48개, Photodetector, IMU (ICM42670P), 온도센서, 압력센서
|
||||
- **저장**: EEPROM (설정값 암호화 저장)
|
||||
|
||||
---
|
||||
|
||||
## 2. 시스템 아키텍처
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ main.c │
|
||||
│ (Application Entry Point) │
|
||||
└──────────────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
┌──────────────────────┼──────────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌───────────────┐ ┌─────────────────┐ ┌─────────────────────┐
|
||||
│ BLE Stack │ │ Power Control │ │ Timer Management │
|
||||
│ (ble_core.c) │ │ (power_ctrl.c) │ │ (main_timer.c) │
|
||||
└───────┬───────┘ └─────────────────┘ └─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ nus_data_handler() │
|
||||
│ (BLE Data Reception) │
|
||||
└──────────────────────────────┬────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ received_command_process() │
|
||||
│ (cmd_parse.c) │
|
||||
└──────────────────────────────┬────────────────────────────────────┘
|
||||
│
|
||||
┌──────────────────────┴──────────────────────┐
|
||||
▼ ▼
|
||||
┌───────────────────────┐ ┌─────────────────────┐
|
||||
│ Mt_parser │ │ Legacy Parser │
|
||||
│ (dr_cmd_parser) │ │ (cmd_parse.c) │
|
||||
│ │ │ │
|
||||
│ parser.c + cmd.c │ │ 기존 명령어 처리 │
|
||||
└───────────┬───────────┘ └─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ Command Handlers (cmd.c) │
|
||||
│ │
|
||||
│ Cmd_mta, Cmd_sta, Cmd_mcj, Cmd_msn, Cmd_mag ... │
|
||||
└───────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Mt_parser 모듈 구조
|
||||
|
||||
Mt_parser는 명령어 파싱과 디스패치를 담당하는 독립 모듈입니다.
|
||||
|
||||
### 3.1 파일 구성
|
||||
|
||||
| 파일 | 경로 | 설명 |
|
||||
|------|------|------|
|
||||
| `parser.h` | `/mt_parser/parser.h` | 파서 인터페이스 정의 |
|
||||
| `parser.c` | `/mt_parser/parser.c` | CRC 검증, TAG 추출, 명령어 디스패치 |
|
||||
| `cmd.h` | `cmd/cmd.h` | 명령어 테이블 구조체 정의 |
|
||||
| `cmd.c` | `cmd/cmd.c` | 명령어 핸들러 구현 및 테이블 |
|
||||
| `dr_util.h/c` | `/mt_parser/dr_util/` | BLE 응답 유틸리티 함수 |
|
||||
|
||||
### 3.2 핵심 구조체
|
||||
|
||||
```c
|
||||
// parser.h - 플랫폼 인터페이스
|
||||
typedef struct {
|
||||
void (*log)(const char *fmt, ...); // 로그 출력 함수
|
||||
void (*tx_bin)(const uint8_t *buf, uint16_t len); // BLE 전송 함수
|
||||
bool crc_check; // CRC 검사 활성화 여부
|
||||
} dr_platform_if_t;
|
||||
|
||||
// cmd.h - 파싱된 명령어 구조체
|
||||
typedef struct {
|
||||
char tag[5]; // 4글자 명령어 + NULL ("sta?")
|
||||
uint8_t data[CMD_MAX_DATA]; // TAG 이후 데이터
|
||||
uint8_t data_len; // 데이터 길이
|
||||
} ParsedCmd;
|
||||
|
||||
// cmd.h - 명령어 테이블 엔트리
|
||||
typedef struct {
|
||||
char tag[5]; // 명령어 TAG ("sta?")
|
||||
bool enabled; // 활성화 여부
|
||||
cmd_handler_t handler; // 핸들러 함수 포인터
|
||||
} CmdEntry;
|
||||
```
|
||||
|
||||
### 3.3 전역 변수
|
||||
|
||||
```c
|
||||
extern dr_platform_if_t g_plat; // 플랫폼 인터페이스
|
||||
extern bool g_log_enable; // 로그 활성화 플래그
|
||||
extern CmdEntry g_cmd_table[]; // 명령어 테이블
|
||||
extern const uint16_t g_cmd_count; // 명령어 개수
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 명령어 처리 흐름
|
||||
|
||||
### 4.1 데이터 수신 경로
|
||||
|
||||
```
|
||||
[BLE Central]
|
||||
│
|
||||
▼ (NUS RX Characteristic Write)
|
||||
[ble_core.c:nus_data_handler()]
|
||||
│
|
||||
▼
|
||||
[cmd_parse.c:received_command_process(data, CMD_BLE, length)]
|
||||
│
|
||||
├─► [Mt_parser 초기화] (최초 1회)
|
||||
│ g_plat.log = log_printf
|
||||
│ g_plat.tx_bin = binary_tx_handler
|
||||
│ g_plat.crc_check = true
|
||||
│
|
||||
▼
|
||||
[parser.c:dr_cmd_parser(data, length)]
|
||||
│
|
||||
├─► [CRC16 검증] → 실패시 "crc!" 응답
|
||||
│
|
||||
├─► [TAG 추출] → 4글자 명령어 파싱
|
||||
│
|
||||
▼
|
||||
[dr_cmd_dispatch()] → g_cmd_table 검색
|
||||
│
|
||||
├─► [명령어 발견 + 활성화] → handler() 호출
|
||||
│
|
||||
├─► [명령어 발견 + 비활성화] → return 0
|
||||
│
|
||||
└─► [명령어 미발견] → return 0 (Legacy 파서로 fallback)
|
||||
```
|
||||
|
||||
### 4.2 CRC16 검증
|
||||
|
||||
```c
|
||||
// 패킷 구조: [TAG(4)] [DATA(N)] [CRC_LO] [CRC_HI]
|
||||
// CRC 계산: TAG + DATA 영역
|
||||
// CRC 위치: 패킷 마지막 2바이트 (Little Endian)
|
||||
|
||||
static bool dr_crc16_check_packet(const uint8_t *packet, uint32_t packet_len)
|
||||
{
|
||||
uint32_t data_len = packet_len - 2;
|
||||
uint16_t expected_crc = (uint16_t)packet[packet_len - 2]
|
||||
| ((uint16_t)packet[packet_len - 1] << 8);
|
||||
return dr_crc16_check(packet, data_len, expected_crc);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 명령어 테이블 (cmd.c)
|
||||
|
||||
### 5.1 명령어 카테고리
|
||||
|
||||
| 카테고리 | 명령어 | 설명 |
|
||||
|----------|--------|------|
|
||||
| **A. Device Status** | `mta?`, `sta?`, `str?`, `mqq?` | 디바이스 상태 제어/조회 |
|
||||
| **B. AGC/Gain** | `mag?`, `sag?`, `sar?` | Auto Gain Control |
|
||||
| **C. LED DP Value** | `ssa?`, `sab?`, `ssb?`, `srb?` | LED 밝기 설정/조회 |
|
||||
| **D. LED On/Off** | `ssc?`, `ssd?`, `sse?`, `ssf?`, `sif?`, `ssg?` | LED/Gain 제어 |
|
||||
| **E. Simple PD** | `ssh?` | 간단한 PD 측정 |
|
||||
| **F. M48 Full** | `mcj?`, `scj?`, `sdj?`, `sej?`, `sfj?`, `ssj?`, `szj?` | 48채널 PD 측정 |
|
||||
| **G. IMM ADC** | `saj?` | Immediate ADC 측정 |
|
||||
| **H. PD Settings** | `ssk?`, `srk?`, `ssl?`, `srl?` | ADC 횟수/지연 설정 |
|
||||
| **I. Sensors** | `msn?`, `ssn?`, `spn?`, `sso?`, `ssp?` | 배터리/압력/온도/IMU |
|
||||
| **J. System** | `ssq?`, `ssr?`, `sss?`, `sst?`, `ssv?` | 전원/리셋/버전 |
|
||||
| **K. Serial/Passkey** | `ssz?`, `spz?`, `sqz?`, `srz?` | 시리얼번호/패스키 |
|
||||
| **L. EEPROM Array** | `sez?`, `sfz?`, `sgz?` | EEPROM 배열 R/W |
|
||||
| **M. HW/Life Cycle** | `siz?`, `shz?`, `sxz?`, `syz?` | HW번호/사용횟수 |
|
||||
| **N. Debug** | `cmd?` | GPIO 테스트 |
|
||||
|
||||
### 5.2 명령어 상세 테이블
|
||||
|
||||
```c
|
||||
CmdEntry g_cmd_table[] = {
|
||||
/* Debug */
|
||||
{ "cmd?", true, Cmd_cmd }, // GPIO 테스트
|
||||
|
||||
/* A. Device Status */
|
||||
{ "mta?", true, Cmd_mta }, // Device Activate/Sleep (신규)
|
||||
{ "sta?", true, Cmd_sta }, // Device Activate/Sleep (호환)
|
||||
{ "str?", false, Cmd_str }, // Status Read
|
||||
{ "mqq?", true, Cmd_mqq }, // Quick Measurement
|
||||
|
||||
/* B. AGC / Gain Measurement */
|
||||
{ "mag?", true, Cmd_mag }, // Full AGC (신규)
|
||||
{ "sag?", true, Cmd_mag }, // Full AGC (호환)
|
||||
{ "sar?", false, Cmd_sar }, // Read LED-PD Gain Array
|
||||
|
||||
/* C. LED Power / DP Value */
|
||||
{ "ssa?", false, Cmd_ssa }, // Single LED Power Read
|
||||
{ "sab?", false, Cmd_sab }, // All LED AGC Data Read
|
||||
{ "ssb?", false, Cmd_ssb }, // Single LED Power Write
|
||||
{ "srb?", false, Cmd_srb }, // Read All 48 LED DP
|
||||
|
||||
/* D. LED On/Off & Gain Control */
|
||||
{ "ssc?", false, Cmd_ssc }, // LED On/Off (index 0-47, 99=off)
|
||||
{ "ssd?", false, Cmd_ssd }, // AGC Switch On/Off
|
||||
{ "sse?", false, Cmd_sse }, // Measure DAC Voltage
|
||||
{ "ssf?", false, Cmd_ssf }, // Set LED DAC Value
|
||||
{ "sif?", false, Cmd_sif }, // Immediate Gain Set
|
||||
{ "ssg?", false, Cmd_ssg }, // Set PD Channel
|
||||
|
||||
/* E. Simple PD Measurement */
|
||||
{ "ssh?", false, Cmd_ssh }, // Simple PD Measurement
|
||||
|
||||
/* F. PD-ADC M48 Full Measurement */
|
||||
{ "mcj?", true, Cmd_mcj }, // MODE=2 (Pressure + M48) - 신규
|
||||
{ "scj?", true, Cmd_mcj }, // MODE=2 (호환)
|
||||
{ "sdj?", false, Cmd_sdj }, // MODE=3 (M48 Only)
|
||||
{ "sej?", false, Cmd_sej }, // MODE=4 (M48 + Batt + IMU)
|
||||
{ "sfj?", false, Cmd_sfj }, // MODE=5 (M48 + Init)
|
||||
{ "ssj?", false, Cmd_ssj }, // MODE=0 (Combined)
|
||||
{ "szj?", false, Cmd_szj }, // FAST Mode Settings
|
||||
|
||||
/* G. IMM ADC */
|
||||
{ "saj?", false, Cmd_saj }, // 4-LED Immediate ADC
|
||||
|
||||
/* H. PD-ADC Count & Delay */
|
||||
{ "ssk?", false, Cmd_ssk }, // Set ADC Count (8/16/24/32)
|
||||
{ "srk?", false, Cmd_srk }, // Read ADC Count
|
||||
{ "ssl?", false, Cmd_ssl }, // Set PD Delay (us)
|
||||
{ "srl?", false, Cmd_srl }, // Read PD Delay
|
||||
|
||||
/* I. Sensor Measurements */
|
||||
{ "msn?", true, Cmd_msn }, // Battery Level (신규)
|
||||
{ "ssn?", true, Cmd_msn }, // Battery Level (호환)
|
||||
{ "spn?", false, Cmd_spn }, // Pressure Measurement
|
||||
{ "sso?", false, Cmd_sso }, // Temperature Measurement
|
||||
{ "ssp?", false, Cmd_ssp }, // IMU Raw Data
|
||||
|
||||
/* J. Power / Reset / Version */
|
||||
{ "ssq?", false, Cmd_ssq }, // Power Off
|
||||
{ "ssr?", false, Cmd_ssr }, // Bond Delete + Reset
|
||||
{ "sss?", false, Cmd_sss }, // Device Reset
|
||||
{ "sst?", false, Cmd_sst }, // Ready Response
|
||||
{ "ssv?", false, Cmd_ssv }, // Firmware Version
|
||||
|
||||
/* K. Serial / Passkey */
|
||||
{ "ssz?", false, Cmd_ssz }, // Write Serial Number
|
||||
{ "spz?", false, Cmd_spz }, // Write Passkey
|
||||
{ "sqz?", false, Cmd_sqz }, // Read Passkey
|
||||
{ "srz?", false, Cmd_srz }, // Read Serial Number
|
||||
|
||||
/* L. EEPROM Array */
|
||||
{ "sez?", false, Cmd_sez }, // Write 48*uint16 Array
|
||||
{ "sfz?", false, Cmd_sfz }, // Read 48*uint16 Array
|
||||
{ "sgz?", false, Cmd_sgz }, // Load DP Preset
|
||||
|
||||
/* M. Hardware No / Life Cycle */
|
||||
{ "siz?", false, Cmd_siz }, // Read HW Number
|
||||
{ "shz?", false, Cmd_shz }, // Write HW Number
|
||||
{ "sxz?", false, Cmd_sxz }, // Write Life Cycle
|
||||
{ "syz?", false, Cmd_syz }, // Read Life Cycle
|
||||
};
|
||||
```
|
||||
|
||||
### 5.3 활성화된 명령어 (enabled=true)
|
||||
|
||||
| 명령어 | 핸들러 | 기능 |
|
||||
|--------|--------|------|
|
||||
| `cmd?` | `Cmd_cmd` | GPIO 핀 제어 테스트 |
|
||||
| `mta?` | `Cmd_mta` | 디바이스 활성화/슬립 |
|
||||
| `sta?` | `Cmd_sta` | 디바이스 활성화/슬립 (호환) |
|
||||
| `mqq?` | `Cmd_mqq` | 빠른 측정 시작 |
|
||||
| `mag?` | `Cmd_mag` | Full AGC 측정 |
|
||||
| `sag?` | `Cmd_mag` | Full AGC 측정 (호환) |
|
||||
| `mcj?` | `Cmd_mcj` | M48 전체 측정 (MODE=2) |
|
||||
| `scj?` | `Cmd_mcj` | M48 전체 측정 (호환) |
|
||||
| `msn?` | `Cmd_msn` | 배터리 레벨 측정 |
|
||||
| `ssn?` | `Cmd_msn` | 배터리 레벨 측정 (호환) |
|
||||
|
||||
---
|
||||
|
||||
## 6. main.c와의 연결
|
||||
|
||||
### 6.1 초기화 순서
|
||||
|
||||
```c
|
||||
int main(void)
|
||||
{
|
||||
// 1. 기본 초기화
|
||||
uart_handler_init(); // UART 디버그
|
||||
log_init(); // NRF 로그
|
||||
gpio_init(); // GPIO 설정 (LED, PD, GAIN_SW)
|
||||
timers_init(); // 타이머 초기화
|
||||
|
||||
// 2. 설정 로드
|
||||
load_device_configuration(); // EEPROM에서 설정 읽기
|
||||
|
||||
// 3. BLE 초기화
|
||||
ble_stack_init(); // SoftDevice 활성화
|
||||
gap_params_init(); // GAP 파라미터 (디바이스명, Passkey)
|
||||
gatt_init(); // GATT 초기화
|
||||
services_init(); // NUS 서비스 등록
|
||||
advertising_init(); // 광고 설정
|
||||
conn_params_init(); // 연결 파라미터
|
||||
|
||||
// 4. 전원 버튼 타이머 시작
|
||||
power_ctrl_timers_start();
|
||||
|
||||
// 5. 메인 루프
|
||||
for (;;) {
|
||||
idle_state_handle(); // 전원 관리 + 보안 처리
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 BLE 데이터 수신 경로
|
||||
|
||||
```c
|
||||
// ble_core.c
|
||||
static void nus_data_handler(ble_nus_evt_t * p_evt)
|
||||
{
|
||||
if (p_evt->type == BLE_NUS_EVT_RX_DATA) {
|
||||
// cmd_parse.c의 received_command_process() 호출
|
||||
received_command_process(
|
||||
p_evt->params.rx_data.p_data,
|
||||
CMD_BLE,
|
||||
p_evt->params.rx_data.length
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 Mt_parser 초기화 (cmd_parse.c)
|
||||
|
||||
```c
|
||||
void received_command_process(uint8_t const *data_array, which_cmd_t cmd_t, uint8_t length)
|
||||
{
|
||||
// Mt_parser 초기화 (최초 1회)
|
||||
static bool parser_initialized = false;
|
||||
if (!parser_initialized) {
|
||||
g_plat.log = log_printf; // 로그 함수 연결
|
||||
g_plat.tx_bin = binary_tx_handler; // BLE TX 함수 연결
|
||||
g_plat.crc_check = true; // CRC 검사 활성화
|
||||
g_log_enable = true;
|
||||
parser_initialized = true;
|
||||
}
|
||||
|
||||
// Mt_parser 호출
|
||||
int result = dr_cmd_parser(r_data, length);
|
||||
|
||||
if (result > 0) {
|
||||
return; // Mt_parser에서 처리됨
|
||||
}
|
||||
|
||||
// Mt_parser에서 처리 안됨 → Legacy 파서로 처리
|
||||
// ... 기존 scmd 기반 처리 ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 소스코드 구조
|
||||
|
||||
### 7.1 디렉토리 구조
|
||||
|
||||
```
|
||||
ble_app_vivaMayo/
|
||||
├── main.c # 메인 엔트리 포인트
|
||||
├── main.h # 메인 헤더 (타입 정의, 함수 프로토타입)
|
||||
├── main_timer.c/h # 애플리케이션 타이머
|
||||
│
|
||||
├── cmd_parse.c/h # 명령어 파싱 (Legacy + Mt_parser 연결)
|
||||
│
|
||||
├── cmd/
|
||||
│ ├── cmd.c # 명령어 핸들러 구현 + 테이블
|
||||
│ └── cmd.h # 명령어 구조체 정의
|
||||
│
|
||||
├── ble/
|
||||
│ ├── ble_core.c/h # BLE 스택, GAP, GATT, 광고
|
||||
│ ├── ble_data_tx.c/h # BLE 데이터 전송, 포맷팅
|
||||
│ ├── ble_services.c/h # BLE 서비스
|
||||
│ └── ble_security.c/h # BLE 보안 (페어링)
|
||||
│
|
||||
├── power/
|
||||
│ └── power_ctrl.c/h # 전원 제어, 슬립 모드
|
||||
│
|
||||
├── peripheral/
|
||||
│ └── uart_handler.c/h # UART 디버그 출력
|
||||
│
|
||||
├── config/
|
||||
│ └── device_config.c/h # EEPROM 설정 관리
|
||||
│
|
||||
├── measurements.c/h # 측정 유틸리티
|
||||
├── meas_pd_*.c/h # PD ADC 측정 모듈들
|
||||
├── full_agc.c/h # AGC 자동 조절
|
||||
├── battery_saadc.c/h # 배터리 ADC
|
||||
│
|
||||
├── icm42670p/ # IMU 드라이버
|
||||
├── i2c_manager.c/h # I2C 관리
|
||||
├── ada2200_spi.c/h # SPI 디바이스
|
||||
├── mcp4725_i2c.c/h # DAC 제어
|
||||
├── tmp235_q1.c/h # 온도 센서
|
||||
├── cat_interface.c/h # CAT (압력센서) 인터페이스
|
||||
│
|
||||
└── docs/
|
||||
└── PROGRAM_ARCHITECTURE.md # 이 문서
|
||||
```
|
||||
|
||||
### 7.2 Mt_parser 디렉토리 (별도 위치)
|
||||
|
||||
```
|
||||
/mt_parser/
|
||||
├── parser.h # 파서 인터페이스
|
||||
├── parser.c # 파서 구현 (CRC, TAG, 디스패치)
|
||||
├── cmd.h # (참조용)
|
||||
│
|
||||
└── dr_util/
|
||||
├── dr_util.h # BLE 응답 유틸리티
|
||||
└── dr_util.c # dr_ble_return_1/2/3()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 명령어 프로토콜
|
||||
|
||||
### 8.1 패킷 구조
|
||||
|
||||
```
|
||||
┌─────────┬──────────────────┬─────────┐
|
||||
│ TAG │ DATA │ CRC │
|
||||
│ 4 bytes │ N bytes │ 2 bytes │
|
||||
└─────────┴──────────────────┴─────────┘
|
||||
|
||||
예시: sta? 명령어로 디바이스 활성화
|
||||
TX: [73 74 61 3F] [00 01] [CRC_LO] [CRC_HI]
|
||||
s t a ? value=1
|
||||
|
||||
응답: rta: value
|
||||
RX: [72 74 61 3A] [00 01] [CRC_LO] [CRC_HI]
|
||||
r t a : value=1
|
||||
```
|
||||
|
||||
### 8.2 데이터 형식
|
||||
|
||||
| 형식 | 설명 | 바이트 순서 |
|
||||
|------|------|-------------|
|
||||
| uint16 | 16비트 정수 | Big Endian (MSB first) |
|
||||
| ASCII | 문자열 | 순차적 |
|
||||
| CRC16 | 체크섬 | Little Endian (LSB first) |
|
||||
|
||||
### 8.3 응답 규칙
|
||||
|
||||
| 요청 TAG | 응답 TAG | 예시 |
|
||||
|----------|----------|------|
|
||||
| `sta?` | `rta:` | 상태 응답 |
|
||||
| `mcj?` | (측정 데이터) | 멀티 패킷 |
|
||||
| 오류 | `xxx!` | `crc!`, `err!` |
|
||||
|
||||
---
|
||||
|
||||
## 9. 주요 핸들러 구현 예시
|
||||
|
||||
### 9.1 Cmd_mta (디바이스 활성화)
|
||||
|
||||
```c
|
||||
static int Cmd_mta(const ParsedCmd *cmd)
|
||||
{
|
||||
uint16_t mode = 0;
|
||||
resetCount = 0;
|
||||
|
||||
// 데이터에서 mode 추출 (word index 0)
|
||||
(void)cmd_get_u16(cmd, 0, &mode);
|
||||
|
||||
if (mode == 1) {
|
||||
// 디바이스 활성화
|
||||
if (device_activated() == 0) {
|
||||
device_status = true;
|
||||
}
|
||||
}
|
||||
else if (mode == 0) {
|
||||
// 슬립 모드 진입
|
||||
if (device_status == true) {
|
||||
if (device_sleep_mode() == 0) {
|
||||
device_status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BLE 응답 전송
|
||||
if (g_plat.tx_bin) {
|
||||
single_format_data(ble_bin_buffer, "rta:", mode);
|
||||
binary_tx_handler(ble_bin_buffer, 3);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2 Cmd_mcj (M48 전체 측정)
|
||||
|
||||
```c
|
||||
static int Cmd_mcj(const ParsedCmd *cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
|
||||
// 디바이스 활성화 확인
|
||||
if (device_status != true) {
|
||||
param_error("mcj?");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 측정 모드 설정
|
||||
ADC_PD_MODE = 2;
|
||||
info4 = true;
|
||||
ble_got_new_data = false;
|
||||
processing = true;
|
||||
|
||||
// 압력 측정
|
||||
pressure_all_level_meas();
|
||||
|
||||
// AGC 스위치 OFF
|
||||
AGC_GAIN_SW(false);
|
||||
|
||||
// M48 ADC 시작
|
||||
m48_samples_in_buffer = m_pd_adc_cnt;
|
||||
pd_adc_m48_start = true;
|
||||
|
||||
// 타이머 시작
|
||||
battery_timer_stop();
|
||||
go_batt = true;
|
||||
motion_data_once = true;
|
||||
main_timer_start();
|
||||
|
||||
return 1;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 에러 코드
|
||||
|
||||
| 코드 | 값 | 설명 |
|
||||
|------|-----|------|
|
||||
| `err_code1` | 65535 | 길이 오류 |
|
||||
| `err_code2` | 65534 | 활성화 오류 |
|
||||
| `err_code3` | 65533 | 파라미터 오류 |
|
||||
| `err_code4` | 65532 | '?' 누락 |
|
||||
| `err_code5` | 65531 | 알 수 없는 명령어 |
|
||||
| `err_code6` | 65530 | CRC 오류 |
|
||||
|
||||
---
|
||||
|
||||
## 11. EEPROM 주소 맵
|
||||
|
||||
| 주소 | 크기 | 내용 |
|
||||
|------|------|------|
|
||||
| 0x0010 | 12 bytes | HW_NO (암호화) |
|
||||
| 0x0020 | 6 bytes | Passkey (암호화) |
|
||||
| 0x0030 | 12 bytes | SERIAL_NO (암호화) |
|
||||
| 0x0060 | 1 byte | bond_data_delete |
|
||||
| 0x0065 | 1 byte | reset_status |
|
||||
| 0x0070 | 1 byte | m_pd_adc_cnt |
|
||||
| 0x0080 | 2 bytes | m_pd_delay_us |
|
||||
| 0x0090 | 4 bytes | m_life_cycle |
|
||||
| 0x0480 | 96 bytes | led_pd_dac_v[48] (AGC Gain) |
|
||||
|
||||
---
|
||||
|
||||
## 12. 버전 정보
|
||||
|
||||
- **펌웨어 버전**: FW25LIT2B102
|
||||
- **디바이스명**: MEDIDEV_2004
|
||||
- **문서 작성일**: 2026-01-30
|
||||
- **작성자**: Claude Assistant
|
||||
|
||||
---
|
||||
|
||||
## 13. 관련 문서
|
||||
|
||||
- [W25Q32RV_FLASH_MEMORY.md](W25Q32RV_FLASH_MEMORY.md) - Flash 메모리 스펙
|
||||
- Nordic nRF52840 Datasheet
|
||||
- Nordic SDK 17.x Documentation
|
||||
Reference in New Issue
Block a user