1+ use super :: i2c:: { SclPin , SdaPin } ;
2+ use super :: pac:: I2C1 ;
3+
4+ #[ derive( PartialEq ) ]
5+ pub enum TransferState {
6+ Idle ,
7+ Addressed ,
8+ RegisterSet ,
9+ Receiving ,
10+ Transmitting ,
11+ }
12+
13+ #[ derive( Copy , Clone ) ]
14+ pub enum State {
15+ DataRequested ( u8 ) ,
16+ DataReceived ( u8 ) ,
17+ }
18+
19+ const BUFFER_SIZE : usize = 32 ;
20+
21+ pub struct I2CSlave < SDA , SCL > {
22+ i2c : I2C1 ,
23+ transfer_buffer : [ u8 ; BUFFER_SIZE ] ,
24+ transfer_len : usize ,
25+ buffer_index : usize ,
26+ register : u8 ,
27+ transfer_state : TransferState ,
28+ state : Option < State > ,
29+ _sda : SDA ,
30+ _scl : SCL ,
31+ }
32+
33+ // direction as specified in the datasheet
34+ #[ derive( PartialEq ) ]
35+ pub enum Direction {
36+ Write , // slave is receiver
37+ Read , // slave is transmitter
38+ }
39+
40+ impl From < Direction > for bool {
41+ fn from ( dir : Direction ) -> Self {
42+ match dir {
43+ Direction :: Write => false ,
44+ Direction :: Read => true ,
45+ }
46+ }
47+ }
48+
49+ impl From < bool > for Direction {
50+ fn from ( raw : bool ) -> Self {
51+ if raw {
52+ Direction :: Read
53+ } else {
54+ Direction :: Write
55+ }
56+ }
57+ }
58+
59+ pub enum Status {
60+ AddressMatch ( Direction ) ,
61+ Busy ,
62+ Timeout ,
63+ Overrun ,
64+ ArbitrationLost ,
65+ BusError ,
66+ TransferCompleteReload ,
67+ Stop ,
68+ NACKReceived ,
69+ RxNotEmpty ,
70+ TxDataMustBeWritten ,
71+ TxEmpty ,
72+ }
73+
74+ impl < SDA , SCL > I2CSlave < SDA , SCL >
75+ where
76+ SDA : SdaPin < I2C1 > ,
77+ SCL : SclPin < I2C1 > ,
78+ {
79+ pub fn new ( i2c : I2C1 , address : u8 , sda : SDA , scl : SCL ) -> Self {
80+ let rcc = unsafe { & ( * stm32f0xx_hal:: pac:: RCC :: ptr ( ) ) } ;
81+ rcc. apb1enr . modify ( |_, w| w. i2c1en ( ) . enabled ( ) ) ;
82+ rcc. apb1rstr . modify ( |_, w| w. i2c1rst ( ) . set_bit ( ) ) ;
83+ rcc. apb1rstr . modify ( |_, w| w. i2c1rst ( ) . clear_bit ( ) ) ;
84+
85+ i2c. cr1 . write ( |w| {
86+ w. nostretch ( )
87+ . enabled ( ) // enable clock stretching
88+ . anfoff ( )
89+ . enabled ( ) // enable analog filter
90+ . dnf ( )
91+ . no_filter ( ) // disable digital filter
92+ . errie ( )
93+ . enabled ( ) // error interrupt enabled
94+ . stopie ( )
95+ . enabled ( ) // stop interrupt enabled
96+ . nackie ( )
97+ . enabled ( ) // nack interrupt enabled
98+ . addrie ( )
99+ . enabled ( ) // address match interrupt enabled
100+ . rxie ( ) // rx interrupt enabled
101+ . enabled ( )
102+ . wupen ( )
103+ . enabled ( ) // wake up when address match
104+ } ) ;
105+
106+ // TODO set up timing for nostretch mode
107+ // let scll = cmp::max((((48_000_000 >> 1) >> 1) / KiloHertz(100).0) - 1, 255) as u8;
108+ // i2c.timingr.write(|w| {
109+ // w.presc()
110+ // .bits(1)
111+ // .scldel()
112+ // .bits(4)
113+ // .sdadel()
114+ // .bits(2)
115+ // .sclh()
116+ // .bits(scll - 4)
117+ // .scll()
118+ // .bits(scll)
119+ // });
120+
121+ i2c. oar1 . write ( |w| {
122+ w. oa1en ( )
123+ . enabled ( )
124+ . oa1 ( )
125+ . bits ( ( address as u16 ) << 1 )
126+ . oa1mode ( )
127+ . bit7 ( )
128+ } ) ;
129+
130+ i2c. cr1 . modify (
131+ |_, w| w. pe ( ) . enabled ( ) , // enable peripheral
132+ ) ;
133+
134+ I2CSlave {
135+ i2c,
136+ transfer_buffer : [ 0u8 ; BUFFER_SIZE ] ,
137+ transfer_len : 0 ,
138+ buffer_index : 0 ,
139+ register : 0 ,
140+ transfer_state : TransferState :: Idle ,
141+ state : None ,
142+ _sda : sda,
143+ _scl : scl,
144+ }
145+ }
146+
147+ pub fn is_status ( & self , status : Status , clear : bool ) -> bool {
148+ let isr = self . i2c . isr . read ( ) ;
149+
150+ match status {
151+ Status :: AddressMatch ( dir) => {
152+ if isr. addr ( ) . bit_is_set ( ) {
153+ if dir != isr. dir ( ) . bit ( ) . into ( ) {
154+ return false ;
155+ }
156+ if clear {
157+ self . i2c . icr . write ( |w| w. addrcf ( ) . clear ( ) ) ;
158+ }
159+ return true ;
160+ } else {
161+ false
162+ }
163+ }
164+ Status :: Busy => {
165+ return isr. busy ( ) . bit_is_set ( ) ;
166+ }
167+ Status :: Timeout => {
168+ if isr. timeout ( ) . bit_is_set ( ) {
169+ if clear {
170+ self . i2c . icr . write ( |w| w. timoutcf ( ) . clear ( ) ) ;
171+ }
172+ return true ;
173+ }
174+ return false ;
175+ }
176+ Status :: Overrun => {
177+ if isr. ovr ( ) . bit_is_set ( ) {
178+ if clear {
179+ self . i2c . icr . write ( |w| w. ovrcf ( ) . clear ( ) ) ;
180+ }
181+ return true ;
182+ }
183+ return false ;
184+ }
185+ Status :: ArbitrationLost => {
186+ if isr. arlo ( ) . bit_is_set ( ) {
187+ if clear {
188+ self . i2c . icr . write ( |w| w. arlocf ( ) . clear ( ) ) ;
189+ }
190+ return true ;
191+ }
192+ return false ;
193+ }
194+ Status :: BusError => {
195+ if isr. berr ( ) . bit_is_set ( ) {
196+ if clear {
197+ self . i2c . icr . write ( |w| w. berrcf ( ) . clear ( ) ) ;
198+ }
199+ return true ;
200+ }
201+ return false ;
202+ }
203+ Status :: TransferCompleteReload => {
204+ if isr. tcr ( ) . bit_is_set ( ) {
205+ if clear {
206+ // defmt::error!("Cannot be cleared.");
207+ }
208+ return true ;
209+ }
210+ return false ;
211+ }
212+ Status :: Stop => {
213+ if isr. stopf ( ) . bit_is_set ( ) {
214+ if clear {
215+ self . i2c . icr . write ( |w| w. stopcf ( ) . clear ( ) ) ;
216+ }
217+ return true ;
218+ }
219+ return false ;
220+ }
221+ Status :: NACKReceived => {
222+ if isr. nackf ( ) . bit_is_set ( ) {
223+ if clear {
224+ self . i2c . icr . write ( |w| w. nackcf ( ) . clear ( ) ) ;
225+ }
226+ return true ;
227+ }
228+ return false ;
229+ }
230+ Status :: RxNotEmpty => {
231+ if isr. rxne ( ) . bit_is_set ( ) {
232+ if clear {
233+ // defmt::error!("Cannot be cleared.");
234+ }
235+ return true ;
236+ }
237+ return false ;
238+ }
239+ Status :: TxDataMustBeWritten => {
240+ if isr. txis ( ) . bit_is_set ( ) {
241+ if clear {
242+ // defmt::error!("Cannot be cleared.");
243+ }
244+ return true ;
245+ }
246+ return false ;
247+ }
248+ Status :: TxEmpty => {
249+ if isr. txe ( ) . bit_is_set ( ) {
250+ if clear {
251+ // defmt::error!("Cannot be cleared.");
252+ }
253+ return true ;
254+ }
255+ return false ;
256+ }
257+ }
258+ }
259+
260+ pub fn read ( & self ) -> u8 {
261+ self . i2c . rxdr . read ( ) . bits ( ) as u8
262+ }
263+
264+ pub fn write ( & self , value : u8 ) {
265+ self . i2c . txdr . write ( |w| w. txdata ( ) . bits ( value) ) ;
266+ }
267+
268+ pub fn set_txe ( & self ) {
269+ self . i2c . isr . modify ( |_, w| w. txe ( ) . set_bit ( ) ) ;
270+ }
271+
272+ pub fn enable_txie ( & self , enable : bool ) {
273+ self . i2c
274+ . cr1
275+ . modify ( |_, w| w. txie ( ) . bit ( enable) . tcie ( ) . bit ( enable) ) ;
276+ }
277+
278+ pub fn interrupt ( & mut self ) {
279+ if self . transfer_state == TransferState :: Idle {
280+ self . state = None ;
281+ self . enable_txie ( false ) ;
282+ }
283+
284+ if self . is_status ( Status :: BusError , true ) {
285+ self . handle_error ( ) ;
286+ return ;
287+ }
288+ if self . is_status ( Status :: Overrun , true ) {
289+ self . handle_error ( ) ;
290+ return ;
291+ }
292+ if self . is_status ( Status :: ArbitrationLost , true ) {
293+ self . handle_error ( ) ;
294+ return ;
295+ }
296+ if self . is_status ( Status :: NACKReceived , true ) {
297+ self . handle_error ( ) ;
298+ return ;
299+ }
300+ if self . is_status ( Status :: Timeout , true ) {
301+ self . handle_error ( ) ;
302+ return ;
303+ }
304+
305+ if self . is_status ( Status :: RxNotEmpty , false ) {
306+ if self . transfer_state == TransferState :: Addressed {
307+ self . transfer_state = TransferState :: RegisterSet ;
308+ self . register = self . read ( ) ;
309+ } else if self . transfer_state == TransferState :: RegisterSet {
310+ self . transfer_state = TransferState :: Receiving ;
311+ } else if self . transfer_state == TransferState :: Receiving {
312+ // do not change state, just read
313+ self . transfer_buffer [ self . buffer_index ] = self . read ( ) ;
314+ self . buffer_index += 1 ;
315+ }
316+ }
317+
318+ if self . is_status ( Status :: Stop , true ) {
319+ // handle reception
320+ if self . transfer_state == TransferState :: Receiving {
321+ self . state = Some ( State :: DataReceived ( self . register ) ) ;
322+ } else if self . transfer_state == TransferState :: Transmitting {
323+ // data was transmitted, nothing else to do
324+ self . state = None ;
325+ }
326+ self . i2c . isr . modify ( |_, w| w. txe ( ) . set_bit ( ) ) ; // flush txdr
327+ self . transfer_state = TransferState :: Idle ;
328+ }
329+
330+ if self . is_status ( Status :: AddressMatch ( Direction :: Write ) , true ) {
331+ self . transfer_state = TransferState :: Addressed ;
332+ }
333+ if self . is_status ( Status :: TxDataMustBeWritten , false ) {
334+ // this may be true more times than actual data length, ignore then
335+ if self . transfer_state == TransferState :: Transmitting {
336+ // state is not changed
337+ if self . buffer_index < self . transfer_len {
338+ self . write ( self . transfer_buffer [ self . buffer_index ] ) ;
339+ self . buffer_index += 1 ;
340+ } else {
341+ self . enable_txie ( false ) ;
342+ self . state = None ;
343+ }
344+ }
345+ }
346+ if self . is_status ( Status :: AddressMatch ( Direction :: Read ) , true ) {
347+ if self . transfer_state == TransferState :: RegisterSet {
348+ self . enable_txie ( true ) ;
349+ self . transfer_state = TransferState :: Transmitting ;
350+ self . state = Some ( State :: DataRequested ( self . register ) ) ;
351+ }
352+ }
353+ }
354+
355+ fn handle_error ( & mut self ) {
356+ self . transfer_state = TransferState :: Idle ;
357+ self . state = None ;
358+ self . transfer_len = 0 ;
359+ self . buffer_index = 0 ;
360+ self . i2c . isr . modify ( |_, w| w. txe ( ) . set_bit ( ) ) ; // flush txdr
361+ }
362+
363+ pub fn set_transmit_buffer ( & mut self , buffer : & [ u8 ] ) {
364+ for ( index, item) in buffer. iter ( ) . enumerate ( ) {
365+ self . transfer_buffer [ index] = * item;
366+ }
367+ self . transfer_len = buffer. len ( ) ;
368+ self . buffer_index = 0 ;
369+ self . state = None
370+ }
371+
372+ pub fn get_received_data ( & mut self ) -> & [ u8 ] {
373+ let data = & self . transfer_buffer [ ..self . buffer_index ] ;
374+ self . state = None ;
375+ self . buffer_index = 0 ;
376+ self . transfer_len = 0 ;
377+ data
378+ }
379+
380+ pub fn get_state ( & self ) -> Option < State > {
381+ self . state
382+ }
383+ }
0 commit comments