1use core::{fmt, marker::PhantomData};
4
5use crate::{
6 init_state,
7 pac::i2c0::{SLVCTL, SLVDAT},
8 reg_proxy::{Reg, RegProxy},
9};
10
11use super::{Error, Instance};
12
13pub struct Slave<I: Instance, State, ModeState> {
23 _state: PhantomData<State>,
24 _mode_state: PhantomData<ModeState>,
25
26 slvctl: RegProxy<SlvCtl<I>>,
27 slvdat: RegProxy<SlvDat<I>>,
28}
29
30impl<I, State, ModeState> Slave<I, State, ModeState>
31where
32 I: Instance,
33{
34 pub(super) fn new() -> Self {
35 Self {
36 _state: PhantomData,
37 _mode_state: PhantomData,
38
39 slvctl: RegProxy::new(),
40 slvdat: RegProxy::new(),
41 }
42 }
43}
44
45impl<I, C> Slave<I, init_state::Enabled<PhantomData<C>>, init_state::Enabled>
46where
47 I: Instance,
48{
49 pub fn wait(&mut self) -> nb::Result<State<I>, Error> {
54 let i2c = unsafe { &*I::REGISTERS };
56
57 Error::read::<I>()?;
58
59 if i2c.stat.read().slvpending().is_in_progress() {
60 return Err(nb::Error::WouldBlock);
61 }
62
63 let slave_state = i2c.stat.read().slvstate();
64
65 if slave_state.is_slave_address() {
66 return Ok(State::AddressMatched(AddressMatched {
67 slvctl: &self.slvctl,
68 slvdat: &self.slvdat,
69 }));
70 }
71 if slave_state.is_slave_receive() {
72 return Ok(State::RxReady(RxReady {
73 slvctl: &self.slvctl,
74 slvdat: &self.slvdat,
75 }));
76 }
77 if slave_state.is_slave_transmit() {
78 return Ok(State::TxReady(TxReady {
79 slvctl: &self.slvctl,
80 slvdat: &self.slvdat,
81 }));
82 }
83
84 Err(nb::Error::Other(Error::UnknownSlaveState(
85 slave_state.bits(),
86 )))
87 }
88}
89
90impl<I, State, ModeState> fmt::Debug for Slave<I, State, ModeState>
93where
94 I: Instance,
95{
96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97 f.debug_struct("Slave")
98 .field("_state", &self._state)
99 .field("_mode_state", &self._mode_state)
100 .field("slvctl", &self.slvctl)
101 .field("slvdat", &self.slvdat)
102 .finish()
103 }
104}
105
106pub enum State<'r, I: Instance> {
113 AddressMatched(AddressMatched<'r, I>),
115
116 RxReady(RxReady<'r, I>),
118
119 TxReady(TxReady<'r, I>),
121}
122
123pub struct AddressMatched<'r, I: Instance> {
129 slvctl: &'r RegProxy<SlvCtl<I>>,
130 slvdat: &'r RegProxy<SlvDat<I>>,
131}
132
133impl<'r, I> AddressMatched<'r, I>
134where
135 I: Instance,
136{
137 pub fn address(&self) -> Result<u8, Error> {
139 Error::read::<I>()?;
140
141 let address = self.slvdat.read().data().bits() >> 1;
142 Ok(address)
143 }
144
145 pub fn ack(self) -> Result<(), Error> {
147 Error::read::<I>()?;
148
149 self.slvctl.write(|w| w.slvcontinue().continue_());
150
151 Ok(())
152 }
153
154 pub fn nack(self) -> Result<(), Error> {
156 Error::read::<I>()?;
157
158 self.slvctl.write(|w| w.slvnack().nack());
159
160 Ok(())
161 }
162}
163
164pub struct RxReady<'r, I: Instance> {
170 slvctl: &'r RegProxy<SlvCtl<I>>,
171 slvdat: &'r RegProxy<SlvDat<I>>,
172}
173
174impl<'r, I> RxReady<'r, I>
175where
176 I: Instance,
177{
178 pub fn read(&self) -> Result<u8, Error> {
187 Error::read::<I>()?;
188
189 let data = self.slvdat.read().data().bits();
190 Ok(data)
191 }
192
193 pub fn ack(self) -> Result<(), Error> {
195 Error::read::<I>()?;
196
197 self.slvctl.write(|w| w.slvcontinue().continue_());
198
199 Ok(())
200 }
201
202 pub fn nack(self) -> Result<(), Error> {
204 Error::read::<I>()?;
205
206 self.slvctl.write(|w| w.slvnack().nack());
207
208 Ok(())
209 }
210}
211
212pub struct TxReady<'r, I: Instance> {
218 slvctl: &'r RegProxy<SlvCtl<I>>,
219 slvdat: &'r RegProxy<SlvDat<I>>,
220}
221
222impl<'r, I> TxReady<'r, I>
223where
224 I: Instance,
225{
226 pub fn transmit(self, data: u8) -> Result<(), Error> {
228 Error::read::<I>()?;
229
230 unsafe {
232 self.slvdat.write(|w| w.data().bits(data));
233 }
234
235 self.slvctl.write(|w| w.slvcontinue().continue_());
236
237 Ok(())
238 }
239}
240
241struct SlvCtl<I>(PhantomData<I>);
242
243unsafe impl<I> Reg for SlvCtl<I>
245where
246 I: Instance,
247{
248 type Target = SLVCTL;
249
250 fn get() -> *const Self::Target {
251 unsafe { &(*I::REGISTERS).slvctl as *const _ }
254 }
255}
256
257impl<I> fmt::Debug for SlvCtl<I> {
260 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261 write!(f, "SlvCtl(...)")
262 }
263}
264
265struct SlvDat<I>(PhantomData<I>);
266
267unsafe impl<I> Reg for SlvDat<I>
269where
270 I: Instance,
271{
272 type Target = SLVDAT;
273
274 fn get() -> *const Self::Target {
275 unsafe { &(*I::REGISTERS).slvdat as *const _ }
278 }
279}
280
281impl<I> fmt::Debug for SlvDat<I> {
284 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
285 write!(f, "SlvDat(...)")
286 }
287}