1use hal::blocking::i2c::{Read, Write, WriteRead};
3
4use crate::gpio::gpiob::{PB10, PB11, PB6, PB7};
5use crate::gpio::{AltMode, OpenDrain, Output};
6use crate::prelude::*;
7use crate::rcc::Rcc;
8use crate::stm32::{I2C1, I2C2};
9use crate::time::Hertz;
10
11pub struct I2c<I2C, PINS> {
13 i2c: I2C,
14 pins: PINS,
15}
16
17pub trait Pins<I2c> {
18 fn setup(&self);
19}
20
21impl Pins<I2C1> for (PB6<Output<OpenDrain>>, PB7<Output<OpenDrain>>) {
22 fn setup(&self) {
23 self.0.set_alt_mode(AltMode::I2C);
24 self.1.set_alt_mode(AltMode::I2C);
25 }
26}
27
28impl Pins<I2C2> for (PB10<Output<OpenDrain>>, PB11<Output<OpenDrain>>) {
29 fn setup(&self) {
30 self.0.set_alt_mode(AltMode::I2C);
31 self.1.set_alt_mode(AltMode::I2C);
32 }
33}
34
35#[derive(Debug)]
36pub enum Error {
37 OVERRUN,
38 NACK,
39}
40
41macro_rules! i2c {
42 ($I2CX:ident, $i2cx:ident, $i2cxen:ident, $i2crst:ident) => {
43 impl<PINS> I2c<$I2CX, PINS> {
44 pub fn $i2cx(i2c: $I2CX, pins: PINS, speed: Hertz, rcc: &mut Rcc) -> Self
45 where
46 PINS: Pins<$I2CX>,
47 {
48 pins.setup();
49 let speed: Hertz = speed.into();
50
51 rcc.rb.apb1enr.modify(|_, w| w.$i2cxen().set_bit());
53
54 rcc.rb.apb1rstr.modify(|_, w| w.$i2crst().set_bit());
56 rcc.rb.apb1rstr.modify(|_, w| w.$i2crst().clear_bit());
57
58 i2c.cr1.modify(|_, w| w.pe().clear_bit());
60
61 let clock = rcc.clocks.apb1_clk().0;
63 let freq = clock / 1_000_000;
64 assert!(freq >= 2 && freq <= 50);
65
66 i2c.cr2.write(|w| unsafe { w.freq().bits(freq as u8) });
68
69 let trise = if speed <= 100_u32.khz().into() {
70 freq + 1
71 } else {
72 (freq * 300) / 1000 + 1
73 };
74
75 i2c.trise.write(|w| w.trise().bits(trise as u8));
77
78 if speed <= 100_u32.khz().into() {
80 let ccr = {
81 let ccr = clock / (speed.0 * 2);
82 if ccr < 4 {
83 4
84 } else {
85 ccr
86 }
87 };
88
89 i2c.ccr.write(|w| unsafe {
91 w.f_s()
92 .clear_bit()
93 .duty()
94 .clear_bit()
95 .ccr()
96 .bits(ccr as u16)
97 });
98 } else {
99 const DUTYCYCLE: u8 = 0;
100 if DUTYCYCLE == 0 {
101 let ccr = clock / (speed.0 * 3);
102 let ccr = if ccr < 1 { 1 } else { ccr };
103
104 i2c.ccr.write(|w| unsafe {
106 w.f_s().set_bit().duty().clear_bit().ccr().bits(ccr as u16)
107 });
108 } else {
109 let ccr = clock / (speed.0 * 25);
110 let ccr = if ccr < 1 { 1 } else { ccr };
111
112 i2c.ccr.write(|w| unsafe {
114 w.f_s().set_bit().duty().set_bit().ccr().bits(ccr as u16)
115 });
116 }
117 }
118
119 i2c.cr1.modify(|_, w| w.pe().set_bit());
121
122 I2c { i2c, pins }
123 }
124
125 pub fn release(self) -> ($I2CX, PINS) {
126 (self.i2c, self.pins)
127 }
128
129 fn send_byte(&self, byte: u8) -> Result<(), Error> {
130 while self.i2c.sr1.read().tx_e().bit_is_clear() {}
132
133 self.i2c.dr.write(|w| unsafe { w.bits(u32::from(byte)) });
135
136 while {
138 let sr1 = self.i2c.sr1.read();
139
140 if sr1.af().bit_is_set() {
142 return Err(Error::NACK);
143 }
144
145 sr1.btf().bit_is_clear()
146 } {}
147
148 Ok(())
149 }
150
151 fn recv_byte(&self) -> Result<u8, Error> {
152 while self.i2c.sr1.read().rx_ne().bit_is_clear() {}
153 let value = self.i2c.dr.read().bits() as u8;
154 Ok(value)
155 }
156 }
157
158 impl<PINS> WriteRead for I2c<$I2CX, PINS> {
159 type Error = Error;
160
161 fn write_read(
162 &mut self,
163 addr: u8,
164 bytes: &[u8],
165 buffer: &mut [u8],
166 ) -> Result<(), Self::Error> {
167 self.write(addr, bytes)?;
168 self.read(addr, buffer)?;
169
170 Ok(())
171 }
172 }
173
174 impl<PINS> Write for I2c<$I2CX, PINS> {
175 type Error = Error;
176
177 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
178 self.i2c.cr1.modify(|_, w| w.start().set_bit());
180
181 while {
183 let sr1 = self.i2c.sr1.read();
184 sr1.sb().bit_is_clear()
185 } {}
186
187 while {
189 let sr2 = self.i2c.sr2.read();
190 sr2.msl().bit_is_clear() && sr2.busy().bit_is_clear()
191 } {}
192
193 self.i2c
195 .dr
196 .write(|w| unsafe { w.bits(u32::from(addr) << 1) });
197
198 while {
200 let sr1 = self.i2c.sr1.read();
201 sr1.addr().bit_is_clear()
202 } {}
203
204 self.i2c.sr2.read();
206
207 for c in bytes {
209 self.send_byte(*c)?;
210 }
211
212 Ok(())
214 }
215 }
216
217 impl<PINS> Read for I2c<$I2CX, PINS> {
218 type Error = Error;
219
220 fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
221 self.i2c
223 .cr1
224 .modify(|_, w| w.start().set_bit().ack().set_bit());
225
226 while {
228 let sr1 = self.i2c.sr1.read();
229 sr1.sb().bit_is_clear()
230 } {}
231
232 while {
234 let sr2 = self.i2c.sr2.read();
235 sr2.msl().bit_is_clear() && sr2.busy().bit_is_clear()
236 } {}
237
238 self.i2c
240 .dr
241 .write(|w| unsafe { w.bits((u32::from(addr) << 1) + 1) });
242
243 while {
245 let sr1 = self.i2c.sr1.read();
246 sr1.addr().bit_is_clear()
247 } {}
248
249 self.i2c.sr2.read();
251
252 for c in buffer {
254 *c = self.recv_byte()?;
255 }
256
257 self.i2c.cr1.modify(|_, w| w.stop().set_bit());
259
260 Ok(())
262 }
263 }
264
265 impl I2cExt<$I2CX> for $I2CX {
266 fn i2c<PINS, T>(self, pins: PINS, speed: T, rcc: &mut Rcc) -> I2c<$I2CX, PINS>
267 where
268 PINS: Pins<$I2CX>,
269 T: Into<Hertz>,
270 {
271 I2c::$i2cx(self, pins, speed.into(), rcc)
272 }
273 }
274 };
275}
276
277pub trait I2cExt<I2C> {
278 fn i2c<PINS, T>(self, pins: PINS, speed: T, rcc: &mut Rcc) -> I2c<I2C, PINS>
279 where
280 PINS: Pins<I2C>,
281 T: Into<Hertz>;
282}
283
284i2c!(I2C1, i2c1, i2c1en, i2c1rst);
285i2c!(I2C2, i2c2, i2c2en, i2c2rst);