JoystickHackx 0.1.0

Joystick driver for hackxpansion!
use alloc::boxed::Box;

use core::{
    future::Future,
    pin::Pin,
};

use embassy_rp::{
    Peri,
    adc::AdcPin,
    gpio::AnyPin,
};

use xpanse_api::interfaces::{
    adc::{self, AdcError},
    buttons::{A, Button, pin_button},
};

trait AdcAxis: Send {
    fn read<'a>(
        &'a mut self,
    ) -> Pin<Box<dyn Future<Output = Result<u16, AdcError>> + Send + 'a>>;
}

struct PinAxis<P>
where
    P: AdcPin + Send + 'static,
{
    pin: Peri<'static, P>,
}

impl<P> AdcAxis for PinAxis<P>
where
    P: AdcPin + Send + 'static,
{
    fn read<'a>(
        &'a mut self,
    ) -> Pin<Box<dyn Future<Output = Result<u16, AdcError>> + Send + 'a>> {
        Box::pin(async move {
            adc::read_adc_pin(
                &mut self.pin,
                embassy_rp::gpio::Pull::None,
            )
            .await
        })
    }
}

pub struct Joystick {
    x: Box<dyn AdcAxis>,
    y: Box<dyn AdcAxis>,
    button: Box<dyn Button<A>>,
}

impl Joystick {
    pub fn new<X, Y>(
        x: Peri<'static, X>,
        y: Peri<'static, Y>,
        button: Peri<'static, AnyPin>,
    ) -> Self
    where
        X: AdcPin + Send + 'static,
        Y: AdcPin + Send + 'static,
    {
        Self {
            x: Box::new(PinAxis { pin: x }),
            y: Box::new(PinAxis { pin: y }),
            button: pin_button::<A>(button),
        }
    }

    pub async fn read_x(&mut self) -> Result<u16, AdcError> {
        self.x.read().await
    }

    pub async fn read_y(&mut self) -> Result<u16, AdcError> {
        self.y.read().await
    }

    pub async fn read(&mut self) -> Result<(u16, u16), AdcError> {
        let x = self.read_x().await?;
        let y = self.read_y().await?;
        Ok((x, y))
    }

    pub fn is_pressed(&self) -> bool {
        self.button.is_pressed()
    }

    pub async fn wait_for_pressed(&mut self) {
        self.button.wait_for_pressed().await;
    }
}