wii_ext/async_impl/
classic.rs

1use crate::async_impl::interface::{AsyncImplError, InterfaceAsync};
2use crate::core::classic::*;
3use crate::core::ControllerType;
4use embedded_hal_async;
5
6#[derive(Debug, Default)]
7pub struct Classic<I2C, Delay> {
8    interface: InterfaceAsync<I2C, Delay>,
9    hires: bool,
10    calibration: CalibrationData,
11}
12
13impl<I2C, Delay> Classic<I2C, Delay>
14where
15    I2C: embedded_hal_async::i2c::I2c,
16    Delay: embedded_hal_async::delay::DelayNs,
17{
18    /// Create a new Wii Classic Controller
19    pub fn new(i2cdev: I2C, delay: Delay) -> Self {
20        let interface = InterfaceAsync::new(i2cdev, delay);
21        Self {
22            interface,
23            hires: false,
24            calibration: CalibrationData::default(),
25        }
26    }
27
28    /// Destroy this driver, recovering the i2c bus and delay used to create it
29    pub fn destroy(self) -> (I2C, Delay) {
30        self.interface.destroy()
31    }
32
33    /// Update the stored calibration for this controller
34    ///
35    /// Since each device will have different tolerances, we take a snapshot of some analog data
36    /// to use as the "baseline" center.
37    pub async fn update_calibration(&mut self) -> Result<(), AsyncImplError> {
38        let data = self.read_report().await?;
39        self.calibration = CalibrationData {
40            joystick_left_x: data.joystick_left_x,
41            joystick_left_y: data.joystick_left_y,
42            joystick_right_x: data.joystick_right_x,
43            joystick_right_y: data.joystick_right_y,
44            trigger_left: data.trigger_left,
45            trigger_right: data.trigger_left,
46        };
47        Ok(())
48    }
49
50    /// Send the init sequence to the controller and calibrate it
51    pub async fn init(&mut self) -> Result<(), AsyncImplError> {
52        self.interface.init().await?;
53        self.update_calibration().await?;
54        Ok(())
55    }
56
57    /// Read uncalibrated data from the controller
58    async fn read_report(&mut self) -> Result<ClassicReading, AsyncImplError> {
59        if self.hires {
60            let buf = self.interface.read_hd_report().await?;
61            ClassicReading::from_data(&buf).ok_or(AsyncImplError::InvalidInputData)
62        } else {
63            let buf = self.interface.read_ext_report().await?;
64            ClassicReading::from_data(&buf).ok_or(AsyncImplError::InvalidInputData)
65        }
66    }
67
68    /// Do a read, and report axis values relative to calibration
69    pub async fn read(&mut self) -> Result<ClassicReadingCalibrated, AsyncImplError> {
70        Ok(ClassicReadingCalibrated::new(
71            self.read_report().await?,
72            &self.calibration,
73        ))
74    }
75
76    /// Switch the driver from standard to hi-resolution reporting
77    ///
78    /// This enables the controllers high-resolution report data mode, which returns each
79    /// analogue axis as a u8, rather than packing smaller integers in a structure.
80    /// If your controllers supports this mode, you should use it. It is much better.
81    pub async fn enable_hires(&mut self) -> Result<(), AsyncImplError> {
82        self.interface.enable_hires().await
83    }
84
85    /// Determine the controller type based on the type ID of the extension controller
86    pub async fn identify_controller(&mut self) -> Result<Option<ControllerType>, AsyncImplError> {
87        self.interface.identify_controller().await
88    }
89}