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

223 lines
8.0 KiB
C

/*******************************************************************************
* @file device_config.c
* @brief Device Configuration Management
* @author Charles KWON <charleskwon@medithings.co.kr>
* @date 2025-01-30
* @copyright (c) 2025 Medithings Inc. All rights reserved.
*
* @details EEPROM configuration loading and default values.
******************************************************************************/
#include "device_config.h"
#include "nrf_delay.h"
#include "debug_print.h"
#include "cat_interface.h"
#include <cmd_parse.h>
#include <string.h>
#include "storage/dr_mem.h"
#include "fstorage.h"
/*==============================================================================
* GLOBAL VARIABLES
*============================================================================*/
char m_static_passkey[7] = "123456";
char SERIAL_NO[16] = "2025VIVAM00001";
char HW_NO[12] = "HW00000001";
bool bond_data_delete = true;
uint8_t m_pd_adc_cnt = 8;
uint16_t m_pd_delay_us = 8000;
uint32_t m_life_cycle = 0;
uint16_t led_pd_dac_v[48];
/*==============================================================================
* VALIDATION FUNCTIONS
*============================================================================*/
bool is_valid_serial_no(const char *serial)
{
if (serial == NULL) return false;
/* Check for reasonable serial number format */
for (int i = 0; i < 12; i++) {
char c = serial[i];
if (c == 0) break;
if (c == 0xFF) return false; /* Uninitialized EEPROM */
if (c < 0x20 || c > 0x7E) return false; /* Non-printable */
}
return true;
}
bool is_valid_passkey(const char *passkey)
{
if (passkey == NULL) return false;
/* Check for 6 digit passkey */
for (int i = 0; i < 6; i++) {
char c = passkey[i];
if (c == 0xFF) return false; /* Uninitialized EEPROM */
if (c < '0' || c > '9') return false; /* Not a digit */
}
return true;
}
/*==============================================================================
* CONFIGURATION LOADING
*============================================================================*/
void load_default_values(void)
{
/* Default Serial Number */
memset(SERIAL_NO, 0, sizeof(SERIAL_NO));
memcpy(SERIAL_NO, "2025AAAAT001", 12);
/* Default Passkey */
memset(m_static_passkey, 0, sizeof(m_static_passkey));
memcpy(m_static_passkey, "123456", 6);
/* Default measurement parameters */
m_pd_delay_us = 8000;
m_pd_adc_cnt = 8;
/* Default state */
bond_data_delete = 1;
/* Default AGC Gain values */
for (int i = 0; i < 48; i++) {
led_pd_dac_v[i] = 2048;
}
DBG_PRINTF("[CFG] Using default values\r\n");
}
static bool is_valid_hw_no(const char *hw)
{
if (hw == NULL) return false;
/* All 0x00 or 0xFF = uninitialized */
bool all_zero = true, all_ff = true;
for (int i = 0; i < 12; i++) {
if (hw[i] != 0x00) all_zero = false;
if ((uint8_t)hw[i] != 0xFF) all_ff = false;
}
if (all_zero || all_ff) return false;
/* Check printable ASCII */
for (int i = 0; i < 12; i++) {
char c = hw[i];
if (c == 0) break;
if (c < 0x20 || c > 0x7E) return false;
}
return true;
}
void load_device_configuration(void)
{
extern uint8_t m_reset_status;
ret_code_t err_code;
/* Start with RAM defaults, then override with FDS-saved values below.
* dr_memSetDefaults() removed: it was clobbering FDS-loaded m_config,
* wiping user-saved data (serial_no, passkey, etc.) on every boot
* when hw_no was still all-zeros. */
load_default_values();
/* Show m_config state right after config_load (before dr_memRead) */
{
char tmp[13] = {0};
memcpy(tmp, m_config.serial_no, 12);
DBG_PRINTF("[CFG] FDS serial_no='%s'\r\n", tmp);
memcpy(tmp, m_config.hw_no, 12);
DBG_PRINTF("[CFG] FDS hw_no='%s'\r\n", tmp);
}
/* Read FDS entries (already loaded by config_load() into m_config) */
err_code = dr_memRead("serial_no", (uint8_t *)SERIAL_NO, 12);
DBG_PRINTF("[CFG] dr_memRead S/N rc=%u valid=%d\r\n", err_code, is_valid_serial_no(SERIAL_NO));
DBG_PRINTF("[CFG] S/N hex: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
(uint8_t)SERIAL_NO[0], (uint8_t)SERIAL_NO[1], (uint8_t)SERIAL_NO[2], (uint8_t)SERIAL_NO[3],
(uint8_t)SERIAL_NO[4], (uint8_t)SERIAL_NO[5], (uint8_t)SERIAL_NO[6], (uint8_t)SERIAL_NO[7],
(uint8_t)SERIAL_NO[8], (uint8_t)SERIAL_NO[9], (uint8_t)SERIAL_NO[10], (uint8_t)SERIAL_NO[11]);
if (err_code != NRF_SUCCESS || !is_valid_serial_no(SERIAL_NO)) {
DBG_PRINTF("[CFG] Invalid S/N - using default\r\n");
memset(SERIAL_NO, 0, sizeof(SERIAL_NO));
memcpy(SERIAL_NO, "2025AAAAT001", 12);
}
err_code = dr_memRead("passkey", (uint8_t *)m_static_passkey, 6);
if (err_code != NRF_SUCCESS || !is_valid_passkey(m_static_passkey)) {
DBG_PRINTF("[CFG] Invalid passkey - using default\r\n");
memset(m_static_passkey, 0, sizeof(m_static_passkey));
memcpy(m_static_passkey, "123456", 6);
}
{
uint8_t raw = 0;
dr_memRead("bond_delete", &raw, 1);
bond_data_delete = (raw != 0);
}
dr_memRead("reset_status", &m_reset_status, 1);
if (m_reset_status > 2) {
DBG_PRINTF("[CFG] Invalid reset_status (%u) - using 1\r\n", m_reset_status);
m_reset_status = 1;
}
dr_memRead("pd_adc_cnt", &m_pd_adc_cnt, 1);
if (m_pd_adc_cnt == 0 || m_pd_adc_cnt >= 255) {
DBG_PRINTF("[CFG] Invalid adc_cnt (%u) - using 8\r\n", m_pd_adc_cnt);
m_pd_adc_cnt = 8;
}
dr_memRead("pd_delay", &m_pd_delay_us, 2);
if (m_pd_delay_us < 5000 || m_pd_delay_us > 30000) {
DBG_PRINTF("[CFG] Invalid pd_delay (%u) - using 8000\r\n", m_pd_delay_us);
m_pd_delay_us = 8000;
}
/* W25Q32 entries - NOT read during boot
* W25Q32 is not initialized at boot (SPIM + BSP event conflict).
* agc_gain and life_cycle use RAM defaults from load_default_values().
* Actual W25Q32 values are loaded later when W25Q32 is powered on
* (via BLE command or measurement start). */
DBG_PRINTF("[CFG] Loaded: S/N=%s, delay=%u, cnt=%u, life=%u\r\n",
SERIAL_NO, m_pd_delay_us, m_pd_adc_cnt, m_life_cycle);
/* 3. config_data_t dump (FDS raw) */
{
char tmp[13] = {0};
#define CFG_DLY() nrf_delay_ms(10)
DBG_PRINTF("[CFG] === config_data_t (FDS) ===\r\n"); CFG_DLY();
DBG_PRINTF("[CFG] magic : 0x%08X\r\n", m_config.magic_number); CFG_DLY();
memcpy(tmp, m_config.hw_no, 12); tmp[12] = 0;
DBG_PRINTF("[CFG] hw_no : %s\r\n", tmp); CFG_DLY();
memcpy(tmp, m_config.serial_no, 12); tmp[12] = 0;
DBG_PRINTF("[CFG] serial : %s\r\n", tmp); CFG_DLY();
DBG_PRINTF("[CFG] passkey : %c%c%c%c%c%c\r\n",
m_config.static_passkey[0], m_config.static_passkey[1],
m_config.static_passkey[2], m_config.static_passkey[3],
m_config.static_passkey[4], m_config.static_passkey[5]); CFG_DLY();
DBG_PRINTF("[CFG] bond_del: %u\r\n", m_config.bond_data_delete); CFG_DLY();
DBG_PRINTF("[CFG] reset_st: %d\r\n", m_config.reset_status); CFG_DLY();
DBG_PRINTF("[CFG] adc_cnt : %u\r\n", m_config.pd_adc_cnt); CFG_DLY();
DBG_PRINTF("[CFG] pd_delay: %u\r\n", m_config.pd_delay_us); CFG_DLY();
/* W25Q32 entries */
DBG_PRINTF("[CFG] agc_gain[48]:\r\n"); CFG_DLY();
for (int i = 0; i < 48; i += 8) {
DBG_PRINTF(" [%2d] %u %u %u %u %u %u %u %u\r\n", i,
led_pd_dac_v[i], led_pd_dac_v[i+1],
led_pd_dac_v[i+2], led_pd_dac_v[i+3],
led_pd_dac_v[i+4], led_pd_dac_v[i+5],
led_pd_dac_v[i+6], led_pd_dac_v[i+7]); CFG_DLY();
}
DBG_PRINTF("[CFG] life : %u\r\n", m_life_cycle); CFG_DLY();
DBG_PRINTF("[CFG] ========================\r\n");
#undef CFG_DLY
}
}