From 488223edee010f9684036cb19c85c23401d94c7b Mon Sep 17 00:00:00 2001 From: jhchun Date: Mon, 20 Jul 2026 17:47:28 +0900 Subject: [PATCH] =?UTF-8?q?MTU=EC=97=90=20=EB=94=B0=EB=A5=B8=20BLE=20?= =?UTF-8?q?=ED=8C=A8=ED=82=B7=20=EB=B6=84=ED=95=A0=20-=20IMU=20FIFO=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=8C=A8=ED=82=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 협상된 MTU 기준으로 rim: 응답 패킷 크기 판단 - 기존 rim:이 MTU에 들어가지 않으면 ric: chunk 분할 전송 --- src/command/cmd_common.c | 93 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/src/command/cmd_common.c b/src/command/cmd_common.c index 9bedd3b..447284a 100644 --- a/src/command/cmd_common.c +++ b/src/command/cmd_common.c @@ -28,6 +28,8 @@ static uint8_t g_echo_session; #define REB_OVERHEAD_SIZE 10U #define REC_OVERHEAD_SIZE 14U #define ECHO_SAMPLE_SIZE 2U +#define RIM_OVERHEAD_SIZE 8U +#define RIC_OVERHEAD_SIZE 12U uint8_t cmd_next_echo_session(void) { @@ -347,7 +349,7 @@ void cmd_send_response_bundle(uint16_t batt_mv, const int16_t accel[3], const in ble_data_send(buf, sizeof(tx_bundle_buf)); } -void cmd_send_response_rim(const uint8_t *sample_bytes, uint16_t sample_count) +static void cmd_send_response_rim_legacy(const uint8_t *sample_bytes, uint16_t sample_count) { uint8_t *buf = tx_rim_buf; uint16_t payload_len; @@ -369,9 +371,98 @@ void cmd_send_response_rim(const uint8_t *sample_bytes, uint16_t sample_count) buf[payload_len + 1U] = (uint8_t)(crc >> 8); DBG_PRINTF("[MTB] tx rim samples=%u len=%u\r\n", sample_count, (uint16_t)(payload_len + 2U)); + ble_data_send(buf, (uint16_t)(payload_len + 2U)); } +static uint16_t calc_ric_samples_per_packet(uint16_t notify_payload_max) +{ + if (notify_payload_max < (RIC_OVERHEAD_SIZE + IMU_FIFO_SAMPLE_BYTES)) + { + return 0U; + } + + return (uint16_t)((notify_payload_max - RIC_OVERHEAD_SIZE) / IMU_FIFO_SAMPLE_BYTES); +} + +/* +* ric: packet layout: +* tag (4B): "ric:" +* offset (2B): 전체 샘플 배열에서 시작 인덱스 +* total_samples (2B): 전체 IMU FIFO 샘플 수 +* chunk_samples (2B): 현재 패킷에 들어간 샘플 수 +* sample data (N): IMU FIFO samples +* crc (2B): tag부터 sample data까지 CRC16 +*/ +static void cmd_send_response_rim_ric(const uint8_t *sample_bytes, uint16_t sample_count, uint16_t samples_per_pkt) +{ + uint8_t *buf = tx_rim_buf; + + for (uint16_t off = 0U; off < sample_count; off = (uint16_t)(off + samples_per_pkt)) + { + uint16_t remain = (uint16_t)(sample_count - off); + uint16_t chunk_samples = MIN(samples_per_pkt, remain); + + buf[0] = 'r'; buf[1] = 'i'; buf[2] = 'c'; buf[3] = ':'; + buf[4] = (uint8_t)(off >> 8); + buf[5] = (uint8_t)(off & 0xFF); + buf[6] = (uint8_t)(sample_count >> 8); + buf[7] = (uint8_t)(sample_count & 0xFF); + buf[8] = (uint8_t)(chunk_samples >> 8); + buf[9] = (uint8_t)(chunk_samples & 0xFF); + + memcpy(&buf[10], &sample_bytes[off * IMU_FIFO_SAMPLE_BYTES], (size_t)chunk_samples * IMU_FIFO_SAMPLE_BYTES); + + uint16_t payload_len = (uint16_t)(RIC_OVERHEAD_SIZE - 2U + (chunk_samples * IMU_FIFO_SAMPLE_BYTES)); + uint16_t crc = cmd_crc16_compute(buf, payload_len); + DBG_PRINTF("[CMD] ric tx off=%u total=%u chunk=%u len=%u\r\n", + off, sample_count, chunk_samples, (uint16_t)(payload_len + 2U)); + + buf[payload_len] = (uint8_t)(crc & 0xFF); + buf[payload_len + 1U] = (uint8_t)(crc >> 8); + + if (ble_data_send(buf, (uint16_t)(payload_len + 2U)) != 0) + { + break; + } + } +} + +void cmd_send_response_rim(const uint8_t *sample_bytes, uint16_t sample_count) +{ + uint16_t notify_payload_max = 0U; + uint16_t mtu = ble_current_mtu(); + + if (sample_count > IMU_FIFO_RIM_TARGET_SAMPLES) + { + sample_count = IMU_FIFO_RIM_TARGET_SAMPLES; + } + + uint16_t rim_len = (uint16_t)(RIM_OVERHEAD_SIZE + (sample_count * IMU_FIFO_SAMPLE_BYTES)); + + if (mtu > ATT_NOTIFY_HEADER_SIZE) + { + notify_payload_max = (uint16_t)(mtu - ATT_NOTIFY_HEADER_SIZE); + } + + if ((notify_payload_max == 0U) || (rim_len <= notify_payload_max)) + { + cmd_send_response_rim_legacy(sample_bytes, sample_count); + return; + } + + uint16_t samples_per_pkt = calc_ric_samples_per_packet(notify_payload_max); + + if (samples_per_pkt == 0U) + { + DBG_ERR("[CMD] ric skip mtu=%u payload=%u samples=%u\r\n", mtu, notify_payload_max, sample_count); + return; + } + + DBG_PRINTF("[CMD] ric split mtu=%u samples=%u chunk=%u\r\n", mtu, sample_count, samples_per_pkt); + cmd_send_response_rim_ric(sample_bytes, sample_count, samples_per_pkt); +} + void cmd_send_response_piezo_config(const char *tag, uint16_t freq, uint16_t cycles, uint16_t avg, uint16_t delay_us, uint16_t samples) { uint8_t *buf = tx_cfg_buf;