wii_ext/core/
nunchuk.rs

1#[cfg(feature = "defmt_print")]
2use defmt;
3
4#[cfg_attr(feature = "defmt_print", derive(defmt::Format))]
5#[derive(Debug, Default)]
6pub struct NunchukReading {
7    pub joystick_x: u8,
8    pub joystick_y: u8,
9    pub accel_x: u16, // 10-bit
10    pub accel_y: u16, // 10-bit
11    pub accel_z: u16, // 10-bit
12    pub button_c: bool,
13    pub button_z: bool,
14}
15
16impl NunchukReading {
17    pub fn from_data(data: &[u8]) -> Option<NunchukReading> {
18        if data.len() < 6 {
19            None
20        } else {
21            Some(NunchukReading {
22                joystick_x: data[0],
23                joystick_y: data[1],
24                accel_x: (u16::from(data[2]) << 2) | ((u16::from(data[5]) >> 6) & 0b11),
25                accel_y: (u16::from(data[3]) << 2) | ((u16::from(data[5]) >> 4) & 0b11),
26                accel_z: (u16::from(data[4]) << 2) | ((u16::from(data[5]) >> 2) & 0b11),
27                button_c: (data[5] & 0b10) == 0,
28                button_z: (data[5] & 0b01) == 0,
29            })
30        }
31    }
32}
33
34/// Relaxed/Center positions for each axis
35///
36/// These are used to calculate the relative deflection of each access from their center point
37#[cfg_attr(feature = "defmt_print", derive(defmt::Format))]
38#[derive(Debug, Default)]
39pub struct CalibrationData {
40    pub joystick_x: u8,
41    pub joystick_y: u8,
42}
43
44/// Data from a Nunchuk after calibration data has been applied
45///
46/// Calibration is done by subtracting the resting values from the current
47/// values, which means that going lower on the axis will go negative.
48/// Due to this, we now store analog values as signed integers
49///
50/// We'll only calibrate the joystick axes, leave accelerometer readings as-is
51#[cfg_attr(feature = "defmt_print", derive(defmt::Format))]
52#[derive(Debug, Default)]
53pub struct NunchukReadingCalibrated {
54    pub joystick_x: i8,
55    pub joystick_y: i8,
56    pub accel_x: u16, // 10-bit
57    pub accel_y: u16, // 10-bit
58    pub accel_z: u16, // 10-bit
59    pub button_c: bool,
60    pub button_z: bool,
61}
62
63impl NunchukReadingCalibrated {
64    pub fn new(r: NunchukReading, c: &CalibrationData) -> NunchukReadingCalibrated {
65        /// Just in case `data` minus `calibration data` is out of range, perform all operations
66        /// on i16 and clamp to i8 limits before returning
67        fn ext_u8_sub(a: u8, b: u8) -> i8 {
68            let res = (a as i16) - (b as i16);
69            res.clamp(i8::MIN as i16, i8::MAX as i16) as i8
70        }
71
72        NunchukReadingCalibrated {
73            joystick_x: ext_u8_sub(r.joystick_x, c.joystick_x),
74            joystick_y: ext_u8_sub(r.joystick_y, c.joystick_y),
75            accel_x: r.accel_x,
76            accel_y: r.accel_y, // 10-bit
77            accel_z: r.accel_z, // 10-bit
78            button_c: r.button_c,
79            button_z: r.button_z,
80        }
81    }
82}