Compare commits
24 Commits
742681554e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f252c7bef | |||
| be1ca58bd6 | |||
| e20e8f5665 | |||
| 2bff259fa3 | |||
| c72349cf13 | |||
| a0aa180ef1 | |||
| e9eb89f203 | |||
| 790e3a1b82 | |||
| 50a8e68cf4 | |||
| 1fa0d8b30b | |||
| 36cd84e49c | |||
| 163593c0cd | |||
| 009897a7d8 | |||
| 93a11b7519 | |||
| 2db6e36c08 | |||
| 231a000849 | |||
| 0294cdb428 | |||
| 80c846fd25 | |||
| 2daa8b3690 | |||
| e04e79ac31 | |||
| 32b6fb800d | |||
| 24e5b2e205 | |||
| 143e22c2d8 | |||
| 24a4be94df |
@@ -216,9 +216,9 @@ uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu)
|
||||
add_char_params.is_var_len = true;
|
||||
add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT;
|
||||
|
||||
add_char_params.cccd_write_access = SEC_OPEN;
|
||||
add_char_params.write_access = SEC_OPEN;
|
||||
add_char_params.read_access = SEC_OPEN;
|
||||
add_char_params.cccd_write_access = SEC_MITM;
|
||||
add_char_params.write_access = SEC_MITM;
|
||||
add_char_params.read_access = SEC_MITM;
|
||||
|
||||
return characteristic_add(p_dfu->service_handle, &add_char_params, &p_dfu->control_point_char);
|
||||
}
|
||||
|
||||
@@ -283,8 +283,8 @@ uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
|
||||
add_char_params.char_props.write = 1;
|
||||
add_char_params.char_props.write_wo_resp = 1;
|
||||
|
||||
add_char_params.read_access = SEC_OPEN;
|
||||
add_char_params.write_access = SEC_OPEN;
|
||||
add_char_params.read_access = SEC_MITM;
|
||||
add_char_params.write_access = SEC_MITM;
|
||||
|
||||
err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
@@ -302,9 +302,9 @@ uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
|
||||
add_char_params.is_var_len = true;
|
||||
add_char_params.char_props.notify = 1;
|
||||
|
||||
add_char_params.read_access = SEC_OPEN;
|
||||
add_char_params.write_access = SEC_OPEN;
|
||||
add_char_params.cccd_write_access = SEC_OPEN;
|
||||
add_char_params.read_access = SEC_MITM;
|
||||
add_char_params.write_access = SEC_MITM;
|
||||
add_char_params.cccd_write_access = SEC_MITM;
|
||||
|
||||
return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles);
|
||||
/**@snippet [Adding proprietary characteristic to the SoftDevice] */
|
||||
|
||||
@@ -36,7 +36,6 @@ extern volatile bool data_tx_in_progress;
|
||||
/*------------------------------------------------------------------------------
|
||||
* Device state / flags
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern volatile bool processing;
|
||||
extern bool device_status;
|
||||
extern bool con_single;
|
||||
extern bool lock_check;
|
||||
|
||||
@@ -41,7 +41,6 @@ static const CmdEntry m_cmd_table[] = {
|
||||
{ "msn?", true, Cmd_msn },
|
||||
{ "mst?", true, Cmd_mst },
|
||||
{ "msp?", true, Cmd_msp },
|
||||
{ "msi?", true, Cmd_msi },
|
||||
|
||||
/* D. Piezo ultrasound */
|
||||
{ "mpa?", true, Cmd_mpa },
|
||||
|
||||
@@ -138,11 +138,18 @@ int Cmd_mrs(const ParsedCmd *cmd)
|
||||
*============================================================================*/
|
||||
int Cmd_mpz(const ParsedCmd *cmd)
|
||||
{
|
||||
if (m_config.factory_provisioned != 0)
|
||||
{
|
||||
dr_ble_return_1("rpz:", 0xFFFF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char passkey[7] = {0};
|
||||
dr_get_ascii(cmd, 0, passkey, 6);
|
||||
|
||||
memcpy(m_static_passkey, passkey, 6);
|
||||
memcpy(m_config.static_passkey, m_static_passkey, 6);
|
||||
m_config.factory_provisioned = 1;
|
||||
config_save();
|
||||
|
||||
ascii_format_data(ble_bin_buffer, "rpz:", passkey, 6);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* msn? -> rsn: battery ADC measurement
|
||||
* mso? -> rso: TMP235 temperature reading
|
||||
* msp? -> rsp: IMU 6-axis single read
|
||||
* msi? -> rsi: IMU motion streaming start
|
||||
* all_sensors() bulk-measurement helper used by the mbb? handler
|
||||
*============================================================================*/
|
||||
|
||||
@@ -74,34 +73,6 @@ int Cmd_msp(const ParsedCmd *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* msi? -> rsi: IMU motion sensor streaming start
|
||||
*
|
||||
* Request: [TAG 4B "msi?"] [mode 1B] [CRC 2B]
|
||||
* mode = 'c': continuous (repeats on timer)
|
||||
* else : single shot (one read then auto stop)
|
||||
* Response: rsi: + IMU data (sent from main timer callback)
|
||||
*============================================================================*/
|
||||
int Cmd_msi(const ParsedCmd *cmd)
|
||||
{
|
||||
hw_i2c_init_once();
|
||||
|
||||
motion_raw_data_enabled = true;
|
||||
ble_got_new_data = false;
|
||||
|
||||
if (cmd->data_len > 0 && (char)cmd->data[0] == 'c')
|
||||
{
|
||||
motion_data_once = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
motion_data_once = true;
|
||||
}
|
||||
|
||||
main_timer_start();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* all_sensors() - Bulk-measurement helper for the mbb? handler
|
||||
*
|
||||
@@ -146,8 +117,10 @@ void all_sensors(void)
|
||||
|
||||
info4 = false;
|
||||
|
||||
/* Assemble and transmit the rbb: packet */
|
||||
buf = ble_bin_buffer;
|
||||
/* Assemble and transmit the rbb: packet (dedicated buffer to avoid
|
||||
collision with ble_bin_buffer used by the async ADC state machine) */
|
||||
static uint8_t rbb_buf[20];
|
||||
buf = rbb_buf;
|
||||
buf[0] = 'r'; buf[1] = 'b'; buf[2] = 'b'; buf[3] = ':';
|
||||
buf[4] = (uint8_t)(info_batt >> 8);
|
||||
buf[5] = (uint8_t)(info_batt & 0xFF);
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
int Cmd_msn(const ParsedCmd *cmd); /* msn? -> rsn: battery ADC measurement */
|
||||
int Cmd_mst(const ParsedCmd *cmd); /* mst? -> rso: TMP235 with piezo power cycle */
|
||||
int Cmd_msp(const ParsedCmd *cmd); /* msp? -> rsp: IMU 6-axis single read */
|
||||
int Cmd_msi(const ParsedCmd *cmd); /* msi? -> rsi: IMU streaming start */
|
||||
|
||||
/* Helper for the mbb? handler: sequentially measures battery / IMU / temperature, then emits a single rbb: response.
|
||||
* Called from Cmd_mbb() in cmd_piezo.c. */
|
||||
void all_sensors(void);
|
||||
|
||||
@@ -112,6 +112,9 @@ void fds_default_value_set(void)
|
||||
m_config.piezo_num_samples = 100; /* 100 samples */
|
||||
m_config.piezo_cycles = 7; /* 7 cycles */
|
||||
m_config.piezo_averaging = 3; /* 3x averaging */
|
||||
|
||||
/* Factory provisioning — default: not provisioned */
|
||||
m_config.factory_provisioned = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,38 +133,34 @@ static void fds_evt_handler( fds_evt_t const *p_evt )
|
||||
{
|
||||
fds_last_evt = p_evt->id;
|
||||
|
||||
switch( p_evt->id )
|
||||
switch (p_evt->id)
|
||||
{
|
||||
case FDS_EVT_INIT:
|
||||
if( p_evt->result == NRF_SUCCESS )
|
||||
if (p_evt->result == NRF_SUCCESS)
|
||||
{
|
||||
m_fds_initialized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case FDS_EVT_WRITE:
|
||||
{
|
||||
fds_flag_write = false;
|
||||
}
|
||||
fds_flag_write = false;
|
||||
break;
|
||||
|
||||
case FDS_EVT_UPDATE:
|
||||
{
|
||||
fds_flag_write = false;
|
||||
fds_flag_write = false;
|
||||
|
||||
if(go_device_power_off == true)
|
||||
{
|
||||
device_power_off();
|
||||
}
|
||||
if(go_sleep_mode_enter == true)
|
||||
{
|
||||
sleep_mode_enter();
|
||||
}
|
||||
if(go_NVIC_SystemReset == true)
|
||||
{
|
||||
DBG_PRINTF("Off FDS_EVENT\r\n");
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
if (go_device_power_off == true)
|
||||
{
|
||||
device_power_off();
|
||||
}
|
||||
if (go_sleep_mode_enter == true)
|
||||
{
|
||||
sleep_mode_enter();
|
||||
}
|
||||
if (go_NVIC_SystemReset == true)
|
||||
{
|
||||
DBG_PRINTF("Off FDS_EVENT\r\n");
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -188,7 +187,7 @@ static void fds_evt_handler( fds_evt_t const *p_evt )
|
||||
static void wait_for_fds_ready( void )
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
while( !m_fds_initialized )
|
||||
while(!m_fds_initialized)
|
||||
{
|
||||
nrf_pwr_mgmt_run();
|
||||
nrf_delay_ms(1);
|
||||
@@ -237,7 +236,7 @@ void config_load( void )
|
||||
goto cfg_load_start;
|
||||
}
|
||||
|
||||
if( rc == NRF_SUCCESS )
|
||||
if (rc == NRF_SUCCESS)
|
||||
{
|
||||
fds_flash_record_t config = { 0 };
|
||||
|
||||
@@ -259,7 +258,7 @@ void config_load( void )
|
||||
|
||||
DBG_PRINTF("[FDS] magic=0x%08X (expect 0x%08X)\r\n", m_config.magic_number, CONFIG_MAGIC_NUMBER_VALUE);
|
||||
|
||||
if( m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE )
|
||||
if (m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE)
|
||||
{
|
||||
DBG_PRINTF("[FDS] FORMAT! overwriting with defaults\r\n");
|
||||
rc = fds_record_delete(&desc);
|
||||
@@ -269,7 +268,7 @@ void config_load( void )
|
||||
fds_default_value_set();
|
||||
|
||||
rc = fds_record_update(&desc, &m_dummy_record);
|
||||
if( (rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH) )
|
||||
if ((rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH))
|
||||
{
|
||||
rc = fds_gc();
|
||||
APP_ERROR_CHECK(rc);
|
||||
@@ -301,20 +300,20 @@ void config_load( void )
|
||||
|
||||
fds_wait_cnt = 0;
|
||||
|
||||
while(fds_flag_write && fds_wait_cnt < 3000) /* 3 second timeout */
|
||||
while (fds_flag_write && fds_wait_cnt < 3000) /* 3 second timeout */
|
||||
{
|
||||
nrf_pwr_mgmt_run();
|
||||
nrf_delay_ms(1);
|
||||
fds_wait_cnt++;
|
||||
}
|
||||
|
||||
if(fds_flag_write)
|
||||
if (fds_flag_write)
|
||||
{
|
||||
DBG_PRINTF("[FDS] write TIMEOUT! forcing flag clear\r\n");
|
||||
fds_flag_write = false;
|
||||
}
|
||||
|
||||
if( (rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH) )
|
||||
if ((rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH))
|
||||
{
|
||||
rc = fds_gc();
|
||||
APP_ERROR_CHECK(rc);
|
||||
@@ -370,7 +369,7 @@ void config_save( void )
|
||||
}
|
||||
}
|
||||
|
||||
if( m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE )
|
||||
if (m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE)
|
||||
{
|
||||
m_config.magic_number = CONFIG_MAGIC_NUMBER_VALUE;
|
||||
}
|
||||
@@ -380,13 +379,13 @@ void config_save( void )
|
||||
rc = fds_record_find(CONFIG_FILE, CONFIG_REC_KEY, &desc, &tok);
|
||||
DBG_PRINTF("[CFG_SAVE] find rc=%u\r\n", rc);
|
||||
|
||||
if( rc == NRF_SUCCESS )
|
||||
if (rc == NRF_SUCCESS)
|
||||
{
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_update(&desc, &m_dummy_record);
|
||||
DBG_PRINTF("[CFG_SAVE] update rc=%u\r\n", rc);
|
||||
|
||||
if( rc == FDS_ERR_NO_SPACE_IN_FLASH )
|
||||
if (rc == FDS_ERR_NO_SPACE_IN_FLASH)
|
||||
{
|
||||
fds_flag_write = false;
|
||||
rc = fds_gc();
|
||||
@@ -396,7 +395,7 @@ void config_save( void )
|
||||
DBG_PRINTF("[CFG_SAVE] retry rc=%u\r\n", rc);
|
||||
}
|
||||
|
||||
if( rc != NRF_SUCCESS )
|
||||
if (rc != NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
||||
fds_flag_write = false;
|
||||
@@ -409,7 +408,7 @@ void config_save( void )
|
||||
rc = fds_record_write(&desc, &m_dummy_record);
|
||||
DBG_PRINTF("[CFG_SAVE] write rc=%u\r\n", rc);
|
||||
|
||||
if( rc != NRF_SUCCESS )
|
||||
if ( rc != NRF_SUCCESS )
|
||||
{
|
||||
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
||||
fds_flag_write = false;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* via the Nordic FDS library. Replaces external EEPROM and coexists safely
|
||||
* with the SoftDevice.
|
||||
*
|
||||
* config_data_t (48 bytes, packed):
|
||||
* config_data_t (49 bytes, packed):
|
||||
* magic_number (4B) : format validation (0x20231226)
|
||||
* hw_no (12B): hardware version string
|
||||
* serial_no (12B): serial number (also used as BLE device name)
|
||||
@@ -14,6 +14,7 @@
|
||||
* reset_status (1B) : reset cause code
|
||||
* life_cycle (4B) : device usage count
|
||||
* piezo_* (8B) : piezo measurement parameters
|
||||
* factory_provisioned(1B): passkey provisioning lock flag
|
||||
*
|
||||
* API:
|
||||
* fs_storage_init() : initialise FDS (once at boot)
|
||||
@@ -65,7 +66,10 @@ typedef struct
|
||||
uint16_t piezo_averaging; /* 2B - averages per channel (1..10) */
|
||||
uint16_t piezo_delay_us; /* 2B - delay from TX pulse to ADC start (us) (0..30) */
|
||||
uint16_t piezo_num_samples; /* 2B - ADC sample count (80..140) */
|
||||
} config_data_t; /* Total: 48 bytes */
|
||||
|
||||
/* Factory provisioning lock */
|
||||
uint8_t factory_provisioned; /* 1B - 0=passkey not set, 1=passkey set (locked) */
|
||||
} config_data_t; /* Total: 49 bytes */
|
||||
|
||||
extern config_data_t m_config;
|
||||
|
||||
|
||||
@@ -39,10 +39,12 @@ static void twi_uninitialize(void)
|
||||
}
|
||||
|
||||
/* Initialise the TWI peripheral (SCL/SDA pins, 400 kHz, blocking mode). */
|
||||
static void twi_initialize(void){
|
||||
static void twi_initialize(void)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
|
||||
const nrfx_twi_config_t twi_config = {
|
||||
const nrfx_twi_config_t twi_config =
|
||||
{
|
||||
.scl = ICM42670_I2C_SCL_PIN,
|
||||
.sda = ICM42670_I2C_SDA_PIN,
|
||||
.frequency = NRF_TWI_FREQ_400K,
|
||||
|
||||
@@ -108,7 +108,6 @@
|
||||
#endif
|
||||
|
||||
/* -- Crypto / command parser / debug -- */
|
||||
#include "nrf_crypto.h" /* nRF crypto library (AES, etc.) */
|
||||
#include "parser.h" /* Binary command parser (dr_cmd_parser) */
|
||||
#include "cmd_table.h" /* Command table registration (cmd_table_init) */
|
||||
#include "debug_print.h" /* Debug output macro (DBG_PRINTF) */
|
||||
@@ -116,8 +115,6 @@
|
||||
#include "dr_piezo.h" /* Piezo ultrasound driver */
|
||||
#include "led_control.h" /* LED direct control driver */
|
||||
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
* Build Configuration
|
||||
*============================================================================*/
|
||||
@@ -149,29 +146,6 @@
|
||||
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /* Subsequent param update interval: 30s */
|
||||
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /* Max param update attempts */
|
||||
|
||||
/* -- BLE security parameters (when FEATURE_SECURE_CONNECTION enabled) --
|
||||
* Bonding (BOND=1): store pairing info in flash for reconnection
|
||||
* MITM protection (MITM=1): prevent man-in-the-middle attacks (passkey auth required)
|
||||
* LESC: disabled(0) in static passkey mode, enabled(1) in dynamic passkey mode
|
||||
* IO capabilities: DISPLAY_ONLY -> device displays passkey, user enters in app
|
||||
*/
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
#define LESC_DEBUG_MODE 0 /* LESC debug mode disabled */
|
||||
#define SEC_PARAM_BOND 1 /* Bonding enabled (store pairing info) */
|
||||
#define SEC_PARAM_MITM 1 /* MITM protection enabled */
|
||||
#if FEATURE_STATIC_PASSKEY
|
||||
#define SEC_PARAM_LESC 0 /* Static passkey mode: LESC disabled */
|
||||
#else
|
||||
#define SEC_PARAM_LESC 1 /* Dynamic passkey mode: LESC enabled */
|
||||
#endif
|
||||
#define SEC_PARAM_KEYPRESS 0 /* Keypress notification disabled */
|
||||
#define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_DISPLAY_ONLY /* Display only */
|
||||
#define SEC_PARAM_OOB 0 /* No OOB (Out-of-Band) data */
|
||||
#define SEC_PARAM_MIN_KEY_SIZE 7 /* Min encryption key size (bytes) */
|
||||
#define SEC_PARAM_MAX_KEY_SIZE 16 /* Max encryption key size (bytes) */
|
||||
#define PASSKEY_TXT_LENGTH 8 /* Passkey text buffer length */
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* System Constants
|
||||
*============================================================================*/
|
||||
@@ -181,9 +155,6 @@
|
||||
#define POWER_ON_DELAY 5 /* Power button polling interval (5ms) */
|
||||
#define POWER_OFF_DELAY 3000 /* Power-off delay: 3s after LED indication */
|
||||
#define POWER_RESET_DELAY 2000 /* Reset delay: 2s */
|
||||
#define LED_NUM 24 /* LED pin number */
|
||||
#define AES_KEY_SIZE 16 /* AES encryption key size (128-bit) */
|
||||
#define AES_BLOCK_SIZE 16 /* AES block size (128-bit) */
|
||||
|
||||
/*==============================================================================
|
||||
* BLE Instances (statically allocated via SoftDevice macros)
|
||||
@@ -219,19 +190,11 @@ static uint8_t c_addr[6] = {0}; /* Connected peer BLE a
|
||||
|
||||
static char * roles_str[] = {"INVALID_ROLE", "CENTRAL", "PERIPHERAL"};
|
||||
|
||||
/*==============================================================================
|
||||
* Global Variables
|
||||
* IEC 62304 §5.5.3: all global buffers zero-initialized for deterministic startup
|
||||
*============================================================================*/
|
||||
uint8_t m_encrypted_text[AES_BLOCK_SIZE] = {0}; /* AES encryption result buffer */
|
||||
uint8_t m_encrypted_text2[AES_BLOCK_SIZE] = {0}; /* AES encryption result buffer 2 */
|
||||
uint8_t m_decrypted_text[AES_BLOCK_SIZE] = {0}; /* AES decryption result buffer */
|
||||
|
||||
volatile uint8_t Sj_type; /* Command type identifier */
|
||||
volatile bool processing; /* Sensor data processing flag (prevents duplicate commands) */
|
||||
bool power_off_duble_prohibit = false; /* Power-off double prevention flag */
|
||||
volatile bool power_state = false; /* Power state tracking */
|
||||
|
||||
/*==============================================================================
|
||||
* Extern Variables and Functions
|
||||
*============================================================================*/
|
||||
/* -- External module flags (defined in main_timer/power_control) -- */
|
||||
extern bool go_device_power_off; /* Power-off request flag */
|
||||
extern bool go_sleep_mode_enter; /* Sleep mode entry request flag */
|
||||
@@ -243,6 +206,14 @@ extern bool info4; /* Device info transmission complete flag
|
||||
extern uint8_t add_cycle; /* Additional measurement cycle counter */
|
||||
extern bool motion_raw_data_enabled; /* Motion raw data streaming enabled */
|
||||
|
||||
/* -- External module functions (used in DFU prepare / disconnect cleanup) -- */
|
||||
extern void maa_async_abort(void);
|
||||
extern bool maa_async_on_tx_ready(void);
|
||||
extern bool maa_async_is_busy(void);
|
||||
extern void dr_piezo_power_off(void);
|
||||
extern void battery_timer_stop(void);
|
||||
extern void main_timer_stop(void);
|
||||
|
||||
uint16_t cnt_s; /* Power button polling counter (5ms units, 150=0.75s) */
|
||||
char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN] = {0}; /* BLE text transmission buffer */
|
||||
uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN] = {0}; /* BLE binary response buffer */
|
||||
@@ -264,7 +235,6 @@ static volatile bool s_tx_pending = false; /* TX re
|
||||
static uint8_t s_tx_pending_buf[BLE_NUS_MAX_DATA_LEN] = {0}; /* Pending packet (with CRC) */
|
||||
static uint16_t s_tx_pending_len = 0; /* Pending packet length */
|
||||
|
||||
|
||||
char m_static_passkey[PASSKEY_LENGTH] = DEFAULT_PASSKEY; /* Static passkey (6 digits, loaded from FDS) */
|
||||
char SERIAL_NO[SERIAL_NO_LENGTH] = {0}; /* Serial number (used as BLE device name) */
|
||||
char HW_NO[HW_NO_LENGTH] = {0}; /* Hardware number (FDS stored/read) */
|
||||
@@ -517,6 +487,10 @@ static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
|
||||
{
|
||||
case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
|
||||
DBG_PRINTF("[DFU] Prepare\r\n");
|
||||
maa_async_abort();
|
||||
dr_piezo_power_off();
|
||||
battery_timer_stop();
|
||||
main_timer_stop();
|
||||
break;
|
||||
case BLE_DFU_EVT_BOOTLOADER_ENTER:
|
||||
DBG_PRINTF("[DFU] Enter\r\n");
|
||||
@@ -526,7 +500,6 @@ static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
|
||||
break;
|
||||
case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
|
||||
DBG_PRINTF("[DFU] Error\r\n");
|
||||
APP_ERROR_CHECK(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -585,10 +558,6 @@ static void nrf_qwr_error_handler(uint32_t nrf_error)
|
||||
APP_ERROR_HANDLER(nrf_error);
|
||||
}
|
||||
|
||||
/* Async MAA TX complete handler (forward declarations) */
|
||||
extern bool maa_async_on_tx_ready(void);
|
||||
extern bool maa_async_is_busy(void);
|
||||
extern void maa_async_abort(void);
|
||||
|
||||
/* 2026-03-17: Prevent blocking in BLE callback -- buffer command for main loop processing */
|
||||
static volatile uint8_t pending_cmd_buf[BLE_NUS_MAX_DATA_LEN] = {0};
|
||||
@@ -605,6 +574,11 @@ static void nus_data_handler(ble_nus_evt_t * p_evt)
|
||||
{
|
||||
if (p_evt->type == BLE_NUS_EVT_RX_DATA)
|
||||
{
|
||||
if (!ble_connection_st)
|
||||
{
|
||||
return; /* Reject command before security is established */
|
||||
}
|
||||
|
||||
cmd_type_t = CMD_BLE;
|
||||
ble_got_new_data = true;
|
||||
|
||||
@@ -612,8 +586,7 @@ static void nus_data_handler(ble_nus_evt_t * p_evt)
|
||||
{
|
||||
static uint32_t last_update_tick = 0;
|
||||
uint32_t now_tick = app_timer_cnt_get();
|
||||
if (last_update_tick == 0 ||
|
||||
app_timer_cnt_diff_compute(now_tick, last_update_tick) >= APP_TIMER_TICKS(30000))
|
||||
if (last_update_tick == 0 || app_timer_cnt_diff_compute(now_tick, last_update_tick) >= APP_TIMER_TICKS(30000))
|
||||
{
|
||||
ble_gap_conn_params_t conn_params;
|
||||
conn_params.min_conn_interval = MIN_CONN_INTERVAL;
|
||||
@@ -1043,7 +1016,7 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
|
||||
* 0x3D MIC failure, 0x3E connection failed to be established
|
||||
* -> maintain unlimited advertising + block sleep entry
|
||||
*/
|
||||
bool unintended_disc = (disc_reason == BLE_HCI_CONNECTION_TIMEOUT) ||
|
||||
bool unintended_disc = (disc_reason == BLE_HCI_CONNECTION_TIMEOUT) ||
|
||||
(disc_reason == BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT) ||
|
||||
(disc_reason == BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE)||
|
||||
(disc_reason == BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED);
|
||||
@@ -1081,11 +1054,14 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
DBG_PRINTF("[BLE] Connected\r\n");
|
||||
DBG_PRINTF("[BLE] GAP Connected\r\n");
|
||||
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
ble_connection_st = 1;
|
||||
battery_timer_start();
|
||||
if (BLE_DEV_MODE)
|
||||
{
|
||||
ble_connection_st = 1;
|
||||
battery_timer_start();
|
||||
}
|
||||
#endif
|
||||
|
||||
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
@@ -1226,9 +1202,7 @@ void uart_event_handle(app_uart_evt_t * p_event)
|
||||
UNUSED_VARIABLE(app_uart_get(&data_array[index]));
|
||||
index++;
|
||||
|
||||
if ((data_array[index - 1] == '\n') ||
|
||||
(data_array[index - 1] == '\r') ||
|
||||
(index >= m_ble_nus_max_data_len))
|
||||
if ((data_array[index - 1] == '\n') || (data_array[index - 1] == '\r') || (index >= m_ble_nus_max_data_len))
|
||||
{
|
||||
if (index > 1)
|
||||
{
|
||||
@@ -1595,12 +1569,19 @@ void dr_binary_tx_safe(uint8_t const *ble_bin_buff, uint16_t length)
|
||||
* Power Button State Machine (main_s)
|
||||
*
|
||||
* Called repeatedly by a 5ms single-shot timer (m_power_on_delay_timer).
|
||||
* Action determined by cnt_s value at button release:
|
||||
* - cnt_s < 150 (< 0.75s): short press -> power OFF
|
||||
* - cnt_s >= 150 (~0.75s): normal boot sequence start
|
||||
*
|
||||
* [Boot phase] (booted == false)
|
||||
* - cnt_s < 400 (< 2s): short press -> power OFF
|
||||
* - cnt_s >= 400 (~2s): normal boot sequence start
|
||||
* - cnt_s > 1000 (~5s): factory reset (passkey reset + power OFF)
|
||||
* - m_reset_status == 2: reboot after software reset
|
||||
*
|
||||
* [Running phase] (booted == true)
|
||||
* - Button pressed 2s (cnt_s >= 400): power OFF
|
||||
* - Button released: reset counter, keep polling
|
||||
*============================================================================*/
|
||||
static bool booted = false;
|
||||
|
||||
static void main_s(void * p_context)
|
||||
{
|
||||
UNUSED_PARAMETER(p_context);
|
||||
@@ -1608,30 +1589,51 @@ static void main_s(void * p_context)
|
||||
|
||||
bool button_released = nrf_gpio_pin_read(POWER_BUTTON);
|
||||
|
||||
/* ---- Running phase: post-boot button polling ---- */
|
||||
if (booted)
|
||||
{
|
||||
if (!button_released)
|
||||
{
|
||||
cnt_s++;
|
||||
if (cnt_s == 400) /* 400 x 5ms = 2s */
|
||||
{
|
||||
DBG_PRINTF("[BTN] Power OFF\r\n");
|
||||
led_set_state(LED_STATE_POWER_OFF);
|
||||
go_device_power_off = true;
|
||||
main_timer_start();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt_s = 0;
|
||||
}
|
||||
timers_start();
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---- Boot phase ---- */
|
||||
if (button_released)
|
||||
{
|
||||
if ((cnt_s < 200) && (m_reset_status != 2))
|
||||
if ((cnt_s < 250) && (m_reset_status != 2))
|
||||
{
|
||||
DBG_PRINTF("[BTN] Short->OFF\r\n");
|
||||
led_set_state(LED_STATE_OFF);
|
||||
power_control_handler(OFF);
|
||||
cnt_s = 0;
|
||||
}
|
||||
else if (cnt_s > 1000)
|
||||
else if (cnt_s >= 3000) /* 3000 x 5ms = 15s */
|
||||
{
|
||||
DBG_PRINTF("[BTN] Long->Reset\r\n");
|
||||
DBG_PRINTF("[BTN] Bond Delete\r\n");
|
||||
power_control_handler(ON);
|
||||
nrf_delay_ms(100);
|
||||
bond_data_delete = true;
|
||||
m_config.bond_data_delete = (uint8_t)bond_data_delete;
|
||||
const char pass_init[PASSKEY_LENGTH] = DEFAULT_PASSKEY;
|
||||
memcpy(m_config.static_passkey, pass_init, PASSKEY_LENGTH);
|
||||
config_save();
|
||||
nrf_delay_ms(1000);
|
||||
go_device_power_off = true;
|
||||
main_timer_start();
|
||||
}
|
||||
else if (cnt_s > 200 || (m_reset_status == 2))
|
||||
else if (cnt_s >= 250 || (m_reset_status == 2)) /* 250 x 5ms = 1.25s + α */
|
||||
{
|
||||
DBG_PRINTF("[BTN] Boot (cnt=%d)\r\n", cnt_s);
|
||||
device_reset = false;
|
||||
@@ -1648,6 +1650,11 @@ static void main_s(void * p_context)
|
||||
DBG_PRINTF("[BOOT] ADV started\r\n");
|
||||
m_reset_status = 1;
|
||||
DBG_PRINTF("[BOOT] Ready\r\n");
|
||||
|
||||
/* Boot complete -> switch to running phase */
|
||||
booted = true;
|
||||
cnt_s = 0;
|
||||
timers_start();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1655,7 +1662,7 @@ static void main_s(void * p_context)
|
||||
cnt_s++;
|
||||
device_reset = false;
|
||||
|
||||
if (cnt_s == 200)
|
||||
if (cnt_s == 250) /* 250 x 5ms = 1.25s + α */
|
||||
{
|
||||
led_set_state(LED_STATE_POWER_ON);
|
||||
DBG_PRINTF("[BTN] 2.0s\r\n");
|
||||
|
||||
@@ -31,8 +31,14 @@
|
||||
* Firmware Version Update History
|
||||
* - VBTFW0101 : Merged reb+red packets (single packet per channel), 260330 jhChun
|
||||
* - VBTFW0102 : Added LED state command (msl) and re-pairing support, 260331 jhChun
|
||||
* - VBTFW0103 260416 jhChun
|
||||
* : Stabilized ADC measurement by clearing buffers before sampling.
|
||||
* : Improved low-battery detection and automatic power-off handling.
|
||||
* : Updated BLE security, bonding, and advertising timeout behavior.
|
||||
* : Cleaned up command parsing and removed unused project files.
|
||||
* - VBTFW0111 260421 jhChun
|
||||
------------------------------------------------------------------------- */
|
||||
#define FIRMWARE_VERSION "VBTFW0102"
|
||||
#define FIRMWARE_VERSION "VBTFW0111"
|
||||
|
||||
/*==============================================================================
|
||||
* Data Length Constants
|
||||
@@ -156,7 +162,6 @@ void ascii_format_data(uint8_t *buffer, const char *tag, const char *data_ascii,
|
||||
*============================================================================*/
|
||||
extern volatile bool data_tx_in_progress; /* BLE TX in progress flag */
|
||||
extern volatile bool ble_connection_st; /* BLE connection state (0=disconnected, 1=connected) */
|
||||
extern volatile bool processing; /* Sensor data processing flag (prevents duplicate commands) */
|
||||
|
||||
/* 2026-03-17: Global variables moved from cmd_parse.c to main.c */
|
||||
extern char SERIAL_NO[SERIAL_NO_LENGTH]; /* Serial number */
|
||||
|
||||
+29
-85
@@ -71,11 +71,25 @@ extern void dr_piezo_power_off(void);
|
||||
/*==============================================================================
|
||||
* PRIVATE DEFINES
|
||||
*============================================================================*/
|
||||
|
||||
/* Extract pin number from NRF_GPIO_PIN_MAP (lower 5 bits) */
|
||||
#define DR_PIN_NUM(pin) ((pin) & 0x1F)
|
||||
#define DR_PIN_PORT(pin) (((pin) >> 5) & 0x01)
|
||||
|
||||
/* BLE packet constants */
|
||||
#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_RDB_HEADER_LEN 8 /* "rdb:" tag(4) + num_samples(2) + compressed_size(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 */
|
||||
|
||||
/* Piezo MUX pins (8ch) */
|
||||
#define DR_PIEZO_EN_MUXA NRF_GPIO_PIN_MAP(0, 21) /**< MUXA Enable */
|
||||
#define DR_PIEZO_EN_MUXB NRF_GPIO_PIN_MAP(0, 23) /**< MUXB Enable */
|
||||
#define DR_PIEZO_MUX_SEL1 NRF_GPIO_PIN_MAP(0, 28) /**< MUX Select 1 */
|
||||
#define DR_PIEZO_MUX_SEL0 NRF_GPIO_PIN_MAP(1, 10) /**< MUX Select 0 */
|
||||
|
||||
/*==============================================================================
|
||||
* PRIVATE VARIABLES
|
||||
*============================================================================*/
|
||||
@@ -133,8 +147,6 @@ dr_adc_err_t dr_adc_init(void)
|
||||
{
|
||||
nrfx_err_t err;
|
||||
|
||||
ADC_LOG("ADC121S051 init (HW SPI, SPIM3)...");
|
||||
|
||||
nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG;
|
||||
config.sck_pin = DR_ADC_PIN_SCLK; /* P0.14 */
|
||||
config.mosi_pin = NRFX_SPIM_PIN_NOT_USED;/* not used (read-only ADC) */
|
||||
@@ -146,7 +158,7 @@ dr_adc_err_t dr_adc_init(void)
|
||||
config.ss_active_high = false; /* CS active LOW */
|
||||
|
||||
err = nrfx_spim_init(&m_spim, &config, NULL, NULL);
|
||||
ADC_LOG("SPIM3 init result: 0x%08X (%s)", err, (err == NRFX_SUCCESS) ? "OK" : "FAIL");
|
||||
|
||||
if (err != NRFX_SUCCESS)
|
||||
{
|
||||
return DR_ADC_ERR_NOT_INIT;
|
||||
@@ -160,8 +172,6 @@ dr_adc_err_t dr_adc_init(void)
|
||||
|
||||
m_initialized = true;
|
||||
|
||||
ADC_LOG("ADC121S051 ready (VREF=%dmV, HW SPI)", m_vref_mv);
|
||||
|
||||
return DR_ADC_OK;
|
||||
}
|
||||
|
||||
@@ -173,10 +183,7 @@ void dr_adc_uninit(void)
|
||||
}
|
||||
|
||||
nrfx_spim_uninit(&m_spim);
|
||||
|
||||
m_initialized = false;
|
||||
|
||||
ADC_LOG("ADC121S051 uninitialized");
|
||||
}
|
||||
|
||||
bool dr_adc_is_initialized(void)
|
||||
@@ -350,8 +357,7 @@ dr_adc_err_t dr_adc_measure_echo(dr_adc_echo_t *echo, const dr_adc_echo_config_t
|
||||
return dr_adc_analyze_echo(m_echo_buffer, cfg.num_samples, echo, cfg.threshold_raw);
|
||||
}
|
||||
|
||||
dr_adc_err_t dr_adc_burst_and_capture(uint8_t cycles, uint16_t delay_us,
|
||||
uint16_t num_samples, dr_adc_echo_t *echo)
|
||||
dr_adc_err_t dr_adc_burst_and_capture(uint8_t cycles, uint16_t delay_us, uint16_t num_samples, dr_adc_echo_t *echo)
|
||||
{
|
||||
(void)cycles; /* Not used - ADC test only */
|
||||
|
||||
@@ -407,8 +413,7 @@ const uint16_t* dr_adc_get_echo_buffer(void)
|
||||
return m_echo_buffer;
|
||||
}
|
||||
|
||||
dr_adc_err_t dr_adc_analyze_echo(const uint16_t *buffer, uint16_t num_samples,
|
||||
dr_adc_echo_t *echo, uint16_t threshold)
|
||||
dr_adc_err_t dr_adc_analyze_echo(const uint16_t *buffer, uint16_t num_samples, dr_adc_echo_t *echo, uint16_t threshold)
|
||||
{
|
||||
if (buffer == NULL || echo == NULL)
|
||||
{
|
||||
@@ -522,57 +527,6 @@ uint32_t dr_adc_get_vref(void)
|
||||
return m_vref_mv;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* PUBLIC FUNCTIONS - DEBUG
|
||||
*============================================================================*/
|
||||
|
||||
bool dr_adc_test(void)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
ADC_LOG("Test FAIL: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t raw;
|
||||
dr_adc_err_t err = dr_adc_read_raw(&raw);
|
||||
|
||||
if (err != DR_ADC_OK)
|
||||
{
|
||||
ADC_LOG("Test FAIL: read error %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (raw > DR_ADC_MAX_VALUE)
|
||||
{
|
||||
ADC_LOG("Test FAIL: invalid value %d", raw);
|
||||
return false;
|
||||
}
|
||||
|
||||
ADC_LOG("Test PASS: raw=%d (%dmV)", raw, dr_adc_raw_to_mv(raw));
|
||||
return true;
|
||||
}
|
||||
|
||||
void dr_adc_print_buffer(const uint16_t *buffer, uint16_t num_samples)
|
||||
{
|
||||
#ifdef DEBUG_ADC
|
||||
if (buffer == NULL || num_samples == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ADC_LOG("Echo buffer (%d samples):", num_samples);
|
||||
|
||||
for (uint16_t i = 0; i < num_samples; i++)
|
||||
{
|
||||
ADC_LOG("[%3d] %4d (%4dmV)", i, buffer[i], dr_adc_raw_to_mv(buffer[i]));
|
||||
}
|
||||
#else
|
||||
(void)buffer;
|
||||
(void)num_samples;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* BLE TRANSMISSION
|
||||
*============================================================================*/
|
||||
@@ -591,26 +545,11 @@ extern void dr_sd_delay_ms(uint32_t ms);
|
||||
/* External piezo burst function */
|
||||
extern void dr_piezo_burst_sw(uint8_t cycles);
|
||||
|
||||
/* BLE packet constants */
|
||||
#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 */
|
||||
|
||||
/*==============================================================================
|
||||
* PIEZO CHANNEL SELECTION
|
||||
*============================================================================*/
|
||||
|
||||
/* Piezo MUX pins (8ch) */
|
||||
#define DR_PIEZO_EN_MUXA NRF_GPIO_PIN_MAP(0, 21) /**< MUXA Enable */
|
||||
#define DR_PIEZO_EN_MUXB NRF_GPIO_PIN_MAP(0, 23) /**< MUXB Enable */
|
||||
#define DR_PIEZO_MUX_SEL1 NRF_GPIO_PIN_MAP(0, 28) /**< MUX Select 1 */
|
||||
#define DR_PIEZO_MUX_SEL0 NRF_GPIO_PIN_MAP(1, 10) /**< MUX Select 0 */
|
||||
|
||||
/*
|
||||
* Channel mapping (8ch) jhChun 26.01.29
|
||||
* Channel mapping (8ch)
|
||||
|
||||
* | EN MUXA | EN MUXB | SEL 0 | SEL 1
|
||||
* ----------------------------------------------
|
||||
@@ -1095,8 +1034,7 @@ dr_adc_err_t dr_adc_delta_compress(const uint16_t *samples, uint16_t num_samples
|
||||
}
|
||||
|
||||
|
||||
dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data,
|
||||
uint8_t *ble_buffer)
|
||||
dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data, uint8_t *ble_buffer)
|
||||
{
|
||||
if (ch_data == NULL || ble_buffer == NULL)
|
||||
{
|
||||
@@ -1104,7 +1042,7 @@ dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data,
|
||||
}
|
||||
|
||||
/* Compress data first */
|
||||
static uint8_t delta_buffer[400] = {0}; /* Worst case: 140*3 = 420 bytes */
|
||||
static uint8_t delta_buffer[420] = {0}; /* Worst case when num_samples=140: 140 * 3 = 420 bytes */
|
||||
uint16_t compressed_size = 0;
|
||||
|
||||
dr_adc_err_t err = dr_adc_delta_compress(ch_data->samples, ch_data->num_samples,
|
||||
@@ -1125,7 +1063,6 @@ dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data,
|
||||
ble_buffer[6] = (uint8_t)(compressed_size >> 8);
|
||||
ble_buffer[7] = (uint8_t)(compressed_size & 0xFF);
|
||||
|
||||
#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 */
|
||||
|
||||
uint16_t dst_idx = BLE_RDB_HEADER_LEN;
|
||||
@@ -1353,6 +1290,9 @@ dr_adc_err_t maa_async_start(uint8_t freq_option, uint16_t delay_us, uint16_t nu
|
||||
return DR_ADC_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* Clear BLE buffer to prevent stale data from previous measurement */
|
||||
memset(ble_buffer, 0, BLE_MTU_SIZE);
|
||||
|
||||
/* Initialize context */
|
||||
g_maa_ctx.freq_option = freq_option;
|
||||
g_maa_ctx.delay_us = delay_us;
|
||||
@@ -1377,7 +1317,11 @@ dr_adc_err_t maa_async_start(uint8_t freq_option, uint16_t delay_us, uint16_t nu
|
||||
{
|
||||
g_plat.log("[maa] maa_async_start: CH%u capture failed (%d)", ch, err);
|
||||
}
|
||||
maa_async_send_completion(0xFFF0 | ch);
|
||||
/* Clean up state only — do NOT send raa: here.
|
||||
The caller (Cmd_maa / Cmd_mbb) sends the raa: error packet
|
||||
to avoid duplicate raa: on the BLE link. */
|
||||
dr_piezo_power_off();
|
||||
g_maa_ctx.state = MAA_ASYNC_IDLE;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,19 +263,6 @@ uint32_t dr_adc_get_vref(void);
|
||||
* DEBUG FUNCTIONS
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Test ADC communication
|
||||
* @return true if OK
|
||||
*/
|
||||
bool dr_adc_test(void);
|
||||
|
||||
/**
|
||||
* @brief Print echo buffer to debug output
|
||||
* @param buffer Sample buffer
|
||||
* @param num_samples Number of samples
|
||||
*/
|
||||
void dr_adc_print_buffer(const uint16_t *buffer, uint16_t num_samples);
|
||||
|
||||
/*==============================================================================
|
||||
* POWER CONTROL
|
||||
*============================================================================*/
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
*
|
||||
* Measures battery voltage via nRF52840 SAADC on AIN2:
|
||||
* - 12-bit resolution, 4x oversampling
|
||||
* - Periodic monitoring via battery_loop timer (60 s interval)
|
||||
* - Auto power-off after 10 consecutive readings below 3500 mV
|
||||
* - Periodic safety check via battery_loop timer (60 s interval)
|
||||
* - Sequential: battery -> temperature measurement
|
||||
* - Auto power-off after 5 consecutive readings below 3500 mV or above 40 C
|
||||
* - In info4 mode (bulk sensor collection): stores to info_batt
|
||||
*
|
||||
* Voltage conversion:
|
||||
@@ -26,7 +27,8 @@
|
||||
#include "app_timer.h"
|
||||
#include "battery_saadc.h"
|
||||
#include "main_timer.h"
|
||||
#include "main.h"
|
||||
#include "tmp235_q1.h"
|
||||
#include "dr_piezo.h"
|
||||
#include "debug_print.h"
|
||||
|
||||
/* SAADC internal reference voltage (mV, float) */
|
||||
@@ -51,49 +53,111 @@ APP_TIMER_DEF(m_battery_loop_timer_id);
|
||||
/* Battery monitoring interval (ms) */
|
||||
#define BATTERY_LOOP_INTERVAL 60000
|
||||
|
||||
/* Safety check consecutive count threshold */
|
||||
#define SAFETY_CHECK_COUNT 5
|
||||
|
||||
/* Low-battery check flag — set by battery_loop, consumed by handler */
|
||||
bool low_battery_check = false;
|
||||
|
||||
/* Safety check mode flag — set by battery handler, consumed by tmp235 handler */
|
||||
bool safety_check_mode = false;
|
||||
|
||||
/* SAADC callback completion flag — used by all_sensors() to wait */
|
||||
volatile bool battery_saadc_done = false;
|
||||
|
||||
/* Safety check: cached battery voltage for use in safety_check_complete() */
|
||||
static float safety_batt_mv = 0;
|
||||
|
||||
/* Safety check: consecutive counters */
|
||||
static uint8_t low_battery_cnt = 0;
|
||||
static uint8_t over_temp_cnt = 0;
|
||||
|
||||
/* info4: bulk sensor collection mode flag */
|
||||
extern bool info4;
|
||||
|
||||
extern char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
|
||||
extern bool go_device_power_off;
|
||||
extern volatile bool processing;
|
||||
extern which_cmd_t cmd_type_t;
|
||||
extern uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN];
|
||||
|
||||
/* info4 mode: cached battery voltage (mV) */
|
||||
volatile uint16_t info_batt;
|
||||
volatile uint16_t info_batt;
|
||||
|
||||
/* info4 sequential measurement control flags */
|
||||
extern bool go_temp;
|
||||
extern bool go_batt;
|
||||
|
||||
extern bool motion_raw_data_enabled ;
|
||||
extern bool motion_raw_data_enabled;
|
||||
extern bool ble_got_new_data;
|
||||
extern bool motion_data_once ;
|
||||
extern bool motion_data_once;
|
||||
|
||||
/*==============================================================================
|
||||
* safety_check_complete - Called by tmp235 handler after temperature measurement
|
||||
*
|
||||
* Checks both battery voltage and temperature against thresholds.
|
||||
* 5 consecutive readings exceeding either threshold triggers power OFF.
|
||||
*============================================================================*/
|
||||
void safety_check_complete(float temp_c)
|
||||
{
|
||||
//DBG_PRINTF("[SAFETY] Batt=%d mV, Temp=%d.%d C\r\n",
|
||||
// (int)safety_batt_mv, (int)temp_c, ((int)(temp_c * 10)) % 10);
|
||||
|
||||
/* Battery check */
|
||||
if (safety_batt_mv <= LOW_BATTERY_VOLTAGE)
|
||||
{
|
||||
low_battery_cnt++;
|
||||
DBG_PRINTF("[SAFETY] Low batt cnt=%d\r\n", low_battery_cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
low_battery_cnt = 0;
|
||||
}
|
||||
|
||||
/* Temperature check */
|
||||
if (temp_c >= OVER_TEMPERATURE_THRESHOLD)
|
||||
{
|
||||
over_temp_cnt++;
|
||||
DBG_PRINTF("[SAFETY] Over temp cnt=%d\r\n", over_temp_cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
over_temp_cnt = 0;
|
||||
}
|
||||
|
||||
/* Power OFF if either threshold exceeded 5 consecutive times */
|
||||
if (low_battery_cnt >= SAFETY_CHECK_COUNT)
|
||||
{
|
||||
low_battery_cnt = 0;
|
||||
DBG_PRINTF("[SAFETY] Low battery -> Power OFF\r\n");
|
||||
go_device_power_off = true;
|
||||
main_timer_start();
|
||||
}
|
||||
else if (over_temp_cnt >= SAFETY_CHECK_COUNT)
|
||||
{
|
||||
over_temp_cnt = 0;
|
||||
DBG_PRINTF("[SAFETY] Over temperature -> Power OFF\r\n");
|
||||
go_device_power_off = true;
|
||||
main_timer_start();
|
||||
}
|
||||
|
||||
dr_piezo_power_off();
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* battery_event_handler - SAADC conversion complete callback
|
||||
*
|
||||
* Converts the raw ADC value to battery voltage (mV) and then:
|
||||
* - Low-battery check mode: if <= 3500 mV for 10 consecutive times -> power OFF
|
||||
* - Low-battery check mode: store voltage, chain temperature measurement
|
||||
* - info4 mode: store to info_batt (no BLE send)
|
||||
* - Normal mode: send rsn: response over BLE or UART
|
||||
*============================================================================*/
|
||||
void battery_event_handler( nrf_drv_saadc_evt_t const * p_event )
|
||||
void battery_event_handler(nrf_drv_saadc_evt_t const * p_event)
|
||||
{
|
||||
static uint8_t low_battery_cnt = 0;
|
||||
|
||||
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
|
||||
{
|
||||
nrf_saadc_value_t register_val = 0;
|
||||
float batt_lvl_in_milli_volt_0 = 0; /* before divider correction */
|
||||
float batt_lvl_in_milli_volt_1 = 0; /* after divider correction */
|
||||
float batt_lvl_in_milli_volt_0 = 0;
|
||||
float batt_lvl_in_milli_volt_1 = 0;
|
||||
|
||||
register_val = p_event->data.done.p_buffer[0];
|
||||
|
||||
@@ -107,28 +171,21 @@ void battery_event_handler( nrf_drv_saadc_evt_t const * p_event )
|
||||
batt_lvl_in_milli_volt_0 = BATTERY_RESULT_IN_MILLI_VOLTS(register_val);
|
||||
|
||||
/* Resistor divider correction factor 1.42 */
|
||||
batt_lvl_in_milli_volt_1 = (batt_lvl_in_milli_volt_0) *1.42f;
|
||||
batt_lvl_in_milli_volt_1 = batt_lvl_in_milli_volt_0 * 1.42f;
|
||||
|
||||
/* --- Low-battery check mode (set by battery_loop timer) --- */
|
||||
if(low_battery_check == true)
|
||||
/* --- Safety check mode: store voltage, chain temperature measurement --- */
|
||||
if (low_battery_check == true)
|
||||
{
|
||||
low_battery_check = false;
|
||||
safety_batt_mv = batt_lvl_in_milli_volt_1;
|
||||
safety_check_mode = true;
|
||||
|
||||
if(batt_lvl_in_milli_volt_1 <= LOW_BATTERY_VOLTAGE)
|
||||
/* TMP235 shares piezo TX/RX power rail */
|
||||
if (!dr_piezo_is_power_on())
|
||||
{
|
||||
if(low_battery_cnt >= 10)
|
||||
{
|
||||
low_battery_cnt = 0;
|
||||
DBG_PRINTF("Save FDS parameters and then Power OFF\r\n");
|
||||
go_device_power_off = true;
|
||||
main_timer_start();
|
||||
}
|
||||
else
|
||||
{
|
||||
low_battery_cnt++;
|
||||
DBG_PRINTF("WARNING!!! low_battery cnt = %d, Batt = %d(mV)\r\n", low_battery_cnt, (int)batt_lvl_in_milli_volt_1);
|
||||
}
|
||||
dr_piezo_power_on();
|
||||
}
|
||||
tmp235_voltage_level_meas();
|
||||
}
|
||||
|
||||
/* --- info4 mode: store value for mbb? bulk response --- */
|
||||
@@ -137,7 +194,7 @@ void battery_event_handler( nrf_drv_saadc_evt_t const * p_event )
|
||||
info_batt = batt_lvl_in_milli_volt_1;
|
||||
}
|
||||
|
||||
/* --- Normal mode: send rsn: BLE / UART response --- */
|
||||
/* --- Normal mode: send rsn: BLE response --- */
|
||||
else
|
||||
{
|
||||
if (cmd_type_t == CMD_UART)
|
||||
@@ -146,8 +203,8 @@ void battery_event_handler( nrf_drv_saadc_evt_t const * p_event )
|
||||
}
|
||||
else if (cmd_type_t == CMD_BLE)
|
||||
{
|
||||
single_format_data(ble_bin_buffer, "rsn:", batt_lvl_in_milli_volt_1);
|
||||
dr_binary_tx_safe(ble_bin_buffer,3);
|
||||
single_format_data(ble_bin_buffer, "rsn:", batt_lvl_in_milli_volt_1);
|
||||
dr_binary_tx_safe(ble_bin_buffer, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +223,8 @@ static void battery_configure(void)
|
||||
saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
|
||||
saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X;
|
||||
ret_code_t err_code = nrf_drv_saadc_init(&saadc_config, battery_event_handler);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return; /* SAADC busy — skip this cycle, retry next */
|
||||
}
|
||||
|
||||
@@ -200,22 +258,19 @@ void battery_level_meas(void)
|
||||
* battery_loop - Periodic battery monitoring timer callback
|
||||
*
|
||||
* Sets the low-battery check flag and starts a measurement.
|
||||
* Skips if another sensor (IMU / info4) is already running (SAADC conflict).
|
||||
* Skips if info4 mode is active (SAADC conflict).
|
||||
*============================================================================*/
|
||||
void battery_loop(void * p_context)
|
||||
{
|
||||
UNUSED_PARAMETER(p_context);
|
||||
|
||||
if (processing == true || info4 == true)
|
||||
if (info4 == true)
|
||||
{
|
||||
processing = false ;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
low_battery_check = true;
|
||||
battery_level_meas();
|
||||
}
|
||||
|
||||
low_battery_check = true;
|
||||
battery_level_meas();
|
||||
}
|
||||
|
||||
/* Start the periodic battery monitoring timer. */
|
||||
|
||||
@@ -5,24 +5,35 @@
|
||||
*
|
||||
* API:
|
||||
* battery_level_meas() : one-shot measurement (async, result via callback)
|
||||
* battery_timer_init/start/stop() : 5-second periodic monitoring timer
|
||||
* battery_timer_init/start/stop() : 60-second periodic monitoring timer
|
||||
*
|
||||
* Auto power-off is triggered after 10 consecutive readings below
|
||||
* LOW_BATTERY_VOLTAGE (3500 mV).
|
||||
* Periodic safety check (every 60 s):
|
||||
* Battery -> Temperature sequential measurement via SAADC.
|
||||
* Auto power-off after 5 consecutive readings below LOW_BATTERY_VOLTAGE (3500 mV)
|
||||
* or above OVER_TEMPERATURE_THRESHOLD (40 C).
|
||||
*============================================================================*/
|
||||
|
||||
#ifndef _BATTERY_SAADC_H_
|
||||
#define _BATTERY_SAADC_H_
|
||||
|
||||
/* Low-battery threshold (mV) — 10 consecutive readings below this -> power OFF */
|
||||
/* Low-battery threshold (mV) — 5 consecutive readings below this -> power OFF */
|
||||
#define LOW_BATTERY_VOLTAGE 3500
|
||||
|
||||
/* Over-temperature threshold (deg C) — 5 consecutive readings above this -> power OFF */
|
||||
#define OVER_TEMPERATURE_THRESHOLD 40.0f
|
||||
|
||||
/* SAADC callback completion flag (used by all_sensors() to wait) */
|
||||
extern volatile bool battery_saadc_done;
|
||||
|
||||
/* Safety check mode flag — set by battery_loop, consumed by tmp235 handler */
|
||||
extern bool safety_check_mode;
|
||||
|
||||
/* Called by tmp235 handler when safety check temperature measurement completes */
|
||||
void safety_check_complete(float temp_c);
|
||||
|
||||
/* Start a single async battery measurement. Result handled in callback. */
|
||||
void battery_level_meas(void);
|
||||
/* Start the 5-second periodic battery monitoring timer. */
|
||||
/* Start the 60-second periodic battery monitoring timer. */
|
||||
void battery_timer_start(void);
|
||||
/* Stop the battery monitoring timer. */
|
||||
void battery_timer_stop(void);
|
||||
|
||||
@@ -101,22 +101,22 @@
|
||||
#define HALF_PERIOD_TICKS 4 /* half period: 250 ns / 62.5 ns = 4 ticks */
|
||||
|
||||
/*==============================================================================
|
||||
* Piezo operating frequency
|
||||
* SW burst port register bitmasks
|
||||
*
|
||||
* Target: 2.1 MHz (HW burst mode).
|
||||
* SW burst timing is hard-coded per-frequency via NOP count.
|
||||
*
|
||||
* NOP timing (CPU 64 MHz, 1 NOP = 15.625 ns):
|
||||
* 1.7 MHz: half 294 ns -> 1st half 18 NOP, 2nd half 10 NOP + loop overhead
|
||||
* 1.8 MHz: half 278 ns -> 1st half 17 NOP, 2nd half 11 NOP + loop overhead
|
||||
* 1.9 MHz: half 263 ns -> 1st half 15 NOP, 2nd half 9 NOP + loop overhead
|
||||
* 2.0 MHz: half 250 ns -> 1st half 15 NOP, 2nd half 10 NOP + loop overhead
|
||||
* 2.1 MHz: half 238 ns -> 1st half 14 NOP, 2nd half 9 NOP + loop overhead
|
||||
* 2.2 MHz: half 227 ns -> 1st half 13 NOP, 2nd half 8 NOP + loop overhead
|
||||
*
|
||||
* To change frequency, modify NOP count in dr_piezo_burst_sw_XXmhz().
|
||||
* Pre-calculated from pin definitions in dr_piezo.h.
|
||||
* Used for direct writes to NRF_P1->OUT, enabling simultaneous multi-pin control.
|
||||
* PE is on P0 port, controlled separately via OUTSET/OUTCLR.
|
||||
*============================================================================*/
|
||||
#define PIEZO_FREQ_MHZ 2.1f /* default operating frequency (MHz) */
|
||||
/* Extract bit position within port from pin number (lower 5 bits = 0~31) */
|
||||
#define PIN_NUM(pin) ((pin) & 0x1F)
|
||||
|
||||
#define P_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_P_OUT)) /* P1.07 positive output */
|
||||
#define N_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_N_OUT)) /* P1.06 negative output */
|
||||
#define PE_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_PE)) /* P0.25 pulse enable */
|
||||
#define DMP_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_DMP)) /* P1.00 dump control */
|
||||
|
||||
/* Combined mask of piezo control pins on P1 port (excludes channel select pins) */
|
||||
#define P1_CTRL_MASK (P_OUT_MASK | N_OUT_MASK | DMP_MASK)
|
||||
|
||||
/*==============================================================================
|
||||
* Static variables
|
||||
@@ -194,7 +194,7 @@ void dr_piezo_power_on(void)
|
||||
nrf_gpio_pin_set(DR_PIEZO_PWR_EN);
|
||||
|
||||
/* Wait for power stabilization */
|
||||
nrf_delay_ms(3);
|
||||
nrf_delay_ms(10);
|
||||
|
||||
m_power_enabled = true;
|
||||
|
||||
@@ -544,6 +544,7 @@ void dr_piezo_mux_init(void)
|
||||
NRF_GPIO_PIN_H0H1, /* High drive */
|
||||
NRF_GPIO_PIN_NOSENSE
|
||||
);
|
||||
|
||||
nrf_gpio_cfg(
|
||||
DR_PIEZO_MUX_SEL1,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
@@ -553,7 +554,7 @@ void dr_piezo_mux_init(void)
|
||||
NRF_GPIO_PIN_NOSENSE
|
||||
);
|
||||
|
||||
/* GPIO PIN Setting jhChun 0129 */
|
||||
/* GPIO PIN Setting */
|
||||
nrf_gpio_cfg(
|
||||
DR_PIEZO_EN_MUXA, // PIN
|
||||
NRF_GPIO_PIN_DIR_OUTPUT, // DIR : OUTPUT
|
||||
@@ -592,37 +593,37 @@ void dr_piezo_select_channel(uint8_t channel)
|
||||
{
|
||||
channel = channel & 0x07; /* Mask to 0~7 range */
|
||||
|
||||
switch (channel) {
|
||||
// EN_A EN_B SEL0 SEL1
|
||||
case 0: // A0: 1 0 0 0
|
||||
switch (channel)
|
||||
{
|
||||
case 0: // A0: EN_MUXA=1, EN_MUXB=0, SEL0=0, SEL1=0
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXB); nrf_gpio_pin_set(DR_PIEZO_EN_MUXA);
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
case 1: // A2: 1 0 1 0
|
||||
case 1: // A1: EN_MUXA=1, EN_MUXB=0, SEL0=1, SEL1=0
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXB); nrf_gpio_pin_set(DR_PIEZO_EN_MUXA);
|
||||
nrf_gpio_pin_set(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
case 2: // A1: 1 0 0 1
|
||||
case 2: // A2: EN_MUXA=1, EN_MUXB=0, SEL0=0, SEL1=1
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXB); nrf_gpio_pin_set(DR_PIEZO_EN_MUXA);
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_set(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
case 3: // A3: 1 0 1 1
|
||||
case 3: // A3: EN_MUXA=1, EN_MUXB=0, SEL0=1, SEL1=1
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXB); nrf_gpio_pin_set(DR_PIEZO_EN_MUXA);
|
||||
nrf_gpio_pin_set(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_set(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
case 4: // B0: 0 1 1 1
|
||||
/*case 4: // B0: EN_MUXA=0, EN_MUXB=1, SEL0=1, SEL1=1
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXA); nrf_gpio_pin_set(DR_PIEZO_EN_MUXB);
|
||||
nrf_gpio_pin_set(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_set(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
case 5: // B1: 0 1 1 0
|
||||
case 5: // B1: EN_MUXA=0, EN_MUXB=1, SEL0=0, SEL1=1
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXA); nrf_gpio_pin_set(DR_PIEZO_EN_MUXB);
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_set(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
case 6: // B2: 0 1 0 1
|
||||
break;*/
|
||||
case 5: // B2: EN_MUXA=0, EN_MUXB=1, SEL0=1, SEL1=0
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXA); nrf_gpio_pin_set(DR_PIEZO_EN_MUXB);
|
||||
nrf_gpio_pin_set(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
case 7: // B3: 0 1 0 0
|
||||
case 4: // B3: EN_MUXA=0, EN_MUXB=1, SEL0=0, SEL1=0
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXA); nrf_gpio_pin_set(DR_PIEZO_EN_MUXB);
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL0); nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL1);
|
||||
break;
|
||||
@@ -741,29 +742,6 @@ void dr_piezo_transmit(uint8_t cycles)
|
||||
* channel select pins (MUX SEL) via P1_CTRL_MASK (only control pins change).
|
||||
* PE is on P0 port, so it is controlled separately via OUTSET/OUTCLR registers.
|
||||
*============================================================================*/
|
||||
/* Extract bit position within port from pin number (lower 5 bits = 0~31) */
|
||||
#define PIN_NUM(pin) ((pin) & 0x1F)
|
||||
|
||||
|
||||
/* P1 port pin bitmasks - auto-generated from pin definitions in dr_piezo.h
|
||||
*
|
||||
* WARNING: Never hardcode pin numbers!
|
||||
* Hardcoding may save a developer's time temporarily,
|
||||
* but it will also shorten that developer's lifespan.
|
||||
* - Charles KWON
|
||||
*
|
||||
* Each mask represents the bit position within the port register.
|
||||
* Used for direct writes to NRF_P1->OUT, enabling simultaneous multi-pin control.
|
||||
*/
|
||||
|
||||
#define P_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_P_OUT)) /* P1.07 positive output */
|
||||
#define N_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_N_OUT)) /* P1.06 negative output */
|
||||
#define PE_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_PE)) /* P0.25 pulse enable */
|
||||
#define DMP_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_DMP)) /* P1.00 dump control */
|
||||
|
||||
/* Combined mask of piezo control pins on P1 port (excludes channel select pins) */
|
||||
#define P1_CTRL_MASK (P_OUT_MASK | N_OUT_MASK | DMP_MASK)
|
||||
|
||||
/*
|
||||
* Software burst - default frequency 2.1MHz
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "tmp235_q1.h"
|
||||
#include "main.h"
|
||||
#include "main_timer.h"
|
||||
#include "battery_saadc.h"
|
||||
#include "debug_print.h"
|
||||
|
||||
/* SAADC internal reference (mV) */
|
||||
@@ -101,20 +102,27 @@ void tmp235_voltage_handler(nrf_drv_saadc_evt_t const * p_event)
|
||||
DBG_PRINTF("ERR!!! Temperature is over 150c\r\n");
|
||||
}
|
||||
|
||||
if (info4 == true)
|
||||
/* --- Safety check mode: pass temperature to battery module for judgment --- */
|
||||
if (safety_check_mode == true)
|
||||
{
|
||||
safety_check_mode = false;
|
||||
safety_check_complete(led_temp);
|
||||
}
|
||||
|
||||
/* --- info4 mode: store value for mbb? bulk response --- */
|
||||
else if (info4 == true)
|
||||
{
|
||||
/* Store as integer (e.g. 36.50 C -> 3650) */
|
||||
info_temp = (uint16_t)(led_temp * 100);
|
||||
}
|
||||
else if(cmd_type_t == CMD_UART)
|
||||
else if (cmd_type_t == CMD_UART)
|
||||
{
|
||||
DBG_PRINTF("To%.2f\r\n\r\n",led_temp);
|
||||
DBG_PRINTF("To%.2f\r\n\r\n", led_temp);
|
||||
}
|
||||
else if(cmd_type_t == CMD_BLE)
|
||||
{
|
||||
else if (cmd_type_t == CMD_BLE)
|
||||
{
|
||||
led_temp_16 = led_temp * 100;
|
||||
single_format_data(ble_bin_buffer, "rso:", (uint16_t)led_temp_16);
|
||||
dr_binary_tx_safe(ble_bin_buffer,3);
|
||||
dr_binary_tx_safe(ble_bin_buffer, 3);
|
||||
}
|
||||
|
||||
tmp235_saadc_done = true;
|
||||
|
||||
@@ -152,28 +152,31 @@ void main_loop(void * p_context) /* For x ms */
|
||||
* Continuous read mode. If not waiting for BLE TX (ble_got_new_data==false),
|
||||
* call icm42670_main() and restart timer after 10ms for repeated execution.
|
||||
*/
|
||||
if(motion_raw_data_enabled == true) {
|
||||
if (motion_raw_data_enabled == true)
|
||||
{
|
||||
main_timer_stop(); /* Stop timer (prevent re-entry) */
|
||||
if(motion_data_once == true)
|
||||
if (motion_data_once == true)
|
||||
{
|
||||
/* One-shot mode: init HW I2C then read IMU data once */
|
||||
hw_i2c_init_once(); /* Switch to HW TWI mode (400kHz) */
|
||||
icm42670_main(); /* Read and process IMU data */
|
||||
}
|
||||
else{
|
||||
hw_i2c_init_once(); /* Switch to HW TWI mode (400kHz) */
|
||||
icm42670_main(); /* Read and process IMU data */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Continuous mode: repeat read if not waiting for BLE TX */
|
||||
if(ble_got_new_data==false){
|
||||
//for(uint16_t i=0 ; i<60 ;i++)
|
||||
//{
|
||||
DBG_PRINTF("IMU \r\n");
|
||||
if (ble_got_new_data==false)
|
||||
{
|
||||
//for(uint16_t i=0 ; i<60 ;i++)
|
||||
//{
|
||||
DBG_PRINTF("IMU \r\n");
|
||||
|
||||
icm42670_main(); /* Read IMU data */
|
||||
motion_raw_data_enabled = true; /* Keep flag set (continuous read) */
|
||||
main_timer_start_ms(1000); /* Next IMU read after 1s */
|
||||
}
|
||||
// else if(ble_got_new_data==true){
|
||||
// motion_data_once = true;
|
||||
// }
|
||||
icm42670_main(); /* Read IMU data */
|
||||
motion_raw_data_enabled = true; /* Keep flag set (continuous read) */
|
||||
main_timer_start_ms(1000); /* Next IMU read after 1s */
|
||||
}
|
||||
// else if(ble_got_new_data==true){
|
||||
// motion_data_once = true;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +187,8 @@ void main_loop(void * p_context) /* For x ms */
|
||||
* Called after IMU continuous read in info4 mode.
|
||||
* Timer remains stopped after measurement.
|
||||
*/
|
||||
if(go_batt == true) {
|
||||
if (go_batt == true)
|
||||
{
|
||||
DBG_PRINTF("IMU BATT\r\n");
|
||||
main_timer_stop(); /* Stop timer */
|
||||
go_batt = false; /* Consume flag (one-shot) */
|
||||
@@ -203,7 +207,8 @@ void main_loop(void * p_context) /* For x ms */
|
||||
* After completion, sets motion_data_once=true so the next IMU read
|
||||
* uses one-shot mode (with HW I2C re-init).
|
||||
*/
|
||||
if(go_temp == true) {
|
||||
if (go_temp == true)
|
||||
{
|
||||
DBG_PRINTF("IMU Temp\r\n");
|
||||
main_timer_stop(); /* Stop timer */
|
||||
// go_batt = false;
|
||||
@@ -218,21 +223,24 @@ void main_loop(void * p_context) /* For x ms */
|
||||
/* ---- System control event handling ---- */
|
||||
|
||||
/* Device power OFF handling */
|
||||
if(go_device_power_off == true){
|
||||
if (go_device_power_off == true)
|
||||
{
|
||||
main_timer_stop(); /* Stop timer */
|
||||
DBG_PRINTF("Off main_timer\r\n");
|
||||
device_power_off(); /* Execute device power OFF */
|
||||
}
|
||||
|
||||
/* Sleep mode entry handling */
|
||||
if(go_sleep_mode_enter == true){
|
||||
if (go_sleep_mode_enter == true)
|
||||
{
|
||||
main_timer_stop(); /* Stop timer */
|
||||
DBG_PRINTF("sleep main timer\r\n");
|
||||
sleep_mode_enter(); /* Execute sleep mode entry */
|
||||
}
|
||||
|
||||
/* NVIC system reset handling */
|
||||
if(go_NVIC_SystemReset == true) {
|
||||
if (go_NVIC_SystemReset == true)
|
||||
{
|
||||
main_timer_stop(); /* Stop timer */
|
||||
NVIC_SystemReset(); /* ARM Cortex-M4 system reset */
|
||||
}
|
||||
|
||||
@@ -48,26 +48,20 @@ APP_TIMER_DEF(m_power_timer_id);
|
||||
/* Power sequence current step (0: I2C init, 1: reserved, 2: complete) */
|
||||
static uint8_t p_order;
|
||||
|
||||
/* Data processing flag (declared in external module) */
|
||||
extern volatile bool processing;
|
||||
|
||||
/* Power sequence lock flag (true = sequence in progress) */
|
||||
bool lock_check = false;
|
||||
|
||||
/**
|
||||
* @brief Enter device sleep mode
|
||||
*
|
||||
* Clears the processing flag so the main loop stops
|
||||
* processing sensor data.
|
||||
*
|
||||
* @return 0 (always succeeds)
|
||||
*/
|
||||
int device_sleep_mode(void){
|
||||
int device_sleep_mode(void)
|
||||
{
|
||||
int rc = 0;
|
||||
nrf_delay_ms(2);
|
||||
DBG_PRINTF("Device_Sleep_Mode OK!\r\n");
|
||||
nrf_delay_ms(10);
|
||||
processing = false; /* Clear processing flag -> stop sensor handling */
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -80,7 +74,8 @@ int device_sleep_mode(void){
|
||||
*
|
||||
* @return 0 (always succeeds)
|
||||
*/
|
||||
int device_activated(void){
|
||||
int device_activated(void)
|
||||
{
|
||||
int rc = 0;
|
||||
p_order = 0; /* State machine start step (Step 0: I2C init) */
|
||||
lock_check =true; /* Lock: power sequence in progress */
|
||||
@@ -123,10 +118,13 @@ void power_loop(void *p_context)
|
||||
|
||||
/* Advance to next step or finish */
|
||||
/* Advance to next step or finish sequence */
|
||||
if (p_order < 2) {
|
||||
if (p_order < 2)
|
||||
{
|
||||
p_order++; /* Move to next step */
|
||||
power_timer_start(); /* Execute next step after 20ms */
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Power sequence fully complete */
|
||||
DBG_PRINTF("[PWR] Device Activated OK!\r\n");
|
||||
}
|
||||
@@ -141,7 +139,8 @@ void power_loop(void *p_context)
|
||||
*
|
||||
* @return 0 (always succeeds)
|
||||
*/
|
||||
int device_reactivated(void){
|
||||
int device_reactivated(void)
|
||||
{
|
||||
int rc = 0;
|
||||
sw_i2c_init_once(); /* Re-initialize I2C bus */
|
||||
nrf_delay_ms(10); /* Stabilization delay */
|
||||
|
||||
@@ -20,6 +20,22 @@ static struct {
|
||||
bool bonds_delete_pending;
|
||||
} m_state = {0};
|
||||
|
||||
static const char * sec_error_name(pm_sec_error_code_t error)
|
||||
{
|
||||
switch (error) {
|
||||
case PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING:
|
||||
return "PIN_OR_KEY_MISSING";
|
||||
case PM_CONN_SEC_ERROR_MIC_FAILURE:
|
||||
return "MIC_FAILURE";
|
||||
case PM_CONN_SEC_ERROR_DISCONNECT:
|
||||
return "DISCONNECT";
|
||||
case PM_CONN_SEC_ERROR_SMP_TIMEOUT:
|
||||
return "SMP_TIMEOUT";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize BLE security
|
||||
*/
|
||||
@@ -102,8 +118,9 @@ void ble_security_quick_pm_handler(pm_evt_t const *p_evt)
|
||||
|
||||
// DEV mode: do not forward security failure events to SDK handler (prevent disconnect)
|
||||
if (m_state.dev_mode && p_evt->evt_id == PM_EVT_CONN_SEC_FAILED) {
|
||||
DBG_PRINTF("Security failed: error=%d\r\n",
|
||||
p_evt->params.conn_sec_failed.error);
|
||||
DBG_PRINTF("Security failed: error=%d (%s)\r\n",
|
||||
p_evt->params.conn_sec_failed.error,
|
||||
sec_error_name(p_evt->params.conn_sec_failed.error));
|
||||
DBG_PRINTF("DEV: Ignoring sec failure, keeping connection\r\n");
|
||||
return;
|
||||
}
|
||||
@@ -129,8 +146,9 @@ void ble_security_quick_pm_handler(pm_evt_t const *p_evt)
|
||||
break;
|
||||
|
||||
case PM_EVT_CONN_SEC_FAILED:
|
||||
DBG_PRINTF("Security failed: error=%d\r\n",
|
||||
p_evt->params.conn_sec_failed.error);
|
||||
DBG_PRINTF("Security failed: error=%d (%s)\r\n",
|
||||
p_evt->params.conn_sec_failed.error,
|
||||
sec_error_name(p_evt->params.conn_sec_failed.error));
|
||||
|
||||
if (m_state.dev_mode) {
|
||||
// DEV mode: ignore security failure, keep connection
|
||||
@@ -138,6 +156,20 @@ void ble_security_quick_pm_handler(pm_evt_t const *p_evt)
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_evt->params.conn_sec_failed.error == PM_CONN_SEC_ERROR_DISCONNECT) {
|
||||
// The peer/link already disconnected before security finished.
|
||||
// There is no live connection to repair; BLE_GAP_EVT_DISCONNECTED
|
||||
// will restart advertising.
|
||||
DBG_PRINTF("Security ended by disconnect; waiting for reconnect\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_evt->params.conn_sec_failed.error == PM_CONN_SEC_ERROR_SMP_TIMEOUT) {
|
||||
// The SDK cannot start another SMP procedure on this link.
|
||||
pm_handler_disconnect_on_sec_failure(p_evt);
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_evt->params.conn_sec_failed.error == PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING) {
|
||||
// Key missing: attempt re-pairing, fall back to disconnect on failure
|
||||
err_code = pm_conn_secure(p_evt->conn_handle, true);
|
||||
|
||||
Reference in New Issue
Block a user