1use crate::{
4    gpio::lp_io::LowPowerOutputOpenDrain,
5    peripherals::{LP_AON, LP_I2C0, LP_IO, LP_PERI, LPWR},
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<'static>,
83}
84
85impl LpI2c {
86    pub fn new(
88        i2c: LP_I2C0<'static>,
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}