1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use crate::core::{
ControllerIdReport, ControllerType, ExtHdReport, ExtReport, EXT_I2C_ADDR,
INTERMESSAGE_DELAY_MICROSEC_U32,
};
use embedded_hal_async;
#[cfg(feature = "defmt_print")]
use defmt;
#[cfg_attr(feature = "defmt_print", derive(defmt::Format))]
#[derive(Debug)]
pub enum AsyncImplError {
I2C,
InvalidInputData,
Error,
ParseError,
}
#[cfg_attr(feature = "defmt_print", derive(defmt::Format))]
#[derive(Debug, Default)]
pub struct InterfaceAsync<I2C, Delay> {
i2cdev: I2C,
delay: Delay,
}
impl<I2C, Delay> InterfaceAsync<I2C, Delay>
where
I2C: embedded_hal_async::i2c::I2c,
Delay: embedded_hal_async::delay::DelayNs,
{
/// Create async interface for wii-extension controller
pub fn new(i2cdev: I2C, delay: Delay) -> Self {
Self { i2cdev, delay }
}
/// Destroy i2c interface, allowing recovery of i2c and delay
pub fn destroy(self) -> (I2C, Delay) {
(self.i2cdev, self.delay)
}
/// Access delay stored in interface
pub(super) async fn delay_us(&mut self, micros: u32) {
self.delay.delay_us(micros).await
}
/// Read report data from the wii-extension controller
pub(super) async fn read_ext_report(&mut self) -> Result<ExtReport, AsyncImplError> {
self.start_sample().await?;
self.delay_us(INTERMESSAGE_DELAY_MICROSEC_U32).await;
let mut buffer: ExtReport = ExtReport::default();
self.i2cdev
.read(EXT_I2C_ADDR as u8, &mut buffer)
.await
.map_err(|_| AsyncImplError::I2C)
.and(Ok(buffer))
}
/// Read a high-resolution version of the report data from the wii-extension controller
pub(super) async fn read_hd_report(&mut self) -> Result<ExtHdReport, AsyncImplError> {
self.start_sample().await?;
self.delay_us(INTERMESSAGE_DELAY_MICROSEC_U32).await;
let mut buffer: ExtHdReport = ExtHdReport::default();
self.i2cdev
.read(EXT_I2C_ADDR as u8, &mut buffer)
.await
.map_err(|_| AsyncImplError::I2C)
.and(Ok(buffer))
}
/// Send the init sequence to the Wii extension controller
pub(super) async fn init(&mut self) -> Result<(), AsyncImplError> {
// Extension controllers by default will use encrypted communication, as that is what the Wii does.
// We can disable this encryption by writing some magic values
// This is described at https://wiibrew.org/wiki/Wiimote/Extension_Controllers#The_New_Way
// Reset to base register first - this should recover a controller in a weird state.
// Use longer delays here than normal reads - the system seems more unreliable performing these commands
self.delay_us(100_000).await;
self.set_read_register_address_with_delay(0).await?;
self.set_register_with_delay(0xF0, 0x55).await?;
self.set_register_with_delay(0xFB, 0x00).await?;
self.delay_us(100_000).await;
Ok(())
}
/// Switch the driver from standard to hi-resolution reporting
///
/// This enables the controller's high-resolution report data mode, which returns each
/// analogue axis as a u8, rather than packing smaller integers in a structure.
/// If your controllers supports this mode, you should use it. It is much better.
pub(super) async fn enable_hires(&mut self) -> Result<(), AsyncImplError> {
self.set_register_with_delay(0xFE, 0x03).await?;
self.delay_us(100_000).await;
Ok(())
}
/// Set the cursor position for the next i2c read
///
/// This hardware has a range of 100 registers and automatically
/// increments the register read postion on each read operation, and also on
/// every write operation.
/// This should be called before a read operation to ensure you get the correct data
pub(super) async fn set_read_register_address(
&mut self,
byte0: u8,
) -> Result<(), AsyncImplError> {
self.i2cdev
.write(EXT_I2C_ADDR as u8, &[byte0])
.await
.map_err(|_| AsyncImplError::I2C)
.and(Ok(()))
}
/// Set the cursor position for the next i2c read after a small delay
///
/// This hardware has a range of 100 registers and automatically
/// increments the register read postion on each read operation, and also on
/// every write operation.
/// This should be called before a read operation to ensure you get the correct data
/// The delay helps ensure that required timings are met
pub(super) async fn set_read_register_address_with_delay(
&mut self,
byte0: u8,
) -> Result<(), AsyncImplError> {
self.delay_us(INTERMESSAGE_DELAY_MICROSEC_U32).await;
let res = self.set_read_register_address(byte0);
res.await
}
/// Set a single register at target address
pub(super) async fn set_register(&mut self, addr: u8, byte1: u8) -> Result<(), AsyncImplError> {
self.i2cdev
.write(EXT_I2C_ADDR as u8, &[addr, byte1])
.await
.map_err(|_| AsyncImplError::I2C)
.and(Ok(()))
}
/// Set a single register at target address after a small delay
pub(super) async fn set_register_with_delay(
&mut self,
addr: u8,
byte1: u8,
) -> Result<(), AsyncImplError> {
self.delay_us(INTERMESSAGE_DELAY_MICROSEC_U32).await;
let res = self.set_register(addr, byte1);
res.await
}
/// Read the controller type ID register from the extension controller
pub(super) async fn read_id(&mut self) -> Result<ControllerIdReport, AsyncImplError> {
self.set_read_register_address(0xfa).await?;
let i2c_id = self.read_ext_report().await?;
Ok(i2c_id)
}
/// Determine the controller type based on the type ID of the extension controller
pub(super) async fn identify_controller(
&mut self,
) -> Result<Option<ControllerType>, AsyncImplError> {
let i2c_id = self.read_id().await?;
Ok(crate::core::identify_controller(i2c_id))
}
/// Instruct the extension controller to start preparing a sample by setting the read cursor to 0
pub(super) async fn start_sample(&mut self) -> Result<(), AsyncImplError> {
self.set_read_register_address(0x00).await?;
Ok(())
}
}