VesiScan BASIC origin: Piezo + IMU firmware initial code
- nRF52840 + SoftDevice S140 BLE firmware - Piezo ultrasound TX driver (2MHz, 8ch MUX) - ICM42670P IMU 6-axis driver - Echo AFE chain (ADA2200 + ADC121S051) - BLE NUS command parser (mpa/mpc/mdc/mec/maa/msp) - FDS flash config storage - pc_firm parser and ADC driver included Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "../../.."
|
||||
},
|
||||
{
|
||||
"path": "../../../../pc_firm"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
1515
project/ble_peripheral/ble_app_bladder_patch/cmd/dr_adc121s051.c
Normal file
1515
project/ble_peripheral/ble_app_bladder_patch/cmd/dr_adc121s051.c
Normal file
File diff suppressed because it is too large
Load Diff
505
project/ble_peripheral/ble_app_bladder_patch/cmd/dr_adc121s051.h
Normal file
505
project/ble_peripheral/ble_app_bladder_patch/cmd/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 200 /**< Maximum samples (20cm+ with margin) */
|
||||
#define DR_ADC_ECHO_SAMPLES_DEFAULT 140 /**< Default samples (20cm depth target) */
|
||||
#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
project/ble_peripheral/ble_app_bladder_patch/cmd/dr_util.c
Normal file
82
project/ble_peripheral/ble_app_bladder_patch/cmd/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
project/ble_peripheral/ble_app_bladder_patch/cmd/dr_util.h
Normal file
18
project/ble_peripheral/ble_app_bladder_patch/cmd/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 */
|
||||
|
||||
1174
project/ble_peripheral/ble_app_bladder_patch/cmd/parser.c
Normal file
1174
project/ble_peripheral/ble_app_bladder_patch/cmd/parser.c
Normal file
File diff suppressed because it is too large
Load Diff
24
project/ble_peripheral/ble_app_bladder_patch/cmd/parser.h
Normal file
24
project/ble_peripheral/ble_app_bladder_patch/cmd/parser.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* 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;
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
@@ -12,6 +12,7 @@ v1.17 p1,p2 parssurer
|
||||
|
||||
#include <cmd_parse.h>
|
||||
#include "debug_print.h"
|
||||
#include "fstorage.h"
|
||||
|
||||
#define DEVICE_VERSION "FW25LIT2B102"
|
||||
#define DEVICE_NAME "MEDIDEV_2004"
|
||||
@@ -1452,7 +1453,7 @@ else if((scmd.tag[1] == 'r') && (scmd.tag[2] == 'k')){ // Set the number of
|
||||
|
||||
}
|
||||
// ssl
|
||||
else if((scmd.tag[1] == 's') && (scmd.tag[2] == 'l')){ // Set the delay for PD stabilization. 0µs ~ FFFF(65535)µs
|
||||
else if((scmd.tag[1] == 's') && (scmd.tag[2] == 'l')){ // Set the delay for PD stabilization. 0<EFBFBD>s ~ FFFF(65535)<EFBFBD>s
|
||||
|
||||
|
||||
// ret_code_t err_code;
|
||||
@@ -1485,7 +1486,7 @@ else if((scmd.tag[1] == 's') && (scmd.tag[2] == 'l')){ // Set the delay for
|
||||
}
|
||||
}
|
||||
// srl
|
||||
else if((scmd.tag[1] == 'r') && (scmd.tag[2] == 'l')){ // Set the delay for PD stabilization. 0µs ~ FFFF(65535)µs
|
||||
else if((scmd.tag[1] == 'r') && (scmd.tag[2] == 'l')){ // Set the delay for PD stabilization. 0<EFBFBD>s ~ FFFF(65535)<EFBFBD>s
|
||||
|
||||
|
||||
|
||||
@@ -1655,69 +1656,30 @@ else if((scmd.tag[1] == 's') && (scmd.tag[2] == 'v')){ // Auto Gain Control
|
||||
|
||||
|
||||
}
|
||||
// ssz
|
||||
else if((scmd.tag[1] == 's') && (scmd.tag[2] == 'z')){ //Write, Serial Number
|
||||
// ssz - Write Serial Number (FDS only)
|
||||
else if((scmd.tag[1] == 's') && (scmd.tag[2] == 'z')){
|
||||
if(length_error(scmd.tag,18,length)==false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint8_t tx_data[EEPROM_PAGE_SIZE];
|
||||
uint8_t rx_data[EEPROM_PAGE_SIZE];
|
||||
uint8_t raw_data[EEPROM_PAGE_SIZE];
|
||||
if(cmd_t == CMD_UART) {
|
||||
DBG_PRINTF("Tz0\r\n\r\n");
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
|
||||
//eeprom_write_encrypted(0x0000, secret_data, strlen((char *)secret_data));
|
||||
|
||||
//eeprom_read_decrypted(0x0000, decrypted, strlen((char *)secret_data));
|
||||
//DBG_PRINTF("Decrypted: %s\n", decrypted);
|
||||
|
||||
memcpy(SERIAL_NO, scmd.value_ascii, 12);
|
||||
//eeprom_write_bytes(uint16_t mem_address, const uint8_t *data, size_t length)
|
||||
for (uint8_t i=0 ; i<12 ;i++)
|
||||
{
|
||||
tx_data[i] = (uint8_t)(scmd.value_ascii[i]);
|
||||
}
|
||||
|
||||
// if (eeprom_write_bytes(0x0030 , tx_data ,12) !=NRF_SUCCESS)
|
||||
// {
|
||||
// DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");
|
||||
// }
|
||||
if(eeprom_write_encrypted(0x0030, tx_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
|
||||
if(eeprom_read_bytes(0x0030, raw_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
|
||||
nrf_delay_ms(10);
|
||||
DBG_PRINTF("encrypted: %s\n", raw_data);
|
||||
if(eeprom_read_decrypted(0x0030, rx_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
DBG_PRINTF("Decrypted: %s\n", rx_data);
|
||||
|
||||
memcpy(m_config.serial_no, scmd.value_ascii, 12);
|
||||
config_save();
|
||||
DBG_PRINTF("[ssz] S/N=%s saved to FDS\r\n", m_config.serial_no);
|
||||
ascii_format_data(ble_bin_buffer, "rsz:", scmd.value_ascii,12);
|
||||
binary_tx_handler(ble_bin_buffer,8);
|
||||
binary_tx_handler(ble_bin_buffer,8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
else{
|
||||
DBG_PRINTF("ERR!!! Serial_number 12\r\n\r\n");
|
||||
if(cmd_t == CMD_UART) {
|
||||
DBG_PRINTF("Tz0FF\r\n\r\n");
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
param_error(scmd.tag );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// spz
|
||||
else if((scmd.tag[1] == 'p') && (scmd.tag[2] == 'z')){ //Write, passkey
|
||||
@@ -1808,33 +1770,14 @@ else if((scmd.tag[1] == 'q') && (scmd.tag[2] == 'z')){ // Read, Seri
|
||||
}
|
||||
|
||||
}
|
||||
// srz
|
||||
else if((scmd.tag[1] == 'r') && (scmd.tag[2] == 'z')){ // Read, Serial Number
|
||||
|
||||
uint8_t rx_data[EEPROM_PAGE_SIZE];
|
||||
|
||||
// srz - Read Serial Number (FDS only)
|
||||
else if((scmd.tag[1] == 'r') && (scmd.tag[2] == 'z')){
|
||||
if(cmd_t == CMD_UART) {
|
||||
DBG_PRINTF("Tz1,%s\r\n\r\n", SERIAL_NO);
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
|
||||
|
||||
if(eeprom_read_decrypted(0x0030, rx_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
DBG_PRINTF("Decrypted: %s\n", rx_data);
|
||||
// if (eeprom_read_bytes(0x0030 , rx_data ,12) !=NRF_SUCCESS)
|
||||
// {
|
||||
// DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");
|
||||
// }
|
||||
// sprintf(ble_tx_buffer, "Tz1,%s\r\n", m_config.serial_number);
|
||||
// data_tx_handler(ble_tx_buffer);
|
||||
for (uint8_t i=0 ; i<12 ;i++)
|
||||
{
|
||||
(SERIAL_NO[i]) = (char)rx_data[i] ;
|
||||
}
|
||||
ascii_format_data(ble_bin_buffer, "rrz:", SERIAL_NO,12);
|
||||
binary_tx_handler(ble_bin_buffer,8);
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
memcpy(SERIAL_NO, m_config.serial_no, 12);
|
||||
ascii_format_data(ble_bin_buffer, "rrz:", SERIAL_NO, 12);
|
||||
binary_tx_handler(ble_bin_buffer, 8);
|
||||
}
|
||||
|
||||
#if 0 // ===== EEPROM start block =====
|
||||
@@ -2024,99 +1967,43 @@ else if((scmd.tag[1] == 'g') && (scmd.tag[2] == 'z')){ // Read, DCP
|
||||
|
||||
}
|
||||
}
|
||||
// siz
|
||||
else if((scmd.tag[1] == 'i') && (scmd.tag[2] == 'z')){ // Read, HW
|
||||
|
||||
hw_i2c_init_once();
|
||||
uint8_t rx_data[EEPROM_PAGE_SIZE];
|
||||
|
||||
// siz - Read HW Number (FDS only)
|
||||
else if((scmd.tag[1] == 'i') && (scmd.tag[2] == 'z')){
|
||||
if(cmd_t == CMD_UART) {
|
||||
DBG_PRINTF("Tz1,%s\r\n\r\n", HW_NO);
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
|
||||
|
||||
if(eeprom_read_decrypted(0x0010, rx_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
DBG_PRINTF("Decrypted: %s\n", rx_data);
|
||||
// if (eeprom_read_bytes(0x0030 , rx_data ,12) !=NRF_SUCCESS)
|
||||
// {
|
||||
// DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");
|
||||
// }
|
||||
// sprintf(ble_tx_buffer, "Tz1,%s\r\n", m_config.serial_number);
|
||||
// data_tx_handler(ble_tx_buffer);
|
||||
for (uint8_t i=0 ; i<12 ;i++)
|
||||
{
|
||||
(HW_NO[i]) = (char)rx_data[i] ;
|
||||
}
|
||||
ascii_format_data(ble_bin_buffer, "riz:", HW_NO,12);
|
||||
binary_tx_handler(ble_bin_buffer,8);
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
memcpy(HW_NO, m_config.hw_no, 12);
|
||||
ascii_format_data(ble_bin_buffer, "riz:", HW_NO, 12);
|
||||
binary_tx_handler(ble_bin_buffer, 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
// shz
|
||||
else if((scmd.tag[1] == 'h') && (scmd.tag[2] == 'z')){ //Write, HW
|
||||
// shz - Write HW Number (FDS only)
|
||||
else if((scmd.tag[1] == 'h') && (scmd.tag[2] == 'z')){
|
||||
if(length_error(scmd.tag,18,length)==false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
hw_i2c_init_once();
|
||||
uint8_t tx_data[EEPROM_PAGE_SIZE];
|
||||
uint8_t rx_data[EEPROM_PAGE_SIZE];
|
||||
uint8_t raw_data[EEPROM_PAGE_SIZE];
|
||||
if(cmd_t == CMD_UART) {
|
||||
DBG_PRINTF("Tz0\r\n\r\n");
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
memcpy(HW_NO, scmd.value_ascii, 12);
|
||||
//eeprom_write_bytes(uint16_t mem_address, const uint8_t *data, size_t length)
|
||||
for (uint8_t i=0 ; i<12 ;i++)
|
||||
{
|
||||
tx_data[i] = (uint8_t)(scmd.value_ascii[i]);
|
||||
}
|
||||
|
||||
|
||||
if(eeprom_write_encrypted(0x0010, tx_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
|
||||
if(eeprom_read_bytes(0x0010, raw_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
|
||||
nrf_delay_ms(10);
|
||||
DBG_PRINTF("encrypted: %s\n", raw_data);
|
||||
if(eeprom_read_decrypted(0x0010, rx_data, 12)!= NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("ERR!!! EEP_Serial_number 12\r\n\r\n");;
|
||||
}
|
||||
DBG_PRINTF("Decrypted: %s\n", rx_data);
|
||||
|
||||
memcpy(m_config.hw_no, scmd.value_ascii, 12);
|
||||
config_save();
|
||||
DBG_PRINTF("[shz] HW=%s saved to FDS\r\n", m_config.hw_no);
|
||||
ascii_format_data(ble_bin_buffer, "rhz:", scmd.value_ascii,12);
|
||||
binary_tx_handler(ble_bin_buffer,8);
|
||||
binary_tx_handler(ble_bin_buffer,8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
else{
|
||||
DBG_PRINTF("ERR!!! passkey 6\r\n\r\n");
|
||||
DBG_PRINTF("ERR!!! HW_NO 12\r\n\r\n");
|
||||
if(cmd_t == CMD_UART) {
|
||||
DBG_PRINTF("Tpz0FF\r\n\r\n");
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
} else if(cmd_t == CMD_BLE) {
|
||||
param_error(scmd.tag );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// sxz
|
||||
else if((scmd.tag[1] == 'x') && (scmd.tag[2] == 'z')){ // Set the delay for PD stabilization. 0µs ~ FFFF(65535)µs
|
||||
else if((scmd.tag[1] == 'x') && (scmd.tag[2] == 'z')){ // Set the delay for PD stabilization. 0<EFBFBD>s ~ FFFF(65535)<EFBFBD>s
|
||||
|
||||
m_life_cycle = ((uint16_t)scmd.value0 << 16) | ((uint16_t)scmd.value1 & 0xFFFF);
|
||||
result_data[0] = scmd.value0;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#define ENABLE_PRINTF 1 // Set to 0 to disable globally
|
||||
|
||||
#if ENABLE_PRINTF
|
||||
#include <stdio.h>
|
||||
#define DBG_PRINTF(...) printf(__VA_ARGS__)
|
||||
#include "SEGGER_RTT.h"
|
||||
#define DBG_PRINTF(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#else
|
||||
#define DBG_PRINTF(...) // Do nothing
|
||||
#endif
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "fstorage.h"
|
||||
#include "nrf_pwr_mgmt.h"
|
||||
#include "measurements.h"
|
||||
#include "main.h"
|
||||
#include "debug_print.h"
|
||||
|
||||
|
||||
/* File ID and Key used for the configuration record. */
|
||||
@@ -54,114 +54,39 @@ static fds_record_t const m_dummy_record =
|
||||
};
|
||||
|
||||
|
||||
/* 공장 입력 항목 1 */
|
||||
|
||||
|
||||
/* 공장 입력 항목 2 */
|
||||
//char serial_number_dflt[12] = "2025AAMAY0FF";
|
||||
//uint16_t pd_delay_us = 0;
|
||||
//int8_t reset_status=0;
|
||||
|
||||
//uint32_t pd_adc_calibration_dflt_PD0[M_LED_NUM] =
|
||||
// {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* PD01 */
|
||||
//};
|
||||
//uint32_t pd_adc_calibration_dflt_PD1[M_LED_NUM] =
|
||||
// {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* PD1 */
|
||||
//};
|
||||
//uint32_t pd_adc_calibration_dflt_PD2[M_LED_NUM] =
|
||||
// {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* MOD1 */
|
||||
//};
|
||||
|
||||
///* 공장 입력 항목 5 */
|
||||
//uint32_t dark_noise_for_pd_dflt[PD_NUM] = /*PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15, PD16, PD17, PD18, PD19, PD20, */
|
||||
// {1111, 1111};
|
||||
|
||||
|
||||
/* 공장 입력 항목 8 */
|
||||
//int8_t pd_adc_cnt_dflt = 8; /* 8, 16, 24, 32 */
|
||||
int8_t reset_status_dflt =99;
|
||||
/* 공장 입력 항목 9 */
|
||||
//uint16_t led_delay_us_dflt = 8000; /* 0 ~ 65535 */
|
||||
|
||||
/* 공장 입력 항목 10 */
|
||||
//uint16_t pd_delay_us_dflt = 8000; /* 0 ~ 65535 */
|
||||
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
/* Bonding information delete */
|
||||
//bool bond_data_delete_dflt = true;//
|
||||
|
||||
/* Static Passkey */
|
||||
int8_t reset_status_dflt = 99;
|
||||
uint8_t static_passkey_dflt[6] = "123456";
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
//uint16_t led_power_dp_dflt[48] = {
|
||||
// //NULL, 42, 29, 41, 31, 28, 28, 42, 28, 39, 29, 27, 27, 42, 29, 40, 30, 28, 28, 40, 27, 38, 28, 25, 22
|
||||
// 25,25,25,18,19,24,24,25,25,18,19,25,23,25,25,18,19,24,24,25,25,19,20,25,24,25,25,25,18,19,24,24,25,25,18,19,25,23,25,25,18,19,24,24,25,25,19,20
|
||||
//};
|
||||
|
||||
void fds_default_value_set(void)
|
||||
{
|
||||
/* HW Number - empty (set via BLE command) */
|
||||
memset(m_config.hw_no, 0, 12);
|
||||
|
||||
/* Serial Number */
|
||||
//memcpy(m_config.serial_number, serial_number_dflt, 12);
|
||||
|
||||
/* PD-ADC Calibration Value */
|
||||
// for(uint8_t j = 0; j < M_LED_NUM; j++){
|
||||
// m_config.pd_adc_calibration_PD0[j] = pd_adc_calibration_dflt_PD0[j];
|
||||
// }
|
||||
// for(uint8_t j = 0; j < M_LED_NUM; j++){
|
||||
// m_config.pd_adc_calibration_PD1[j] = pd_adc_calibration_dflt_PD1[j];
|
||||
// }
|
||||
// for(uint8_t j = 0; j < M_LED_NUM; j++){
|
||||
// m_config.pd_adc_calibration_PD2[j] = pd_adc_calibration_dflt_PD2[j];
|
||||
// }
|
||||
|
||||
|
||||
// /* Dark Noise of PD */
|
||||
// for(uint8_t i = 0; i < PD_NUM; i++){
|
||||
// m_config.dark_noise_for_pd[i] = dark_noise_for_pd_dflt[i];
|
||||
// }
|
||||
|
||||
/* PD-ADC Cycle for 8, 16, 24, 32 */
|
||||
// m_config.pd_adc_cnt = pd_adc_cnt_dflt;
|
||||
|
||||
/* LED ON Delay for usec */
|
||||
// m_config.led_delay_us = led_delay_us_dflt;
|
||||
|
||||
/* PD ON Delay for usec */
|
||||
// m_config.pd_delay_us = pd_delay_us_dflt;
|
||||
|
||||
|
||||
m_config.reset_status = reset_status_dflt;
|
||||
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
/* Bonding information delete */
|
||||
// m_config.bond_data_delete = bond_data_delete_dflt;
|
||||
/* Serial Number - default from FIRMWARE_SERIAL_NO */
|
||||
memset(m_config.serial_no, 0, 12);
|
||||
memcpy(m_config.serial_no, "VB026030000", 11);
|
||||
|
||||
/* Static Passkey */
|
||||
memcpy(m_config.static_passkey, static_passkey_dflt, 6);
|
||||
|
||||
#endif
|
||||
//for(uint8_t i = 0; i < PD_NUM; i++){
|
||||
// for(uint8_t j = 0; j < LED_NUM; j++){
|
||||
// m_config.led_pd_dac_v[j] = 1000;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// for(uint8_t j = 0; j < LED_NUM; j++){
|
||||
// m_config.led_power_dp[j] = led_power_dp_dflt[j] ;
|
||||
// }
|
||||
//
|
||||
}
|
||||
|
||||
/* Bond data delete */
|
||||
m_config.bond_data_delete = 1;
|
||||
|
||||
/* Reset status */
|
||||
m_config.reset_status = reset_status_dflt;
|
||||
|
||||
/* Measurement parameters */
|
||||
m_config.pd_adc_cnt = 8;
|
||||
m_config.pd_delay_us = 8000;
|
||||
}
|
||||
|
||||
|
||||
static volatile uint8_t fds_last_evt = 0xFF;
|
||||
|
||||
static void fds_evt_handler( fds_evt_t const *p_evt )
|
||||
{
|
||||
fds_last_evt = p_evt->id;
|
||||
|
||||
switch( p_evt->id )
|
||||
{
|
||||
case FDS_EVT_INIT:
|
||||
@@ -191,20 +116,20 @@ static void fds_evt_handler( fds_evt_t const *p_evt )
|
||||
}
|
||||
if(go_NVIC_SystemReset == true) {
|
||||
/* After flash writing completed, System Reset */
|
||||
printf("Off FDS_ENVET\r\n");
|
||||
NVIC_SystemReset(); //0112
|
||||
DBG_PRINTF("Off FDS_EVENT\r\n");
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FDS_EVT_DEL_RECORD:
|
||||
break;
|
||||
break;
|
||||
|
||||
case FDS_EVT_DEL_FILE:
|
||||
break;
|
||||
|
||||
case FDS_EVT_GC:
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -215,9 +140,16 @@ static void fds_evt_handler( fds_evt_t const *p_evt )
|
||||
/**@brief Wait for fds to initialize. */
|
||||
static void wait_for_fds_ready( void )
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
while( !m_fds_initialized )
|
||||
{
|
||||
nrf_pwr_mgmt_run();
|
||||
nrf_delay_ms(1);
|
||||
timeout++;
|
||||
if (timeout > 3000) { /* 3 second timeout */
|
||||
DBG_PRINTF("[FDS] TIMEOUT!\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,11 +159,21 @@ void config_load( void )
|
||||
ret_code_t rc;
|
||||
fds_record_desc_t desc = { 0 };
|
||||
fds_find_token_t tok = { 0 };
|
||||
uint8_t cfg_retry = 0;
|
||||
|
||||
cfg_load_start:
|
||||
memset((char *)&desc, 0, sizeof(desc));
|
||||
memset((char *)&tok, 0, sizeof(tok));
|
||||
rc = fds_record_find(CONFIG_FILE, CONFIG_REC_KEY, &desc, &tok);
|
||||
DBG_PRINTF("[FDS] find rc=%u\r\n", rc);
|
||||
|
||||
/* FDS may not be fully ready yet - retry before writing defaults */
|
||||
if (rc != NRF_SUCCESS && cfg_retry < 10) {
|
||||
cfg_retry++;
|
||||
DBG_PRINTF("[FDS] retry %u/10\r\n", cfg_retry);
|
||||
nrf_delay_ms(100);
|
||||
goto cfg_load_start;
|
||||
}
|
||||
|
||||
if( rc == NRF_SUCCESS )
|
||||
{
|
||||
@@ -240,21 +182,32 @@ void config_load( void )
|
||||
|
||||
/* Open the record and read its contents. */
|
||||
rc = fds_record_open(&desc, &config);
|
||||
APP_ERROR_CHECK(rc);
|
||||
if (rc != NRF_SUCCESS) {
|
||||
/* CRC error or corrupt record - delete and use defaults */
|
||||
DBG_PRINTF("[FDS] open ERR=%u, deleting\r\n", rc);
|
||||
(void)fds_record_delete(&desc);
|
||||
fds_gc();
|
||||
fds_default_value_set();
|
||||
goto cfg_load_write_new;
|
||||
}
|
||||
|
||||
/* Copy the configuration from flash into m_dummy_cfg. */
|
||||
/* Copy the configuration from flash into m_config. */
|
||||
memcpy(&m_config, config.p_data, sizeof(config_data_t));
|
||||
|
||||
/* Close the record when done reading. */
|
||||
rc = fds_record_close(&desc);
|
||||
APP_ERROR_CHECK(rc);
|
||||
|
||||
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 )
|
||||
{ // first init
|
||||
DBG_PRINTF("[FDS] FORMAT! overwriting with defaults\r\n");
|
||||
rc = fds_record_delete(&desc);
|
||||
APP_ERROR_CHECK(rc);
|
||||
m_config.magic_number = CONFIG_MAGIC_NUMBER_VALUE;
|
||||
|
||||
|
||||
// default....
|
||||
fds_default_value_set();
|
||||
|
||||
@@ -271,16 +224,24 @@ void config_load( void )
|
||||
}
|
||||
goto cfg_load_start;
|
||||
}
|
||||
DBG_PRINTF("[FDS] Loaded OK\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* System config not found; write a new one. */
|
||||
cfg_load_write_new:
|
||||
DBG_PRINTF("[FDS] New - writing defaults\r\n");
|
||||
/* System config not found (or corrupt); write a new one. */
|
||||
m_config.magic_number = CONFIG_MAGIC_NUMBER_VALUE;
|
||||
|
||||
// default....
|
||||
fds_default_value_set();
|
||||
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_write(&desc, &m_dummy_record);
|
||||
if (rc != NRF_SUCCESS) {
|
||||
DBG_PRINTF("[FDS] Write ERR=%u\r\n", rc);
|
||||
fds_flag_write = false;
|
||||
}
|
||||
while( fds_flag_write )
|
||||
{
|
||||
nrf_pwr_mgmt_run();
|
||||
@@ -306,44 +267,58 @@ void config_save( void )
|
||||
fds_record_desc_t desc = { 0 };
|
||||
fds_find_token_t tok = { 0 };
|
||||
|
||||
rc = fds_gc();
|
||||
APP_ERROR_CHECK(rc);
|
||||
DBG_PRINTF("[CFG_SAVE] start\r\n");
|
||||
|
||||
/* Skip if a previous FDS operation is still in progress (non-blocking) */
|
||||
if (fds_flag_write) {
|
||||
DBG_PRINTF("[CFG_SAVE] busy, skipped\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE )
|
||||
{
|
||||
m_config.magic_number = CONFIG_MAGIC_NUMBER_VALUE;
|
||||
}
|
||||
|
||||
config_save_start:
|
||||
|
||||
fds_flag_write = true;
|
||||
|
||||
memset((char *)&desc, 0, sizeof(desc));
|
||||
memset((char *)&tok, 0, sizeof(tok));
|
||||
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 )
|
||||
{
|
||||
/* Write the updated record to flash. */
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_update(&desc, &m_dummy_record);
|
||||
if( (rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH) )
|
||||
DBG_PRINTF("[CFG_SAVE] update rc=%u\r\n", rc);
|
||||
if( rc == FDS_ERR_NO_SPACE_IN_FLASH )
|
||||
{
|
||||
fds_flag_write = false;
|
||||
rc = fds_gc();
|
||||
APP_ERROR_CHECK(rc);
|
||||
goto config_save_start;
|
||||
DBG_PRINTF("[CFG_SAVE] gc rc=%u, retry\r\n", rc);
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_update(&desc, &m_dummy_record);
|
||||
DBG_PRINTF("[CFG_SAVE] retry rc=%u\r\n", rc);
|
||||
}
|
||||
else
|
||||
if( rc != NRF_SUCCESS )
|
||||
{
|
||||
APP_ERROR_CHECK(rc);
|
||||
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
||||
fds_flag_write = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_PRINTF("[CFG_SAVE] not found, writing new\r\n");
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_write(&desc, &m_dummy_record);
|
||||
APP_ERROR_CHECK(rc);
|
||||
|
||||
goto config_save_start;
|
||||
DBG_PRINTF("[CFG_SAVE] write rc=%u\r\n", rc);
|
||||
if( rc != NRF_SUCCESS )
|
||||
{
|
||||
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
||||
fds_flag_write = false;
|
||||
}
|
||||
}
|
||||
|
||||
DBG_PRINTF("[CFG_SAVE] done\r\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -359,12 +334,16 @@ void fs_storage_init(void)
|
||||
/* Register first to receive an event when initialization is complete. */
|
||||
rc = fds_register(fds_evt_handler);
|
||||
APP_ERROR_CHECK(rc);
|
||||
|
||||
rc = fds_init();
|
||||
APP_ERROR_CHECK(rc);
|
||||
|
||||
/* Wait for fds to initialize. */
|
||||
wait_for_fds_ready();
|
||||
|
||||
fds_stat_t stat = { 0 };
|
||||
rc = fds_stat(&stat);
|
||||
APP_ERROR_CHECK(rc);
|
||||
}
|
||||
|
||||
DBG_PRINTF("[FDS] OK\r\n");
|
||||
}
|
||||
|
||||
@@ -13,39 +13,19 @@
|
||||
|
||||
#include "nordic_common.h"
|
||||
#include <stdint.h>
|
||||
#include "measurements.h"
|
||||
|
||||
#define LED_NUM 48 /* LED0 사용하지 않음, 대신 NULL값 입력 */
|
||||
#define PD_NUM 2 /* PD0 사용하지 않음, 대신 NULL값 입력 * 0,1 data 2 mod 3 off*/
|
||||
#define mW 13 /* LED mW 설정 파워 값 */
|
||||
#define M_LED_NUM 24 /*측정할 L*/
|
||||
#pragma pack(1)
|
||||
typedef struct
|
||||
{
|
||||
uint32_t magic_number;
|
||||
//char serial_number[13];
|
||||
|
||||
// uint32_t pd_adc_calibration_PD0[M_LED_NUM];
|
||||
// uint32_t pd_adc_calibration_PD1[M_LED_NUM];
|
||||
// uint32_t pd_adc_calibration_PD2[M_LED_NUM];
|
||||
|
||||
|
||||
// uint32_t dark_noise_for_pd[PD_NUM];
|
||||
// int8_t pd_adc_cnt;
|
||||
int8_t reset_status;
|
||||
// uint16_t led_delay_us;
|
||||
// uint16_t pd_delay_us;
|
||||
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
// bool bond_data_delete;
|
||||
uint8_t static_passkey[6];
|
||||
|
||||
#endif
|
||||
|
||||
// uint16_t led_pd_dac_v[LED_NUM];
|
||||
// uint16_t led_power_dp[LED_NUM];
|
||||
|
||||
} config_data_t; /* Flash에 저장하는 값 */
|
||||
uint32_t magic_number; /* 4B - 0x20231226 */
|
||||
char hw_no[12]; /* 12B - HW Number */
|
||||
char serial_no[12]; /* 12B - Serial Number */
|
||||
uint8_t static_passkey[6]; /* 6B - BLE Passkey */
|
||||
uint8_t bond_data_delete; /* 1B - Bond delete flag */
|
||||
int8_t reset_status; /* 1B - Reset status */
|
||||
uint8_t pd_adc_cnt; /* 1B - ADC sample count */
|
||||
uint16_t pd_delay_us; /* 2B - PD delay (us) */
|
||||
} config_data_t; /* Total: 41 bytes - FDS에 저장하는 디바이스 설정 */
|
||||
|
||||
extern config_data_t m_config;
|
||||
|
||||
|
||||
183
project/ble_peripheral/ble_app_bladder_patch/hex/cpd.bat
Normal file
183
project/ble_peripheral/ble_app_bladder_patch/hex/cpd.bat
Normal file
@@ -0,0 +1,183 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
echo ==========================================
|
||||
echo MEDiThings Bladder Patch Programming
|
||||
echo (DEBUG MODE - No Readback Protection)
|
||||
echo ==========================================
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM Set script directory as base path
|
||||
REM -----------------------------------------------------
|
||||
cd /d "%~dp0"
|
||||
echo Working directory: %CD%
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM Create hex output folder
|
||||
REM -----------------------------------------------------
|
||||
if not exist hex mkdir hex
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM 1. Copy HEX files (with verification)
|
||||
REM -----------------------------------------------------
|
||||
echo [1/6] Copying HEX files...
|
||||
|
||||
set "APP_SRC=..\pca10056\s140\arm5_no_packs\_build\nrf52840_xxaa.hex"
|
||||
set "BOOT_SRC=..\..\..\dfu\secure_bootloader\pca10056_s140_ble\arm5_no_packs\_build\nrf52840_xxaa_s140.hex"
|
||||
|
||||
REM Check source files exist
|
||||
if not exist "%APP_SRC%" (
|
||||
echo ERROR: Application HEX not found: %APP_SRC%
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "%BOOT_SRC%" (
|
||||
echo ERROR: Bootloader HEX not found: %BOOT_SRC%
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Copy with /Y to overwrite without prompt
|
||||
copy /Y "%APP_SRC%" hex\app.hex
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: Failed to copy app.hex
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo - app.hex copied OK
|
||||
|
||||
copy /Y "%BOOT_SRC%" hex\boot.hex
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: Failed to copy boot.hex
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo - boot.hex copied OK
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM 2. Generate Bootloader DFU Settings
|
||||
REM -----------------------------------------------------
|
||||
echo [2/6] Generating Bootloader DFU settings...
|
||||
nrfutil settings generate ^
|
||||
--family NRF52840 ^
|
||||
--application hex\app.hex ^
|
||||
--application-version 1 ^
|
||||
--bootloader-version 1 ^
|
||||
--bl-settings-version 2 ^
|
||||
hex\settings.hex
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: nrfutil settings failed.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM 3. Merge HEX (SoftDevice + Application)
|
||||
REM -----------------------------------------------------
|
||||
echo [3/6] Merging SoftDevice + Application...
|
||||
mergehex.exe --merge s140_nrf52_7.2.0_softdevice.hex hex\app.hex --output hex\part1.hex
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: mergehex part1 failed.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM 4. Merge HEX (Bootloader + Settings)
|
||||
REM -----------------------------------------------------
|
||||
echo [4/6] Merging Bootloader + Settings...
|
||||
mergehex.exe --merge hex\boot.hex hex\settings.hex --output hex\part2.hex
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: mergehex part2 failed.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM 5. Final HEX merge (Combine everything)
|
||||
REM -----------------------------------------------------
|
||||
echo [5/6] Creating final combined HEX...
|
||||
mergehex.exe --merge hex\part1.hex hex\part2.hex --output hex\firmware_all.hex
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: mergehex final merge failed.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Final merged HEX: hex\firmware_all.hex
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM 6. Detect device SERIAL NUMBER and Flash
|
||||
REM -----------------------------------------------------
|
||||
echo [6/6] Detecting device serial number...
|
||||
|
||||
for /f %%A in ('
|
||||
powershell -Command "(nrfutil device list --json | Select-String '\"type\":\"info\"' | ConvertFrom-Json).data.devices[0].serialNumber"
|
||||
') do set SERIALNUMBER=%%A
|
||||
|
||||
if "%SERIALNUMBER%"=="" (
|
||||
echo ERROR: No serial number found.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Using Serial Number: %SERIALNUMBER%
|
||||
echo Flashing: program → reset (NO erase, FDS preserved)
|
||||
|
||||
REM recover - SKIP to preserve internal flash data
|
||||
REM erase - SKIP to preserve FDS/fstorage data
|
||||
|
||||
REM program (sector-erase only for hex regions, FDS pages untouched)
|
||||
nrfutil device program --firmware hex\firmware_all.hex --serial-number %SERIALNUMBER%
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo [WARNING] Program failed - device may have Readback Protection enabled.
|
||||
echo Recover will ERASE ALL flash including FDS data.
|
||||
echo.
|
||||
set /p RECOVER_YN="Recover and retry? (Y/N): "
|
||||
if /i "!RECOVER_YN!"=="Y" (
|
||||
echo Recovering device...
|
||||
nrfutil device recover --serial-number %SERIALNUMBER%
|
||||
if %errorlevel% neq 0 goto flash_fail
|
||||
echo Re-programming...
|
||||
nrfutil device program --firmware hex\firmware_all.hex --serial-number %SERIALNUMBER%
|
||||
if %errorlevel% neq 0 goto flash_fail
|
||||
) else (
|
||||
goto flash_fail
|
||||
)
|
||||
)
|
||||
|
||||
REM reset
|
||||
nrfutil device reset --serial-number %SERIALNUMBER%
|
||||
if %errorlevel% neq 0 goto flash_fail
|
||||
|
||||
goto flash_success
|
||||
|
||||
:flash_fail
|
||||
echo ERROR: Flashing failed.
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:flash_success
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM NOTE: Readback Protection SKIPPED for debugging
|
||||
REM -----------------------------------------------------
|
||||
echo ==========================================
|
||||
echo Programming Complete! (DEBUG MODE)
|
||||
echo No Readback Protection Applied
|
||||
echo Internal Flash (FDS) Preserved
|
||||
echo %date% %time%
|
||||
echo ==========================================
|
||||
|
||||
REM -----------------------------------------------------
|
||||
REM Open J-Link RTT Viewer for RTT debugging
|
||||
REM -----------------------------------------------------
|
||||
echo Starting J-Link RTT Viewer...
|
||||
|
||||
endlocal
|
||||
@@ -1,3 +1,3 @@
|
||||
set path=d:\nrfutil\bin;%path%
|
||||
d:
|
||||
cd D:\mt_project\mt_firmware\project\ble_peripheral\ble_app_bladder_patch\hex
|
||||
cd D:\mt_project\vesiscan\project\ble_peripheral\ble_app_bladder_patch\hex
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "main.h"
|
||||
#include "meas_pd_48.h"
|
||||
#include <cmd_parse.h>
|
||||
#include "debug_print.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -312,7 +314,7 @@ static void apply_mounting_matrix(const int32_t matrix[9], int32_t raw[3])
|
||||
{
|
||||
unsigned i;
|
||||
int64_t data_q30[3];
|
||||
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
data_q30[i] = ((int64_t)matrix[3*i+0] * raw[0]);
|
||||
data_q30[i] += ((int64_t)matrix[3*i+1] * raw[1]);
|
||||
@@ -322,3 +324,80 @@ static void apply_mounting_matrix(const int32_t matrix[9], int32_t raw[3])
|
||||
raw[1] = (int32_t)(data_q30[1]>>30);
|
||||
raw[2] = (int32_t)(data_q30[2]>>30);
|
||||
}
|
||||
|
||||
|
||||
/* Raw I2C read from ICM42670P — bypasses driver API entirely */
|
||||
#include "system_interface.h"
|
||||
#include "nrfx_twi.h"
|
||||
|
||||
extern const nrfx_twi_t m_twi_icm42670;
|
||||
|
||||
#define IMU_I2C_ADDR 0x68
|
||||
#define REG_ACCEL_X1 0x0B /* ACCEL_DATA_X1 */
|
||||
|
||||
/* Direct IMU register read — raw I2C, no DRDY, sends rsp: via BLE */
|
||||
int imu_read_direct(void)
|
||||
{
|
||||
uint8_t raw[12]; /* 6 accel + 6 gyro */
|
||||
int32_t accel[3], gyro[3];
|
||||
uint8_t reg;
|
||||
uint32_t ret;
|
||||
|
||||
static bool twi_ready = false;
|
||||
|
||||
DBG_PRINTF("[IMU] enter\r\n");
|
||||
|
||||
/* Ensure ICM42670P TWI is initialized (once only) */
|
||||
if (!twi_ready) {
|
||||
inv_i2c_master_uninitialize();
|
||||
inv_i2c_master_initialize();
|
||||
twi_ready = true;
|
||||
}
|
||||
|
||||
/* Enable accel (low-noise) + gyro (low-noise): PWR_MGMT0 = 0x0F */
|
||||
{
|
||||
uint8_t pwr_cmd[2] = { 0x1F, 0x0F }; /* reg=0x1F, val=0x0F */
|
||||
icm42670_twi_tx(IMU_I2C_ADDR, pwr_cmd, 2, false);
|
||||
nrf_delay_ms(2); /* wait for sensor startup */
|
||||
}
|
||||
|
||||
/* Read 12 bytes starting from ACCEL_DATA_X1 (0x0B..0x16) */
|
||||
reg = REG_ACCEL_X1;
|
||||
ret = icm42670_twi_tx(IMU_I2C_ADDR, ®, 1, true);
|
||||
if (ret) {
|
||||
DBG_PRINTF("[IMU] tx FAIL %u\r\n", ret);
|
||||
return -1;
|
||||
}
|
||||
ret = icm42670_twi_rx(IMU_I2C_ADDR, raw, 12);
|
||||
if (ret) {
|
||||
DBG_PRINTF("[IMU] rx FAIL %u\r\n", ret);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Big-Endian register layout: [0..5]=accel, [6..11]=gyro */
|
||||
accel[0] = (int16_t)((raw[0] << 8) | raw[1]);
|
||||
accel[1] = (int16_t)((raw[2] << 8) | raw[3]);
|
||||
accel[2] = (int16_t)((raw[4] << 8) | raw[5]);
|
||||
gyro[0] = (int16_t)((raw[6] << 8) | raw[7]);
|
||||
gyro[1] = (int16_t)((raw[8] << 8) | raw[9]);
|
||||
gyro[2] = (int16_t)((raw[10] << 8) | raw[11]);
|
||||
|
||||
apply_mounting_matrix(icm_mounting_matrix, accel);
|
||||
apply_mounting_matrix(icm_mounting_matrix, gyro);
|
||||
|
||||
DBG_PRINTF("[IMU] A:%d,%d,%d G:%d,%d,%d\r\n",
|
||||
accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
|
||||
|
||||
ssp_data[0] = (uint16_t)accel[0];
|
||||
ssp_data[1] = (uint16_t)accel[1];
|
||||
ssp_data[2] = (uint16_t)accel[2];
|
||||
ssp_data[3] = (uint16_t)gyro[0];
|
||||
ssp_data[4] = (uint16_t)gyro[1];
|
||||
ssp_data[5] = (uint16_t)gyro[2];
|
||||
|
||||
format_data(imu_bin_buffer, "rsp:", ssp_data, 12);
|
||||
binary_tx_handler(imu_bin_buffer, 8);
|
||||
|
||||
DBG_PRINTF("[IMU] sent OK\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -71,5 +71,11 @@ int get_imu_data(void);
|
||||
*/
|
||||
void imu_callback(inv_imu_sensor_event_t *event);
|
||||
|
||||
/**
|
||||
* \brief Direct IMU register read — bypasses DRDY, sends rsp: via BLE.
|
||||
* \return 0 on success, negative value on error.
|
||||
*/
|
||||
int imu_read_direct(void);
|
||||
|
||||
|
||||
#endif /* !_APP_RAW_H_ */
|
||||
|
||||
@@ -34,7 +34,7 @@ void inv_i2c_master_uninitialize(void){
|
||||
nrfx_twi_uninit(&m_twi_icm42670);
|
||||
}
|
||||
|
||||
static void inv_i2c_master_initialize(void){
|
||||
void inv_i2c_master_initialize(void){
|
||||
ret_code_t err_code;
|
||||
|
||||
const nrfx_twi_config_t twi_icm42670_config = {
|
||||
|
||||
@@ -32,6 +32,7 @@ uint32_t icm42670_twi_rx( uint8_t device_id,
|
||||
uint8_t cat_read (uint8_t device_id, uint8_t address, uint8_t *data);
|
||||
void cat_write (uint8_t device_id, uint8_t address, uint8_t *data);
|
||||
void inv_i2c_master_uninitialize(void);
|
||||
void inv_i2c_master_initialize(void);
|
||||
int inv_io_hal_init(struct inv_imu_serif *serif);
|
||||
int inv_io_hal_read_reg(struct inv_imu_serif *serif, uint8_t reg, uint8_t * rbuffer, uint32_t rlen);
|
||||
int inv_io_hal_write_reg(struct inv_imu_serif *serif, uint8_t reg, const uint8_t * wbuffer, uint32_t wlen);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* @file main.c
|
||||
* @brief Medithings Bladder Patch Firmware
|
||||
* @brief Medithings VesiScan BASIC
|
||||
* @version 1.17
|
||||
* @date 2025-12-09
|
||||
* @author Charles KWON
|
||||
@@ -93,6 +93,13 @@
|
||||
#include "nrf_crypto.h"
|
||||
#include <cmd_parse.h>
|
||||
#include "debug_print.h"
|
||||
#include "fstorage.h"
|
||||
|
||||
|
||||
#define HARDWARE_VERSION "VB0HW0000"
|
||||
#define FIRMWARE_VERSION "VB0FW0000"
|
||||
#define FIRMWARE_SERIAL_NO "VB026030000"
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
* BUILD CONFIGURATION
|
||||
@@ -319,19 +326,71 @@ static void full_gpio_init(void)
|
||||
static void load_default_config(void)
|
||||
{
|
||||
memset(SERIAL_NO, 0, 16);
|
||||
memcpy(SERIAL_NO, "2025MEDIP0001", 13);
|
||||
|
||||
memcpy(SERIAL_NO, FIRMWARE_SERIAL_NO, strlen(FIRMWARE_SERIAL_NO));
|
||||
|
||||
memset(m_static_passkey, 0, 16);
|
||||
memcpy(m_static_passkey, "123456", 6);
|
||||
|
||||
|
||||
m_pd_delay_us = 8000;
|
||||
m_pd_adc_cnt = 8;
|
||||
m_reset_status = 1;
|
||||
bond_data_delete = 1;
|
||||
|
||||
|
||||
DBG_PRINTF("[CFG] Default (S/N=%s)\r\n", SERIAL_NO);
|
||||
}
|
||||
|
||||
/**@brief Load configuration from internal Flash (FDS) into global variables.
|
||||
*
|
||||
* Must be called AFTER ble_stack_init() → fs_storage_init() → config_load().
|
||||
* Reads m_config (populated by config_load) and copies to runtime globals.
|
||||
*/
|
||||
static bool m_need_save_defaults = false;
|
||||
|
||||
static void load_flash_config(void)
|
||||
{
|
||||
m_need_save_defaults = false;
|
||||
|
||||
/* Hardware Number — fill default if empty */
|
||||
if (m_config.hw_no[0] == 0 || m_config.hw_no[0] == (char)0xFF) {
|
||||
memset(m_config.hw_no, 0, 12);
|
||||
memcpy(m_config.hw_no, HARDWARE_VERSION, strlen(HARDWARE_VERSION));
|
||||
DBG_PRINTF("[CFG] HW empty, set default: %s\r\n", HARDWARE_VERSION);
|
||||
m_need_save_defaults = true;
|
||||
}
|
||||
|
||||
/* Serial Number — fill default if empty */
|
||||
if (m_config.serial_no[0] == 0 || m_config.serial_no[0] == (char)0xFF) {
|
||||
memset(m_config.serial_no, 0, 12);
|
||||
memcpy(m_config.serial_no, FIRMWARE_SERIAL_NO, strlen(FIRMWARE_SERIAL_NO));
|
||||
DBG_PRINTF("[CFG] S/N empty, set default: %s\r\n", FIRMWARE_SERIAL_NO);
|
||||
m_need_save_defaults = true;
|
||||
}
|
||||
|
||||
/* Serial Number → BLE device name */
|
||||
memset(SERIAL_NO, 0, 16);
|
||||
memcpy(SERIAL_NO, m_config.serial_no, 12);
|
||||
|
||||
/* Passkey */
|
||||
memset(m_static_passkey, 0, 16);
|
||||
memcpy(m_static_passkey, m_config.static_passkey, 6);
|
||||
|
||||
/* Bond data delete flag */
|
||||
bond_data_delete = m_config.bond_data_delete;
|
||||
|
||||
/* Reset status */
|
||||
m_reset_status = m_config.reset_status;
|
||||
|
||||
/* Measurement parameters (with validation) */
|
||||
m_pd_adc_cnt = (m_config.pd_adc_cnt > 0 && m_config.pd_adc_cnt <= 32)
|
||||
? m_config.pd_adc_cnt : 8;
|
||||
m_pd_delay_us = (m_config.pd_delay_us > 0)
|
||||
? m_config.pd_delay_us : 8000;
|
||||
|
||||
DBG_PRINTF("[CFG] HW=%.12s S/N=%s passkey=%.6s bond=%d rst=%d adc=%d delay=%u\r\n",
|
||||
m_config.hw_no, SERIAL_NO, m_static_passkey, bond_data_delete,
|
||||
m_reset_status, m_pd_adc_cnt, m_pd_delay_us);
|
||||
}
|
||||
|
||||
#if !DEBUG_MINIMAL_BOOT
|
||||
static void load_eeprom_config(void)
|
||||
{
|
||||
@@ -345,13 +404,13 @@ static void load_eeprom_config(void)
|
||||
|
||||
#if BLE_DEV_MODE
|
||||
memset(SERIAL_NO, 0, 16);
|
||||
memcpy(SERIAL_NO, "2005MEDIP001", 12);
|
||||
memcpy(SERIAL_NO, FIRMWARE_SERIAL_NO, strlen(FIRMWARE_SERIAL_NO));
|
||||
DBG_PRINTF("[CFG] DEV S/N=%s\r\n", SERIAL_NO);
|
||||
#else
|
||||
if (!is_valid_serial_no(SERIAL_NO))
|
||||
{
|
||||
memset(SERIAL_NO, 0, 16);
|
||||
memcpy(SERIAL_NO, "2025AAAAP000", 12);
|
||||
memcpy(SERIAL_NO, FIRMWARE_SERIAL_NO, strlen(FIRMWARE_SERIAL_NO));
|
||||
}
|
||||
|
||||
char const init_pass[6] = "123456";
|
||||
@@ -1441,23 +1500,19 @@ int main(void)
|
||||
DBG_PRINTF("[2] Timers\r\n");
|
||||
timers_init();
|
||||
|
||||
// PHASE 4: 설정
|
||||
DBG_PRINTF("[3] Config\r\n");
|
||||
#if DEBUG_MINIMAL_BOOT
|
||||
// PHASE 4: 설정 (기본값 로드)
|
||||
DBG_PRINTF("[3] Config (defaults)\r\n");
|
||||
load_default_config();
|
||||
#else
|
||||
load_eeprom_config();
|
||||
#endif
|
||||
|
||||
// PHASE 5: 버튼/LED
|
||||
DBG_PRINTF("[4] Buttons\r\n");
|
||||
buttons_leds_init(&erase_bonds_local);
|
||||
|
||||
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
erase_bonds = erase_bonds_local;
|
||||
#endif
|
||||
|
||||
// PHASE 6: BLE
|
||||
// PHASE 6: BLE 스택
|
||||
DBG_PRINTF("[5] BLE\r\n");
|
||||
|
||||
power_management_init();
|
||||
@@ -1466,6 +1521,13 @@ int main(void)
|
||||
ble_stack_init();
|
||||
DBG_PRINTF(" stack OK\r\n");
|
||||
|
||||
// PHASE 6.5: 내장 Flash (FDS) - BLE 스택 이후에 초기화해야 함
|
||||
DBG_PRINTF("[5.5] FDS\r\n");
|
||||
fs_storage_init();
|
||||
config_load();
|
||||
load_flash_config();
|
||||
DBG_PRINTF(" fds OK\r\n");
|
||||
|
||||
gap_params_init();
|
||||
DBG_PRINTF(" gap OK\r\n");
|
||||
|
||||
@@ -1487,6 +1549,13 @@ int main(void)
|
||||
peer_manager_init();
|
||||
#endif
|
||||
|
||||
// PHASE 7.5: FDS 기본값 저장 (advertising 이후)
|
||||
if (m_need_save_defaults) {
|
||||
DBG_PRINTF("[FDS] Saving defaults after ADV\r\n");
|
||||
config_save();
|
||||
m_need_save_defaults = false;
|
||||
}
|
||||
|
||||
// PHASE 8: 완료
|
||||
DBG_PRINTF("\r\n========================================\r\n");
|
||||
DBG_PRINTF(" READY [%s]\r\n", SERIAL_NO);
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
T17578 000:016.299 SEGGER J-Link V7.22b Log File
|
||||
T17578 000:016.864 DLL Compiled: Jun 17 2021 17:22:49
|
||||
T17578 000:016.869 Logging started @ 2026-01-24 07:30
|
||||
T17578 000:016.873 - 16.875ms
|
||||
T17578 000:017.062 JLINK_SetWarnOutHandler(...)
|
||||
T17578 000:017.200 - 0.139ms
|
||||
T17578 000:017.206 JLINK_OpenEx(...)
|
||||
T17578 000:021.737 Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Jul 8 2025 10:14:41
|
||||
T17578 000:021.932 Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Jul 8 2025 10:14:41
|
||||
T17578 000:023.526 Hardware: V1.00
|
||||
T17578 000:023.541 S/N: 682060510
|
||||
T17578 000:023.553 OEM: SEGGER
|
||||
T17578 000:023.584 Feature(s): RDI, FlashBP, FlashDL, JFlash, GDB
|
||||
T17578 000:024.858 TELNET listener socket opened on port 19021
|
||||
T17578 000:025.175 WEBSRV Starting webserver
|
||||
T17578 000:025.338 WEBSRV Webserver running on local port 19080
|
||||
T17578 000:025.348 - 8.144ms returns "O.K."
|
||||
T17578 000:025.367 JLINK_GetEmuCaps()
|
||||
T17578 000:025.371 - 0.007ms returns 0xB8EA5A33
|
||||
T17578 000:025.659 JLINK_TIF_GetAvailable(...)
|
||||
T17578 000:025.792 - 0.142ms
|
||||
T17578 000:025.810 JLINK_SetErrorOutHandler(...)
|
||||
T17578 000:025.815 - 0.006ms
|
||||
T17578 000:026.191 JLINK_ExecCommand("ProjectFile = "D:\mt_project\mt_firmware\project\ble_peripheral\ble_app_bladder_patch\pca10056\s140\arm5_no_packs\JLinkSettings.ini"", ...).
|
||||
T17578 000:042.853 - 16.685ms returns 0x00
|
||||
T17578 000:050.030 JLINK_ExecCommand("Device = nRF52840_xxAA", ...).
|
||||
T17578 000:056.080 Device "NRF52840_XXAA" selected.
|
||||
T17578 000:056.499 - 6.440ms returns 0x00
|
||||
T17578 000:056.983 JLINK_GetHardwareVersion()
|
||||
T17578 000:056.998 - 0.017ms returns 10000
|
||||
T17578 000:057.003 JLINK_GetDLLVersion()
|
||||
T17578 000:057.007 - 0.005ms returns 72202
|
||||
T17578 000:057.013 JLINK_GetOEMString(...)
|
||||
T17578 000:057.018 JLINK_GetFirmwareString(...)
|
||||
T17578 000:057.027 - 0.011ms
|
||||
T17578 000:067.210 JLINK_GetDLLVersion()
|
||||
T17578 000:067.242 - 0.034ms returns 72202
|
||||
T17578 000:067.248 JLINK_GetCompileDateTime()
|
||||
T17578 000:067.253 - 0.006ms
|
||||
T17578 000:070.610 JLINK_GetFirmwareString(...)
|
||||
T17578 000:070.630 - 0.022ms
|
||||
T17578 000:076.118 JLINK_GetHardwareVersion()
|
||||
T17578 000:076.149 - 0.036ms returns 10000
|
||||
T17578 000:081.686 JLINK_GetSN()
|
||||
T17578 000:081.735 - 0.054ms returns 682060510
|
||||
T17578 000:086.288 JLINK_GetOEMString(...)
|
||||
T17578 000:096.973 JLINK_TIF_Select(JLINKARM_TIF_SWD)
|
||||
T17578 000:097.628 - 0.671ms returns 0x00
|
||||
T17578 000:097.653 JLINK_HasError()
|
||||
T17578 000:099.547 JLINK_SetSpeed(5000)
|
||||
T17578 000:099.820 - 0.282ms
|
||||
T17578 000:099.835 JLINK_GetId()
|
||||
T17578 000:105.067 InitTarget() start
|
||||
T17578 000:105.093 J-Link Script File: Executing InitTarget()
|
||||
T17578 000:108.737 Looking for J-Link GUI Server exe at: C:\Keil_v5\ARM\Segger\JLinkGUIServer.exe
|
||||
T17578 000:108.890 Looking for J-Link GUI Server exe at: C:\Program Files\SEGGER\JLink_V818\JLinkGUIServer.exe
|
||||
T17578 000:108.954 Forking J-Link GUI Server: C:\Program Files\SEGGER\JLink_V818\JLinkGUIServer.exe
|
||||
T17578 000:181.575 J-Link GUI Server info: "J-Link GUI server V8.18 "
|
||||
T17578 002:406.198 Device will be unsecured now.
|
||||
T17578 002:631.975 InitTarget() end
|
||||
T17578 002:796.797 InitTarget() start
|
||||
T17578 002:796.830 J-Link Script File: Executing InitTarget()
|
||||
T17578 002:911.808 InitTarget() end
|
||||
T17578 003:014.808 - 2915.023ms returns 0x00000000
|
||||
T17578 006:160.609 JLINK_Close()
|
||||
T17578 006:185.982 - 25.395ms
|
||||
T17578 006:186.008
|
||||
T17578 006:186.012 Closed
|
||||
File diff suppressed because one or more lines are too long
@@ -1508,7 +1508,7 @@
|
||||
<GroupNumber>1</GroupNumber>
|
||||
<FileNumber>33</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\..\..\..\dr_piezo\dr_piezo.c</PathWithFileName>
|
||||
|
||||
@@ -9,27 +9,16 @@
|
||||
#include "main.h"
|
||||
#include "power_control.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "measurements.h"
|
||||
|
||||
#include "meas_pd_voltage_simple.h"
|
||||
|
||||
//#include "inv_imu_driver.h"
|
||||
//#include "app_raw_main.h"
|
||||
#include "mcp4725_i2c.h"
|
||||
#include "ada2200_spi.h"
|
||||
#include "ad5272_i2c.h"
|
||||
#include "nrf_log.h"
|
||||
#include "app_timer.h"
|
||||
#include "debug_print.h"
|
||||
#include "cat_interface.h"
|
||||
#include "i2c_manager.h"
|
||||
#define IR_POWER_HOLD NRF_GPIO_PIN_MAP(0, 11)
|
||||
//#define RCV_POWER_HOLD NRF_GPIO_PIN_MAP(1, 9)
|
||||
#define EEP_WP NRF_GPIO_PIN_MAP(0, 24)
|
||||
APP_TIMER_DEF(m_power_timer_id);
|
||||
|
||||
//#define POWER_LOOP_INTERVAL 30
|
||||
|
||||
// 2025-12-08 change to #define POWER_LOOP_INTERVAL 30 -> 20
|
||||
#define POWER_LOOP_INTERVAL 20
|
||||
|
||||
@@ -37,27 +26,14 @@ APP_TIMER_DEF(m_power_timer_id);
|
||||
|
||||
|
||||
static uint8_t p_order;
|
||||
extern uint8_t simple_samples_in_buffer;
|
||||
extern volatile bool processing;
|
||||
bool lock_check = false;
|
||||
void power_gpio_init(void)
|
||||
{
|
||||
nrf_gpio_cfg_output(IR_POWER_HOLD);
|
||||
//nrf_gpio_cfg_output(RCV_POWER_HOLD);
|
||||
nrf_gpio_cfg_output(EEP_WP);
|
||||
}
|
||||
|
||||
|
||||
void ir_power_control(on_off_cont_t ir_power_st)
|
||||
{
|
||||
if(ir_power_st == OFF) {
|
||||
nrf_gpio_pin_clear(IR_POWER_HOLD);
|
||||
}else if(ir_power_st == ON){
|
||||
nrf_gpio_pin_set(IR_POWER_HOLD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void eeprom_control(on_off_cont_t eeprom_st)
|
||||
{
|
||||
if(eeprom_st == OFF) {
|
||||
@@ -67,43 +43,11 @@ void eeprom_control(on_off_cont_t eeprom_st)
|
||||
}
|
||||
}
|
||||
|
||||
//void rcv_power_control(on_off_cont_t rcv_power_st)
|
||||
//{
|
||||
// if(rcv_power_st == OFF) {
|
||||
// nrf_gpio_pin_clear(RCV_POWER_HOLD);
|
||||
// }else if(rcv_power_st == ON){
|
||||
// nrf_gpio_pin_set(RCV_POWER_HOLD);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
int device_sleep_mode(void){
|
||||
int rc = 0;
|
||||
eeprom_control(OFF);
|
||||
mcp4725_PowerDownMode();
|
||||
|
||||
nrf_delay_ms(2);
|
||||
ada2200_stop();
|
||||
nrf_delay_ms(2);
|
||||
// ada2200_uninit();
|
||||
|
||||
nrf_delay_ms(2);
|
||||
|
||||
nrf_delay_ms(2);
|
||||
// ad5272_i2c_uninit();
|
||||
|
||||
nrf_delay_ms(2);
|
||||
// rcv_power_control(OFF);
|
||||
nrf_delay_ms(2);
|
||||
ir_power_control(OFF);
|
||||
eeprom_control(OFF);
|
||||
nrf_delay_ms(2);
|
||||
DBG_PRINTF("Device_Sleep_Mode OK!\r\n");
|
||||
if(rc == 0) {
|
||||
// DBG_PRINTF("Device_Sleep_Mode OK!\r\n");
|
||||
} else {
|
||||
DBG_PRINTF("ERR!!! Device_Sleep_Mode Failed!\r\n");
|
||||
}
|
||||
|
||||
nrf_delay_ms(10);
|
||||
processing = false;
|
||||
return rc;
|
||||
@@ -116,140 +60,58 @@ int device_activated(void){
|
||||
lock_check =true;
|
||||
power_timer_start();
|
||||
eeprom_control(OFF);
|
||||
// nrf_delay_ms(1);
|
||||
// ir_power_control(ON);
|
||||
// nrf_delay_ms(1);
|
||||
// rcv_power_control(ON);
|
||||
|
||||
// // nrf_delay_ms(5);
|
||||
//// ada2200_start();
|
||||
// nrf_delay_ms(100);
|
||||
// ada2200_init();
|
||||
// nrf_delay_ms(50);
|
||||
// mcp4725_init();
|
||||
// nrf_delay_ms(50);
|
||||
// ad5272_i2c_init();
|
||||
// nrf_delay_ms(50);
|
||||
// mcp4725_powerOnWakeUp();
|
||||
//
|
||||
// nrf_delay_ms(10);
|
||||
//
|
||||
//
|
||||
// ad5272_normal_mode();
|
||||
// nrf_delay_ms(50);
|
||||
// ada2200_start();
|
||||
|
||||
|
||||
|
||||
|
||||
// if( rc == 0) {
|
||||
// DBG_PRINTF("Device_Activate_Mode OK!\r\n");
|
||||
// } else {
|
||||
// DBG_PRINTF("ERR!!! Device_Activated Failed!\r\n");
|
||||
// }
|
||||
// nrf_delay_ms(1000);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Power-up sequence state machine
|
||||
*
|
||||
* Executes hardware initialization in 9 steps (case 0-8)
|
||||
*
|
||||
* Executes hardware initialization steps
|
||||
* Called by app_timer at POWER_LOOP_INTERVAL (20ms)
|
||||
*
|
||||
*
|
||||
* Sequence:
|
||||
* 0: LED off, IR power on
|
||||
* 0: I2C init
|
||||
* 1: (reserved)
|
||||
* 2: I2C init
|
||||
* 3: (reserved)
|
||||
* 4: DAC wake-up
|
||||
* 5: LED-PD modulation set
|
||||
* 6: ADA2200 lock-in amp start
|
||||
* 7: PD channel select
|
||||
* 8: Complete
|
||||
* 2: Complete
|
||||
*/
|
||||
void power_loop(void *p_context)
|
||||
{
|
||||
UNUSED_PARAMETER(p_context);
|
||||
|
||||
|
||||
power_timer_stop();
|
||||
|
||||
|
||||
#if DEBUG_MINIMAL_BOOT
|
||||
/* Minimal Boot: Skip sensor initialization */
|
||||
DBG_PRINTF("[PWR] Minimal mode - skipping sensor init\r\n");
|
||||
p_order = 8; // Jump to complete
|
||||
p_order = 2; // Jump to complete
|
||||
#else
|
||||
/* Full Boot: Execute power sequence */
|
||||
switch (p_order) {
|
||||
/* Step 0: Power On */
|
||||
/* Step 0: I2C Initialize */
|
||||
case 0:
|
||||
LED_ALLOFF();
|
||||
ir_power_control(ON);
|
||||
nrf_delay_ms(20);
|
||||
DBG_PRINTF("[PWR] Step %d: IR Power ON\r\n", p_order);
|
||||
break;
|
||||
|
||||
/* Step 1: Reserved */
|
||||
case 1:
|
||||
DBG_PRINTF("[PWR] Step %d: (reserved)\r\n", p_order);
|
||||
break;
|
||||
|
||||
/* Step 2: I2C Initialize */
|
||||
case 2:
|
||||
sw_i2c_init_once();
|
||||
nrf_delay_ms(10);
|
||||
DBG_PRINTF("[PWR] Step %d: I2C Init\r\n", p_order);
|
||||
break;
|
||||
|
||||
/* Step 3: Reserved */
|
||||
case 3:
|
||||
|
||||
/* Step 1: Reserved */
|
||||
case 1:
|
||||
DBG_PRINTF("[PWR] Step %d: (reserved)\r\n", p_order);
|
||||
break;
|
||||
|
||||
/* Step 4: DAC Wake-up */
|
||||
case 4:
|
||||
nrf_delay_ms(10);
|
||||
mcp4725_powerOnWakeUp();
|
||||
nrf_delay_ms(20);
|
||||
DBG_PRINTF("[PWR] Step %d: MCP4725 Wake-up\r\n", p_order);
|
||||
break;
|
||||
|
||||
/* Step 5: LED-PD Modulation Set */
|
||||
case 5:
|
||||
led_pd_mod_set(1000);
|
||||
nrf_delay_ms(10);
|
||||
led_pd_mod_set(1000);
|
||||
nrf_delay_ms(10);
|
||||
DBG_PRINTF("[PWR] Step %d: LED-PD Mod Set (1000)\r\n", p_order);
|
||||
break;
|
||||
|
||||
/* Step 6: ADA2200 Lock-in Amplifier Start */
|
||||
case 6:
|
||||
ada2200_start();
|
||||
nrf_delay_ms(100);
|
||||
DBG_PRINTF("[PWR] Step %d: ADA2200 Start\r\n", p_order);
|
||||
break;
|
||||
|
||||
/* Step 7: PD Channel Select */
|
||||
case 7:
|
||||
if (NRF_SUCCESS == pd_on(2)) {
|
||||
DBG_PRINTF("[PWR] Step %d: PD Channel ON\r\n", p_order);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Step 8: Complete */
|
||||
case 8:
|
||||
|
||||
/* Step 2: Complete */
|
||||
case 2:
|
||||
DBG_PRINTF("[PWR] Step %d: Sequence Complete\r\n", p_order);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Advance to next step or finish */
|
||||
if (p_order < 8) {
|
||||
if (p_order < 2) {
|
||||
p_order++;
|
||||
power_timer_start();
|
||||
} else {
|
||||
@@ -258,21 +120,9 @@ void power_loop(void *p_context)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int device_reactivated(void){
|
||||
|
||||
int rc = 0;
|
||||
sw_i2c_init_once();
|
||||
mcp4725_PowerDownMode();
|
||||
DBG_PRINTF("LOCKIN!!\r\n");
|
||||
nrf_delay_ms(10);
|
||||
ada2200_stop();
|
||||
|
||||
|
||||
nrf_delay_ms(10);
|
||||
|
||||
ir_power_control(OFF);
|
||||
sw_i2c_init_once();
|
||||
nrf_delay_ms(10);
|
||||
lock_check = true;
|
||||
p_order = 0;
|
||||
@@ -293,13 +143,12 @@ void power_timer_stop(void)
|
||||
}
|
||||
|
||||
|
||||
void power_timer_init(void) //active start
|
||||
void power_timer_init(void) //active start
|
||||
{
|
||||
APP_ERROR_CHECK(app_timer_create(&m_power_timer_id, APP_TIMER_MODE_SINGLE_SHOT, power_loop));
|
||||
|
||||
|
||||
// 2025-12-08 change to APP_TIMER_MODE_REPEATED mode
|
||||
//APP_ERROR_CHECK(app_timer_create(&m_power_timer_id, APP_TIMER_MODE_REPEATED, power_loop));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
#include "main.h"
|
||||
|
||||
void power_gpio_init(void);
|
||||
void ir_power_control(on_off_cont_t ir_power_st);
|
||||
void rcv_power_control(on_off_cont_t rcv_power_st);
|
||||
void eeprom_control(on_off_cont_t rcv_power_st);
|
||||
void eeprom_control(on_off_cont_t eeprom_st);
|
||||
int device_sleep_mode(void);
|
||||
int device_activated(void);
|
||||
int device_reactivated(void);
|
||||
|
||||
Binary file not shown.
@@ -145,19 +145,12 @@ void TIMER2_IRQHandler(void)
|
||||
|
||||
void dr_piezo_power_on(void)
|
||||
{
|
||||
/* 1. IR power ON (from power_control.c) */
|
||||
ir_power_control(ON);
|
||||
nrf_delay_ms(20);
|
||||
|
||||
/* 2. Configure power control pins */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PWR_SHDN);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PWR_EN_10V);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PWR_EN);
|
||||
nrf_gpio_pin_set(DR_PIEZO_PWR_EN);
|
||||
|
||||
/* 3. Enable DC/DC converter (+/-20V) */
|
||||
nrf_gpio_pin_set(DR_PIEZO_PWR_SHDN);
|
||||
nrf_gpio_pin_set(DR_PIEZO_PWR_EN_10V);
|
||||
|
||||
/* 4. Wait for power stabilization */
|
||||
/* Wait for power stabilization */
|
||||
nrf_delay_ms(10);
|
||||
|
||||
m_power_enabled = true;
|
||||
@@ -169,8 +162,7 @@ void dr_piezo_power_off(void)
|
||||
{
|
||||
dr_piezo_disable();
|
||||
|
||||
nrf_gpio_pin_clear(DR_PIEZO_PWR_SHDN);
|
||||
nrf_gpio_pin_clear(DR_PIEZO_PWR_EN_10V);
|
||||
nrf_gpio_pin_clear(DR_PIEZO_PWR_EN);
|
||||
|
||||
m_power_enabled = false;
|
||||
|
||||
@@ -470,16 +462,108 @@ void dr_piezo_set_frequency(uint32_t freq_hz)
|
||||
void dr_piezo_mux_init(void)
|
||||
{
|
||||
/* Configure MUX control pins as outputs */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_MUX_SEL1);
|
||||
/*nrf_gpio_cfg_output(DR_PIEZO_MUX_SEL1);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_MUX_SEL2);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_MUX_SEL3);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_MUX_SEL3);*/
|
||||
|
||||
/*nrf_gpio_cfg_output(DR_PIEZO_EN_MUXA);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_EN_MUXB);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_MUX_SEL0);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_MUX_SEL1);*/
|
||||
|
||||
/* Configure pins as output with high drive strength */
|
||||
nrf_gpio_cfg(
|
||||
DR_PIEZO_MUX_SEL0,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_H0H1, /* High drive */
|
||||
NRF_GPIO_PIN_NOSENSE
|
||||
);
|
||||
nrf_gpio_cfg(
|
||||
DR_PIEZO_MUX_SEL1,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_H0H1, /* High drive */
|
||||
NRF_GPIO_PIN_NOSENSE
|
||||
);
|
||||
|
||||
/* GPIO PIN Setting jhChun 0129 */
|
||||
nrf_gpio_cfg(
|
||||
DR_PIEZO_EN_MUXA, // PIN
|
||||
NRF_GPIO_PIN_DIR_OUTPUT, // DIR : OUTPUT
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT, // INPUT BUFFER X (DIR : OUTPUT)
|
||||
NRF_GPIO_PIN_NOPULL, // PULL UP, PULL DOWN X
|
||||
NRF_GPIO_PIN_H0H1, // HIGH DRIVE(STRONG OUTPUT) !!
|
||||
NRF_GPIO_PIN_NOSENSE // INTERRUPT X
|
||||
);
|
||||
|
||||
nrf_gpio_cfg(
|
||||
DR_PIEZO_EN_MUXB,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_H0H1,
|
||||
NRF_GPIO_PIN_NOSENSE
|
||||
);
|
||||
|
||||
/* Set MUX selection: P1.13=HIGH, P1.12=LOW, P1.11=LOW */
|
||||
nrf_gpio_pin_set(DR_PIEZO_MUX_SEL1); /* P1.13 = HIGH */
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL2); /* P1.12 = LOW */
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL3); /* P1.11 = LOW */
|
||||
//nrf_gpio_pin_set(DR_PIEZO_MUX_SEL1); /* P1.13 = HIGH */
|
||||
//nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL2); /* P1.12 = LOW */
|
||||
//nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL3); /* P1.11 = LOW */
|
||||
|
||||
DBG_PRINTF("[DR_PIEZO] MUX init: SEL1=HIGH, SEL2=LOW, SEL3=LOW\r\n");
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXA); /* P0.21 = LOW, Select Channel -> HIGH */
|
||||
nrf_gpio_pin_clear(DR_PIEZO_EN_MUXB); /* P0.23 = LOW, Select Channel -> HIGH */
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL0); /* P1.10 = LOW */
|
||||
nrf_gpio_pin_clear(DR_PIEZO_MUX_SEL1); /* P0.28 = LOW */
|
||||
|
||||
DBG_PRINTF("[DR_PIEZO] MUX init done\r\n");
|
||||
}
|
||||
|
||||
|
||||
void dr_piezo_select_channel(uint8_t channel)
|
||||
{
|
||||
channel = channel & 0x07; /* Mask to 0-7 */
|
||||
|
||||
switch (channel) {
|
||||
// EN_A EN_B SEL0 SEL1
|
||||
case 0: // A0: 1 0 0 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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
/* Delay for MUX settling (analog path stabilization) */
|
||||
nrf_delay_us(DR_PIEZO_MUX_SETTLING_US);
|
||||
}
|
||||
|
||||
void dr_piezo_test_pins(void)
|
||||
@@ -599,32 +683,33 @@ void dr_piezo_transmit(uint8_t cycles)
|
||||
* but it will also shorten their lifespan
|
||||
* - Charles KWON
|
||||
*/
|
||||
|
||||
#define P_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_P_OUT)) /* P1.03 */ // Save your li
|
||||
#define N_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_N_OUT)) /* P1.02 */
|
||||
#define PE_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_PE)) /* P1.05 */
|
||||
#define DMP_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_DMP)) /* P1.09 */
|
||||
|
||||
/* Piezo channel select pins - MUST BE PRESERVED during burst */
|
||||
#define CH_SEL0_MASK (1UL << 11) /* P1.11 - Channel select LSB */
|
||||
#define CH_SEL1_MASK (1UL << 12) /* P1.12 - Channel select MSB */
|
||||
#define CH_SEL_MASK (CH_SEL0_MASK | CH_SEL1_MASK)
|
||||
#define P_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_P_OUT)) /* P1.03 -> P1.07 */
|
||||
#define N_OUT_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_N_OUT)) /* P1.02 -> P1.06 */
|
||||
#define PE_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_PE)) /* P1.05 -> P0.25 */
|
||||
#define DMP_MASK (1UL << PIN_NUM(DR_PIEZO_PIN_DMP)) /* P1.09 -> P1.00 */
|
||||
|
||||
/* Combined mask for all piezo control signals (excluding channel select) */
|
||||
#define PIEZO_CTRL_MASK (P_OUT_MASK | N_OUT_MASK | PE_MASK | DMP_MASK)
|
||||
#define P1_CTRL_MASK (P_OUT_MASK | N_OUT_MASK | DMP_MASK)
|
||||
|
||||
void dr_piezo_burst_sw(uint8_t cycles)
|
||||
{
|
||||
/* Clamp cycles to valid range (1-20) */
|
||||
if (cycles < 1) cycles = 1;
|
||||
if (cycles > 20) cycles = 20;
|
||||
|
||||
|
||||
/* RTT: snapshot then single print */
|
||||
uint32_t _d0 = NRF_P1->OUT;
|
||||
|
||||
/* Disable GPIOTE hardware control to prevent conflicts */
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_P_OUT);
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_N_OUT);
|
||||
|
||||
|
||||
uint32_t _d1 = NRF_P1->OUT;
|
||||
|
||||
/* Save ENTIRE P1 port state BEFORE any GPIO config */
|
||||
uint32_t saved_p1_out = NRF_P1->OUT;
|
||||
uint32_t saved_p0_out = NRF_P0->OUT;
|
||||
|
||||
/* Configure all signal pins as outputs */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_PE);
|
||||
@@ -632,30 +717,26 @@ void dr_piezo_burst_sw(uint8_t cycles)
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_P_OUT);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_N_OUT);
|
||||
|
||||
uint32_t _d2 = NRF_P1->OUT;
|
||||
|
||||
DBG_PRINTF("[B]S0:%u%u%u\r\n", (_d0>>10)&1, (_d1>>10)&1, (_d2>>10)&1);
|
||||
|
||||
/* Restore P1 port state (nrf_gpio_cfg_output may clear bits) */
|
||||
NRF_P1->OUT = saved_p1_out;
|
||||
|
||||
NRF_P0->OUT = (NRF_P0->OUT & ~PE_MASK) | (saved_p0_out & PE_MASK);
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Pre-calculate all output states for fast switching
|
||||
* Each state represents a specific combination of pin levels
|
||||
* IMPORTANT: Channel select pins (P1.11, P1.12) are preserved in all states
|
||||
*------------------------------------------------------------------------*/
|
||||
uint32_t ch_sel_state = saved_p1_out & CH_SEL_MASK;
|
||||
|
||||
/* State 1: All control signals LOW (idle state) - preserve CH_SEL and other pins */
|
||||
uint32_t state_all_low = (saved_p1_out & ~PIEZO_CTRL_MASK);
|
||||
// PE는 OUTSET/OUTCLR 사용 (다른 P0 핀 영향 방지)
|
||||
|
||||
/* State 2: Only PE HIGH (margin periods before pulses and after DMP) */
|
||||
uint32_t state_PE_only = (state_all_low | PE_MASK);
|
||||
|
||||
/* State 3: PE=HIGH, P_OUT=HIGH, N_OUT=LOW (first half of each cycle) */
|
||||
uint32_t state_PE_P_high_N_low = (state_all_low | PE_MASK | P_OUT_MASK);
|
||||
|
||||
/* State 4: PE=HIGH, P_OUT=LOW, N_OUT=HIGH (second half of each cycle) */
|
||||
uint32_t state_PE_P_low_N_high = (state_all_low | PE_MASK | N_OUT_MASK);
|
||||
|
||||
/* State 5: PE=HIGH, DMP=HIGH, P_OUT=LOW, N_OUT=LOW (dump period) */
|
||||
uint32_t state_PE_DMP_high = (state_all_low | PE_MASK | DMP_MASK);
|
||||
uint32_t p1_all_low = saved_p1_out & ~P1_CTRL_MASK;
|
||||
uint32_t p1_P_high_N_low = p1_all_low | P_OUT_MASK;
|
||||
uint32_t p1_P_low_N_high = p1_all_low | N_OUT_MASK;
|
||||
uint32_t p1_DMP_high = p1_all_low | DMP_MASK;
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Critical timing section - interrupts disabled
|
||||
@@ -663,34 +744,36 @@ void dr_piezo_burst_sw(uint8_t cycles)
|
||||
__disable_irq();
|
||||
|
||||
/* Initialize: Set all signals to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
|
||||
NRF_P0->OUTCLR = PE_MASK; // PE OFF (OUTCLR로 다른 핀 영향 없음)
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
|
||||
/* PE rises first with margin before pulses start */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P0->OUTSET = PE_MASK; // PE ON (OUTSET로 다른 핀 영향 없음)
|
||||
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
|
||||
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
|
||||
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
|
||||
|
||||
|
||||
@@ -706,15 +789,17 @@ void dr_piezo_burst_sw(uint8_t cycles)
|
||||
for (uint8_t i = 0; i < cycles; i++)
|
||||
{
|
||||
/* First half-period: P_OUT=HIGH, N_OUT=LOW */
|
||||
NRF_P1->OUT = state_PE_P_high_N_low;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
NRF_P1->OUT = p1_P_high_N_low;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();__NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
|
||||
/* Second half-period: P_OUT=LOW, N_OUT=HIGH */
|
||||
NRF_P1->OUT = state_PE_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
NRF_P1->OUT = p1_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
@@ -722,7 +807,8 @@ void dr_piezo_burst_sw(uint8_t cycles)
|
||||
* - Starts simultaneously with N_OUT falling edge
|
||||
* - Duration: ~500ns (32 NOPs)
|
||||
*------------------------------------------------------------------------*/
|
||||
NRF_P1->OUT = state_PE_DMP_high;
|
||||
|
||||
NRF_P1->OUT = p1_DMP_high;
|
||||
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
@@ -734,12 +820,11 @@ void dr_piezo_burst_sw(uint8_t cycles)
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
/* DMP falls, PE remains HIGH for margin period */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
__NOP(); __NOP(); __NOP(); /* ~47ns margin */
|
||||
|
||||
/* End of sequence: All signals return to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
|
||||
|
||||
NRF_P0->OUTCLR = PE_MASK; // PE OFF
|
||||
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
@@ -763,8 +848,9 @@ void dr_piezo_burst_sw_18mhz(uint8_t cycles)
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_P_OUT);
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_N_OUT);
|
||||
|
||||
/* Save ENTIRE P1 port state BEFORE any GPIO config */
|
||||
/* Save port states BEFORE any GPIO config */
|
||||
uint32_t saved_p1_out = NRF_P1->OUT;
|
||||
uint32_t saved_p0_out = NRF_P0->OUT;
|
||||
|
||||
/* Configure all signal pins as outputs */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_PE);
|
||||
@@ -772,24 +858,26 @@ void dr_piezo_burst_sw_18mhz(uint8_t cycles)
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_P_OUT);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_N_OUT);
|
||||
|
||||
/* Restore P1 port state (nrf_gpio_cfg_output may clear bits) */
|
||||
/* Restore port states (nrf_gpio_cfg_output may clear bits) */
|
||||
NRF_P1->OUT = saved_p1_out;
|
||||
NRF_P0->OUT = (NRF_P0->OUT & ~PE_MASK) | (saved_p0_out & PE_MASK);
|
||||
|
||||
/* Pre-calculate all output states for fast switching
|
||||
* IMPORTANT: Channel select pins (P1.11, P1.12) are preserved in all states */
|
||||
uint32_t state_all_low = (saved_p1_out & ~PIEZO_CTRL_MASK);
|
||||
uint32_t state_PE_only = (state_all_low | PE_MASK);
|
||||
uint32_t state_PE_P_high_N_low = (state_all_low | PE_MASK | P_OUT_MASK);
|
||||
uint32_t state_PE_P_low_N_high = (state_all_low | PE_MASK | N_OUT_MASK);
|
||||
uint32_t state_PE_DMP_high = (state_all_low | PE_MASK | DMP_MASK);
|
||||
//NRF_P0->OUT = saved_p0_out;
|
||||
|
||||
/* Pre-calculate P1 output states (PE는 P0.25 - OUTSET/OUTCLR로 제어) */
|
||||
uint32_t p1_all_low = saved_p1_out & ~P1_CTRL_MASK;
|
||||
uint32_t p1_P_high_N_low = p1_all_low | P_OUT_MASK;
|
||||
uint32_t p1_P_low_N_high = p1_all_low | N_OUT_MASK;
|
||||
uint32_t p1_DMP_high = p1_all_low | DMP_MASK;
|
||||
|
||||
__disable_irq();
|
||||
|
||||
/* Initialize: Set all signals to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
|
||||
/* PE rises first with margin before pulses start */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P0->OUTSET = PE_MASK;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
@@ -826,20 +914,21 @@ void dr_piezo_burst_sw_18mhz(uint8_t cycles)
|
||||
for (uint8_t i = 0; i < cycles; i++)
|
||||
{
|
||||
/* First half-period: P_OUT=HIGH, N_OUT=LOW */
|
||||
NRF_P1->OUT = state_PE_P_high_N_low;
|
||||
NRF_P1->OUT = p1_P_high_N_low;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
/* Second half-period: P_OUT=LOW, N_OUT=HIGH */
|
||||
NRF_P1->OUT = state_PE_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP();
|
||||
|
||||
/* Second half-period: P_OUT=LOW, N_OUT=HIGH */
|
||||
NRF_P1->OUT = p1_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP();
|
||||
}
|
||||
|
||||
/* DMP (Dump) pulse */
|
||||
NRF_P1->OUT = state_PE_DMP_high;
|
||||
NRF_P1->OUT = p1_DMP_high;
|
||||
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
@@ -851,11 +940,11 @@ void dr_piezo_burst_sw_18mhz(uint8_t cycles)
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
/* DMP falls, PE remains HIGH for margin period */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
/* End of sequence: All signals return to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
/* End of sequence: PE OFF */
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
|
||||
__enable_irq();
|
||||
}
|
||||
@@ -881,8 +970,9 @@ void dr_piezo_burst_sw_20mhz(uint8_t cycles)
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_P_OUT);
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_N_OUT);
|
||||
|
||||
/* Save ENTIRE P1 port state BEFORE any GPIO config */
|
||||
/* Save port states BEFORE any GPIO config */
|
||||
uint32_t saved_p1_out = NRF_P1->OUT;
|
||||
uint32_t saved_p0_out = NRF_P0->OUT;
|
||||
|
||||
/* Configure all signal pins as outputs */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_PE);
|
||||
@@ -890,24 +980,25 @@ void dr_piezo_burst_sw_20mhz(uint8_t cycles)
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_P_OUT);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_N_OUT);
|
||||
|
||||
/* Restore P1 port state (nrf_gpio_cfg_output may clear bits) */
|
||||
/* Restore port states (nrf_gpio_cfg_output may clear bits) */
|
||||
NRF_P1->OUT = saved_p1_out;
|
||||
//NRF_P0->OUT = saved_p0_out;
|
||||
NRF_P0->OUT = (NRF_P0->OUT & ~PE_MASK) | (saved_p0_out & PE_MASK);
|
||||
|
||||
/* Pre-calculate all output states for fast switching
|
||||
* IMPORTANT: Channel select pins (P1.11, P1.12) are preserved in all states */
|
||||
uint32_t state_all_low = (saved_p1_out & ~PIEZO_CTRL_MASK);
|
||||
uint32_t state_PE_only = (state_all_low | PE_MASK);
|
||||
uint32_t state_PE_P_high_N_low = (state_all_low | PE_MASK | P_OUT_MASK);
|
||||
uint32_t state_PE_P_low_N_high = (state_all_low | PE_MASK | N_OUT_MASK);
|
||||
uint32_t state_PE_DMP_high = (state_all_low | PE_MASK | DMP_MASK);
|
||||
/* Pre-calculate P1 output states (PE는 P0.25 - OUTSET/OUTCLR로 제어) */
|
||||
uint32_t p1_all_low = saved_p1_out & ~P1_CTRL_MASK;
|
||||
uint32_t p1_P_high_N_low = p1_all_low | P_OUT_MASK;
|
||||
uint32_t p1_P_low_N_high = p1_all_low | N_OUT_MASK;
|
||||
uint32_t p1_DMP_high = p1_all_low | DMP_MASK;
|
||||
|
||||
__disable_irq();
|
||||
|
||||
/* Initialize: Set all signals to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
|
||||
/* PE rises first with margin before pulses start */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P0->OUTSET = PE_MASK;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
@@ -944,20 +1035,21 @@ void dr_piezo_burst_sw_20mhz(uint8_t cycles)
|
||||
for (uint8_t i = 0; i < cycles; i++)
|
||||
{
|
||||
/* First half-period: P_OUT=HIGH, N_OUT=LOW */
|
||||
NRF_P1->OUT = state_PE_P_high_N_low;
|
||||
NRF_P1->OUT = p1_P_high_N_low;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP();
|
||||
|
||||
/* Second half-period: P_OUT=LOW, N_OUT=HIGH */
|
||||
NRF_P1->OUT = state_PE_P_low_N_high;
|
||||
NRF_P1->OUT = p1_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP();
|
||||
|
||||
}
|
||||
|
||||
/* DMP (Dump) pulse */
|
||||
NRF_P1->OUT = state_PE_DMP_high;
|
||||
NRF_P1->OUT = p1_DMP_high;
|
||||
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
@@ -969,11 +1061,257 @@ void dr_piezo_burst_sw_20mhz(uint8_t cycles)
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
/* DMP falls, PE remains HIGH for margin period */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
/* End of sequence: All signals return to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
/* End of sequence: PE OFF */
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Software-based burst at 2.0 MHz
|
||||
* @param cycles Number of cycles (1~20)
|
||||
*
|
||||
* Timing:
|
||||
* 1.9 MHz: 500ns period, 250ns half-period
|
||||
* At 64MHz CPU (1 NOP = 15.625ns):
|
||||
* First half: 14 NOPs (~219ns) + register write (~30ns) = ~249ns
|
||||
* Second half: 11 NOPs (~172ns) + loop overhead (~47ns) = ~219ns
|
||||
* Total: ~468-500ns per cycle
|
||||
*/
|
||||
void dr_piezo_burst_sw_19mhz(uint8_t cycles)
|
||||
{
|
||||
/* Clamp cycles to valid range (1-20) */
|
||||
if (cycles < 1) cycles = 1;
|
||||
if (cycles > 20) cycles = 20;
|
||||
|
||||
/* Disable GPIOTE hardware control to prevent conflicts */
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_P_OUT);
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_N_OUT);
|
||||
|
||||
/* Save port states BEFORE any GPIO config */
|
||||
uint32_t saved_p1_out = NRF_P1->OUT;
|
||||
uint32_t saved_p0_out = NRF_P0->OUT;
|
||||
|
||||
/* Configure all signal pins as outputs */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_PE);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_DMP);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_P_OUT);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_N_OUT);
|
||||
|
||||
/* Restore port states (nrf_gpio_cfg_output may clear bits) */
|
||||
NRF_P1->OUT = saved_p1_out;
|
||||
//NRF_P0->OUT = saved_p0_out;
|
||||
NRF_P0->OUT = (NRF_P0->OUT & ~PE_MASK) | (saved_p0_out & PE_MASK);
|
||||
|
||||
/* Pre-calculate P1 output states (PE는 P0.25 - OUTSET/OUTCLR로 제어) */
|
||||
uint32_t p1_all_low = saved_p1_out & ~P1_CTRL_MASK;
|
||||
uint32_t p1_P_high_N_low = p1_all_low | P_OUT_MASK;
|
||||
uint32_t p1_P_low_N_high = p1_all_low | N_OUT_MASK;
|
||||
uint32_t p1_DMP_high = p1_all_low | DMP_MASK;
|
||||
|
||||
__disable_irq();
|
||||
|
||||
/* Initialize: Set all signals to LOW */
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
|
||||
/* PE rises first with margin before pulses start */
|
||||
NRF_P0->OUTSET = PE_MASK;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Generate 2.0MHz pulse burst
|
||||
*
|
||||
* 2.0 MHz: 500ns period, 250ns half-period
|
||||
* At 64MHz CPU (1 NOP = 15.625ns):
|
||||
* First half: 14 NOPs (~219ns) + register write (~30ns) = ~249ns
|
||||
* Second half: 11 NOPs (~172ns) + loop overhead (~47ns) = ~219ns
|
||||
* Total: ~468-500ns per cycle
|
||||
*------------------------------------------------------------------------*/
|
||||
for (uint8_t i = 0; i < cycles; i++)
|
||||
{
|
||||
/* First half-period: P_OUT=HIGH, N_OUT=LOW */
|
||||
NRF_P1->OUT = p1_P_high_N_low;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP();
|
||||
|
||||
/* Second half-period: P_OUT=LOW, N_OUT=HIGH */
|
||||
NRF_P1->OUT = p1_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
}
|
||||
|
||||
/* DMP (Dump) pulse */
|
||||
NRF_P1->OUT = p1_DMP_high;
|
||||
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
/* DMP falls, PE remains HIGH for margin period */
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
/* End of sequence: PE OFF */
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Software-based burst at 2.2 MHz
|
||||
* @param cycles Number of cycles (1~20)
|
||||
*
|
||||
* Timing:
|
||||
* 2.2 MHz: 454ns period, 227ns half-period
|
||||
* At 64MHz CPU (1 NOP = 15.625ns):
|
||||
* First half: 13 NOPs (~203ns) + register write (~30ns) = ~233ns
|
||||
* Second half: 11 NOPs (~172ns) + loop overhead (~47ns) = ~219ns
|
||||
* Total: ~452ns per cycle (~2.21 MHz)
|
||||
*/
|
||||
void dr_piezo_burst_sw_22mhz(uint8_t cycles)
|
||||
{
|
||||
/* Clamp cycles to valid range (1-20) */
|
||||
if (cycles < 1) cycles = 1;
|
||||
if (cycles > 20) cycles = 20;
|
||||
|
||||
/* Disable GPIOTE hardware control to prevent conflicts */
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_P_OUT);
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_N_OUT);
|
||||
|
||||
/* Save port states BEFORE any GPIO config */
|
||||
uint32_t saved_p1_out = NRF_P1->OUT;
|
||||
uint32_t saved_p0_out = NRF_P0->OUT;
|
||||
|
||||
/* Configure all signal pins as outputs */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_PE);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_DMP);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_P_OUT);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_N_OUT);
|
||||
|
||||
/* Restore port states (nrf_gpio_cfg_output may clear bits) */
|
||||
NRF_P1->OUT = saved_p1_out;
|
||||
NRF_P0->OUT = (NRF_P0->OUT & ~PE_MASK) | (saved_p0_out & PE_MASK);
|
||||
|
||||
/* Pre-calculate P1 output states */
|
||||
uint32_t p1_all_low = saved_p1_out & ~P1_CTRL_MASK;
|
||||
uint32_t p1_P_high_N_low = p1_all_low | P_OUT_MASK;
|
||||
uint32_t p1_P_low_N_high = p1_all_low | N_OUT_MASK;
|
||||
uint32_t p1_DMP_high = p1_all_low | DMP_MASK;
|
||||
|
||||
__disable_irq();
|
||||
|
||||
/* Initialize: Set all signals to LOW */
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
|
||||
/* PE rises first with margin before pulses start */
|
||||
NRF_P0->OUTSET = PE_MASK;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Generate 2.2MHz pulse burst
|
||||
*
|
||||
* 2.2 MHz: 454ns period, 227ns half-period
|
||||
* At 64MHz CPU (1 NOP = 15.625ns):
|
||||
* First half: 11 NOPs - positive pulse width
|
||||
* Second half: 10 NOPs - negative pulse width
|
||||
* Total: 21 NOPs per cycle (~2.2 MHz)
|
||||
*------------------------------------------------------------------------*/
|
||||
for (uint8_t i = 0; i < cycles; i++)
|
||||
{
|
||||
/* First half-period: P_OUT=HIGH, N_OUT=LOW (positive pulse width) */
|
||||
NRF_P1->OUT = p1_P_high_N_low;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP();
|
||||
__NOP();
|
||||
|
||||
/* Second half-period: P_OUT=LOW, N_OUT=HIGH (negative pulse width) */
|
||||
NRF_P1->OUT = p1_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
}
|
||||
|
||||
/* DMP (Dump) pulse */
|
||||
NRF_P1->OUT = p1_DMP_high;
|
||||
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
/* DMP falls, PE remains HIGH for margin period */
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
/* End of sequence: PE OFF */
|
||||
NRF_P0->OUTCLR = PE_MASK;
|
||||
|
||||
__enable_irq();
|
||||
}
|
||||
@@ -999,8 +1337,9 @@ void dr_piezo_burst_sw_17mhz(uint8_t cycles)
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_P_OUT);
|
||||
nrf_gpiote_task_disable(GPIOTE_CH_N_OUT);
|
||||
|
||||
/* Save ENTIRE P1 port state BEFORE any GPIO config */
|
||||
/* Save port states BEFORE any GPIO config */
|
||||
uint32_t saved_p1_out = NRF_P1->OUT;
|
||||
uint32_t saved_p0_out = NRF_P0->OUT;
|
||||
|
||||
/* Configure all signal pins as outputs */
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_PE);
|
||||
@@ -1008,24 +1347,24 @@ void dr_piezo_burst_sw_17mhz(uint8_t cycles)
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_P_OUT);
|
||||
nrf_gpio_cfg_output(DR_PIEZO_PIN_N_OUT);
|
||||
|
||||
/* Restore P1 port state (nrf_gpio_cfg_output may clear bits) */
|
||||
/* Restore port states (nrf_gpio_cfg_output may clear bits) */
|
||||
NRF_P1->OUT = saved_p1_out;
|
||||
NRF_P0->OUT = (NRF_P0->OUT & ~PE_MASK) | (saved_p0_out & PE_MASK);
|
||||
|
||||
/* Pre-calculate all output states for fast switching
|
||||
* IMPORTANT: Channel select pins (P1.11, P1.12) are preserved in all states */
|
||||
uint32_t state_all_low = (saved_p1_out & ~PIEZO_CTRL_MASK);
|
||||
uint32_t state_PE_only = (state_all_low | PE_MASK);
|
||||
uint32_t state_PE_P_high_N_low = (state_all_low | PE_MASK | P_OUT_MASK);
|
||||
uint32_t state_PE_P_low_N_high = (state_all_low | PE_MASK | N_OUT_MASK);
|
||||
uint32_t state_PE_DMP_high = (state_all_low | PE_MASK | DMP_MASK);
|
||||
/* Pre-calculate P1 output states (PE는 P0에서 OUTSET/OUTCLR로 제어) */
|
||||
uint32_t p1_all_low = saved_p1_out & ~P1_CTRL_MASK;
|
||||
uint32_t p1_P_high_N_low = p1_all_low | P_OUT_MASK;
|
||||
uint32_t p1_P_low_N_high = p1_all_low | N_OUT_MASK;
|
||||
uint32_t p1_DMP_high = p1_all_low | DMP_MASK;
|
||||
|
||||
__disable_irq();
|
||||
|
||||
/* Initialize: Set all signals to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
NRF_P0->OUTCLR = PE_MASK; // PE OFF
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
|
||||
/* PE rises first with margin before pulses start */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P0->OUTSET = PE_MASK; // PE ON
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP();
|
||||
@@ -1062,21 +1401,23 @@ void dr_piezo_burst_sw_17mhz(uint8_t cycles)
|
||||
for (uint8_t i = 0; i < cycles; i++)
|
||||
{
|
||||
/* First half-period: P_OUT=HIGH, N_OUT=LOW */
|
||||
NRF_P1->OUT = state_PE_P_high_N_low;
|
||||
NRF_P1->OUT = p1_P_high_N_low;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP();
|
||||
__NOP();
|
||||
|
||||
|
||||
/* Second half-period: P_OUT=LOW, N_OUT=HIGH */
|
||||
NRF_P1->OUT = state_PE_P_low_N_high;
|
||||
NRF_P1->OUT = p1_P_low_N_high;
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
//__NOP(); __NOP(); __NOP(); __NOP();
|
||||
}
|
||||
|
||||
/* DMP (Dump) pulse */
|
||||
NRF_P1->OUT = state_PE_DMP_high;
|
||||
NRF_P1->OUT = p1_DMP_high;
|
||||
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
@@ -1088,11 +1429,11 @@ void dr_piezo_burst_sw_17mhz(uint8_t cycles)
|
||||
__NOP(); __NOP(); __NOP(); __NOP();
|
||||
|
||||
/* DMP falls, PE remains HIGH for margin period */
|
||||
NRF_P1->OUT = state_PE_only;
|
||||
NRF_P1->OUT = p1_all_low;
|
||||
__NOP(); __NOP(); __NOP();
|
||||
|
||||
/* End of sequence: All signals return to LOW */
|
||||
NRF_P1->OUT = state_all_low;
|
||||
/* End of sequence: PE OFF */
|
||||
NRF_P0->OUTCLR = PE_MASK; // PE OFF
|
||||
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
@@ -27,23 +27,36 @@
|
||||
/*==============================================================================
|
||||
* POWER CONTROL PINS (DC/DC Converter +/-20V)
|
||||
*============================================================================*/
|
||||
#define DR_PIEZO_PWR_SHDN NRF_GPIO_PIN_MAP(0, 21) /**< SHDN_VPP/VNN (LT3463) */
|
||||
#define DR_PIEZO_PWR_EN_10V NRF_GPIO_PIN_MAP(0, 22) /**< EN_+10V (MCP1804) */
|
||||
//#define DR_PIEZO_PWR_SHDN NRF_GPIO_PIN_MAP(0, 21) /**< SHDN_VPP/VNN (LT3463) */ // P0.21 : PZT_EN_MUXA jhChun 0128
|
||||
//#define DR_PIEZO_PWR_EN_10V NRF_GPIO_PIN_MAP(0, 22) /**< EN_+10V (MCP1804) */ // P0.22 : NIRS PIN
|
||||
|
||||
#define DR_PIEZO_PWR_EN NRF_GPIO_PIN_MAP(1, 9) /** Power Enable jhChun 0128 */
|
||||
|
||||
/*==============================================================================
|
||||
* TX SIGNAL PINS (MOSFET Driver Control)
|
||||
*============================================================================*/
|
||||
#define DR_PIEZO_PIN_PE NRF_GPIO_PIN_MAP(1, 5) /**< Pulse Enable */
|
||||
#define DR_PIEZO_PIN_DMP NRF_GPIO_PIN_MAP(1, 9) /**< Dump control */
|
||||
#define DR_PIEZO_PIN_P_OUT NRF_GPIO_PIN_MAP(1, 3) /**< Positive output */
|
||||
#define DR_PIEZO_PIN_N_OUT NRF_GPIO_PIN_MAP(1, 2) /**< Negative output */
|
||||
//#define DR_PIEZO_PIN_PE NRF_GPIO_PIN_MAP(1, 5) /**< Pulse Enable */
|
||||
//#define DR_PIEZO_PIN_DMP NRF_GPIO_PIN_MAP(1, 9) /**< Dump control */
|
||||
//#define DR_PIEZO_PIN_P_OUT NRF_GPIO_PIN_MAP(1, 3) /**< Positive output */
|
||||
//#define DR_PIEZO_PIN_N_OUT NRF_GPIO_PIN_MAP(1, 2) /**< Negative output */
|
||||
|
||||
#define DR_PIEZO_PIN_PE NRF_GPIO_PIN_MAP(0, 25) /**< Pulse Enable */ // P1.05 -> P0.25
|
||||
#define DR_PIEZO_PIN_DMP NRF_GPIO_PIN_MAP(1, 0) /**< Dump control */ // P1.9 -> P1.0
|
||||
#define DR_PIEZO_PIN_P_OUT NRF_GPIO_PIN_MAP(1, 7) /**< Positive output */ // P1.3 -> P1.7
|
||||
#define DR_PIEZO_PIN_N_OUT NRF_GPIO_PIN_MAP(1, 6) /**< Negative output */ // P1.2 -> P1.6 jhChun 0128
|
||||
|
||||
/*==============================================================================
|
||||
* MUX CONTROL PINS (Echo Signal Path Selection)
|
||||
*============================================================================*/
|
||||
#define DR_PIEZO_MUX_SEL1 NRF_GPIO_PIN_MAP(1, 13) /**< MUX Select 1 (HIGH) */
|
||||
#define DR_PIEZO_MUX_SEL2 NRF_GPIO_PIN_MAP(1, 12) /**< MUX Select 2 (LOW) */
|
||||
#define DR_PIEZO_MUX_SEL3 NRF_GPIO_PIN_MAP(1, 11) /**< MUX Select 3 (LOW) */
|
||||
//#define DR_PIEZO_MUX_SEL1 NRF_GPIO_PIN_MAP(1, 13) /**< MUX Select 1 (HIGH) */
|
||||
//#define DR_PIEZO_MUX_SEL2 NRF_GPIO_PIN_MAP(1, 12) /**< MUX Select 2 (LOW) */
|
||||
//#define DR_PIEZO_MUX_SEL3 NRF_GPIO_PIN_MAP(1, 11) /**< MUX Select 3 (LOW) */
|
||||
|
||||
/* Piezo MUX pins (8ch) jhChun 0129 */
|
||||
#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_SEL0 NRF_GPIO_PIN_MAP(1, 10) /**< MUX Select 0 */
|
||||
#define DR_PIEZO_MUX_SEL1 NRF_GPIO_PIN_MAP(0, 28) /**< MUX Select 1 */
|
||||
|
||||
/*==============================================================================
|
||||
* CONFIGURATION
|
||||
@@ -57,6 +70,7 @@
|
||||
#define DR_PIEZO_DEFAULT_CYCLES 5 /**< Default burst cycles (3~5) */
|
||||
#define DR_PIEZO_MIN_CYCLES 3
|
||||
#define DR_PIEZO_MAX_CYCLES 10
|
||||
#define DR_PIEZO_MUX_SETTLING_US 1300 /**< MUX settling delay (us) */
|
||||
|
||||
/*==============================================================================
|
||||
* POWER CONTROL FUNCTIONS
|
||||
@@ -126,10 +140,21 @@ void dr_piezo_test_pins(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize MUX control pins for echo signal path
|
||||
* @note Sets P1.13=HIGH, P1.12=LOW, P1.11=LOW
|
||||
*/
|
||||
void dr_piezo_mux_init(void);
|
||||
|
||||
/**
|
||||
* @brief Select piezo channel (0~7) via 8ch MUX
|
||||
* @param channel Piezo channel number (0~7)
|
||||
*
|
||||
* Channel mapping (EN_MUXA, EN_MUXB, SEL0, SEL1):
|
||||
* CH0=A0(1,0,0,0) CH1=A2(1,0,1,0) CH2=A1(1,0,0,1) CH3=A3(1,0,1,1)
|
||||
* CH4=B0(0,1,1,1) CH5=B1(0,1,0,1) CH6=B2(0,1,1,0) CH7=B3(0,1,0,0)
|
||||
*
|
||||
* @note MUX settling time: 1.3ms delay after switching
|
||||
*/
|
||||
void dr_piezo_select_channel(uint8_t channel);
|
||||
|
||||
/*==============================================================================
|
||||
* SYSTEM FUNCTIONS (Power + TX combined)
|
||||
*============================================================================*/
|
||||
@@ -171,6 +196,13 @@ void dr_piezo_burst_sw_18mhz(uint8_t cycles);
|
||||
*/
|
||||
void dr_piezo_burst_sw_20mhz(uint8_t cycles);
|
||||
|
||||
/**
|
||||
* @brief Software-based burst at 2.2 MHz
|
||||
* @param cycles Number of cycles (1~20)
|
||||
* @note Fixed frequency: 2.2 MHz
|
||||
*/
|
||||
void dr_piezo_burst_sw_22mhz(uint8_t cycles);
|
||||
|
||||
/**
|
||||
* @brief Software-based burst at 1.7 MHz
|
||||
* @param cycles Number of cycles (1~20)
|
||||
@@ -178,5 +210,12 @@ void dr_piezo_burst_sw_20mhz(uint8_t cycles);
|
||||
*/
|
||||
void dr_piezo_burst_sw_17mhz(uint8_t cycles);
|
||||
|
||||
/**
|
||||
* @brief Software-based burst at 1.9 MHz
|
||||
* @param cycles Number of cycles (1~20)
|
||||
* @note Fixed frequency: 1.9 MHz
|
||||
*/
|
||||
void dr_piezo_burst_sw_19mhz(uint8_t cycles);
|
||||
|
||||
#endif /* DR_PIEZO_H */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user