esp_hal/i2c/
lp_i2c.rs
1use crate::{
4 gpio::lp_io::LowPowerOutputOpenDrain,
5 peripherals::{LPWR, LP_AON, LP_I2C0, LP_IO, LP_PERI},
6 time::Rate,
7};
8
9const LP_I2C_FILTER_CYC_NUM_DEF: u8 = 7;
10
11#[derive(Debug, Clone, Copy, PartialEq)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14pub enum Error {
15 ExceedingFifo,
17 AckCheckFailed,
19 TimeOut,
21 ArbitrationLost,
23 ExecIncomplete,
25 CommandNrExceeded,
27 InvalidResponse,
29}
30
31#[allow(unused)]
32enum OperationType {
33 Write = 0,
34 Read = 1,
35}
36
37#[allow(unused)]
38#[derive(Eq, PartialEq, Copy, Clone)]
39enum Ack {
40 Ack,
41 Nack,
42}
43
44#[derive(PartialEq)]
45#[allow(unused)]
46enum Command {
47 Start,
48 Stop,
49 End,
50 Write {
51 ack_exp: Ack,
53 ack_check_en: bool,
56 length: u8,
59 },
60 Read {
61 ack_value: Ack,
64 length: u8,
67 },
68}
69
70pub struct LpI2c {
82 i2c: LP_I2C0,
83}
84
85impl LpI2c {
86 pub fn new(
88 i2c: LP_I2C0,
89 _sda: LowPowerOutputOpenDrain<'_, 6>,
90 _scl: LowPowerOutputOpenDrain<'_, 7>,
91 frequency: Rate,
92 ) -> Self {
93 let me = Self { i2c };
94
95 let lp_io = LP_IO::regs();
98 let lp_aon = LP_AON::regs();
99 let lp_peri = LP_PERI::regs();
100
101 unsafe {
102 lp_aon
104 .gpio_mux()
105 .modify(|r, w| w.sel().bits(r.sel().bits() | (1 << 6)));
106 lp_aon
107 .gpio_mux()
108 .modify(|r, w| w.sel().bits(r.sel().bits() | (1 << 7)));
109 lp_io.gpio(6).modify(|_, w| w.mcu_sel().bits(1)); lp_io.gpio(7).modify(|_, w| w.mcu_sel().bits(1));
112
113 lp_io.pin(6).modify(|_, w| w.pad_driver().set_bit());
115 lp_io
118 .out_enable_w1ts()
119 .write(|w| w.enable_w1ts().bits(1 << 6));
120 lp_io.gpio(6).modify(|_, w| w.fun_ie().set_bit());
122
123 lp_io.gpio(6).modify(|_, w| w.fun_wpd().clear_bit());
125 lp_io.gpio(6).modify(|_, w| w.fun_wpu().set_bit());
127
128 lp_io.pin(7).modify(|_, w| w.pad_driver().set_bit());
130 lp_io
133 .out_enable_w1ts()
134 .write(|w| w.enable_w1ts().bits(1 << 7));
135 lp_io.gpio(7).modify(|_, w| w.fun_ie().set_bit());
137 lp_io.gpio(7).modify(|_, w| w.fun_wpd().clear_bit());
139 lp_io.gpio(7).modify(|_, w| w.fun_wpu().set_bit());
141
142 lp_io.gpio(6).modify(|_, w| w.mcu_sel().bits(1));
144 lp_io.gpio(7).modify(|_, w| w.mcu_sel().bits(1));
145 }
146
147 me.i2c
149 .register_block()
150 .clk_conf()
151 .modify(|_, w| w.sclk_active().set_bit());
152
153 lp_peri
155 .clk_en()
156 .modify(|_, w| w.lp_ext_i2c_ck_en().set_bit());
157
158 lp_peri
159 .reset_en()
160 .modify(|_, w| w.lp_ext_i2c_reset_en().set_bit());
161 lp_peri
162 .reset_en()
163 .modify(|_, w| w.lp_ext_i2c_reset_en().clear_bit());
164
165 LPWR::regs()
167 .lpperi()
168 .modify(|_, w| w.lp_i2c_clk_sel().clear_bit());
169
170 me.i2c.register_block().ctr().modify(|_, w| unsafe {
172 w.bits(0);
174 w.sda_force_out().set_bit();
176 w.scl_force_out().set_bit();
177 w.clk_en().set_bit()
179 });
180
181 me.i2c
183 .register_block()
184 .fifo_conf()
185 .modify(|_, w| w.nonfifo_en().clear_bit());
186
187 me.i2c.register_block().ctr().modify(|_, w| {
188 w.tx_lsb_first().clear_bit();
189 w.rx_lsb_first().clear_bit()
190 });
191
192 me.reset_fifo();
193
194 LPWR::regs()
196 .lpperi()
197 .modify(|_, w| w.lp_i2c_clk_sel().clear_bit());
198
199 let source_clk = 16_000_000;
203 let bus_freq = frequency.as_hz();
204
205 let clkm_div: u32 = source_clk / (bus_freq * 1024) + 1;
206 let sclk_freq: u32 = source_clk / clkm_div;
207 let half_cycle: u32 = sclk_freq / bus_freq / 2;
208
209 let scl_low = half_cycle;
211 let scl_wait_high = if bus_freq >= 80 * 1000 {
216 half_cycle / 2 - 2
217 } else {
218 half_cycle / 4
219 };
220 let scl_high = half_cycle - scl_wait_high;
221 let sda_hold = half_cycle / 4;
222 let sda_sample = half_cycle / 2; let setup = half_cycle;
224 let hold = half_cycle;
225 let tout = (4 * 8 - (5 * half_cycle).leading_zeros()) + 2;
228
229 let scl_low_period = scl_low - 1;
237 let scl_high_period = scl_high;
238 let scl_wait_high_period = scl_wait_high;
239 let sda_hold_time = sda_hold - 1;
241 let sda_sample_time = sda_sample - 1;
242 let scl_rstart_setup_time = setup - 1;
244 let scl_stop_setup_time = setup - 1;
245 let scl_start_hold_time = hold - 1;
247 let scl_stop_hold_time = hold - 1;
248 let time_out_value = tout;
249 let time_out_en = true;
250
251 unsafe {
253 me.i2c.register_block().clk_conf().modify(|_, w| {
254 w.sclk_sel().clear_bit();
255 w.sclk_div_num().bits((clkm_div - 1) as u8)
256 });
257
258 me.i2c
260 .register_block()
261 .scl_low_period()
262 .write(|w| w.scl_low_period().bits(scl_low_period as u16));
263
264 me.i2c.register_block().scl_high_period().write(|w| {
265 w.scl_high_period().bits(scl_high_period as u16);
266 w.scl_wait_high_period().bits(scl_wait_high_period as u8)
267 });
268 me.i2c
270 .register_block()
271 .sda_hold()
272 .write(|w| w.time().bits(sda_hold_time as u16));
273 me.i2c
274 .register_block()
275 .sda_sample()
276 .write(|w| w.time().bits(sda_sample_time as u16));
277
278 me.i2c
280 .register_block()
281 .scl_rstart_setup()
282 .write(|w| w.time().bits(scl_rstart_setup_time as u16));
283 me.i2c
284 .register_block()
285 .scl_stop_setup()
286 .write(|w| w.time().bits(scl_stop_setup_time as u16));
287
288 me.i2c
290 .register_block()
291 .scl_start_hold()
292 .write(|w| w.time().bits(scl_start_hold_time as u16));
293 me.i2c
294 .register_block()
295 .scl_stop_hold()
296 .write(|w| w.time().bits(scl_stop_hold_time as u16));
297
298 me.i2c.register_block().to().write(|w| {
299 w.time_out_en().bit(time_out_en);
300 w.time_out_value().bits(time_out_value.try_into().unwrap())
301 });
302 }
303
304 me.i2c
308 .register_block()
309 .filter_cfg()
310 .modify(|_, w| unsafe { w.sda_filter_thres().bits(LP_I2C_FILTER_CYC_NUM_DEF) });
311 me.i2c
312 .register_block()
313 .filter_cfg()
314 .modify(|_, w| unsafe { w.scl_filter_thres().bits(LP_I2C_FILTER_CYC_NUM_DEF) });
315
316 me.i2c
317 .register_block()
318 .filter_cfg()
319 .modify(|_, w| w.sda_filter_en().set_bit());
320 me.i2c
321 .register_block()
322 .filter_cfg()
323 .modify(|_, w| w.scl_filter_en().set_bit());
324
325 me.i2c
327 .register_block()
328 .ctr()
329 .modify(|_, w| w.rx_full_ack_level().set_bit());
330
331 me.lp_i2c_update();
333
334 me
335 }
336
337 fn lp_i2c_update(&self) {
339 self.i2c
340 .register_block()
341 .ctr()
342 .modify(|_, w| w.conf_upgate().set_bit());
343 }
344
345 fn reset_fifo(&self) {
347 self.i2c
348 .register_block()
349 .fifo_conf()
350 .modify(|_, w| w.tx_fifo_rst().set_bit());
351
352 self.i2c
353 .register_block()
354 .fifo_conf()
355 .modify(|_, w| w.tx_fifo_rst().clear_bit());
356
357 self.i2c
358 .register_block()
359 .fifo_conf()
360 .modify(|_, w| w.rx_fifo_rst().set_bit());
361
362 self.i2c
363 .register_block()
364 .fifo_conf()
365 .modify(|_, w| w.rx_fifo_rst().clear_bit());
366 }
367}