1use core::marker::PhantomData;
2use core::time::Duration;
3
4use embedded_hal::i2c::{ErrorKind, NoAcknowledgeSource};
5
6use esp_idf_sys::*;
7
8use crate::delay::*;
9use crate::gpio::*;
10use crate::interrupt::InterruptType;
11use crate::units::*;
12
13pub use embedded_hal::i2c::Operation;
14
15crate::embedded_hal_error!(
16 I2cError,
17 embedded_hal::i2c::Error,
18 embedded_hal::i2c::ErrorKind
19);
20
21#[allow(unused)]
22#[cfg(not(esp32c2))]
23const APB_TICK_PERIOD_NS: u32 = 1_000_000_000 / APB_CLK_FREQ;
24
25#[cfg(esp_idf_xtal_freq_48)]
26#[allow(unused)]
27const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 48_000_000;
28#[cfg(esp_idf_xtal_freq_40)]
29#[allow(unused)]
30const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 40_000_000;
31#[cfg(esp_idf_xtal_freq_32)]
32#[allow(unused)]
33const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 32_000_000;
34#[cfg(esp_idf_xtal_freq_26)]
35#[allow(unused)]
36const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 26_000_000;
37
38#[cfg(all(
39 not(any(
40 esp_idf_xtal_freq_48,
41 esp_idf_xtal_freq_40,
42 esp_idf_xtal_freq_32,
43 esp_idf_xtal_freq_26
44 )),
45 any(esp32c5, esp32c61)
46))]
47const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 48_000_000;
48#[cfg(not(esp_idf_version_at_least_6_0_0))]
49#[cfg(all(
50 not(any(
51 esp_idf_xtal_freq_48,
52 esp_idf_xtal_freq_40,
53 esp_idf_xtal_freq_32,
54 esp_idf_xtal_freq_26
55 )),
56 not(any(esp32, esp32s2, esp32c2, esp32c5, esp32c61))
57))]
58const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / XTAL_CLK_FREQ;
59#[cfg(esp_idf_version_at_least_6_0_0)]
61#[cfg(all(
62 not(any(
63 esp_idf_xtal_freq_48,
64 esp_idf_xtal_freq_40,
65 esp_idf_xtal_freq_32,
66 esp_idf_xtal_freq_26
67 )),
68 not(any(esp32, esp32s2, esp32c2, esp32c5, esp32c61))
69))]
70const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 40_000_000;
71
72#[derive(Copy, Clone, Debug)]
73pub struct APBTickType(::core::ffi::c_int);
74impl From<Duration> for APBTickType {
75 #[cfg(any(esp32, esp32s2))]
76 #[allow(clippy::manual_div_ceil)]
77 fn from(duration: Duration) -> Self {
78 APBTickType(
79 ((duration.as_nanos() + APB_TICK_PERIOD_NS as u128 - 1) / APB_TICK_PERIOD_NS as u128)
80 as ::core::ffi::c_int,
81 )
82 }
83 #[cfg(not(any(esp32, esp32s2)))]
84 fn from(duration: Duration) -> Self {
86 let target_ns = duration.as_nanos() as u64;
87 let timeout_in_xtal_clock_cycles = target_ns / (XTAL_TICK_PERIOD_NS as u64);
88 let register_value = timeout_in_xtal_clock_cycles.ilog2()
90 + (if timeout_in_xtal_clock_cycles.leading_zeros()
91 + timeout_in_xtal_clock_cycles.trailing_zeros()
92 + 1
93 < 64
94 {
95 1
96 } else {
97 0
98 });
99 if register_value <= 22 {
100 return APBTickType(register_value as ::core::ffi::c_int);
101 }
102 APBTickType(32 as ::core::ffi::c_int)
104 }
105}
106
107pub type I2cConfig = config::Config;
108#[cfg(not(esp32c2))]
109pub type I2cSlaveConfig = config::SlaveConfig;
110
111pub mod config {
113 use enumset::EnumSet;
114
115 use super::APBTickType;
116 use crate::{interrupt::InterruptType, units::*};
117
118 #[derive(Debug, Clone)]
120 pub struct Config {
121 pub baudrate: Hertz,
122 pub sda_pullup_enabled: bool,
123 pub scl_pullup_enabled: bool,
124 pub timeout: Option<APBTickType>,
125 pub intr_flags: EnumSet<InterruptType>,
126 }
127
128 impl Config {
129 pub fn new() -> Self {
130 Default::default()
131 }
132
133 #[must_use]
134 pub fn baudrate(mut self, baudrate: Hertz) -> Self {
135 self.baudrate = baudrate;
136 self
137 }
138
139 #[must_use]
140 pub fn sda_enable_pullup(mut self, enable: bool) -> Self {
141 self.sda_pullup_enabled = enable;
142 self
143 }
144
145 #[must_use]
146 pub fn scl_enable_pullup(mut self, enable: bool) -> Self {
147 self.scl_pullup_enabled = enable;
148 self
149 }
150
151 #[must_use]
152 pub fn timeout(mut self, timeout: APBTickType) -> Self {
153 self.timeout = Some(timeout);
154 self
155 }
156
157 #[must_use]
158 pub fn intr_flags(mut self, flags: EnumSet<InterruptType>) -> Self {
159 self.intr_flags = flags;
160 self
161 }
162 }
163
164 impl Default for Config {
165 fn default() -> Self {
166 Self {
167 baudrate: Hertz(1_000_000),
168 sda_pullup_enabled: true,
169 scl_pullup_enabled: true,
170 timeout: None,
171 intr_flags: EnumSet::<InterruptType>::empty(),
172 }
173 }
174 }
175
176 #[cfg(not(esp32c2))]
178 #[derive(Debug, Clone)]
179 pub struct SlaveConfig {
180 pub sda_pullup_enabled: bool,
181 pub scl_pullup_enabled: bool,
182 pub rx_buf_len: usize,
183 pub tx_buf_len: usize,
184 pub intr_flags: EnumSet<InterruptType>,
185 }
186
187 #[cfg(not(esp32c2))]
188 impl SlaveConfig {
189 pub fn new() -> Self {
190 Default::default()
191 }
192
193 #[must_use]
194 pub fn sda_enable_pullup(mut self, enable: bool) -> Self {
195 self.sda_pullup_enabled = enable;
196 self
197 }
198
199 #[must_use]
200 pub fn scl_enable_pullup(mut self, enable: bool) -> Self {
201 self.scl_pullup_enabled = enable;
202 self
203 }
204
205 #[must_use]
206 pub fn rx_buffer_length(mut self, len: usize) -> Self {
207 self.rx_buf_len = len;
208 self
209 }
210
211 #[must_use]
212 pub fn tx_buffer_length(mut self, len: usize) -> Self {
213 self.tx_buf_len = len;
214 self
215 }
216
217 #[must_use]
218 pub fn intr_flags(mut self, flags: EnumSet<InterruptType>) -> Self {
219 self.intr_flags = flags;
220 self
221 }
222 }
223
224 #[cfg(not(esp32c2))]
225 impl Default for SlaveConfig {
226 fn default() -> Self {
227 Self {
228 sda_pullup_enabled: true,
229 scl_pullup_enabled: true,
230 rx_buf_len: 0,
231 tx_buf_len: 0,
232 intr_flags: EnumSet::<InterruptType>::empty(),
233 }
234 }
235 }
236}
237
238pub trait I2c: Send {
239 fn port() -> i2c_port_t;
240}
241
242pub struct I2cDriver<'d> {
243 i2c: u8,
244 _p: PhantomData<&'d mut ()>,
245}
246
247impl<'d> I2cDriver<'d> {
248 pub fn new<I2C: I2c + 'd>(
249 _i2c: I2C,
250 sda: impl InputPin + OutputPin + 'd,
251 scl: impl InputPin + OutputPin + 'd,
252 config: &config::Config,
253 ) -> Result<Self, EspError> {
254 if config.baudrate > 1.MHz().into() {
256 return Err(EspError::from_infallible::<ESP_ERR_INVALID_ARG>());
257 }
258
259 let sys_config = i2c_config_t {
260 mode: i2c_mode_t_I2C_MODE_MASTER,
261 sda_io_num: sda.pin() as _,
262 sda_pullup_en: config.sda_pullup_enabled,
263 scl_io_num: scl.pin() as _,
264 scl_pullup_en: config.scl_pullup_enabled,
265 __bindgen_anon_1: i2c_config_t__bindgen_ty_1 {
266 master: i2c_config_t__bindgen_ty_1__bindgen_ty_1 {
267 clk_speed: config.baudrate.into(),
268 },
269 },
270 ..Default::default()
271 };
272
273 esp!(unsafe { i2c_param_config(I2C::port(), &sys_config) })?;
274
275 esp!(unsafe {
276 i2c_driver_install(
277 I2C::port(),
278 i2c_mode_t_I2C_MODE_MASTER,
279 0, 0, InterruptType::to_native(config.intr_flags) as _,
282 )
283 })?;
284
285 if let Some(timeout) = config.timeout {
286 esp!(unsafe { i2c_set_timeout(I2C::port(), timeout.0) })?;
287 }
288
289 Ok(I2cDriver {
290 i2c: I2C::port() as _,
291 _p: PhantomData,
292 })
293 }
294
295 pub fn read(
296 &mut self,
297 addr: u8,
298 buffer: &mut [u8],
299 timeout: TickType_t,
300 ) -> Result<(), EspError> {
301 let mut command_link = CommandLink::new()?;
302
303 command_link.master_start()?;
304 command_link.master_write_byte((addr << 1) | (i2c_rw_t_I2C_MASTER_READ as u8), true)?;
305
306 if !buffer.is_empty() {
307 command_link.master_read(buffer, AckType::LastNack)?;
308 }
309
310 command_link.master_stop()?;
311
312 self.cmd_begin(&command_link, timeout)
313 }
314
315 pub fn write(&mut self, addr: u8, bytes: &[u8], timeout: TickType_t) -> Result<(), EspError> {
316 let mut command_link = CommandLink::new()?;
317
318 command_link.master_start()?;
319 command_link.master_write_byte((addr << 1) | (i2c_rw_t_I2C_MASTER_WRITE as u8), true)?;
320
321 if !bytes.is_empty() {
322 command_link.master_write(bytes, true)?;
323 }
324
325 command_link.master_stop()?;
326
327 self.cmd_begin(&command_link, timeout)
328 }
329
330 pub fn write_read(
331 &mut self,
332 addr: u8,
333 bytes: &[u8],
334 buffer: &mut [u8],
335 timeout: TickType_t,
336 ) -> Result<(), EspError> {
337 let mut command_link = CommandLink::new()?;
338
339 command_link.master_start()?;
340 command_link.master_write_byte((addr << 1) | (i2c_rw_t_I2C_MASTER_WRITE as u8), true)?;
341
342 if !bytes.is_empty() {
343 command_link.master_write(bytes, true)?;
344 }
345
346 command_link.master_start()?;
347 command_link.master_write_byte((addr << 1) | (i2c_rw_t_I2C_MASTER_READ as u8), true)?;
348
349 if !buffer.is_empty() {
350 command_link.master_read(buffer, AckType::LastNack)?;
351 }
352
353 command_link.master_stop()?;
354
355 self.cmd_begin(&command_link, timeout)
356 }
357
358 pub fn transaction(
359 &mut self,
360 address: u8,
361 operations: &mut [Operation<'_>],
362 timeout: TickType_t,
363 ) -> Result<(), EspError> {
364 let mut command_link = CommandLink::new()?;
365
366 let last_op_index = operations.len() - 1;
367 let mut prev_was_read = None;
368
369 for (i, operation) in operations.iter_mut().enumerate() {
370 match operation {
371 Operation::Read(buf) => {
372 if Some(true) != prev_was_read {
373 command_link.master_start()?;
374 command_link.master_write_byte(
375 (address << 1) | (i2c_rw_t_I2C_MASTER_READ as u8),
376 true,
377 )?;
378 }
379 prev_was_read = Some(true);
380
381 if !buf.is_empty() {
382 let ack = if i == last_op_index {
383 AckType::LastNack
384 } else {
385 AckType::Ack
386 };
387
388 command_link.master_read(buf, ack)?;
389 }
390 }
391 Operation::Write(buf) => {
392 if Some(false) != prev_was_read {
393 command_link.master_start()?;
394 command_link.master_write_byte(
395 (address << 1) | (i2c_rw_t_I2C_MASTER_WRITE as u8),
396 true,
397 )?;
398 }
399 prev_was_read = Some(false);
400
401 if !buf.is_empty() {
402 command_link.master_write(buf, true)?;
403 }
404 }
405 }
406 }
407
408 command_link.master_stop()?;
409
410 self.cmd_begin(&command_link, timeout)
411 }
412
413 fn cmd_begin(
414 &mut self,
415 command_link: &CommandLink,
416 timeout: TickType_t,
417 ) -> Result<(), EspError> {
418 esp!(unsafe { i2c_master_cmd_begin(self.port(), command_link.0, timeout) })
419 }
420
421 pub fn port(&self) -> i2c_port_t {
422 self.i2c as _
423 }
424}
425
426impl Drop for I2cDriver<'_> {
427 fn drop(&mut self) {
428 esp!(unsafe { i2c_driver_delete(self.port()) }).unwrap();
429 }
430}
431
432unsafe impl Send for I2cDriver<'_> {}
433
434impl embedded_hal_0_2::blocking::i2c::Read for I2cDriver<'_> {
435 type Error = I2cError;
436
437 fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
438 I2cDriver::read(self, addr, buffer, BLOCK).map_err(to_i2c_err)
439 }
440}
441
442impl embedded_hal_0_2::blocking::i2c::Write for I2cDriver<'_> {
443 type Error = I2cError;
444
445 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
446 I2cDriver::write(self, addr, bytes, BLOCK).map_err(to_i2c_err)
447 }
448}
449
450impl embedded_hal_0_2::blocking::i2c::WriteRead for I2cDriver<'_> {
451 type Error = I2cError;
452
453 fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
454 I2cDriver::write_read(self, addr, bytes, buffer, BLOCK).map_err(to_i2c_err)
455 }
456}
457
458impl embedded_hal::i2c::ErrorType for I2cDriver<'_> {
459 type Error = I2cError;
460}
461
462impl embedded_hal::i2c::I2c<embedded_hal::i2c::SevenBitAddress> for I2cDriver<'_> {
463 fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
464 I2cDriver::read(self, addr, buffer, BLOCK).map_err(to_i2c_err)
465 }
466
467 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
468 I2cDriver::write(self, addr, bytes, BLOCK).map_err(to_i2c_err)
469 }
470
471 fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
472 I2cDriver::write_read(self, addr, bytes, buffer, BLOCK).map_err(to_i2c_err)
473 }
474
475 fn transaction(
476 &mut self,
477 address: u8,
478 operations: &mut [embedded_hal::i2c::Operation<'_>],
479 ) -> Result<(), Self::Error> {
480 I2cDriver::transaction(self, address, operations, BLOCK).map_err(to_i2c_err)
481 }
482}
483
484fn to_i2c_err(err: EspError) -> I2cError {
485 if err.code() == ESP_FAIL {
486 I2cError::new(ErrorKind::NoAcknowledge(NoAcknowledgeSource::Unknown), err)
487 } else {
488 I2cError::other(err)
489 }
490}
491
492#[cfg(not(esp32c2))]
493pub struct I2cSlaveDriver<'d> {
494 i2c: u8,
495 _p: PhantomData<&'d mut ()>,
496}
497
498#[cfg(not(esp32c2))]
499unsafe impl Send for I2cSlaveDriver<'_> {}
500
501#[cfg(not(esp32c2))]
502impl<'d> I2cSlaveDriver<'d> {
503 pub fn new<I2C: I2c + 'd>(
504 _i2c: I2C,
505 sda: impl InputPin + OutputPin + 'd,
506 scl: impl InputPin + OutputPin + 'd,
507 slave_addr: u8,
508 config: &config::SlaveConfig,
509 ) -> Result<Self, EspError> {
510 let sys_config = i2c_config_t {
511 mode: i2c_mode_t_I2C_MODE_SLAVE,
512 sda_io_num: sda.pin() as _,
513 sda_pullup_en: config.sda_pullup_enabled,
514 scl_io_num: scl.pin() as _,
515 scl_pullup_en: config.scl_pullup_enabled,
516 __bindgen_anon_1: i2c_config_t__bindgen_ty_1 {
517 slave: i2c_config_t__bindgen_ty_1__bindgen_ty_2 {
518 slave_addr: slave_addr as u16,
519 addr_10bit_en: 0, maximum_speed: 0,
521 },
522 },
523 ..Default::default()
524 };
525
526 esp!(unsafe { i2c_param_config(I2C::port(), &sys_config) })?;
527
528 esp!(unsafe {
529 i2c_driver_install(
530 I2C::port(),
531 i2c_mode_t_I2C_MODE_SLAVE,
532 config.rx_buf_len,
533 config.tx_buf_len,
534 InterruptType::to_native(config.intr_flags) as _,
535 )
536 })?;
537
538 Ok(Self {
539 i2c: I2C::port() as _,
540 _p: PhantomData,
541 })
542 }
543
544 pub fn read(&mut self, buffer: &mut [u8], timeout: TickType_t) -> Result<usize, EspError> {
545 let n = unsafe {
546 i2c_slave_read_buffer(self.port(), buffer.as_mut_ptr(), buffer.len(), timeout)
547 };
548
549 if n > 0 {
550 Ok(n as usize)
551 } else {
552 Err(EspError::from_infallible::<ESP_ERR_TIMEOUT>())
553 }
554 }
555
556 pub fn write(&mut self, bytes: &[u8], timeout: TickType_t) -> Result<usize, EspError> {
557 let n = unsafe {
558 i2c_slave_write_buffer(self.port(), bytes.as_ptr(), bytes.len() as i32, timeout)
559 };
560
561 if n > 0 {
562 Ok(n as usize)
563 } else {
564 Err(EspError::from_infallible::<ESP_ERR_TIMEOUT>())
565 }
566 }
567
568 pub fn port(&self) -> i2c_port_t {
569 self.i2c as _
570 }
571}
572
573#[cfg(not(esp32c2))]
574impl Drop for I2cSlaveDriver<'_> {
575 fn drop(&mut self) {
576 esp!(unsafe { i2c_driver_delete(self.port()) }).unwrap();
577 }
578}
579
580#[repr(u32)]
581enum AckType {
582 Ack = i2c_ack_type_t_I2C_MASTER_ACK,
583 #[allow(dead_code)]
584 Nack = i2c_ack_type_t_I2C_MASTER_NACK,
585 LastNack = i2c_ack_type_t_I2C_MASTER_LAST_NACK,
586}
587
588struct CommandLink<'buffers>(i2c_cmd_handle_t, PhantomData<&'buffers u8>);
589
590impl<'buffers> CommandLink<'buffers> {
591 fn new() -> Result<Self, EspError> {
592 let handle = unsafe { i2c_cmd_link_create() };
593
594 if handle.is_null() {
595 return Err(EspError::from_infallible::<ESP_ERR_NO_MEM>());
596 }
597
598 Ok(CommandLink(handle, PhantomData))
599 }
600
601 fn master_start(&mut self) -> Result<(), EspError> {
602 esp!(unsafe { i2c_master_start(self.0) })
603 }
604
605 fn master_stop(&mut self) -> Result<(), EspError> {
606 esp!(unsafe { i2c_master_stop(self.0) })
607 }
608
609 fn master_write_byte(&mut self, data: u8, ack_en: bool) -> Result<(), EspError> {
610 esp!(unsafe { i2c_master_write_byte(self.0, data, ack_en) })
611 }
612
613 fn master_write(&mut self, buf: &'buffers [u8], ack_en: bool) -> Result<(), EspError> {
614 esp!(unsafe { i2c_master_write(self.0, buf.as_ptr(), buf.len(), ack_en,) })
615 }
616
617 fn master_read(&mut self, buf: &'buffers mut [u8], ack: AckType) -> Result<(), EspError> {
618 esp!(unsafe { i2c_master_read(self.0, buf.as_mut_ptr().cast(), buf.len(), ack as u32,) })
619 }
620}
621
622impl Drop for CommandLink<'_> {
623 fn drop(&mut self) {
624 unsafe {
625 i2c_cmd_link_delete(self.0);
626 }
627 }
628}
629
630macro_rules! impl_i2c {
631 ($i2c:ident: $port:expr) => {
632 crate::impl_peripheral!($i2c);
633
634 impl I2c for $i2c<'_> {
635 #[inline(always)]
636 fn port() -> i2c_port_t {
637 $port
638 }
639 }
640 };
641}
642
643impl_i2c!(I2C0: 0);
644#[cfg(not(any(esp32c3, esp32c2, esp32c6)))]
645impl_i2c!(I2C1: 1);