Files
VivaMyo-firmware-test/project/ble_peripheral/ble_app_vivaMayo/cmd_parse.c
2026-04-08 16:59:20 +09:00

319 lines
10 KiB
C

/*******************************************************************************
* @file cmd_parse.c
* @brief Command Parser Wrapper (Legacy Compatibility)
* @author Charles KWON <charleskwon@medithings.co.kr>
* @date 2025-02-04
* @copyright (c) 2025 Medithings Inc. All rights reserved.
*
* @details This file provides:
* - Legacy compatibility wrapper (received_command_process)
* - Utility functions (error handling, validation)
* - EEPROM read functions
*
* Actual parsing is handled by mt_parser/parser.c
* Command handlers are in cmd/cmd.c
******************************************************************************/
#include "cmd_parse.h"
#include "debug_print.h"
#include "parser.h"
#include "i2c_manager.h"
#include "app_timer.h"
#include "config/device_config.h"
#include "ble/ble_data_tx.h"
#include "ble_nus.h"
#include "crc16.h"
#include "cat_interface.h"
#include "storage/dr_mem.h"
#include <stdarg.h>
#include <string.h>
/*==============================================================================
* @section DEFINES Constants
*============================================================================*/
#define err_code1 65535 /* length error */
#define err_code2 65534 /* activate error */
#define err_code3 65533 /* param error */
#define err_code4 65532 /* ? missing */
#define err_code5 65531 /* CMD wrong */
#define err_code6 65530 /* CRC wrong */
/*==============================================================================
* @section EXTERN External Declarations
*============================================================================*/
extern uint8_t m_reset_status;
/* Note: SERIAL_NO, bond_data_delete, m_static_passkey, m_pd_adc_cnt,
m_pd_delay_us, m_life_cycle are declared in device_config.h */
/* Defined in measurements.h */
extern uint16_t led_pd_dac_v[];
/* Defined in main.c */
extern char ble_tx_buffer[];
extern volatile bool processing;
extern bool ble_got_new_data;
/* BLE buffer (defined in ble_data_tx.c) */
extern uint8_t ble_bin_buffer[];
/* Parser globals (defined in parser.c) */
extern dr_platform_if_t g_plat;
extern bool g_log_enable;
/*==============================================================================
* @section GLOBALS Global Variables (used by other modules)
*============================================================================*/
uint8_t resetCount = 0; /**< Reset counter */
bool info4 = false; /**< Additional info flag for PD Full mode */
/*==============================================================================
* @section STATIC Static Variables
*============================================================================*/
static uint32_t processing_start_tick = 0;
/*==============================================================================
* @section UTIL Utility Functions
*============================================================================*/
/**
* @brief Internal log function for parser
*/
static void log_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
/*==============================================================================
* @section CRC CRC Functions
*============================================================================*/
bool crc16_check(uint8_t const *p_data, uint32_t data_len, uint16_t expected_crc)
{
uint16_t computed_crc = crc16_compute(p_data, data_len, NULL);
return (computed_crc == expected_crc);
}
bool crc16_check_packet(uint8_t const *packet, uint32_t packet_len)
{
if (packet_len < 2) return false;
uint32_t data_len = packet_len - 2;
uint16_t expected_crc = (packet[packet_len - 1] << 8) | packet[packet_len - 2];
return crc16_check(packet, data_len, expected_crc);
}
/*==============================================================================
* @section ERROR Error Handling Functions
*============================================================================*/
bool length_error(const char *cmd, uint8_t target_length, uint8_t length)
{
if (target_length == length) {
return true;
}
char resp_error[4];
resp_error[0] = 'r';
resp_error[1] = cmd[1];
resp_error[2] = cmd[2];
resp_error[3] = '!';
single_format_data(ble_bin_buffer, resp_error, err_code1);
binary_tx_handler(ble_bin_buffer, 3);
return false;
}
bool activate_error(const char *cmd, bool device_status)
{
if (device_status == true) {
return true;
}
char resp_error[4];
resp_error[0] = 'r';
resp_error[1] = cmd[1];
resp_error[2] = cmd[2];
resp_error[3] = '!';
single_format_data(ble_bin_buffer, resp_error, err_code2);
binary_tx_handler(ble_bin_buffer, 3);
return false;
}
void param_error(const char *cmd)
{
char resp_error[4];
resp_error[0] = 'r';
resp_error[1] = cmd[1];
resp_error[2] = cmd[2];
resp_error[3] = '!';
single_format_data(ble_bin_buffer, resp_error, err_code3);
binary_tx_handler(ble_bin_buffer, 3);
}
void quest_error(const char *cmd)
{
char resp_error[4];
const char pass_init[6] = "123456";
if ((cmd[0] == '*') && (cmd[1] == '*') && (cmd[2] == '*') && (cmd[3] == '*')) {
if (dr_memWrite("passkey", (uint8_t *)pass_init, 6) != NRF_SUCCESS) {
DBG_PRINTF("ERR!!! passkey write fail\r\n\r\n");
}
resp_error[0] = '*';
resp_error[1] = cmd[1];
resp_error[2] = cmd[2];
resp_error[3] = '*';
single_format_data(ble_bin_buffer, resp_error, err_code4);
binary_tx_handler(ble_bin_buffer, 3);
} else {
resp_error[0] = 'r';
resp_error[1] = cmd[1];
resp_error[2] = cmd[2];
resp_error[3] = '!';
single_format_data(ble_bin_buffer, resp_error, err_code4);
binary_tx_handler(ble_bin_buffer, 3);
}
}
/*==============================================================================
* @section INIT_READ Initial Values Read (via dr_mem API)
*============================================================================*/
ret_code_t eeprom_init_values_read(void)
{
ret_code_t err_code;
/* FDS entries: Serial Number (12B, AES) */
err_code = dr_memRead("serial_no", (uint8_t *)SERIAL_NO, 12);
if (err_code != NRF_SUCCESS) return err_code;
DBG_PRINTF("\r\n SN:%s \r\n", SERIAL_NO);
/* FDS entries: Passkey (6B, AES) */
err_code = dr_memRead("passkey", (uint8_t *)m_static_passkey, 6);
if (err_code != NRF_SUCCESS) return err_code;
DBG_PRINTF("\r\n passkey-0 :%s \n", m_static_passkey);
/* FDS entries: Bond data delete (1B) */
{
uint8_t raw = 0;
err_code = dr_memRead("bond_delete", &raw, 1);
if (err_code != NRF_SUCCESS) return err_code;
bond_data_delete = (raw != 0);
}
DBG_PRINTF("\r\n bond_data_delete :%d \n", bond_data_delete);
/* FDS entries: Reset status (1B) */
err_code = dr_memRead("reset_status", &m_reset_status, 1);
if (err_code != NRF_SUCCESS) return err_code;
/* FDS entries: PD ADC count (1B) */
err_code = dr_memRead("pd_adc_cnt", &m_pd_adc_cnt, 1);
if (err_code != NRF_SUCCESS) return err_code;
if (m_pd_adc_cnt == 0 || m_pd_adc_cnt >= 255) {
m_pd_adc_cnt = 8;
}
/* FDS entries: PD delay (2B) */
err_code = dr_memRead("pd_delay", &m_pd_delay_us, 2);
if (err_code != NRF_SUCCESS) return err_code;
if (m_pd_delay_us < 5000 || m_pd_delay_us > 30000) {
m_pd_delay_us = 8000;
}
/* W25Q32 entries: AGC Gain array (96B) */
err_code = dr_memRead("agc_gain", led_pd_dac_v, 96);
if (err_code != NRF_SUCCESS) return err_code;
/* W25Q32 entries: Life cycle (4B) */
err_code = dr_memRead("life_cycle", &m_life_cycle, 4);
if (err_code != NRF_SUCCESS) return err_code;
DBG_PRINTF("\r\n m_life_cycle:%u, m_pd_delay_us:%u, m_pd_adc_cnt:%u \r\n",
m_life_cycle, m_pd_delay_us, m_pd_adc_cnt);
return NRF_SUCCESS;
}
/*==============================================================================
* @section API Main Entry Point
*============================================================================*/
/**
* @brief Process received command from UART or BLE
* @details Initializes parser on first call, then delegates to dr_cmd_parser
*/
void received_command_process(uint8_t const *data_array, which_cmd_t cmd_t, uint8_t length)
{
uint8_t r_data[BLE_NUS_MAX_DATA_LEN] = {0};
int parser_result;
(void)cmd_t; /* Currently not used by new parser */
ble_got_new_data = true;
memset(ble_tx_buffer, 0, BLE_NUS_MAX_DATA_LEN);
/* Copy data to local buffer */
for (uint16_t i = 0; i < length; i++) {
r_data[i] = data_array[i];
}
DBG_PRINTF("data : %s\r\n", r_data);
DBG_PRINTF("Length : %d\r\n", length);
/* Initialize parser (once) */
static bool parser_initialized = false;
if (!parser_initialized) {
g_plat.log = log_printf;
g_plat.tx_bin = binary_tx_handler;
g_plat.crc_check = true; /* CRC enabled */
g_log_enable = true;
parser_initialized = true;
DBG_PRINTF(">>> Parser initialized (mt_parser)\r\n");
}
/* Check if already processing */
if (processing == true) {
uint32_t now = app_timer_cnt_get();
if (processing_start_tick == 0) {
processing_start_tick = now;
}
/* Timeout check (5 seconds) */
if (app_timer_cnt_diff_compute(now, processing_start_tick) > APP_TIMER_TICKS(5000)) {
processing = false;
processing_start_tick = 0;
DBG_PRINTF("processing timeout -> force reset to false\r\n");
} else {
DBG_PRINTF("Busy - command ignored\r\n");
return;
}
}
/* Call mt_parser */
parser_result = dr_cmd_parser(r_data, length);
if (parser_result > 0) {
DBG_PRINTF(">>> Handled by mt_parser (result=%d)\r\n", parser_result);
} else if (parser_result == 9) {
DBG_PRINTF(">>> CRC/Parse error\r\n");
} else {
DBG_PRINTF(">>> Unknown command\r\n");
}
}