#ifndef ULTRASONIC_H
#define ULTRASONIC_H

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

/*
 * ultrasonic.h — HC-SR04 ultrasonic distance sensor driver (Issue #243)
 *
 * STM32F722 driver for HC-SR04 ultrasonic ranger with TIM1 input capture.
 * Trigger: PA0 (GPIO output, active high pulse 10µs)
 * Echo: PA1 (TIM1_CH2, input capture on rising/falling edges)
 *
 * Non-blocking operation: trigger measurement, get result via callback.
 * Distance calculated from echo pulse width: distance_mm = (pulse_us / 2) / 29.1
 * Typical range: 20-4000mm (accuracy ±3mm above 30mm)
 */

/* Ultrasonic sensor states */
typedef enum {
    ULTRASONIC_IDLE,        /* Ready for new measurement */
    ULTRASONIC_TRIGGERED,   /* Trigger pulse sent, waiting for echo */
    ULTRASONIC_MEASURING,   /* Echo rising edge detected, measuring */
    ULTRASONIC_COMPLETE,    /* Measurement complete */
    ULTRASONIC_ERROR        /* Timeout or out-of-range */
} UltrasonicState;

/* Measurement result callback: called when measurement completes
 * Arguments:
 *   - distance_mm: measured distance in mm (0 if error/timeout)
 *   - is_valid: true if measurement valid, false if timeout/error
 */
typedef void (*ultrasonic_callback_t)(uint16_t distance_mm, bool is_valid);

/*
 * ultrasonic_init()
 *
 * Initialize HC-SR04 driver:
 * - PA0 as GPIO output (trigger pin)
 * - PA1 as TIM1_CH2 input capture (echo pin)
 * - Configure TIM1 for input capture on both edges (rising/falling)
 * - Enable timer interrupt for echo measurement
 */
void ultrasonic_init(void);

/*
 * ultrasonic_trigger()
 *
 * Start a non-blocking distance measurement.
 * Sends 10µs trigger pulse on PA0, sets up echo measurement.
 * Measurement completes asynchronously (typically 25-300ms depending on distance).
 * Call ultrasonic_get_state() to check status or wait for callback.
 *
 * Returns: true if triggered successfully, false if still measuring previous result
 */
bool ultrasonic_trigger(void);

/*
 * ultrasonic_set_callback(callback)
 *
 * Register callback to be called when measurement completes.
 * Callback receives: distance_mm (0 if error), is_valid (true if successful)
 * Callback is optional; can poll with ultrasonic_get_result() instead.
 */
void ultrasonic_set_callback(ultrasonic_callback_t callback);

/*
 * ultrasonic_get_state()
 *
 * Returns current measurement state (IDLE, TRIGGERED, MEASURING, COMPLETE, ERROR).
 * Useful for non-blocking polling.
 */
UltrasonicState ultrasonic_get_state(void);

/*
 * ultrasonic_get_result(distance_mm, is_valid)
 *
 * Retrieve result of last measurement (only valid when state == ULTRASONIC_COMPLETE).
 * Resets state to IDLE after reading.
 *
 * Arguments:
 *   - distance_mm: pointer to store distance in mm
 *   - is_valid: pointer to store validity flag
 *
 * Returns: true if result retrieved, false if no measurement available
 */
bool ultrasonic_get_result(uint16_t *distance_mm, bool *is_valid);

/*
 * ultrasonic_tick(now_ms)
 *
 * Update function called periodically (recommended: every 1-10ms in main loop).
 * Handles timeout detection for echo measurement.
 * Must be called regularly for non-blocking operation.
 *
 * Arguments:
 *   - now_ms: current time in milliseconds (from HAL_GetTick() or similar)
 */
void ultrasonic_tick(uint32_t now_ms);

#endif /* ULTRASONIC_H */
