ask433 0.2.1

A no_std, embedded-hal ASK/OOK modem driver for 433 MHz RF modules (e.g., FS1000A). Supports RX/TX, 4b6b encoding, and software PLL demodulation.
Documentation
use crate::driver::AskDriver;
use embedded_hal::delay::DelayNs;
use embedded_hal::digital::{InputPin, OutputPin};

/// Runs a blocking loop that repeatedly calls `tick()` on the provided ASK driver.
///
/// This is a simple timing loop for use in environments where interrupts are unavailable
/// or undesired. It drives the ASK modem's timing using a delay provider implementing
/// `embedded_hal::blocking::delay::DelayUs`.
///
/// # Arguments
/// - `driver`: A mutable reference to an `AskDriver` instance.
/// - `delay`: A delay provider implementing `DelayUs<u16>`, typically from the HAL.
/// - `tick_us`: The delay between each tick call, in microseconds (e.g. 63 for ~2 kbps).
///
/// # Example
/// ```rust
/// # use embedded_hal_mock::eh1::delay::NoopDelay as Delay;
/// # use embedded_hal_mock::eh1::digital::{
/// #     Mock as Pin, State as PinState, Transaction as PinTransaction,
/// # };
/// use ask433::driver::AskDriver;
/// use ask433::timer::run_ask_tick_loop;
/// # let tx = Pin::new(&[PinTransaction::set(PinState::Low)]);
/// # let rx = Pin::new(&[]);
/// let mut driver: AskDriver<Pin, Pin, Pin> = AskDriver::new(tx, rx, None, 8, None, None);
/// let mut delay = Delay::new();
/// run_ask_tick_loop(&mut driver, &mut delay, 63);
/// # driver.tx.done();
/// # driver.rx.done();
/// ```
///
/// # Notes
/// - This loop will never return; it is intended for single-purpose polling firmware.
/// - For more efficient or concurrent applications, prefer interrupt-driven tick scheduling.
/// - `delay.delay_us()` errors are ignored, which is acceptable in typical HALs where
///   the only error case is an uninitialized peripheral or transient underrun.
pub fn run_ask_tick_loop<D, TX, RX, PTT>(
    driver: &mut AskDriver<TX, RX, PTT>,
    delay: &mut D,
    tick_us: u32,
) where
    D: DelayNs,
    TX: OutputPin,
    RX: InputPin,
    PTT: OutputPin,
{
    driver.tick();
    delay.delay_us(tick_us);
}

#[cfg(test)]
mod tests {
    use super::*;
    use embedded_hal_mock::eh1::delay::NoopDelay as MockDelay;
    use embedded_hal_mock::eh1::digital::{
        Mock as PinMock, State as PinState, Transaction as PinTransaction,
    };

    #[test]
    fn test_run_ask_tick_loop_invokes_tick_and_delay() {
        // NOTE: We can't run the actual loop in test because it is infinite
        // Instead, we check that the function compiles and can be called with correct arguments.
        let tx = PinMock::new(&[PinTransaction::set(PinState::Low)]);
        let rx = PinMock::new(&[]);
        let ptt = PinMock::new(&[]);
        let mut driver = AskDriver::new(tx, rx, Some(ptt), 8, Some(false), Some(false));
        let mut delay = MockDelay::new();

        // Just call tick manually to simulate one loop iteration
        delay.delay_us(63);
        run_ask_tick_loop(&mut driver, &mut delay, 63);
        driver.tx.done();
        driver.rx.done();
        let _ = driver.ptt.map(|mut ptt| ptt.done());
    }
}