// =============================================================================
//  di_do.h -- generic digital-input / digital-output helpers
// =============================================================================
//
//  Thin layer above Arduino digitalRead / digitalWrite that:
//      - Tracks the *logical* state of every input/output so other tasks can
//        query without re-reading the pin.
//      - Debounces DIs in software (configurable, default 20 ms).
//      - Caches the last commanded DO state so we never write the same value
//        twice (cheap optimisation for slow open-drain outputs).
//
//  Pins handled by this module are the ones listed in hal/pinout.h.
// =============================================================================

#pragma once

#include <cstdint>

namespace arautopilot::hal {

// ----- Digital inputs -------------------------------------------------------

/// Initialise all DI pins declared in pinout.h with INPUT_PULLUP.
/// Must be called once during setup() before any di_read() call.
void di_init();

/// Sample every DI once, run the debounce filter, and store the result.
/// Intended to be called from the safety task at a fixed rate (50 Hz).
void di_poll();

/// Return the last debounced logical state of a DI pin.
/// Pin must be one of the PIN_DIx_* constants from pinout.h.
bool di_read(uint8_t pin);

/// Return true if the pin changed state on the most recent di_poll() call
/// (edge-detect). Useful for the disengage button.
bool di_rising_edge(uint8_t pin);
bool di_falling_edge(uint8_t pin);

// ----- Digital outputs ------------------------------------------------------

/// Initialise all DO pins declared in pinout.h as OUTPUT and drive them LOW.
/// Must be called once during setup() before any do_write() call.
void do_init();

/// Set a DO pin to the given logical state. No-op if the pin was already in
/// that state. Returns true if the write actually happened.
/// Pin must be one of the PIN_DOx_* constants from pinout.h.
bool do_write(uint8_t pin, bool high);

/// Return the last commanded state of a DO pin.
bool do_state(uint8_t pin);

/// Drive every DO LOW. Called by the safety system on emergency disengage.
void do_all_off();

}  // namespace arautopilot::hal
