1use stm32::{I2C1, RCC};
2
3use hal::blocking::i2c::{Write, WriteRead};
4
5use core::cmp;
6use gpio::gpioa::{PA10, PA11, PA12, PA9};
7use gpio::gpiob::{PB10, PB11, PB13, PB14, PB6, PB7, PB8, PB9};
8use gpio::gpiof::{PF0, PF1};
9use gpio::{Alternate, AF1, AF4, AF5};
10use time::{KiloHertz, U32Ext};
11
12pub struct I2c<I2C, PINS> {
14 i2c: I2C,
15 pins: PINS,
16}
17
18pub trait Pins<I2c> {}
19
20impl Pins<I2C1> for (PA9<Alternate<AF4>>, PA10<Alternate<AF4>>) {}
21impl Pins<I2C1> for (PA11<Alternate<AF5>>, PA12<Alternate<AF5>>) {}
22impl Pins<I2C1> for (PB6<Alternate<AF1>>, PB7<Alternate<AF1>>) {}
23impl Pins<I2C1> for (PB8<Alternate<AF1>>, PB9<Alternate<AF1>>) {}
24impl Pins<I2C1> for (PB10<Alternate<AF1>>, PB11<Alternate<AF1>>) {}
25impl Pins<I2C1> for (PB13<Alternate<AF5>>, PB14<Alternate<AF5>>) {}
26impl Pins<I2C1> for (PF1<Alternate<AF1>>, PF0<Alternate<AF1>>) {}
27
28#[derive(Debug)]
29pub enum Error {
30 OVERRUN,
31 NACK,
32}
33
34impl<PINS> I2c<I2C1, PINS> {
35 pub fn i2c1(i2c: I2C1, pins: PINS, speed: KiloHertz) -> Self
36 where
37 PINS: Pins<I2C1>,
38 {
39 let rcc = unsafe { &(*RCC::ptr()) };
41
42 rcc.apb1enr.modify(|_, w| w.i2c1en().set_bit());
44
45 rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit());
47 rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit());
48
49 i2c.cr1.modify(|_, w| w.pe().clear_bit());
51
52 let presc;
54 let scldel;
55 let sdadel;
56 let sclh;
57 let scll;
58
59 const FREQ: u32 = 8_000_000;
61
62 if speed <= 100_u32.khz() {
64 presc = 1;
65 scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8;
66 sclh = scll - 4;
67 sdadel = 2;
68 scldel = 4;
69 } else {
70 presc = 0;
71 scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8;
72 sclh = scll - 6;
73 sdadel = 1;
74 scldel = 3;
75 }
76
77 i2c.timingr.write(|w| {
79 w.presc()
80 .bits(presc)
81 .scldel()
82 .bits(scldel)
83 .sdadel()
84 .bits(sdadel)
85 .sclh()
86 .bits(sclh)
87 .scll()
88 .bits(scll)
89 });
90
91 i2c.cr1.modify(|_, w| w.pe().set_bit());
93
94 I2c { i2c, pins }
95 }
96
97 pub fn release(self) -> (I2C1, PINS) {
98 (self.i2c, self.pins)
99 }
100
101 fn send_byte(&self, byte: u8) -> Result<(), Error> {
102 while self.i2c.isr.read().txis().bit_is_clear() {}
104
105 self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) });
107
108 if self.i2c.isr.read().nackf().bit_is_set() {
110 self.i2c
111 .icr
112 .write(|w| w.stopcf().set_bit().nackcf().set_bit());
113 return Err(Error::NACK);
114 }
115
116 Ok(())
117 }
118
119 fn recv_byte(&self) -> Result<u8, Error> {
120 while self.i2c.isr.read().rxne().bit_is_clear() {}
121 let value = self.i2c.rxdr.read().bits() as u8;
122 Ok(value)
123 }
124}
125
126impl<PINS> WriteRead for I2c<I2C1, PINS> {
127 type Error = Error;
128
129 fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
130 self.i2c.cr2.modify(|_, w| {
133 w.sadd()
134 .bits(u16::from(addr) << 1)
135 .nbytes()
136 .bits(bytes.len() as u8)
137 .rd_wrn()
138 .clear_bit()
139 .autoend()
140 .clear_bit()
141 });
142
143 self.i2c.cr2.modify(|_, w| w.start().set_bit());
145
146 let mut isr;
149 while {
150 isr = self.i2c.isr.read();
151 isr.txis().bit_is_clear()
152 && isr.nackf().bit_is_clear()
153 && isr.stopf().bit_is_clear()
154 && isr.tc().bit_is_clear()
155 } {}
156
157 if isr.nackf().bit_is_set() {
159 self.i2c
160 .icr
161 .write(|w| w.stopcf().set_bit().nackcf().set_bit());
162 return Err(Error::NACK);
163 }
164
165 for c in bytes {
166 self.send_byte(*c)?;
167 }
168
169 while self.i2c.isr.read().tc().bit_is_clear() {}
171
172 self.i2c.cr2.modify(|_, w| {
175 w.sadd()
176 .bits(u16::from(addr) << 1)
177 .nbytes()
178 .bits(buffer.len() as u8)
179 .rd_wrn()
180 .set_bit()
181 });
182
183 self.i2c.cr2.modify(|_, w| w.start().set_bit());
185
186 self.i2c.cr2.modify(|_, w| w.autoend().set_bit());
188
189 for c in buffer.iter_mut() {
191 *c = self.recv_byte()?;
192 }
193
194 self.i2c
196 .icr
197 .write(|w| w.stopcf().set_bit().nackcf().set_bit());
198
199 Ok(())
200 }
201}
202
203impl<PINS> Write for I2c<I2C1, PINS> {
204 type Error = Error;
205
206 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
207 self.i2c.cr2.modify(|_, w| {
210 w.sadd()
211 .bits(u16::from(addr) << 1)
212 .nbytes()
213 .bits(bytes.len() as u8)
214 .rd_wrn()
215 .clear_bit()
216 .autoend()
217 .set_bit()
218 });
219
220 self.i2c.cr2.modify(|_, w| w.start().set_bit());
222
223 for c in bytes {
224 self.send_byte(*c)?;
225 }
226
227 self.i2c
229 .icr
230 .write(|w| w.stopcf().set_bit().nackcf().set_bit());
231 Ok(())
232 }
233}