diff --git a/src/command/handlers/cmd_piezo.c b/src/command/handlers/cmd_piezo.c index ff8e19a..96d5367 100644 --- a/src/command/handlers/cmd_piezo.c +++ b/src/command/handlers/cmd_piezo.c @@ -16,6 +16,10 @@ static uint8_t tx_rim_samples[IMU_FIFO_RIM_TARGET_SAMPLES * IMU_FIFO_SAMPLE_BYTES]; +/* + * 테스트용 + * mpa?: piezo 전원 ON + */ int cmd_mpa(const uint8_t *data, uint8_t data_len) { ARG_UNUSED(data); @@ -37,12 +41,15 @@ int cmd_mpa(const uint8_t *data, uint8_t data_len) return 1; } +/* + * 테스트용 + * mpb?: piezo 전원 OFF + */ int cmd_mpb(const uint8_t *data, uint8_t data_len) { ARG_UNUSED(data); ARG_UNUSED(data_len); - /* mpb?: piezo TX/RX 전원 레일을 끈다. */ DBG_CORE("[MPB] enter\r\n"); if (piezo_init() != 0) { @@ -229,11 +236,12 @@ int cmd_mad(const uint8_t *data, uint8_t data_len) /* * 테스트용(이전 정렬모드) - * maa?: - * - piezo 6채널 burst 순서대로 쏘고 - * - echo 샘플을 채널별로 모은 뒤 - * - reb: 패킷 6개 전송 - * - raa: 상태값은 전체 작업 성공/실패 요약 + * maa?: piezo echo sweep + * - 순서: + * 1. piezo 6채널 burst + * 2. echo 샘플 채널별로 모으기 + * 3. reb: 패킷 6개 전송 + * 4. raa: 상태값은 전체 작업 성공/실패 요약 */ int cmd_maa(const uint8_t *data, uint8_t data_len) { @@ -246,22 +254,22 @@ int cmd_maa(const uint8_t *data, uint8_t data_len) power_button_suspend(true); int status = piezo_measure_start_session(); - if (status == ECHO_STATUS_OK) - { - status = piezo_measure_sweep(); - } - if (status == ECHO_STATUS_OK) + if (status == ECHO_STATUS_OK) // Piezo GPIO, 전원, ADC 초기화/wake 성공 { + DBG_PRINTF("[MBB] piezo sweep start\r\n"); + status = piezo_measure_sweep(); + for (uint8_t ch = 0; ch < PIEZO_NUM_CHANNELS; ch++) { + DBG_PRINTF("[MBB] response reb: tx start ch=%d\r\n", ch); cmd_send_response_echo(session, ch, piezo_measure_channel_buffer(ch), piezo_config_get()->samples); } } piezo_power_off(); power_button_suspend(false); - cmd_send_response_u16("raa:", (uint16_t)status); + cmd_send_response_u16("raa:", (uint16_t)status); // 최종 상태값 raa: 전송 DBG_PRINTF("[CMD] maa status=0x%04X\r\n", status); processing = false; @@ -272,8 +280,16 @@ int cmd_maa(const uint8_t *data, uint8_t data_len) * 전체 측정 명령 * mbb?: piezo echo sweep + 배터리 + IMU + IMU 온도 측정 * - 성공 시 rbb 1개, reb 6개, raa 상태값 전송 - * - 실패 시 rbb/reb 생략, raa에 실패 원인 코드 전송 * - processing=true 구간에서는 내부 모니터의 I2C 접근을 막는 기준으로 사용 + * + * - 순서: + * 1. battery / imu / temp 측정 + * 2. rbb: 1개 전송 + * 3. piezo / echo ADC 준비 + * 4. piezo 6채널 burst + * 5. echo 샘플 채널별로 모으기 + * 6. reb: 6개 전송 + * 7. raa: 최종 상태 전송 */ int cmd_mbb(const uint8_t *data, uint8_t data_len) { @@ -285,88 +301,40 @@ int cmd_mbb(const uint8_t *data, uint8_t data_len) int16_t accel[3]; int16_t gyro[3]; - /* - * mbb?는 이 프로젝트에서 가장 무거운 명령 중 하나다. - * - * 순서: - * 1. piezo/echo ADC 준비 - * 2. 6채널 echo sweep - * 3. battery / imu / temp 추가 측정 - * 4. rbb: 1개 전송 - * 5. reb: 6개 전송 - * 6. raa: 최종 상태 전송 - * - * 중간에 하나라도 실패하면 status에 에러 코드를 넣고, - * 성공한 경우에만 묶음 응답(rbb + reb)을 보낸다. - */ processing = true; power_button_suspend(true); DBG_PRINTF("[MBB] cmd start\r\n"); int status = piezo_measure_start_session(); - if (status == ECHO_STATUS_OK) - { - status = piezo_measure_sweep(); - } int batt_mv = -1; int16_t temp_cdeg = INT16_MIN; - if (status == ECHO_STATUS_OK) + if (status == ECHO_STATUS_OK) // Piezo GPIO, 전원, ADC 초기화/wake 성공 { - /* echo sweep 성공 후에만 부가 센서값 읽기 - * - rbb에 포함되는 배터리 전압 - * - 실패 시 ECHO_STATUS_BATT로 종료 - */ DBG_PRINTF("[MBB] battery read\r\n"); batt_mv = battery_read_mv(); - if (batt_mv < 0) - { - status = ECHO_STATUS_BATT; - } - } - if (status == ECHO_STATUS_OK) - { - /* rbb에 포함되는 IMU 6축 값과 IMU 내부 온도 읽기 - * - direct read 경로 사용 - * - 실패 시 ECHO_STATUS_IMU로 종료 - */ DBG_PRINTF("[MBB] imu/temp read\r\n"); - if (imu_read_with_temperature(accel, gyro, &temp_cdeg) != 0) - { - status = ECHO_STATUS_IMU; - } - } + imu_read_with_temperature(accel, gyro, &temp_cdeg); - if (status == ECHO_STATUS_OK) - { - /* mbb? 성공 응답값으로 연속 측정 보호 판정 갱신 - * - 실패한 측정은 호출하지 않아 기존 저전압/고온 카운트 유지 - * - rbb에 실리는 배터리/IMU 온도 값과 같은 값을 사용 - */ - battery_protection_record_continuous(batt_mv, temp_cdeg); - - /* 측정 성공 응답 순서 - * - rbb: 배터리 + IMU + IMU 온도 요약 - * - reb: 채널별 echo raw 데이터 - * - raa: 마지막 상태 코드 - */ - DBG_PRINTF("[MBB] response tx start\r\n"); + DBG_PRINTF("[MBB] response rbb: tx start\r\n"); cmd_send_response_bundle((uint16_t)batt_mv, accel, gyro, temp_cdeg); + DBG_PRINTF("[MBB] piezo sweep start\r\n"); + status = piezo_measure_sweep(); + for (uint8_t ch = 0; ch < PIEZO_NUM_CHANNELS; ch++) { - /* reb: 채널별 raw echo 파형 */ - DBG_PRINTF("[MBB] tx reb ch=%d\r\n", ch); + DBG_PRINTF("[MBB] response reb: tx start ch=%d\r\n", ch); cmd_send_response_echo(session, ch, piezo_measure_channel_buffer(ch), piezo_config_get()->samples); } } piezo_power_off(); power_button_suspend(false); - DBG_PRINTF("[MBB] power off\r\n"); - cmd_send_response_u16("raa:", (uint16_t)status); + DBG_PRINTF("[MBB] done\r\n"); + cmd_send_response_u16("raa:", (uint16_t)status); // 최종 상태값 raa: 전송 DBG_PRINTF("[CMD] mbb status=0x%04X\r\n", status); processing = false; @@ -374,7 +342,15 @@ int cmd_mbb(const uint8_t *data, uint8_t data_len) } /* - * mtb?: piezo sweep + IMU FIFO + * 정렬모드 + * mtb?: IMU FIFO + piezo echo sweep + * - 순서: + * 1. IMU FIFO start + * 2. piezo 6채널 burst + * 3. echo 샘플 채널별로 모으기 + * 4. reb: 패킷 6개 전송 + * 5. raa: 상태값은 전체 작업 성공/실패 요약 + * - IMU FIFO 샘플은 rim: 패킷으로 전송 */ int cmd_mtb(const uint8_t *data, uint8_t data_len) { @@ -389,54 +365,47 @@ int cmd_mtb(const uint8_t *data, uint8_t data_len) power_button_suspend(true); DBG_PRINTF("[MTB] cmd start\r\n"); - int status = ECHO_STATUS_OK; int imu_ret = imu_fifo_start(); if (imu_ret != 0) { DBG_PRINTF("[MTB] fifo start fail ret=%d\r\n", imu_ret); - status = ECHO_STATUS_IMU; } else { fifo_started = true; } - if (status == ECHO_STATUS_OK) - { - status = piezo_measure_start_session(); - } - - if (status == ECHO_STATUS_OK) + int status = piezo_measure_start_session(); + + if (status == ECHO_STATUS_OK) // Piezo GPIO, 전원, ADC 초기화/wake 성공 { + DBG_PRINTF("[MTB] piezo sweep start\r\n"); status = piezo_measure_sweep(); - } - - if (status == ECHO_STATUS_OK) - { + for (uint8_t ch = 0; ch < PIEZO_NUM_CHANNELS; ch++) { + DBG_PRINTF("[MTB] response reb: tx start ch=%d\r\n", ch); cmd_send_response_echo(session, ch, piezo_measure_channel_buffer(ch), piezo_config_get()->samples); } } + + cmd_send_response_u16("raa:", (uint16_t)status); // 최종 상태값 raa: 전송 if (fifo_started) { - int imu_ret = imu_fifo_read_latest(tx_rim_samples, - IMU_FIFO_RIM_TARGET_SAMPLES, - &rim_count); + int imu_ret = imu_fifo_read_latest(tx_rim_samples, IMU_FIFO_RIM_TARGET_SAMPLES, &rim_count); if (imu_ret != 0) { DBG_PRINTF("[MTB] fifo read fail ret=%d\r\n", imu_ret); - status = ECHO_STATUS_IMU; rim_count = 0U; } } - cmd_send_response_rim(tx_rim_samples, rim_count); + cmd_send_response_rim(tx_rim_samples, rim_count); // IMU FIFO 샘플 rim: 전송 + DBG_PRINTF("[CMD] mtb status=0x%04X\r\n", status); piezo_power_off(); power_button_suspend(false); - cmd_send_response_u16("raa:", (uint16_t)status); DBG_PRINTF("[CMD] mtb status=0x%04X rim=%u\r\n", status, rim_count); processing = false; diff --git a/src/command/parser.c b/src/command/parser.c index b89e991..e855091 100644 --- a/src/command/parser.c +++ b/src/command/parser.c @@ -17,8 +17,8 @@ *============================================================================*/ int ble_cmd_dispatch(const uint8_t *buf, uint16_t len) { - DBG_CORE("[PARSER] enter len=%u\r\n", len); - DBG_CORE("[CMD] RX len=%u\r\n", len); + //DBG_CORE("[PARSER] enter len=%u\r\n", len); + //DBG_CORE("[CMD] RX len=%u\r\n", len); char raw_tag[5] = { '?', '?', '?', '?', '\0' }; for (uint16_t i = 0; i < len && i < 4U; i++) diff --git a/src/measurement/piezo_measure.c b/src/measurement/piezo_measure.c index 5d4ae7a..fd2f10e 100644 --- a/src/measurement/piezo_measure.c +++ b/src/measurement/piezo_measure.c @@ -152,7 +152,7 @@ const uint16_t *piezo_measure_single_buffer(void) */ int piezo_measure_start_session(void) { - DBG_PRINTF("[MBB] piezo session start\r\n"); + DBG_PRINTF("[SWEEP] piezo session start\r\n"); int err = piezo_init(); if (err) @@ -178,7 +178,7 @@ int piezo_measure_start_session(void) return ECHO_STATUS_ADC_INIT; } - DBG_PRINTF("[MBB] piezo session ready\r\n"); + DBG_PRINTF("[SWEEP] piezo session ready\r\n"); return ECHO_STATUS_OK; } @@ -191,7 +191,7 @@ int piezo_measure_sweep(void) const piezo_config_t *cfg = piezo_config_get(); uint16_t capture_delay_us = cfg->delay_us; - /* 너무 짧은 delay가 들어오면 burst 직후 ADC capture가 겹치므로 최소 delay 보장 */ + // 너무 짧은 delay가 들어오면 burst 직후 ADC capture가 겹치므로 최소 delay 보장 if (capture_delay_us < PIEZO_BURST_TO_ADC_DELAY_US) { capture_delay_us = PIEZO_BURST_TO_ADC_DELAY_US; @@ -199,12 +199,9 @@ int piezo_measure_sweep(void) for (uint8_t ch = 0; ch < PIEZO_NUM_CHANNELS; ch++) { - DBG_PRINTF("[MBB] sweep ch=%d start\r\n", ch); + DBG_PRINTF("[SWEEP] ch=%d start\r\n", ch); - /* - * MUX 채널 선택 - * 드라이버 내부에서 1.3 ms settle을 기다리고, 아래에서 measurement layer settle 0.5 ms를 추가로 기다린다. - */ + // MUX 채널 선택 int err = piezo_select_channel(ch); if (err) { @@ -214,7 +211,7 @@ int piezo_measure_sweep(void) k_busy_wait(PIEZO_POST_SELECT_SETTLE_US); - /* ADC dummy read/wake (채널 전환 직후 첫 ADC 접근을 실제 데이터에 섞지 않기 위한 준비 단계) */ + // ADC dummy read/wake 2byte (채널 전환 직후 첫 ADC 접근을 실제 데이터에 섞지 않기 위한 준비 단계) err = echo_adc_wake(); if (err) { @@ -222,10 +219,7 @@ int piezo_measure_sweep(void) return ECHO_STATUS_CAPTURE; } - /* - * Dummy burst + dummy capture - * 결과는 버리고, piezo/mux/ADC 입력의 이전 상태가 real 평균에 섞이지 않도록 함 - */ + // Dummy burst + dummy capture - 결과는 버리고, piezo/mux/ADC 입력의 이전 상태가 real 평균에 섞이지 않도록 함 for (uint8_t dummy = 0; dummy < PIEZO_DUMMY_CAPTURE_COUNT; dummy++) { k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); @@ -240,25 +234,25 @@ int piezo_measure_sweep(void) } } - /* 마지막 dummy capture와 첫 real capture 사이에도 같은 회복 시간을 둔다. */ + // 마지막 dummy capture와 첫 real capture 사이에도 같은 회복 시간 k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); - /* 여기부터 실제 평균에 들어갈 capture */ + // 여기부터 실제 평균에 들어갈 capture memset(echo_accum, 0, sizeof(echo_accum)); for (uint16_t avg = 0; avg < cfg->avg; avg++) { - if (avg > 0U) - { - k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); - } + k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); - /* burst-to-capture 사이 타이밍 흔들림을 줄이기 위해 real capture 구간만 IRQ를 잠금 */ + // burst-to-capture 사이 타이밍 흔들림을 줄이기 위해 real capture 구간만 IRQ를 잠금 unsigned int key = irq_lock(); + + // burst + delay + capture piezo_burst_sw((uint8_t)cfg->cycles); k_busy_wait(capture_delay_us); - err = echo_adc_capture(echo_capture, cfg->samples); + + // IRQ 잠금 해제 irq_unlock(key); if (err) { @@ -266,29 +260,30 @@ int piezo_measure_sweep(void) return ECHO_STATUS_CAPTURE; } - /* 같은 sample index끼리 누적 */ + // 같은 sample index끼리 누적 for (uint16_t i = 0; i < cfg->samples; i++) { echo_accum[i] += echo_capture[i]; } } - /* 채널별 최종 평균 파형 저장 - 이후 cmd handler가 reb: 패킷으로 전송 */ + // 채널별 최종 평균 파형 저장 - 이후 cmd handler가 reb: 패킷으로 전송 for (uint16_t i = 0; i < cfg->samples; i++) { piezo_channels[ch][i] = (uint16_t)(echo_accum[i] / cfg->avg); } - DBG_PRINTF("[MBB] sweep ch=%d done\r\n", ch); + DBG_PRINTF("[SWEEP] ch=%d done\r\n", ch); } - DBG_PRINTF("[MBB] sweep done\r\n"); + DBG_PRINTF("[SWEEP] done\r\n"); return ECHO_STATUS_OK; } /* + * 테스트용 * 단일 채널 burst + echo capture - * mec? 디버그/테스트 명령에서 사용하며, 결과는 echo_capture에 평균 저장된다. + * mec? 디버그/테스트 명령에서 사용하며, 결과는 echo_capture에 평균 저장 */ int piezo_measure_single_capture(uint8_t cycles, uint16_t delay_us, @@ -306,7 +301,7 @@ int piezo_measure_single_capture(uint8_t cycles, return ECHO_STATUS_CAPTURE; } - /* averaging 0은 명령 파라미터 누락/미지정으로 보고 1회 capture로 보정한다. */ + /* averaging 0은 명령 파라미터 누락/미지정으로 보고 1회 capture로 보정 */ if (averaging == 0U) { averaging = 1U; @@ -326,7 +321,7 @@ int piezo_measure_single_capture(uint8_t cycles, return ECHO_STATUS_CAPTURE; } - /* real capture 전에 같은 채널에서 dummy burst/capture를 수행하고 버린다. */ + /* real capture 전에 같은 채널에서 dummy burst/capture를 수행하고 버림 */ for (uint8_t dummy = 0; dummy < PIEZO_DUMMY_CAPTURE_COUNT; dummy++) { k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); @@ -340,7 +335,7 @@ int piezo_measure_single_capture(uint8_t cycles, } } - /* 마지막 dummy capture와 첫 real capture 사이에도 같은 회복 시간을 둔다. */ + /* 마지막 dummy capture와 첫 real capture 사이에도 같은 회복 시간 */ k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); memset(echo_accum, 0, sizeof(echo_accum)); @@ -378,8 +373,9 @@ int piezo_measure_single_capture(uint8_t cycles, } /* - * 단일 채널 ADC-only capture. - * piezo burst 없이 현재 echo ADC 입력만 평균해서 확인할 때 사용한다. + * 테스트용 + * 단일 채널 ADC-only capture + * piezo burst 없이 현재 echo ADC 입력만 평균해서 확인할 때 사용 */ int piezo_measure_adc_only_capture(uint16_t num_samples, uint16_t averaging, @@ -423,7 +419,7 @@ int piezo_measure_adc_only_capture(uint16_t num_samples, k_busy_wait(PIEZO_AVG_INTER_BURST_GAP_US); } - /* burst가 없으므로 ADC capture 자체의 간섭만 줄이기 위해 짧게 IRQ를 잠근다. */ + /* burst가 없으므로 ADC capture 자체의 간섭만 줄이기 위해 짧게 IRQ를 잠금 */ unsigned int key = irq_lock(); err = echo_adc_capture(echo_capture, num_samples); irq_unlock(key);