atsamd_hal/sercom/i2c/
reg.rs1use super::InactiveTimeout;
4use super::flags::{BusState, Error};
5use super::{Flags, Status};
6use crate::pac;
7use crate::sercom::Sercom;
8use crate::time::Hertz;
9use atsamd_hal_macros::hal_cfg;
10
11const MASTER_ACT_READ: u8 = 2;
12const MASTER_ACT_STOP: u8 = 3;
13const MASTER_ACT_REPEATED_START: u8 = 1;
14
15#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
16type DataReg = u8;
17
18#[hal_cfg("sercom0-d5x")]
19type DataReg = u32;
20
21pub(in super::super) struct Registers<S: Sercom> {
22    pub sercom: S,
23}
24
25unsafe impl<S: Sercom> Sync for Registers<S> {}
28
29impl<S: Sercom> Registers<S> {
30    #[inline]
32    pub(super) fn new(sercom: S) -> Self {
33        Self { sercom }
34    }
35
36    #[inline]
38    pub(in super::super) fn i2c_master(&self) -> &pac::sercom0::I2cm {
39        self.sercom.i2cm()
40    }
41
42    pub(super) fn data_ptr<T>(&self) -> *mut T {
44        self.i2c_master().data().as_ptr() as *mut _
45    }
46
47    #[inline]
49    pub(super) fn free(self) -> S {
50        self.sercom
51    }
52
53    #[inline]
55    pub(super) fn swrst(&mut self) {
56        self.i2c_master().ctrla().write(|w| w.swrst().set_bit());
57        while self.i2c_master().syncbusy().read().swrst().bit_is_set() {}
58    }
59
60    #[inline]
62    pub(super) fn set_op_mode(&mut self, mode: pac::sercom0::i2cm::ctrla::Modeselect) {
63        self.i2c_master()
64            .ctrla()
65            .modify(|_, w| w.mode().variant(mode));
66    }
67
68    pub(super) fn set_baud(&mut self, clock_freq: impl Into<Hertz>, baud: impl Into<Hertz>) {
70        let baud = (clock_freq.into().to_Hz() / (2 * baud.into().to_Hz()) - 1) as u8;
73
74        unsafe {
75            self.i2c_master().baud().modify(|_, w| w.baud().bits(baud));
76        }
77    }
78
79    #[inline]
81    pub(super) fn get_baud(&self) -> u32 {
82        self.i2c_master().baud().read().bits()
83    }
84
85    #[inline]
93    pub(super) fn set_low_timeout(&mut self, set: bool) {
94        self.i2c_master()
95            .ctrla()
96            .modify(|_, w| w.lowtouten().bit(set));
97    }
98
99    #[inline]
107    pub(super) fn get_low_timeout(&mut self) -> bool {
108        self.i2c_master().ctrla().read().lowtouten().bit()
109    }
110
111    #[inline]
114    pub(super) fn set_inactive_timeout(&mut self, timeout: super::InactiveTimeout) {
115        #[allow(unused_unsafe)]
118        self.i2c_master()
119            .ctrla()
120            .modify(|_, w| unsafe { w.inactout().bits(timeout as u8) })
121    }
122
123    #[inline]
125    pub(super) fn get_inactive_timeout(&mut self) -> InactiveTimeout {
126        let timeout = self.i2c_master().ctrla().read().inactout().bits();
127
128        match timeout {
129            0 => InactiveTimeout::Disabled,
130            1 => InactiveTimeout::Us55,
131            2 => InactiveTimeout::Us105,
132            3 => InactiveTimeout::Us205,
133            _ => unreachable!(),
134        }
135    }
136
137    #[inline]
142    pub(super) fn set_run_in_standby(&mut self, set: bool) {
143        self.i2c_master()
144            .ctrla()
145            .modify(|_, w| w.runstdby().bit(set));
146    }
147
148    #[inline]
150    pub(super) fn get_run_in_standby(&self) -> bool {
151        self.i2c_master().ctrla().read().runstdby().bit()
152    }
153
154    #[inline]
156    pub(super) fn set_smart_mode(&mut self, set: bool) {
157        self.i2c_master().ctrlb().modify(|_, w| w.smen().bit(set));
158    }
159
160    #[inline]
162    pub(super) fn get_smart_mode(&self) -> bool {
163        self.i2c_master().ctrlb().read().smen().bit()
164    }
165
166    #[inline]
168    pub(super) fn clear_flags(&mut self, flags: Flags) {
169        self.i2c_master()
170            .intflag()
171            .modify(|_, w| unsafe { w.bits(flags.bits()) });
172    }
173
174    #[inline]
176    pub(super) fn read_flags(&self) -> Flags {
177        Flags::from_bits_truncate(self.i2c_master().intflag().read().bits())
178    }
179
180    #[inline]
182    pub(super) fn enable_interrupts(&mut self, flags: Flags) {
183        self.i2c_master()
184            .intenset()
185            .write(|w| unsafe { w.bits(flags.bits()) });
186    }
187
188    #[inline]
190    pub(super) fn disable_interrupts(&mut self, flags: Flags) {
191        self.i2c_master()
192            .intenclr()
193            .write(|w| unsafe { w.bits(flags.bits()) });
194    }
195
196    #[inline]
198    pub(super) fn clear_status(&mut self, status: Status) {
199        self.i2c_master()
200            .status()
201            .modify(|_, w| unsafe { w.bits(status.into()) });
202    }
203
204    #[inline]
206    pub(super) fn read_status(&self) -> Status {
207        self.i2c_master().status().read().bits().into()
208    }
209
210    pub(super) fn check_bus_status(&self) -> Result<(), Error> {
211        let status = self.read_status();
212        if status.busstate() == BusState::Busy
213            || (status.arblost() && status.busstate() != BusState::Idle)
214            || status.busstate() == BusState::Unknown
215        {
216            Err(Error::BusError)
217        } else {
218            Ok(())
219        }
220    }
221
222    #[inline]
225    pub(super) fn start_write(&mut self, addr: u8) -> Result<(), Error> {
226        if self.get_smart_mode() {
227            self.disable();
228            self.set_smart_mode(false);
229            self.enable();
230        }
231
232        self.check_bus_status()?;
233
234        unsafe {
237            self.i2c_master()
238                .addr()
239                .write(|w| w.addr().bits(encode_write_address(addr)));
240        }
241
242        Ok(())
243    }
244
245    #[inline]
247    pub(super) fn start_write_blocking(&mut self, addr: u8) -> Result<(), Error> {
248        self.start_write(addr)?;
249
250        while !self.i2c_master().intflag().read().mb().bit_is_set() {}
252        self.read_status().check_bus_error()
253    }
254
255    pub(super) fn start_read(&mut self, addr: u8) -> Result<(), Error> {
258        if self.get_smart_mode() {
259            self.disable();
260            self.set_smart_mode(false);
261            self.enable();
262        }
263
264        self.check_bus_status()?;
265
266        self.i2c_master()
267            .intflag()
268            .modify(|_, w| w.error().clear_bit());
269
270        unsafe {
273            self.i2c_master()
274                .addr()
275                .write(|w| w.addr().bits(encode_read_address(addr)));
276        }
277
278        Ok(())
279    }
280
281    #[inline]
283    pub(super) fn start_read_blocking(&mut self, addr: u8) -> Result<(), Error> {
284        self.start_read(addr)?;
285
286        loop {
288            let intflag = self.i2c_master().intflag().read();
289            if intflag.mb().bit_is_set() {
291                return Err(Error::ArbitrationLost);
292            }
293            if intflag.sb().bit_is_set() || intflag.error().bit_is_set() {
294                break;
295            }
296        }
297
298        self.read_status().check_bus_error()
299    }
300
301    #[cfg(feature = "dma")]
309    #[inline]
310    pub(in super::super) fn start_dma_write(&mut self, address: u8, xfer_len: u8) {
311        if !self.get_smart_mode() {
312            self.disable();
313            self.set_smart_mode(true);
314            self.enable();
315        }
316
317        self.i2c_master().addr().write(|w| unsafe {
318            w.addr().bits(encode_write_address(address));
319            w.len().bits(xfer_len);
320            w.lenen().set_bit()
321        });
322
323        self.sync_sysop();
324    }
325
326    #[cfg(feature = "dma")]
334    #[inline]
335    pub(in super::super) fn start_dma_read(&mut self, address: u8, xfer_len: u8) {
336        if !self.get_smart_mode() {
337            self.disable();
338            self.set_smart_mode(true);
339            self.enable();
340        }
341
342        self.i2c_master().addr().write(|w| unsafe {
343            w.addr().bits(encode_read_address(address));
344            w.len().bits(xfer_len);
345            w.lenen().set_bit()
346        });
347
348        self.sync_sysop();
349    }
350
351    #[inline]
354    pub(super) fn cmd_stop(&mut self) {
355        unsafe {
356            self.i2c_master().ctrlb().modify(|_, w| {
357                w.ackact().set_bit();
359                w.cmd().bits(MASTER_ACT_STOP)
360            });
361        }
362        self.sync_sysop();
363    }
364
365    #[inline]
368    pub(super) fn cmd_repeated_start(&mut self) {
369        unsafe {
370            self.i2c_master().ctrlb().modify(|_, w| {
371                w.ackact().set_bit();
373                w.cmd().bits(MASTER_ACT_REPEATED_START)
374            });
375        }
376        self.sync_sysop();
377    }
378
379    #[inline]
380    pub(super) fn cmd_read(&mut self) {
381        unsafe {
382            self.i2c_master().ctrlb().modify(|_, w| {
383                w.ackact().clear_bit();
385                w.cmd().bits(MASTER_ACT_READ)
386            });
387        }
388        self.sync_sysop();
389    }
390
391    #[inline]
392    pub(super) fn write_one(&mut self, byte: u8) {
393        unsafe {
394            self.i2c_master().data().write(|w| w.bits(byte as DataReg));
395        }
396    }
397
398    #[inline]
399    pub(super) fn send_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
400        for b in bytes {
401            self.write_one(*b);
402
403            loop {
404                let intflag = self.i2c_master().intflag().read();
405                if intflag.mb().bit_is_set() || intflag.error().bit_is_set() {
406                    break;
407                }
408            }
409            self.read_status().check_bus_error()?;
410        }
411        Ok(())
412    }
413
414    #[inline]
415    #[allow(clippy::unnecessary_cast)]
416    pub(super) fn read_one(&mut self) -> u8 {
417        self.i2c_master().data().read().bits() as u8
420    }
421
422    #[inline]
423    pub(super) fn read_one_blocking(&mut self) -> u8 {
424        while !self.i2c_master().intflag().read().sb().bit_is_set() {
425            core::hint::spin_loop();
426        }
427        self.read_one()
428    }
429
430    #[inline]
431    pub(super) fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
432        let mut iter = buffer.iter_mut();
434        *iter.next().expect("buffer len is at least 1") = self.read_one_blocking();
435
436        loop {
437            match iter.next() {
438                None => break,
439                Some(dest) => {
440                    self.cmd_read();
442                    *dest = self.read_one_blocking();
443                }
444            }
445        }
446
447        self.i2c_master()
450            .ctrlb()
451            .modify(|_, w| w.ackact().set_bit());
452
453        Ok(())
454    }
455
456    #[inline]
457    pub(super) fn do_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
458        self.start_write_blocking(addr)?;
459        self.send_bytes(bytes)
460    }
461
462    #[inline]
466    pub(super) fn continue_write(&mut self, bytes: &[u8]) -> Result<(), Error> {
467        self.send_bytes(bytes)
468    }
469
470    #[inline]
471    pub(super) fn do_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
472        self.start_read_blocking(addr)?;
473        self.fill_buffer(buffer)
474    }
475
476    #[inline]
483    pub(super) fn continue_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
484        self.cmd_read();
488
489        self.fill_buffer(buffer)
490    }
491
492    #[inline]
493    pub(super) fn do_write_read(
494        &mut self,
495        addr: u8,
496        bytes: &[u8],
497        buffer: &mut [u8],
498    ) -> Result<(), Error> {
499        self.start_write_blocking(addr)?;
500        self.send_bytes(bytes)?;
501        self.start_read_blocking(addr)?;
502        self.fill_buffer(buffer)?;
503        Ok(())
504    }
505
506    #[inline]
508    pub(super) fn bus_idle(&mut self) {
509        self.i2c_master()
511            .status()
512            .modify(|_, w| unsafe { w.busstate().bits(BusState::Idle as u8) });
513        self.sync_sysop();
515    }
516
517    #[inline]
518    fn sync_sysop(&mut self) {
519        while self.i2c_master().syncbusy().read().sysop().bit_is_set() {}
520    }
521
522    #[inline]
526    pub(super) fn enable(&mut self) {
527        self.enable_peripheral(true);
529        self.bus_idle();
531    }
532
533    #[inline]
534    pub(super) fn disable(&mut self) {
535        self.enable_peripheral(false);
536    }
537
538    #[inline]
541    pub(super) fn enable_peripheral(&mut self, enable: bool) {
542        self.i2c_master()
543            .ctrla()
544            .modify(|_, w| w.enable().bit(enable));
545        while self.i2c_master().syncbusy().read().enable().bit_is_set() {}
546    }
547}
548
549fn encode_write_address(addr_7_bits: u8) -> u16 {
550    (addr_7_bits as u16) << 1
551}
552
553fn encode_read_address(addr_7_bits: u8) -> u16 {
554    ((addr_7_bits as u16) << 1) | 1
555}