From ae19c959f41b3bf38af8f514206e453414d4f980 Mon Sep 17 00:00:00 2001 From: jhChun Date: Mon, 30 Mar 2026 16:37:41 +0900 Subject: [PATCH] =?UTF-8?q?BLE=20Piezo=206=EC=B1=84=EB=84=90=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=ED=8C=A8=ED=82=B7=20=EB=B3=91=ED=95=A9=20?= =?UTF-8?q?(reb+red=20->=20reb=20=EB=8B=A8=EC=9D=BC=20=ED=8C=A8=ED=82=B7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BLE_MTU_SIZE 240 -> 244 (ATT MTU 247 - 3 = 244, 기존 4B 낭비 해소) - reb: 헤더 축소(14B → 6B) 후 데이터 병합 -> 119샘플까지 단일 패킷(현재 100샘플) - reb: 헤더에서 peak_raw/peak_index/baseline_raw/버전마커 제거 → PC에서 raw 데이터로 직접 계산, 단일 패킷이므로 버전마커 불필요 - 채널 간 딜레이 50ms -> 5ms (dr_binary_tx_safe 내부 재시도로 TX 보장) - delta 전송(rdb/rdd)도 동일 방식 적용, 종료 패킷(ree:/rde:) 제거 - 채널 완료 판단: 종료 패킷(ree:) 제거, reb: 수신 시 채널 완료 (100샘플 기준 단일 패킷) - 전체 완료는 기존과 동일하게 raa:로 판단 --- pc_firm/dr_adc121s051/dr_adc121s051.c | 375 +++++++++----------------- pc_firm/dr_adc121s051/dr_adc121s051.h | 22 +- pc_firm/parser.c | 31 +-- 3 files changed, 150 insertions(+), 278 deletions(-) diff --git a/pc_firm/dr_adc121s051/dr_adc121s051.c b/pc_firm/dr_adc121s051/dr_adc121s051.c index d59c444..3e0e597 100644 --- a/pc_firm/dr_adc121s051/dr_adc121s051.c +++ b/pc_firm/dr_adc121s051/dr_adc121s051.c @@ -517,17 +517,12 @@ extern void dr_sd_delay_ms(uint32_t ms); extern void dr_piezo_burst_sw(uint8_t cycles); /* BLE packet constants */ -#define BLE_MTU_SIZE 240 -#define BLE_FIRST_HEADER_LEN 14 /* "rec:" + header */ -#define BLE_CONT_HEADER_LEN 6 /* "red:" + packet_index */ -#define BLE_FIRST_DATA_LEN (BLE_MTU_SIZE - BLE_FIRST_HEADER_LEN) -#define BLE_CONT_DATA_LEN (BLE_MTU_SIZE - BLE_CONT_HEADER_LEN) +#define BLE_MTU_SIZE 244 /* ATT MTU 247 - 3 (ATT header) = 244 */ +#define BLE_REB_HEADER_LEN 6 /* "reb:" tag(4) + num_samples(2) */ +#define BLE_RED_HEADER_LEN 6 /* "red:" tag(4) + pkt_idx(2) */ +#define BLE_REB_DATA_LEN (BLE_MTU_SIZE - BLE_REB_HEADER_LEN) /* 238 bytes = 119 samples */ +#define BLE_RED_DATA_LEN (BLE_MTU_SIZE - BLE_RED_HEADER_LEN) /* 238 bytes = 119 samples */ #define BLE_PACKET_DELAY_MS 100 /* Inter-packet delay - allow BLE TX buffer to drain */ -#define BLE_FIRST_PACKET_DELAY 5 /* Minimal delay */ - -/* Protocol version markers (OR'd with packet count in reb: header) */ -#define MEC_VERSION_MARKER 0xD000 /* vD: raa only (no ree) - ree causes packet loss */ -#define MAA_VERSION_MARKER 0xF000 /* vF: maa? hardcoded 8-channel debug */ /*============================================================================== * PIEZO CHANNEL SELECTION @@ -565,15 +560,14 @@ extern void dr_piezo_select_channel(uint8_t channel); /** * @brief Integrated burst + capture + BLE transmit (16-bit raw data) * - * PROTOCOL v3: Small header packet + separate data packets with delays - * (Large first packets were being dropped by BLE stack) + * reb+red merged protocol: header와 데이터를 첫 패킷에 합침 * * Response format: - * Packet 1 (reb:): header only (14 bytes) - * Packet 2~N (red:): pkt_idx(2) + raw_data(up to 234 bytes = 117 samples) - * Final (ree:): total_packets(2) + * Packet 1 (reb:): num_samples(2) + raw_data(up to 238 bytes = 119 samples) + * Packet 2~N (red:): pkt_idx(2) + raw_data(up to 238 bytes) — 119샘플 초과 시만 + * Final (raa:): status(2) — skip_raa=0 일 때만 * - * With 140 samples: 280 bytes = reb:(14) + red:(6+234) + red:(6+46) + ree:(6) + * With 100 samples: 200 bytes = reb:(6+200) = 206 bytes (단일 패킷) */ dr_adc_err_t dr_adc_burst_capture_transmit(uint8_t freq_option, uint16_t delay_us, uint16_t num_samples, uint8_t cycles, @@ -589,13 +583,7 @@ dr_adc_err_t dr_adc_burst_capture_transmit(uint8_t freq_option, uint16_t delay_u if (averaging > 1000) averaging = 1000; /* Maximum 1000 */ if (piezo_ch >= MAA_NUM_CHANNELS) piezo_ch = 0; /* 채널 범위 검증 */ - dr_adc_echo_t echo; - echo.peak_raw = 0; - echo.peak_mv = 0; - echo.peak_index = 0; - echo.peak_time_us = 0; - echo.baseline_raw = 0; - echo.num_samples = 0; + /* echo 분석은 PC에서 raw 데이터로 직접 수행 */ /* Accumulator buffer for averaging (32-bit to prevent overflow) */ static uint32_t accum_buffer[DR_ADC_ECHO_SAMPLES_MAX]; @@ -717,82 +705,58 @@ dr_adc_err_t dr_adc_burst_capture_transmit(uint8_t freq_option, uint16_t delay_u ADC_LOG("mec: averaged %u measurements", averaging); } - /*--- Step 6: Analyze averaged data ---*/ - dr_adc_analyze_echo(m_echo_buffer, num_samples, &echo, 100); + /*--- Step 6: Transmit via BLE - reb: + red: merged protocol ---*/ + /* Packet 1 (reb:): tag(4) + num_samples(2) + data(up to 238 bytes = 119 samples) */ + /* Packet 2~N (red:): tag(4) + pkt_idx(2) + data(up to 238 bytes) — only if > 119 samples */ - /*--- Step 6: Transmit via BLE - PROTOCOL v3 ---*/ - /* Packet 1: reb:(4) + header(10) = 14 bytes ONLY (no data) */ - /* Packet 2~N: red:(4) + pkt_idx(2) + data(up to 234 bytes) */ - /* Final: ree:(4) + total_pkts(2) = 6 bytes */ - - uint16_t total_data_bytes = echo.num_samples * 2; - uint16_t cont_pkt_data_cap = BLE_MTU_SIZE - BLE_CONT_HEADER_LEN; /* 234 bytes */ - - /* Calculate data packets needed (header packet doesn't carry data) */ - uint16_t data_packets = (total_data_bytes + cont_pkt_data_cap - 1) / cont_pkt_data_cap; - - /* Version marker: select based on skip_raa (0=mec, 1=maa) */ - uint16_t version_marker = skip_raa ? MAA_VERSION_MARKER : MEC_VERSION_MARKER; - uint16_t pkts_with_ver = data_packets | version_marker; - - ADC_LOG("mec v6: samples=%u data=%u bytes, packets=%u", echo.num_samples, total_data_bytes, data_packets); - - /* Packet 1: reb: header ONLY (14 bytes) - small packet won't be dropped */ - ble_buffer[0] = 'r'; - ble_buffer[1] = 'e'; - ble_buffer[2] = 'b'; - ble_buffer[3] = ':'; - ble_buffer[4] = (uint8_t)(pkts_with_ver & 0xFF); - ble_buffer[5] = (uint8_t)(pkts_with_ver >> 8); - ble_buffer[6] = (uint8_t)(echo.peak_raw & 0xFF); - ble_buffer[7] = (uint8_t)(echo.peak_raw >> 8); - ble_buffer[8] = (uint8_t)(echo.peak_index & 0xFF); - ble_buffer[9] = (uint8_t)(echo.peak_index >> 8); - ble_buffer[10] = (uint8_t)(echo.baseline_raw & 0xFF); - ble_buffer[11] = (uint8_t)(echo.baseline_raw >> 8); - ble_buffer[12] = (uint8_t)(echo.num_samples & 0xFF); - ble_buffer[13] = (uint8_t)(echo.num_samples >> 8); - - dr_binary_tx_safe(ble_buffer, 7); /* Send header only: 14 bytes = 7 words */ - dr_sd_delay_ms(BLE_PACKET_DELAY_MS); /* Wait for BLE stack */ - - /* Data packets (red:) - starting from pkt index 0 */ + uint16_t total_data_bytes = num_samples * 2; uint16_t src_idx = 0; - for (uint16_t pkt = 0; pkt < data_packets; pkt++) { - ble_buffer[0] = 'r'; - ble_buffer[1] = 'e'; - ble_buffer[2] = 'd'; - ble_buffer[3] = ':'; + + /* Packet 1: reb: header + data merged */ + ble_buffer[0] = 'r'; ble_buffer[1] = 'e'; ble_buffer[2] = 'b'; ble_buffer[3] = ':'; + ble_buffer[4] = (uint8_t)(num_samples & 0xFF); + ble_buffer[5] = (uint8_t)(num_samples >> 8); + + uint16_t dst_idx = BLE_REB_HEADER_LEN; + uint16_t first_chunk = (total_data_bytes > BLE_REB_DATA_LEN) ? BLE_REB_DATA_LEN : total_data_bytes; + while (src_idx < num_samples && (dst_idx - BLE_REB_HEADER_LEN) < first_chunk) { + uint16_t sample = m_echo_buffer[src_idx++] & 0x0FFF; + ble_buffer[dst_idx++] = (uint8_t)(sample & 0xFF); + ble_buffer[dst_idx++] = (uint8_t)(sample >> 8); + } + + dr_binary_tx_safe(ble_buffer, dst_idx / 2); + + /* Continuation packets (red:) — only if data didn't fit in reb: */ + uint16_t pkt = 0; + while (src_idx < num_samples) { + dr_sd_delay_ms(BLE_PACKET_DELAY_MS); + + ble_buffer[0] = 'r'; ble_buffer[1] = 'e'; ble_buffer[2] = 'd'; ble_buffer[3] = ':'; ble_buffer[4] = (uint8_t)(pkt & 0xFF); ble_buffer[5] = (uint8_t)(pkt >> 8); - uint16_t dst_idx = 6; - uint16_t bytes_this_pkt = 0; - while (src_idx < echo.num_samples && bytes_this_pkt < cont_pkt_data_cap) { + dst_idx = BLE_RED_HEADER_LEN; + while (src_idx < num_samples && (dst_idx - BLE_RED_HEADER_LEN) < BLE_RED_DATA_LEN) { uint16_t sample = m_echo_buffer[src_idx++] & 0x0FFF; ble_buffer[dst_idx++] = (uint8_t)(sample & 0xFF); ble_buffer[dst_idx++] = (uint8_t)(sample >> 8); - bytes_this_pkt += 2; } - dr_binary_tx_safe(ble_buffer, dst_idx / 2); /* bytes to words */ - dr_sd_delay_ms(BLE_PACKET_DELAY_MS); /* Inter-packet delay */ + dr_binary_tx_safe(ble_buffer, dst_idx / 2); + pkt++; } - /* vD: Send raa: only - ree: causes subsequent packet loss */ - /* DrBench now saves channel data when receiving raa: */ - /* skip_raa: 0=send raa (mec), 1=skip raa (maa - caller sends final raa) */ + /* raa: completion — skip_raa: 0=send (mec), 1=skip (maa - caller sends final raa) */ if (!skip_raa) { - ble_buffer[0] = 'r'; - ble_buffer[1] = 'a'; - ble_buffer[2] = 'a'; - ble_buffer[3] = ':'; + dr_sd_delay_ms(BLE_PACKET_DELAY_MS); + ble_buffer[0] = 'r'; ble_buffer[1] = 'a'; ble_buffer[2] = 'a'; ble_buffer[3] = ':'; ble_buffer[4] = 0x00; ble_buffer[5] = 0x00; - dr_binary_tx_safe(ble_buffer, 3); /* 6 bytes = 3 words */ + dr_binary_tx_safe(ble_buffer, 3); } - ADC_LOG("mec v6: complete - reb + red*%u + skip_raa=%u (%u samples)", data_packets, skip_raa, echo.num_samples); + ADC_LOG("mec: reb+data merged, skip_raa=%u (%u samples)", skip_raa, num_samples); return DR_ADC_OK; } @@ -876,16 +840,7 @@ dr_adc_err_t dr_adc_capture_channel_only(uint8_t freq_option, uint16_t delay_us, } out_channel->num_samples = num_samples; - - /* Analyze echo data */ - dr_adc_echo_t echo; - dr_adc_analyze_echo(out_channel->samples, num_samples, &echo, 100); - out_channel->peak_raw = echo.peak_raw; - out_channel->peak_index = echo.peak_index; - out_channel->baseline_raw = echo.baseline_raw; - - /* peak, index, baseline 확인용 로그 */ - //if (g_plat.log) g_plat.log("CH%u: peak=%u index=%u baseline=%u\r\n", piezo_ch, out_channel->peak_raw, out_channel->peak_index, out_channel->baseline_raw); + /* peak/baseline 분석은 PC에서 raw 데이터로 직접 수행 */ return DR_ADC_OK; } @@ -894,87 +849,48 @@ dr_adc_err_t dr_adc_capture_channel_only(uint8_t freq_option, uint16_t delay_us, dr_adc_err_t dr_adc_transmit_channel(const dr_maa_channel_t *ch_data, uint8_t *ble_buffer) { - /* Debug BEFORE null check to see if we even enter the function */ - dr_ble_debug(0x00FF, 0xAAAA); /* Function called marker */ - if (ch_data == NULL || ble_buffer == NULL) { - dr_ble_debug(0x00FE, (ch_data == NULL ? 0x0001 : 0) | (ble_buffer == NULL ? 0x0002 : 0)); return DR_ADC_ERR_INVALID_PARAM; } - dr_ble_debug(0x0100, ch_data->num_samples); /* Function entry - params valid */ - uint16_t total_data_bytes = ch_data->num_samples * 2; - uint16_t cont_pkt_data_cap = BLE_MTU_SIZE - BLE_CONT_HEADER_LEN; /* 234 bytes */ - uint16_t data_packets = (total_data_bytes + cont_pkt_data_cap - 1) / cont_pkt_data_cap; - uint16_t total_packets = 1 + data_packets; - - /* Version marker: MAA_VERSION_MARKER | total_packets */ - uint16_t pkt_with_ver = total_packets | MAA_VERSION_MARKER; - - dr_ble_debug(0x0101, total_packets); /* Before reb: */ - - /* Packet 1: reb: header (14 bytes) */ - ble_buffer[0] = 'r'; - ble_buffer[1] = 'e'; - ble_buffer[2] = 'b'; - ble_buffer[3] = ':'; - ble_buffer[4] = (uint8_t)(pkt_with_ver & 0xFF); - ble_buffer[5] = (uint8_t)(pkt_with_ver >> 8); - ble_buffer[6] = (uint8_t)(ch_data->peak_raw & 0xFF); - ble_buffer[7] = (uint8_t)(ch_data->peak_raw >> 8); - ble_buffer[8] = (uint8_t)(ch_data->peak_index & 0xFF); - ble_buffer[9] = (uint8_t)(ch_data->peak_index >> 8); - ble_buffer[10] = (uint8_t)(ch_data->baseline_raw & 0xFF); - ble_buffer[11] = (uint8_t)(ch_data->baseline_raw >> 8); - ble_buffer[12] = (uint8_t)(ch_data->num_samples & 0xFF); - ble_buffer[13] = (uint8_t)(ch_data->num_samples >> 8); - - /* Send reb: header */ - /* Use dr_binary_tx_safe like mec? does, with dr_sd_delay_ms for SoftDevice */ - dr_binary_tx_safe(ble_buffer, 7); - dr_sd_delay_ms(BLE_PACKET_DELAY_MS); - - dr_ble_debug(0x0102, data_packets); /* After reb: */ - - /* Data packets (red:) */ uint16_t src_idx = 0; - for (uint16_t pkt = 0; pkt < data_packets; pkt++) { - ble_buffer[0] = 'r'; - ble_buffer[1] = 'e'; - ble_buffer[2] = 'd'; - ble_buffer[3] = ':'; + + /* Packet 1: reb: header + data merged */ + ble_buffer[0] = 'r'; ble_buffer[1] = 'e'; ble_buffer[2] = 'b'; ble_buffer[3] = ':'; + ble_buffer[4] = (uint8_t)(ch_data->num_samples & 0xFF); + ble_buffer[5] = (uint8_t)(ch_data->num_samples >> 8); + + uint16_t dst_idx = BLE_REB_HEADER_LEN; + uint16_t first_chunk = (total_data_bytes > BLE_REB_DATA_LEN) ? BLE_REB_DATA_LEN : total_data_bytes; + while (src_idx < ch_data->num_samples && (dst_idx - BLE_REB_HEADER_LEN) < first_chunk) { + uint16_t sample = ch_data->samples[src_idx++] & 0x0FFF; + ble_buffer[dst_idx++] = (uint8_t)(sample & 0xFF); + ble_buffer[dst_idx++] = (uint8_t)(sample >> 8); + } + + dr_binary_tx_safe(ble_buffer, dst_idx / 2); + + /* Continuation packets (red:) — only if data didn't fit in reb: */ + uint16_t pkt = 0; + while (src_idx < ch_data->num_samples) { + dr_sd_delay_ms(BLE_PACKET_DELAY_MS); + + ble_buffer[0] = 'r'; ble_buffer[1] = 'e'; ble_buffer[2] = 'd'; ble_buffer[3] = ':'; ble_buffer[4] = (uint8_t)(pkt & 0xFF); ble_buffer[5] = (uint8_t)(pkt >> 8); - uint16_t dst_idx = 6; - uint16_t bytes_this_pkt = 0; - while (src_idx < ch_data->num_samples && bytes_this_pkt < cont_pkt_data_cap) { + dst_idx = BLE_RED_HEADER_LEN; + while (src_idx < ch_data->num_samples && (dst_idx - BLE_RED_HEADER_LEN) < BLE_RED_DATA_LEN) { uint16_t sample = ch_data->samples[src_idx++] & 0x0FFF; ble_buffer[dst_idx++] = (uint8_t)(sample & 0xFF); ble_buffer[dst_idx++] = (uint8_t)(sample >> 8); - bytes_this_pkt += 2; } dr_binary_tx_safe(ble_buffer, dst_idx / 2); - dr_sd_delay_ms(BLE_PACKET_DELAY_MS); - - dr_ble_debug(0x0103, pkt); /* red: packet sent */ + pkt++; } - dr_ble_debug(0x0104, 0); /* Before ree: */ - - /* Final packet: ree: */ - ble_buffer[0] = 'r'; - ble_buffer[1] = 'e'; - ble_buffer[2] = 'e'; - ble_buffer[3] = ':'; - ble_buffer[4] = (uint8_t)(total_packets & 0xFF); - ble_buffer[5] = (uint8_t)(total_packets >> 8); - dr_binary_tx_safe(ble_buffer, 3); - - dr_ble_debug(0x010F, 0); /* Function complete */ - return DR_ADC_OK; } @@ -1036,73 +952,46 @@ dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data, ch_data->num_samples, compressed_size, 100.0f * compressed_size / (ch_data->num_samples * 2)); - uint16_t cont_pkt_data_cap = BLE_MTU_SIZE - BLE_CONT_HEADER_LEN; /* 234 bytes */ - uint16_t data_packets = (compressed_size + cont_pkt_data_cap - 1) / cont_pkt_data_cap; - uint16_t total_packets = 1 + data_packets; + /* Packet 1: rdb: header(8) + delta data merged */ + ble_buffer[0] = 'r'; ble_buffer[1] = 'd'; ble_buffer[2] = 'b'; ble_buffer[3] = ':'; + ble_buffer[4] = (uint8_t)(ch_data->num_samples & 0xFF); + ble_buffer[5] = (uint8_t)(ch_data->num_samples >> 8); + ble_buffer[6] = (uint8_t)(compressed_size & 0xFF); + ble_buffer[7] = (uint8_t)(compressed_size >> 8); - /* Version marker for delta mode: 0xC000 | total_packets */ - uint16_t pkt_with_ver = total_packets | 0xC000; /* v2 delta marker */ + #define BLE_RDB_HEADER_LEN 8 /* rdb: tag(4) + num_samples(2) + compressed_size(2) */ + uint16_t rdb_data_cap = BLE_MTU_SIZE - BLE_RDB_HEADER_LEN; /* 236 bytes */ - /* Packet 1: rdb: header (16 bytes) - includes compressed_size */ - ble_buffer[0] = 'r'; - ble_buffer[1] = 'd'; - ble_buffer[2] = 'b'; - ble_buffer[3] = ':'; - ble_buffer[4] = (uint8_t)(pkt_with_ver & 0xFF); - ble_buffer[5] = (uint8_t)(pkt_with_ver >> 8); - ble_buffer[6] = (uint8_t)(ch_data->peak_raw & 0xFF); - ble_buffer[7] = (uint8_t)(ch_data->peak_raw >> 8); - ble_buffer[8] = (uint8_t)(ch_data->peak_index & 0xFF); - ble_buffer[9] = (uint8_t)(ch_data->peak_index >> 8); - ble_buffer[10] = (uint8_t)(ch_data->baseline_raw & 0xFF); - ble_buffer[11] = (uint8_t)(ch_data->baseline_raw >> 8); - ble_buffer[12] = (uint8_t)(ch_data->num_samples & 0xFF); - ble_buffer[13] = (uint8_t)(ch_data->num_samples >> 8); - ble_buffer[14] = (uint8_t)(compressed_size & 0xFF); - ble_buffer[15] = (uint8_t)(compressed_size >> 8); - - dr_binary_tx_safe(ble_buffer, 8); /* 16 bytes = 8 words */ - dr_sd_delay_ms(BLE_PACKET_DELAY_MS); - - /* Data packets (rdd:) */ + uint16_t dst_idx = BLE_RDB_HEADER_LEN; uint16_t src_idx = 0; - for (uint16_t pkt = 0; pkt < data_packets; pkt++) - { - ble_buffer[0] = 'r'; - ble_buffer[1] = 'd'; - ble_buffer[2] = 'd'; - ble_buffer[3] = ':'; + uint16_t first_chunk = (compressed_size > rdb_data_cap) ? rdb_data_cap : compressed_size; + while (src_idx < first_chunk) { + ble_buffer[dst_idx++] = delta_buffer[src_idx++]; + } + /* Pad to word boundary if needed */ + if (dst_idx & 1) ble_buffer[dst_idx++] = 0; + + dr_binary_tx_safe(ble_buffer, dst_idx / 2); + + /* Continuation packets (rdd:) — only if data didn't fit */ + uint16_t pkt = 0; + while (src_idx < compressed_size) { + dr_sd_delay_ms(BLE_PACKET_DELAY_MS); + + ble_buffer[0] = 'r'; ble_buffer[1] = 'd'; ble_buffer[2] = 'd'; ble_buffer[3] = ':'; ble_buffer[4] = (uint8_t)(pkt & 0xFF); ble_buffer[5] = (uint8_t)(pkt >> 8); - uint16_t dst_idx = 6; - uint16_t bytes_this_pkt = 0; - while (src_idx < compressed_size && bytes_this_pkt < cont_pkt_data_cap) - { + dst_idx = BLE_RED_HEADER_LEN; + while (src_idx < compressed_size && (dst_idx - BLE_RED_HEADER_LEN) < BLE_RED_DATA_LEN) { ble_buffer[dst_idx++] = delta_buffer[src_idx++]; - bytes_this_pkt++; - } - - /* Pad to word boundary if needed */ - if (dst_idx & 1) - { - ble_buffer[dst_idx++] = 0; } + if (dst_idx & 1) ble_buffer[dst_idx++] = 0; dr_binary_tx_safe(ble_buffer, dst_idx / 2); - dr_sd_delay_ms(BLE_PACKET_DELAY_MS); + pkt++; } - /* Final packet: rde: */ - ble_buffer[0] = 'r'; - ble_buffer[1] = 'd'; - ble_buffer[2] = 'e'; - ble_buffer[3] = ':'; - ble_buffer[4] = (uint8_t)(total_packets & 0xFF); - ble_buffer[5] = (uint8_t)(total_packets >> 8); - dr_binary_tx_safe(ble_buffer, 3); - dr_sd_delay_ms(BLE_PACKET_DELAY_MS); - return DR_ADC_OK; } @@ -1117,8 +1006,7 @@ dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data, /* Global async context */ static maa_async_ctx_t g_maa_ctx = { .state = MAA_ASYNC_IDLE }; -/* Version marker for async MAA */ -#define MAA_ASYNC_VERSION_MARKER 0xC000 /* vC: async 8-channel + raa delay fix + cleanup */ +/* (version marker 제거 — reb+red merged protocol) */ /** * @brief Capture one channel (internal helper) @@ -1141,7 +1029,10 @@ static dr_adc_err_t maa_async_capture_channel(uint8_t ch) } /** - * @brief Send reb: header for current channel + * @brief Send reb: header + data merged for current channel + * + * reb: tag(4) + num_samples(2) + data(up to 238 bytes) + * 100샘플(200B) 이하면 이 패킷 하나로 채널 전송 완료 */ static void maa_async_send_header(void) { @@ -1149,45 +1040,33 @@ static void maa_async_send_header(void) uint8_t *buf = g_maa_ctx.ble_buffer; uint16_t total_data_bytes = ch->num_samples * 2; - uint16_t cont_pkt_data_cap = BLE_MTU_SIZE - BLE_CONT_HEADER_LEN; - g_maa_ctx.data_packets = (total_data_bytes + cont_pkt_data_cap - 1) / cont_pkt_data_cap; - g_maa_ctx.total_packets = 1 + g_maa_ctx.data_packets; - uint16_t pkts_with_ver = g_maa_ctx.total_packets | MAA_ASYNC_VERSION_MARKER; - - /* reb: header (14 bytes) */ + /* reb: header + data merged */ buf[0] = 'r'; buf[1] = 'e'; buf[2] = 'b'; buf[3] = ':'; - buf[4] = (uint8_t)(pkts_with_ver & 0xFF); - buf[5] = (uint8_t)(pkts_with_ver >> 8); - buf[6] = (uint8_t)(ch->peak_raw & 0xFF); - buf[7] = (uint8_t)(ch->peak_raw >> 8); - buf[8] = (uint8_t)(ch->peak_index & 0xFF); - buf[9] = (uint8_t)(ch->peak_index >> 8); - buf[10] = (uint8_t)(ch->baseline_raw & 0xFF); - buf[11] = (uint8_t)(ch->baseline_raw >> 8); - buf[12] = (uint8_t)(ch->num_samples & 0xFF); - buf[13] = (uint8_t)(ch->num_samples >> 8); + buf[4] = (uint8_t)(ch->num_samples & 0xFF); + buf[5] = (uint8_t)(ch->num_samples >> 8); - dr_binary_tx_safe(buf, 7); /* 14 bytes = 7 words */ + uint16_t dst_idx = BLE_REB_HEADER_LEN; + uint16_t first_chunk = (total_data_bytes > BLE_REB_DATA_LEN) ? BLE_REB_DATA_LEN : total_data_bytes; + uint16_t src_idx = 0; + while (src_idx < ch->num_samples && (dst_idx - BLE_REB_HEADER_LEN) < first_chunk) { + uint16_t sample = ch->samples[src_idx++]; + buf[dst_idx++] = (uint8_t)(sample & 0xFF); + buf[dst_idx++] = (uint8_t)(sample >> 8); + } - /* 50ms BLE 대기 시간을 활용하여 raw 덤프 로그 (캡처 시간에 영향 없음) - if (g_plat.log) - { - if (g_maa_ctx.current_ch > 0) g_plat.log("\r\n"); - g_plat.log("CH%u raw (%u samples):\r\n", g_maa_ctx.current_ch, ch->num_samples); - for (uint16_t i = 0; i < ch->num_samples; i++) - { - g_plat.log("%u ", ch->samples[i]); - if ((i + 1) % 16 == 0) g_plat.log("\r\n"); - } - if (ch->num_samples % 16 != 0) g_plat.log("\r\n"); - }*/ - - dr_sd_delay_ms(50); /* Allow BLE stack to process TX */ + dr_binary_tx_safe(buf, dst_idx / 2); + dr_sd_delay_ms(5); /* dr_binary_tx_safe 내부 재시도(40ms)로 TX 완료 보장, 최소 딜레이만 */ g_maa_ctx.current_pkt = 0; - g_maa_ctx.data_offset = 0; - g_maa_ctx.state = MAA_ASYNC_TX_DATA; + g_maa_ctx.data_offset = src_idx * 2; /* 이미 전송한 바이트 수 */ + + /* 데이터가 첫 패킷에 다 들어갔으면 바로 다음 채널로 */ + if (g_maa_ctx.data_offset >= total_data_bytes) { + g_maa_ctx.state = MAA_ASYNC_TX_DATA; /* send_data_packet()에서 false 반환 → 다음 채널 */ + } else { + g_maa_ctx.state = MAA_ASYNC_TX_DATA; + } } /** @@ -1207,7 +1086,7 @@ static bool maa_async_send_data_packet(void) uint16_t pkt_idx = g_maa_ctx.current_pkt; uint16_t remaining = total_data_bytes - g_maa_ctx.data_offset; - uint16_t chunk_size = (remaining > BLE_CONT_DATA_LEN) ? BLE_CONT_DATA_LEN : remaining; + uint16_t chunk_size = (remaining > BLE_RED_DATA_LEN) ? BLE_RED_DATA_LEN : remaining; /* red: packet header */ buf[0] = 'r'; buf[1] = 'e'; buf[2] = 'd'; buf[3] = ':'; diff --git a/pc_firm/dr_adc121s051/dr_adc121s051.h b/pc_firm/dr_adc121s051/dr_adc121s051.h index 507e685..b668897 100644 --- a/pc_firm/dr_adc121s051/dr_adc121s051.h +++ b/pc_firm/dr_adc121s051/dr_adc121s051.h @@ -311,7 +311,7 @@ void dr_adc_print_buffer(const uint16_t *buffer, uint16_t num_samples); * @return dr_adc_err_t Error code * * @note Must call dr_adc_register_ble_tx() before using this function - * @note BLE packets: reb: (header), red: (data), ree: (end) + * @note BLE packets: reb: (header+data merged), red: (continuation, >119 samples only) * @note Higher averaging reduces noise but increases measurement time (~0.3ms per avg) */ dr_adc_err_t dr_adc_burst_capture_transmit(uint8_t freq_option, uint16_t delay_us, @@ -345,9 +345,6 @@ void dr_piezo_select_channel(uint8_t channel); typedef struct { uint16_t samples[MAA_SAMPLES_MAX]; /**< Raw sample data */ uint16_t num_samples; /**< Actual sample count */ - uint16_t peak_raw; /**< Peak amplitude */ - uint16_t peak_index; /**< Peak sample index */ - uint16_t baseline_raw; /**< Baseline level */ } dr_maa_channel_t; /** @@ -373,10 +370,11 @@ dr_adc_err_t dr_adc_capture_channel_only(uint8_t freq_option, uint16_t delay_us, /** * @brief Transmit captured channel data via BLE * - * Sends previously captured channel data using reb:/red:/ree: protocol. + * Sends previously captured channel data using reb+red merged protocol. + * reb: tag(4) + num_samples(2) + data(up to 238B). red: only if > 119 samples. * * @param ch_data Pointer to captured channel data - * @param ble_buffer Working buffer for BLE packets (>= 240 bytes) + * @param ble_buffer Working buffer for BLE packets (>= 244 bytes) * @return dr_adc_err_t Error code */ dr_adc_err_t dr_adc_transmit_channel(const dr_maa_channel_t *ch_data, @@ -410,7 +408,7 @@ dr_adc_err_t dr_adc_delta_compress(const uint16_t *samples, uint16_t num_samples /** * @brief Transmit captured channel data via BLE with delta compression * - * Uses rdb:/rdd:/rde: protocol (delta variant of reb:/red:/ree:) + * Uses rdb+rdd merged protocol (delta variant of reb+red merged) * * @param ch_data Pointer to captured channel data * @param ble_buffer Working buffer for BLE packets (>= 240 bytes) @@ -424,8 +422,8 @@ dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data, * * Design: State machine driven by BLE TX complete events * Flow: - * maa? cmd -> maa_async_start() -> capture CH0 -> TX reb: -> TX red: ... - * BLE_NUS_EVT_TX_RDY -> maa_async_continue() -> TX next packet or next channel + * maa? cmd -> maa_async_start() -> capture all CH -> TX reb:(header+data) -> TX red: (if needed) + * BLE_NUS_EVT_TX_RDY -> maa_async_on_tx_ready() -> TX next packet or next channel * All done -> TX raa: -> state=IDLE *============================================================================*/ @@ -433,7 +431,7 @@ dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data, typedef enum { MAA_ASYNC_IDLE = 0, /**< Not active */ MAA_ASYNC_CAPTURING, /**< ADC capture in progress */ - MAA_ASYNC_TX_HEADER, /**< Sending reb: header */ + MAA_ASYNC_TX_HEADER, /**< Sending reb: header+data merged */ MAA_ASYNC_TX_DATA, /**< Sending red: data packets */ MAA_ASYNC_NEXT_CHANNEL, /**< Preparing next channel */ MAA_ASYNC_COMPLETE /**< Sending raa: and finishing */ @@ -452,8 +450,6 @@ typedef struct { uint16_t averaging; /**< Averaging count */ uint8_t *ble_buffer; /**< Working buffer for BLE packets */ dr_maa_channel_t channels[MAA_NUM_CHANNELS]; /**< Captured data for each channel */ - uint16_t total_packets; /**< Total packets for current channel */ - uint16_t data_packets; /**< Data packets for current channel */ bool pre_capture_all; /**< true: 전채널 캡처 완료 후 일괄 전송 (mbb용) */ void (*on_complete_cb)(void); /**< 비동기 캡처 완료 후 호출될 콜백 (NULL이면 미사용) */ } maa_async_ctx_t; @@ -469,7 +465,7 @@ typedef struct { * @param num_samples Samples per channel (1~200) * @param cycles Burst cycles (3~7) * @param averaging Averaging count (1~1000) - * @param ble_buffer Working buffer (>= 240 bytes) + * @param ble_buffer Working buffer (>= 244 bytes) * @return dr_adc_err_t DR_ADC_OK if started successfully */ dr_adc_err_t maa_async_start(uint8_t freq_option, uint16_t delay_us, diff --git a/pc_firm/parser.c b/pc_firm/parser.c index 6324fa7..1f36d83 100644 --- a/pc_firm/parser.c +++ b/pc_firm/parser.c @@ -356,9 +356,9 @@ static bool dr_parse_cmd(const uint8_t *buffer, uint8_t length, ParsedCmd *out) * - TX/RX 전원 활성화 (mpa? / rpa:) - test용 * - TX/RX 전원 비활성화 (mpb? / rpb:) - test용 * - 단일 채널 Burst (mpc? / rpc:) - test용 - * - 단일 채널 Burst + ADC -> echo capture (mec? / reb: -> red: -> ree:) : TX/RX Active -> 응답 -> TX/RX Sleep - * - 모든 채널 Burst + ADC -> echo capture (maa? / reb: -> red: -> raa:) : TX/RX Active -> 응답 -> TX/RX Sleep - * - 모든 채널 Burst + ADC -> echo capture (mbb? / reb: -> red: -> raa:) + 각종 센서 측정(배터리, IMU, 온도) : TX/RX Active -> 응답 -> TX/RX Sleep (NEW!) + * - 단일 채널 Burst + ADC -> echo capture (mec? / reb: merged -> raa:) : TX/RX Active -> 응답 -> TX/RX Sleep + * - 모든 채널 Burst + ADC -> echo capture (maa? / reb: merged -> raa:) : TX/RX Active -> 응답 -> TX/RX Sleep + * - 모든 채널 Burst + ADC -> echo capture (mbb? / reb: merged -> raa:) + 각종 센서 측정(배터리, IMU, 온도) : TX/RX Active -> 응답 -> TX/RX Sleep * * 삭제 명령어 * - 디바이스 활성화/슬립 : TX 전원 활성화/비활성화와 동일 기능 @@ -787,13 +787,12 @@ static int Cmd_mpc(const ParsedCmd *cmd) * word 4: averaging (기본=1) - 평균화 횟수 (1~1000, 노이즈 저감용) * word 5: piezo_ch (기본=0) - 피에조 채널 (0~7) * - * 응답 멀티패킷 형식 (16비트 원시): - * 헤더 패킷 ("reb:"): total_pkts, peak, idx, baseline, samples - * 데이터 패킷 ("red:"): pkt_idx + 16비트 ADC 원시 데이터 - * 종료 패킷 ("ree:"): total_bytes_sent + * 응답 패킷 형식 (reb+red merged protocol): + * 첫 패킷 ("reb:"): num_samples(2) + raw_data(up to 238B = 119샘플) + * 연속 패킷 ("red:"): pkt_idx(2) + raw_data(up to 238B) — 119샘플 초과 시만 + * 완료 패킷 ("raa:"): status(2) * - * 16비트 포맷: 샘플당 2바이트 (Little-Endian) - * 예: 140샘플(20cm) = 280바이트 = 약 2패킷 + * 100샘플 기준: reb: 1패킷(206B)으로 완료 */ static int Cmd_mec(const ParsedCmd *cmd) { @@ -936,14 +935,12 @@ static int Cmd_cmd(const ParsedCmd *cmd) * 주파수 = 1.8MHz, 딜레이 = 10us, 샘플 수 = 140 * 사이클 = 7, 평균화 = 5회 * - * 응답 형식: - * 각 채널(CH0~CH3)마다: - * reb: [총패킷수(2)] [피크(2)] [인덱스(2)] [기준선(2)] [샘플수(2)] - * red: [패킷순번(2)] [데이터...] + * 응답 형식 (reb+red merged protocol): + * 각 채널마다: + * reb: [샘플수(2)] [raw_data...] — 119샘플 이하면 단일 패킷 + * red: [패킷순번(2)] [데이터...] — 119샘플 초과 시만 * 전체 완료: * raa: [상태(2)] - * - * 버전 마커: 0xA000 (vA) = 비동기 4채널 */ /* 피에조 캡처 파라미터: FDS(m_config)에서 로드, 앱에서 변경 가능 */ @@ -1072,11 +1069,11 @@ static void all_sensors(void) /** * @brief mbb? - 6채널 전체 캡처 + 센서 측정 (배터리/온도/IMU) * - * 센서 측정(rbb:) → 6채널 비동기 캡처(reb:/red:/raa:) → TX/RX OFF + * 센서 측정(rbb:) → 6채널 비동기 캡처(reb: merged) → raa: → TX/RX OFF * * 응답 흐름: * 1) 센서 측정: rbb: [배터리(2) + IMU 6축(12) + 온도(2)] - * 2) 각 채널(CH0~CH5): reb: [헤더] → red: [데이터...] + * 2) 각 채널: reb: [샘플수(2) + raw_data] (100샘플이면 단일 패킷) * 3) 캡처 완료: raa: [상태] */