/*==============================================================================
 * dr_piezo.h - Piezo Transducer Driver (2 MHz Signal Generator)
 *
 * Hardware: nRF52840 + MD1822K6-G MOSFET Driver + TC7920K6-G MOSFET
 * Output:   +/-20V at 2 MHz, 3..7 cycles burst
 *
 * Timing Sequence:
 *   1. PE = HIGH (enable)
 *   2. P_OUT/N_OUT = 2 MHz pulses (3..7 cycles)
 *   3. DMP = HIGH (dump residual energy)
 *   4. DMP = LOW
 *   5. PE = LOW (disable)
 *
 * Pin assignment:
 *   Power:   DR_PIEZO_PWR_EN (P1.9)  — DC/DC +/-20V enable
 *   TX:      PE (P0.25), DMP (P1.0), P_OUT (P1.7), N_OUT (P1.6)
 *   MUX:     EN_MUXA (P0.21), EN_MUXB (P0.23), SEL0 (P1.10), SEL1 (P0.28)
 *
 * MUX channel mapping (8ch):
 *   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)
 *
 * Two burst modes:
 *   1) HW burst (dr_piezo_burst): Timer2 + PPI + GPIOTE, CPU-independent
 *   2) SW burst (dr_piezo_burst_sw_XXmhz): CPU NOP-based precise timing
 *      Per-frequency functions: 1.7 / 1.8 / 1.9 / 2.0 / 2.1 / 2.2 MHz
 *============================================================================*/

#ifndef DR_PIEZO_H
#define DR_PIEZO_H

#include <stdint.h>
#include <stdbool.h>
#include "nrf_gpio.h"

/*==============================================================================
 * Power control pin (+/-20V DC/DC converter)
 *============================================================================*/
#define DR_PIEZO_PWR_EN       NRF_GPIO_PIN_MAP(1, 9)

/*==============================================================================
 * TX signal pins (MOSFET driver)
 *   PE:    Pulse Enable — activates the entire TX sequence
 *   DMP:   Dump — discharges residual piezo energy after burst
 *   P_OUT: Positive output — drives piezo positive terminal
 *   N_OUT: Negative output — drives piezo negative terminal (inverted P_OUT)
 *============================================================================*/
#define DR_PIEZO_PIN_PE         NRF_GPIO_PIN_MAP(0, 25)   /**< Pulse Enable */
#define DR_PIEZO_PIN_DMP        NRF_GPIO_PIN_MAP(1, 0)    /**< Dump control */
#define DR_PIEZO_PIN_P_OUT      NRF_GPIO_PIN_MAP(1, 7)    /**< Positive output */
#define DR_PIEZO_PIN_N_OUT      NRF_GPIO_PIN_MAP(1, 6)    /**< Negative output */

/*==============================================================================
 * MUX control pins (echo signal path selection, 8 channels)
 *   MUXA handles CH0..CH3, MUXB handles CH4..CH7.
 *   Only one MUX is enabled at a time.
 *============================================================================*/
#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
 *============================================================================*/
#define DR_PIEZO_FREQ_HZ        2100000     /**< Target frequency (set PIEZO_FREQ_MHZ in .c) */
#define DR_PIEZO_DEFAULT_CYCLES 5           /**< Default burst cycles */
#define DR_PIEZO_MIN_CYCLES     3
#define DR_PIEZO_MAX_CYCLES     7
#define DR_PIEZO_MUX_SETTLING_US 1300       /**< MUX settling delay (us) */

/*==============================================================================
 * Power control
 *============================================================================*/

void dr_piezo_power_on(void);
void dr_piezo_power_off(void);

/** @return true if power is ON */
bool dr_piezo_is_power_on(void);

/*==============================================================================
 * TX driver
 *============================================================================*/

void dr_piezo_init(void);
void dr_piezo_uninit(void);
void dr_piezo_burst(uint8_t cycles);
void dr_piezo_pulse(void);
void dr_piezo_enable(void);
void dr_piezo_disable(void);
bool dr_piezo_is_busy(void);
void dr_piezo_set_frequency(uint32_t freq_hz);
void dr_piezo_test_pins(void);
void dr_piezo_mux_init(void);

/**
 * @brief Select piezo channel and wait for MUX settling
 * @note Uses a one-shot timer for the ~1.3 ms settling interval.
 */
void dr_piezo_select_channel(uint8_t channel);

/**
 * @brief Select piezo channel and start MUX settling timer
 * @note Does not wait for settling to complete.
 */
void dr_piezo_select_channel_start(uint8_t channel);

/**
 * @brief Wait until the outstanding MUX settling interval completes
 */
void dr_piezo_wait_mux_settled(void);

/**
 * @brief Check whether the current MUX settling interval has completed
 */
bool dr_piezo_is_mux_settled(void);

/*==============================================================================
 * System functions (power + TX combined)
 *============================================================================*/

void dr_piezo_system_init(void);
void dr_piezo_system_uninit(void);
void dr_piezo_transmit(uint8_t cycles);

/*==============================================================================
 * Software burst — CPU NOP-based precise timing, no Timer/PPI
 *
 * Interrupts are disabled during burst for timing accuracy.
 * Per-frequency functions (NOP count varies):
 *============================================================================*/

void dr_piezo_burst_sw(uint8_t cycles);          /**< 2.1 MHz (default) */
void dr_piezo_burst_sw_18mhz(uint8_t cycles);   /**< 1.8 MHz */
void dr_piezo_burst_sw_20mhz(uint8_t cycles);   /**< 2.0 MHz */
void dr_piezo_burst_sw_22mhz(uint8_t cycles);   /**< 2.2 MHz */
void dr_piezo_burst_sw_17mhz(uint8_t cycles);   /**< 1.7 MHz */
void dr_piezo_burst_sw_19mhz(uint8_t cycles);   /**< 1.9 MHz */

#endif /* DR_PIEZO_H */
