Files
firmware-test/pc_firm/dr_adc121s051/dr_adc121s051.h
2026-03-19 18:04:04 +09:00

522 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*******************************************************************************
* @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~7)
* @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 6 /* 4 -> 8 -> 6 jhChun 26.03.17*/
#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 */
bool auto_powered; /**< true: 자동 전원 ON → 완료 후 OFF */
bool pre_capture_all; /**< true: 전채널 캡처 완료 후 일괄 전송 (mbb용) */
void (*on_complete_cb)(void); /**< 비동기 캡처 완료 후 호출될 콜백 (NULL이면 미사용) */
} 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~7)
* @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);
/**
* @brief 자동 전원 플래그 설정 (완료 후 자동 power off)
*/
void maa_async_set_auto_power(bool on);
void maa_async_set_pre_capture_all(bool on);
/**
* @brief 비동기 캡처 완료 콜백 설정
* raa: 전송 + 전원 OFF 이후 호출된다. NULL이면 콜백 없음.
*/
void maa_async_set_on_complete(void (*cb)(void));
#endif /* DR_ADC121S051_H */