initial commit
This commit is contained in:
33
lib/pc_firm/.gitignore
vendored
Normal file
33
lib/pc_firm/.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Compiled binaries
|
||||
*.o
|
||||
*.hex
|
||||
*.bin
|
||||
*.elf
|
||||
*.map
|
||||
*.lst
|
||||
|
||||
# Build directories
|
||||
_build/
|
||||
build/
|
||||
output/
|
||||
|
||||
# IDE/Editor
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Segger/J-Link
|
||||
*.jlink
|
||||
|
||||
# nRF specific
|
||||
*.zip
|
||||
sdk_config.h.bak
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.bak
|
||||
145
lib/pc_firm/ble_security/ble_quick_security.c
Normal file
145
lib/pc_firm/ble_security/ble_quick_security.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* @file ble_quick_security.c
|
||||
* @brief Ultra-simple BLE Security Configuration Implementation
|
||||
*
|
||||
* Compatible with existing debug_print.h system.
|
||||
*/
|
||||
|
||||
#include "ble_quick_security.h"
|
||||
#include "peer_manager_handler.h"
|
||||
#include "app_error.h"
|
||||
#include <string.h>
|
||||
|
||||
// Use existing debug system
|
||||
#include "debug_print.h"
|
||||
|
||||
// Module state
|
||||
static struct {
|
||||
bool dev_mode;
|
||||
bool bonds_delete_pending;
|
||||
} m_state = {0};
|
||||
|
||||
/**
|
||||
* @brief Initialize BLE security
|
||||
*/
|
||||
void ble_security_quick_init(bool development_mode)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_gap_sec_params_t sec_params;
|
||||
|
||||
// Save mode
|
||||
m_state.dev_mode = development_mode;
|
||||
m_state.bonds_delete_pending = false;
|
||||
|
||||
// Initialize Peer Manager FIRST
|
||||
err_code = pm_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Configure security parameters
|
||||
memset(&sec_params, 0, sizeof(ble_gap_sec_params_t));
|
||||
|
||||
if (development_mode) {
|
||||
// ===== DEVELOPMENT MODE: No security =====
|
||||
sec_params.bond = 0; // No bonding
|
||||
sec_params.mitm = 0; // No MITM
|
||||
sec_params.lesc = 0; // No LESC
|
||||
sec_params.keypress = 0;
|
||||
sec_params.io_caps = BLE_GAP_IO_CAPS_NONE; // No passkey
|
||||
sec_params.oob = 0;
|
||||
sec_params.min_key_size = 7;
|
||||
sec_params.max_key_size = 16;
|
||||
|
||||
DBG_PRINTF("DEV MODE: Security DISABLED - Fast connection\r\n");
|
||||
|
||||
// Delete all bonds (async)
|
||||
err_code = pm_peers_delete();
|
||||
if (err_code == NRF_SUCCESS) {
|
||||
m_state.bonds_delete_pending = true;
|
||||
DBG_PRINTF("DEV MODE: Deleting all bonds...\r\n");
|
||||
}
|
||||
} else {
|
||||
// ===== PRODUCTION MODE: Full security =====
|
||||
sec_params.bond = 1; // Enable bonding
|
||||
sec_params.mitm = 1; // Enable MITM
|
||||
sec_params.lesc = 0; // Standard pairing
|
||||
sec_params.keypress = 0;
|
||||
sec_params.io_caps = BLE_GAP_IO_CAPS_DISPLAY_ONLY; // Show passkey
|
||||
sec_params.oob = 0;
|
||||
sec_params.min_key_size = 7;
|
||||
sec_params.max_key_size = 16;
|
||||
sec_params.kdist_own.enc = 1;
|
||||
sec_params.kdist_own.id = 1;
|
||||
sec_params.kdist_peer.enc = 1;
|
||||
sec_params.kdist_peer.id = 1;
|
||||
|
||||
DBG_PRINTF("PROD MODE: Security ENABLED - Full protection\r\n");
|
||||
}
|
||||
|
||||
// Apply security parameters
|
||||
err_code = pm_sec_params_set(&sec_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current mode
|
||||
*/
|
||||
bool ble_security_is_dev_mode(void)
|
||||
{
|
||||
return m_state.dev_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PM event handler
|
||||
*/
|
||||
void ble_security_quick_pm_handler(pm_evt_t const *p_evt)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
|
||||
// Call standard handlers (required)
|
||||
pm_handler_on_pm_evt(p_evt);
|
||||
pm_handler_disconnect_on_sec_failure(p_evt);
|
||||
pm_handler_flash_clean(p_evt);
|
||||
|
||||
// Handle events
|
||||
switch (p_evt->evt_id) {
|
||||
case PM_EVT_CONN_SEC_SUCCEEDED:
|
||||
if (m_state.dev_mode) {
|
||||
DBG_PRINTF("DEV: Connected (no security)\r\n");
|
||||
} else {
|
||||
DBG_PRINTF("PROD: Link secured (bonded)\r\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case PM_EVT_CONN_SEC_FAILED:
|
||||
DBG_PRINTF("Security failed: error=%d\r\n",
|
||||
p_evt->params.conn_sec_failed.error);
|
||||
|
||||
// Auto-retry if key missing
|
||||
if (p_evt->params.conn_sec_failed.error == PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING) {
|
||||
err_code = pm_conn_secure(p_evt->conn_handle, true);
|
||||
if (err_code != NRF_ERROR_INVALID_STATE) {
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PM_EVT_CONN_SEC_CONFIG_REQ:
|
||||
{
|
||||
pm_conn_sec_config_t config = {
|
||||
.allow_repairing = m_state.dev_mode
|
||||
};
|
||||
pm_conn_sec_config_reply(p_evt->conn_handle, &config);
|
||||
}
|
||||
break;
|
||||
|
||||
case PM_EVT_PEERS_DELETE_SUCCEEDED:
|
||||
if (m_state.bonds_delete_pending) {
|
||||
m_state.bonds_delete_pending = false;
|
||||
DBG_PRINTF("DEV MODE: Bonds cleared!\r\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
56
lib/pc_firm/ble_security/ble_quick_security.h
Normal file
56
lib/pc_firm/ble_security/ble_quick_security.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file ble_quick_security.h
|
||||
* @brief Ultra-simple BLE Security Configuration
|
||||
*
|
||||
* ONE function call to control entire security behavior.
|
||||
* Works with existing debug_print.h system.
|
||||
*/
|
||||
|
||||
#ifndef BLE_QUICK_SECURITY_H
|
||||
#define BLE_QUICK_SECURITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "peer_manager.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize BLE security with ONE simple parameter
|
||||
*
|
||||
* @param[in] development_mode true (1) = Fast development (no security)
|
||||
* false (0) = Production (full security)
|
||||
*
|
||||
* Development mode (1):
|
||||
* - No pairing/bonding required
|
||||
* - Auto-deletes all bonds on startup
|
||||
* - Instant connection
|
||||
* - Fast iteration
|
||||
*
|
||||
* Production mode (0):
|
||||
* - Full security with passkey
|
||||
* - Bonding preserved
|
||||
* - MITM protection
|
||||
* - Secure deployment
|
||||
*
|
||||
* Usage in main.c:
|
||||
* #define BLE_DEV_MODE 1 // or 0
|
||||
* ble_security_quick_init(BLE_DEV_MODE);
|
||||
*/
|
||||
void ble_security_quick_init(bool development_mode);
|
||||
|
||||
/**
|
||||
* @brief Get current mode
|
||||
* @return true if in development mode, false if production
|
||||
*/
|
||||
bool ble_security_is_dev_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Peer Manager event handler
|
||||
*
|
||||
* Call this from your pm_evt_handler() function.
|
||||
* It handles all security events automatically.
|
||||
*
|
||||
* @param[in] p_evt Peer Manager event
|
||||
*/
|
||||
void ble_security_quick_pm_handler(pm_evt_t const *p_evt);
|
||||
|
||||
#endif // BLE_QUICK_SECURITY_H
|
||||
1
lib/pc_firm/cmd.h
Normal file
1
lib/pc_firm/cmd.h
Normal file
@@ -0,0 +1 @@
|
||||
void battery_level_meas(void);
|
||||
1554
lib/pc_firm/dr_adc121s051/dr_adc121s051.c
Normal file
1554
lib/pc_firm/dr_adc121s051/dr_adc121s051.c
Normal file
File diff suppressed because it is too large
Load Diff
505
lib/pc_firm/dr_adc121s051/dr_adc121s051.h
Normal file
505
lib/pc_firm/dr_adc121s051/dr_adc121s051.h
Normal file
@@ -0,0 +1,505 @@
|
||||
/*******************************************************************************
|
||||
* @file dr_adc121s051.h
|
||||
* @brief ADC121S051 12-bit ADC Driver for nRF52840
|
||||
* For 1.2MHz Piezo Echo Envelope Detection
|
||||
* @author Charles KWON
|
||||
* @date 2025-12-15
|
||||
*
|
||||
* @details This driver reads the envelope-detected DC level from piezo echo.
|
||||
*
|
||||
* Signal Flow:
|
||||
*
|
||||
* [Piezo TX] [Echo RX] [Envelope] [ADC] [MCU]
|
||||
* 1.2MHz --> Reflect --> Detector --> DC Level --> Digital
|
||||
* burst signal (hardware) reading value
|
||||
*
|
||||
* The envelope detector circuit converts the 1.2MHz echo burst
|
||||
* into a DC voltage proportional to the echo amplitude.
|
||||
* ADC samples this DC level for amplitude measurement.
|
||||
*
|
||||
* @note Hardware: Texas Instruments ADC121S051
|
||||
* - 12-bit resolution (0-4095)
|
||||
* - Sample rate: 200-500 ksps
|
||||
* - Input range: 0V to VA
|
||||
* - SPI interface (software bit-bang)
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef DR_ADC121S051_H
|
||||
#define DR_ADC121S051_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
/*==============================================================================
|
||||
* PIN CONFIGURATION
|
||||
*
|
||||
* WARNING: Never hardcode pin numbers!
|
||||
* Hardcoding may save a developer's time momentarily,
|
||||
* but it will also shorten their lifespan.
|
||||
*============================================================================*/
|
||||
#define DR_ADC_PIN_SCLK NRF_GPIO_PIN_MAP(0, 14) /**< Serial Clock */
|
||||
#define DR_ADC_PIN_SDATA NRF_GPIO_PIN_MAP(0, 15) /**< Serial Data (MISO) */
|
||||
#define DR_ADC_PIN_CS NRF_GPIO_PIN_MAP(0, 19) /**< Chip Select P0.13 -> P0.19 */
|
||||
|
||||
/*==============================================================================
|
||||
* ADC SPECIFICATIONS
|
||||
*============================================================================*/
|
||||
#define DR_ADC_RESOLUTION 12 /**< Bits */
|
||||
#define DR_ADC_MAX_VALUE 4095 /**< 2^12 - 1 */
|
||||
#define DR_ADC_VREF_MV 3300 /**< Reference voltage (mV) */
|
||||
|
||||
/*==============================================================================
|
||||
* ECHO DETECTION CONFIGURATION
|
||||
*
|
||||
* Bladder Measurement Requirements:
|
||||
* - Target measurement range: 20cm (200mm)
|
||||
* - SCLK frequency: 8.6MHz (bit-bang SPI)
|
||||
* - ADC121S051 requires 16 SCLK cycles per sample
|
||||
* - Actual sample rate: 8.6MHz / 16 = 0.5375MHz = 537.5kHz
|
||||
* - Actual sample interval: 16 / 8.6MHz = 1.86us
|
||||
* - Sound speed in tissue: 1540m/s = 1.54mm/us
|
||||
*
|
||||
* Formula: samples = distance(mm) * 2 / (1.86us * 1.54mm/us)
|
||||
* = distance(mm) * 2 / 2.86
|
||||
* = distance(mm) * 0.7
|
||||
*
|
||||
* 10cm = 100mm -> 100 * 0.7 = 70 samples (round-trip 130us)
|
||||
* 17cm = 170mm -> 170 * 0.7 = 119 samples (round-trip 221us)
|
||||
* 20cm = 200mm -> 200 * 0.7 = 140 samples (round-trip 260us)
|
||||
*
|
||||
* Buffer size: 200 samples * 2 bytes = 400 bytes (RAM 256KB, OK)
|
||||
* BLE transmission: 140 samples * 2 bytes = 280 bytes (16-bit raw, no packing)
|
||||
*============================================================================*/
|
||||
#define DR_ADC_SCLK_MHZ 8.6f /**< SPI bit-bang SCLK frequency */
|
||||
#define DR_ADC_CLOCKS_PER_SAMPLE 16 /**< ADC121S051: 16 SCLK per sample */
|
||||
#define DR_ADC_ECHO_SAMPLES_MAX 100 /**< Maximum samples */
|
||||
#define DR_ADC_ECHO_SAMPLES_DEFAULT 100 /**< Default samples */
|
||||
#define DR_ADC_SAMPLE_INTERVAL_US 1.86f /**< 16 / 8.6MHz = 1.86us per sample */
|
||||
#define DR_ADC_SOUND_SPEED_MM_US 1.54f /**< Sound speed in tissue (mm/us) */
|
||||
|
||||
/*==============================================================================
|
||||
* ERROR CODES
|
||||
*============================================================================*/
|
||||
typedef enum {
|
||||
DR_ADC_OK = 0,
|
||||
DR_ADC_ERR_NOT_INIT,
|
||||
DR_ADC_ERR_INVALID_PARAM,
|
||||
DR_ADC_ERR_NO_ECHO
|
||||
} dr_adc_err_t;
|
||||
|
||||
/*==============================================================================
|
||||
* DATA STRUCTURES
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Single ADC reading result
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t raw; /**< Raw 12-bit value (0-4095) */
|
||||
uint32_t voltage_mv; /**< Voltage in millivolts */
|
||||
} dr_adc_result_t;
|
||||
|
||||
/**
|
||||
* @brief Echo measurement result
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t peak_raw; /**< Peak amplitude (raw) */
|
||||
uint32_t peak_mv; /**< Peak amplitude (mV) */
|
||||
uint16_t peak_index; /**< Sample index of peak */
|
||||
uint32_t peak_time_us; /**< Time to peak (us) */
|
||||
uint16_t baseline_raw; /**< Baseline level before echo */
|
||||
uint16_t num_samples; /**< Number of samples captured */
|
||||
} dr_adc_echo_t;
|
||||
|
||||
/**
|
||||
* @brief Echo capture configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t num_samples; /**< Samples to capture (1-200) */
|
||||
uint16_t threshold_raw; /**< Minimum peak threshold */
|
||||
uint16_t delay_us; /**< Delay before capture starts */
|
||||
} dr_adc_echo_config_t;
|
||||
|
||||
/*==============================================================================
|
||||
* INITIALIZATION
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Initialize ADC driver
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_init(void);
|
||||
|
||||
/**
|
||||
* @brief Uninitialize ADC driver
|
||||
*/
|
||||
void dr_adc_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Check if initialized
|
||||
*/
|
||||
bool dr_adc_is_initialized(void);
|
||||
|
||||
/*==============================================================================
|
||||
* BASIC READ FUNCTIONS
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Read single ADC value
|
||||
* @param result Pointer to result structure
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_read(dr_adc_result_t *result);
|
||||
|
||||
/**
|
||||
* @brief Read raw 12-bit value only
|
||||
* @param raw_value Pointer to store value
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_read_raw(uint16_t *raw_value);
|
||||
|
||||
/**
|
||||
* @brief Read averaged value
|
||||
* @param result Pointer to result structure
|
||||
* @param num_samples Number of samples to average (1-256)
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_read_averaged(dr_adc_result_t *result, uint16_t num_samples);
|
||||
|
||||
/*==============================================================================
|
||||
* ECHO DETECTION FUNCTIONS
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Capture echo envelope after piezo burst
|
||||
* @param buffer Array to store samples (must be pre-allocated)
|
||||
* @param num_samples Number of samples to capture
|
||||
* @return dr_adc_err_t Error code
|
||||
*
|
||||
* @note Call this immediately after dr_piezo_burst_sw()
|
||||
*/
|
||||
dr_adc_err_t dr_adc_capture_echo(uint16_t *buffer, uint16_t num_samples);
|
||||
|
||||
/**
|
||||
* @brief Capture and analyze echo in one call
|
||||
* @param echo Pointer to echo result structure
|
||||
* @param config Pointer to capture configuration (NULL for defaults)
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_measure_echo(dr_adc_echo_t *echo, const dr_adc_echo_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Piezo burst + Echo capture in one call
|
||||
* @param cycles Number of burst cycles (3~9)
|
||||
* @param delay_us Delay before capture (us)
|
||||
* @param num_samples Number of samples to capture
|
||||
* @param echo Pointer to echo result structure
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Get pointer to last captured echo buffer
|
||||
* @return Pointer to internal buffer (valid until next capture)
|
||||
* @note Buffer contains num_samples values from last burst_and_capture call
|
||||
*/
|
||||
const uint16_t* dr_adc_get_echo_buffer(void);
|
||||
|
||||
/**
|
||||
* @brief Analyze captured echo buffer
|
||||
* @param buffer Sample buffer
|
||||
* @param num_samples Number of samples in buffer
|
||||
* @param echo Pointer to echo result structure
|
||||
* @param threshold Minimum threshold for valid peak
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_analyze_echo(const uint16_t *buffer, uint16_t num_samples,
|
||||
dr_adc_echo_t *echo, uint16_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Find peak in buffer
|
||||
* @param buffer Sample buffer
|
||||
* @param num_samples Number of samples
|
||||
* @param peak_value Pointer to store peak value
|
||||
* @param peak_index Pointer to store peak index (can be NULL)
|
||||
*/
|
||||
void dr_adc_find_peak(const uint16_t *buffer, uint16_t num_samples,
|
||||
uint16_t *peak_value, uint16_t *peak_index);
|
||||
|
||||
/**
|
||||
* @brief Calculate baseline (average of first N samples)
|
||||
* @param buffer Sample buffer
|
||||
* @param num_samples Number of samples to average for baseline
|
||||
* @return Baseline value
|
||||
*/
|
||||
uint16_t dr_adc_calc_baseline(const uint16_t *buffer, uint16_t num_samples);
|
||||
|
||||
/*==============================================================================
|
||||
* UTILITY FUNCTIONS
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Convert raw value to millivolts
|
||||
* @param raw_value Raw 12-bit value
|
||||
* @return Voltage in millivolts
|
||||
*/
|
||||
uint32_t dr_adc_raw_to_mv(uint16_t raw_value);
|
||||
|
||||
/**
|
||||
* @brief Set reference voltage
|
||||
* @param vref_mv Reference voltage in millivolts
|
||||
*/
|
||||
void dr_adc_set_vref(uint32_t vref_mv);
|
||||
|
||||
/**
|
||||
* @brief Get reference voltage
|
||||
* @return Reference voltage in millivolts
|
||||
*/
|
||||
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
|
||||
*============================================================================*/
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
* BLE TRANSMISSION CALLBACK
|
||||
*============================================================================*/
|
||||
|
||||
/*==============================================================================
|
||||
* INTEGRATED BURST + CAPTURE + TRANSMIT
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Piezo burst + ADC capture + BLE transmission (all-in-one)
|
||||
*
|
||||
* This function performs the complete measurement cycle internally:
|
||||
* 1. Power on ADC
|
||||
* 2. Select piezo channel (0~7)
|
||||
* 3. Execute piezo burst (frequency based on freq_option)
|
||||
* 4. Capture echo samples (after delay_us) - repeated 'averaging' times
|
||||
* 5. Average the captured samples (firmware-level noise reduction)
|
||||
* 6. Analyze peak/baseline
|
||||
* 7. Transmit data via BLE with proper packet timing
|
||||
*
|
||||
* @param freq_option Frequency option: 0=1.8MHz (default), 1=2.1MHz, 2=2.0MHz, 3=1.7MHz
|
||||
* @param delay_us Delay before capture (us), default 20
|
||||
* @param num_samples Number of samples to capture (1~200)
|
||||
* @param cycles Number of burst cycles (3~7), default 5
|
||||
* @param averaging Number of measurements to average (1~1000), default 1
|
||||
* @param piezo_ch Piezo channel to use (0~7), default 0
|
||||
* @param ble_buffer Working buffer for BLE packets (must be >= 240 bytes)
|
||||
* @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 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,
|
||||
uint16_t num_samples, uint8_t cycles,
|
||||
uint16_t averaging, uint8_t piezo_ch,
|
||||
uint8_t *ble_buffer, uint8_t skip_raa);
|
||||
|
||||
/**
|
||||
* @brief Select piezo channel (0~7)
|
||||
* @param channel Piezo channel number (0~7)
|
||||
*
|
||||
* @note Hardware-dependent: requires MUX or individual GPIO control
|
||||
* Currently uses placeholder - implement based on actual hardware
|
||||
*/
|
||||
void dr_piezo_select_channel(uint8_t channel);
|
||||
|
||||
/*==============================================================================
|
||||
* 4-CHANNEL CAPTURE (maa? command support)
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief 8-channel echo buffer for maa? command
|
||||
* Memory: 140 samples × 2 bytes × 8 channels = 2,240 bytes
|
||||
*/
|
||||
#define MAA_NUM_CHANNELS 8 /* 4 -> 8 jhChun 26.02.12*/
|
||||
#define MAA_SAMPLES_MAX 200
|
||||
|
||||
/**
|
||||
* @brief Echo data for one 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;
|
||||
|
||||
/**
|
||||
* @brief Capture echo from one channel (no BLE transmission)
|
||||
*
|
||||
* Captures averaged echo data for a single channel and stores
|
||||
* in the provided channel buffer. Does NOT transmit via BLE.
|
||||
*
|
||||
* @param freq_option Frequency: 0=1.8MHz, 1=2.1MHz, 2=2.0MHz, 3=1.7MHz
|
||||
* @param delay_us Delay before capture (us)
|
||||
* @param num_samples Number of samples (1~200)
|
||||
* @param cycles Burst cycles (3~7)
|
||||
* @param averaging Number of averages (1~1000)
|
||||
* @param piezo_ch Piezo channel (0~7)
|
||||
* @param out_channel Output channel data structure
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_capture_channel_only(uint8_t freq_option, uint16_t delay_us,
|
||||
uint16_t num_samples, uint8_t cycles,
|
||||
uint16_t averaging, uint8_t piezo_ch,
|
||||
dr_maa_channel_t *out_channel);
|
||||
|
||||
/**
|
||||
* @brief Transmit captured channel data via BLE
|
||||
*
|
||||
* Sends previously captured channel data using reb:/red:/ree: protocol.
|
||||
*
|
||||
* @param ch_data Pointer to captured channel data
|
||||
* @param ble_buffer Working buffer for BLE packets (>= 240 bytes)
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_transmit_channel(const dr_maa_channel_t *ch_data,
|
||||
uint8_t *ble_buffer);
|
||||
|
||||
/*==============================================================================
|
||||
* DELTA COMPRESSION (maa? mode=1)
|
||||
*
|
||||
* Format:
|
||||
* Byte 0-1: First sample (16-bit, little endian)
|
||||
* Byte 2+: Delta values (8-bit signed)
|
||||
* If delta > 127 or < -127: escape (0x80) + 16-bit value
|
||||
*
|
||||
* Expected compression: ~50% (280 bytes -> ~140 bytes)
|
||||
*============================================================================*/
|
||||
|
||||
#define DELTA_ESCAPE_BYTE 0x80 /**< Escape marker for out-of-range delta */
|
||||
|
||||
/**
|
||||
* @brief Compress sample data using delta encoding
|
||||
*
|
||||
* @param samples Input sample array (16-bit values)
|
||||
* @param num_samples Number of samples
|
||||
* @param out_buffer Output buffer for compressed data
|
||||
* @param out_size Output: number of bytes written
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_delta_compress(const uint16_t *samples, uint16_t num_samples,
|
||||
uint8_t *out_buffer, uint16_t *out_size);
|
||||
|
||||
/**
|
||||
* @brief Transmit captured channel data via BLE with delta compression
|
||||
*
|
||||
* Uses rdb:/rdd:/rde: protocol (delta variant of reb:/red:/ree:)
|
||||
*
|
||||
* @param ch_data Pointer to captured channel data
|
||||
* @param ble_buffer Working buffer for BLE packets (>= 240 bytes)
|
||||
* @return dr_adc_err_t Error code
|
||||
*/
|
||||
dr_adc_err_t dr_adc_transmit_channel_delta(const dr_maa_channel_t *ch_data,
|
||||
uint8_t *ble_buffer);
|
||||
|
||||
/*==============================================================================
|
||||
* ASYNC MAA - Non-blocking 8-channel capture
|
||||
*
|
||||
* 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
|
||||
* All done -> TX raa: -> state=IDLE
|
||||
*============================================================================*/
|
||||
|
||||
/** @brief MAA async state machine states */
|
||||
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_DATA, /**< Sending red: data packets */
|
||||
MAA_ASYNC_NEXT_CHANNEL, /**< Preparing next channel */
|
||||
MAA_ASYNC_COMPLETE /**< Sending raa: and finishing */
|
||||
} maa_async_state_t;
|
||||
|
||||
/** @brief MAA async context */
|
||||
typedef struct {
|
||||
maa_async_state_t state; /**< Current state */
|
||||
uint8_t current_ch; /**< Current channel (0~7) */
|
||||
uint8_t current_pkt; /**< Current packet index */
|
||||
uint16_t data_offset; /**< Bytes sent so far for current channel */
|
||||
uint8_t freq_option; /**< Frequency option */
|
||||
uint16_t delay_us; /**< Capture delay */
|
||||
uint16_t num_samples; /**< Samples per channel */
|
||||
uint8_t cycles; /**< Burst cycles */
|
||||
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 */
|
||||
} maa_async_ctx_t;
|
||||
|
||||
/**
|
||||
* @brief Start async MAA 8-channel capture
|
||||
*
|
||||
* Initiates the async state machine. Captures CH0 and begins transmission.
|
||||
* Subsequent packets are sent when maa_async_on_tx_ready() is called.
|
||||
*
|
||||
* @param freq_option Frequency: 0=1.8MHz, 1=2.1MHz, 2=2.0MHz, 3=1.7MHz
|
||||
* @param delay_us Capture delay (us)
|
||||
* @param num_samples Samples per channel (1~200)
|
||||
* @param cycles Burst cycles (3~9)
|
||||
* @param averaging Averaging count (1~1000)
|
||||
* @param ble_buffer Working buffer (>= 240 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,
|
||||
uint16_t num_samples, uint8_t cycles,
|
||||
uint16_t averaging, uint8_t *ble_buffer);
|
||||
|
||||
/**
|
||||
* @brief Handle BLE TX ready event
|
||||
*
|
||||
* Called from BLE_NUS_EVT_TX_RDY handler. Sends next packet or
|
||||
* transitions to next state.
|
||||
*
|
||||
* @return true if more work pending, false if complete or idle
|
||||
*/
|
||||
bool maa_async_on_tx_ready(void);
|
||||
|
||||
/**
|
||||
* @brief Check if async MAA is active
|
||||
* @return true if state != IDLE
|
||||
*/
|
||||
bool maa_async_is_busy(void);
|
||||
|
||||
/**
|
||||
* @brief Get current async state (for debugging)
|
||||
* @return Current state
|
||||
*/
|
||||
maa_async_state_t maa_async_get_state(void);
|
||||
|
||||
/**
|
||||
* @brief Abort async MAA operation
|
||||
*/
|
||||
void maa_async_abort(void);
|
||||
|
||||
#endif /* DR_ADC121S051_H */
|
||||
|
||||
82
lib/pc_firm/dr_util/dr_util.c
Normal file
82
lib/pc_firm/dr_util/dr_util.c
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "dr_util.h"
|
||||
#include "parser.h"
|
||||
|
||||
extern void single_format_data(uint8_t *buffer, const char *tag, uint16_t value);
|
||||
extern void format_data(uint8_t *buffer, const char *tag, uint16_t *data, uint8_t length);
|
||||
extern void binary_tx_handler(uint8_t *buffer, uint8_t length);
|
||||
extern uint8_t ble_bin_buffer[];
|
||||
|
||||
/* Use dr_binary_tx_safe from main.c - has retry logic for BLE TX queue */
|
||||
extern void dr_binary_tx_safe(uint8_t const *ble_bin_buff, uint16_t length);
|
||||
|
||||
void dr_ble_return_1(const char *tag, uint16_t value)
|
||||
{
|
||||
single_format_data(ble_bin_buffer, tag, value);
|
||||
dr_binary_tx_safe(ble_bin_buffer, 3); /* Use safe TX with retry */
|
||||
}
|
||||
|
||||
void dr_ble_return_2(const char *tag, uint16_t v1, uint16_t v2)
|
||||
{
|
||||
ble_bin_buffer[0] = tag[0];
|
||||
ble_bin_buffer[1] = tag[1];
|
||||
ble_bin_buffer[2] = tag[2];
|
||||
ble_bin_buffer[3] = tag[3];
|
||||
|
||||
ble_bin_buffer[4] = (uint8_t)(v1 >> 8);
|
||||
ble_bin_buffer[5] = (uint8_t)(v1 & 0xFF);
|
||||
ble_bin_buffer[6] = (uint8_t)(v2 >> 8);
|
||||
ble_bin_buffer[7] = (uint8_t)(v2 & 0xFF);
|
||||
|
||||
dr_binary_tx_safe(ble_bin_buffer, 4); /* Use safe TX with retry */
|
||||
}
|
||||
|
||||
void dr_ble_return_3(const char *tag, uint16_t v1, uint16_t v2, uint16_t v3)
|
||||
{
|
||||
ble_bin_buffer[0] = tag[0];
|
||||
ble_bin_buffer[1] = tag[1];
|
||||
ble_bin_buffer[2] = tag[2];
|
||||
ble_bin_buffer[3] = tag[3];
|
||||
|
||||
ble_bin_buffer[4] = (uint8_t)(v1 >> 8);
|
||||
ble_bin_buffer[5] = (uint8_t)(v1 & 0xFF);
|
||||
ble_bin_buffer[6] = (uint8_t)(v2 >> 8);
|
||||
ble_bin_buffer[7] = (uint8_t)(v2 & 0xFF);
|
||||
ble_bin_buffer[8] = (uint8_t)(v3 >> 8);
|
||||
ble_bin_buffer[9] = (uint8_t)(v3 & 0xFF);
|
||||
|
||||
dr_binary_tx_safe(ble_bin_buffer, 5); /* Use safe TX with retry */
|
||||
}
|
||||
|
||||
void dr_ble_debug(uint16_t point_id, uint16_t value)
|
||||
{
|
||||
/* Use dedicated buffer to avoid conflicts with ble_bin_buffer */
|
||||
static uint8_t dbg_buffer[8];
|
||||
|
||||
dbg_buffer[0] = 'd';
|
||||
dbg_buffer[1] = 'b';
|
||||
dbg_buffer[2] = 'g';
|
||||
dbg_buffer[3] = ':';
|
||||
|
||||
dbg_buffer[4] = (uint8_t)(point_id >> 8);
|
||||
dbg_buffer[5] = (uint8_t)(point_id & 0xFF);
|
||||
dbg_buffer[6] = (uint8_t)(value >> 8);
|
||||
dbg_buffer[7] = (uint8_t)(value & 0xFF);
|
||||
|
||||
dr_binary_tx_safe(dbg_buffer, 4);
|
||||
}
|
||||
|
||||
void dr_ble_return_piezo_1(const char *tag, uint16_t value)
|
||||
{
|
||||
/* Use dedicated buffer for piezo responses to avoid conflicts with ble_bin_buffer */
|
||||
static uint8_t piezo_buffer[8];
|
||||
|
||||
piezo_buffer[0] = tag[0];
|
||||
piezo_buffer[1] = tag[1];
|
||||
piezo_buffer[2] = tag[2];
|
||||
piezo_buffer[3] = tag[3];
|
||||
|
||||
piezo_buffer[4] = (uint8_t)(value >> 8);
|
||||
piezo_buffer[5] = (uint8_t)(value & 0xFF);
|
||||
|
||||
dr_binary_tx_safe(piezo_buffer, 3); /* 6 bytes = 3 words */
|
||||
}
|
||||
18
lib/pc_firm/dr_util/dr_util.h
Normal file
18
lib/pc_firm/dr_util/dr_util.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef DR_UTIL_H
|
||||
#define DR_UTIL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void dr_ble_return_1(const char *tag, uint16_t value);
|
||||
void dr_ble_return_2(const char *tag, uint16_t v1, uint16_t v2);
|
||||
void dr_ble_return_3(const char *tag, uint16_t v1, uint16_t v2, uint16_t v3);
|
||||
void dr_ble_return_3_be(const char *tag, uint16_t v1, uint16_t v2, uint16_t v3);
|
||||
|
||||
/* Piezo dedicated BLE return - uses separate buffer to avoid conflicts */
|
||||
void dr_ble_return_piezo_1(const char *tag, uint16_t value);
|
||||
|
||||
/* BLE debug output - sends "dbg:" + point_id + value */
|
||||
void dr_ble_debug(uint16_t point_id, uint16_t value);
|
||||
|
||||
#endif /* DR_UTIL_H */
|
||||
|
||||
2
lib/pc_firm/f.bat
Normal file
2
lib/pc_firm/f.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
gcc -std=c99 -Wall -Wextra -o parser.exe parser.c pcmain.c
|
||||
|
||||
1062
lib/pc_firm/parser.c
Normal file
1062
lib/pc_firm/parser.c
Normal file
File diff suppressed because it is too large
Load Diff
40
lib/pc_firm/parser.h
Normal file
40
lib/pc_firm/parser.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* parser.h */
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Platform-dependent function pointer set */
|
||||
typedef struct {
|
||||
void (*log)(const char *fmt, ...);
|
||||
void (*tx_bin)(const uint8_t *buf, uint16_t len);
|
||||
bool crc_check;
|
||||
} dr_platform_if_t;
|
||||
|
||||
|
||||
#define DR_MAX_DATA 128 /* Max data length after TAG */
|
||||
|
||||
typedef struct {
|
||||
char tag[5]; /* "sta?" etc 4 chars + '\0' */
|
||||
uint8_t data[DR_MAX_DATA]; /* Raw data after TAG */
|
||||
uint8_t data_len; /* Length of data[] */
|
||||
} ParsedCmd;
|
||||
|
||||
typedef int (*cmd_handler_t)(const ParsedCmd *cmd);
|
||||
|
||||
typedef struct {
|
||||
char tag[5]; /* "sta?" */
|
||||
bool enabled; /* false = handler won't be called */
|
||||
cmd_handler_t handler; /* 1=success, 0=fail */
|
||||
} CmdEntry;
|
||||
|
||||
/* Global interface & log flag */
|
||||
extern dr_platform_if_t g_plat;
|
||||
extern bool g_log_enable;
|
||||
|
||||
/* Main parser entry point */
|
||||
int dr_cmd_parser(const uint8_t *buf, uint8_t len);
|
||||
|
||||
#endif /* PARSER_H */
|
||||
|
||||
Reference in New Issue
Block a user