ftdi_embedded_hal/
i2c.rs

1use crate::error::Error;
2use crate::error::ErrorKind::I2cNoAck;
3use crate::{FtInner, PinUse};
4use eh1::i2c::{NoAcknowledgeSource, Operation, SevenBitAddress};
5use ftdi_mpsse::{ClockBitsIn, ClockBitsOut, MpsseCmdBuilder, MpsseCmdExecutor};
6use std::sync::{Arc, Mutex};
7
8/// SCL bitmask
9const SCL: u8 = 1 << 0;
10/// SDA bitmask
11const SDA: u8 = 1 << 1;
12
13const BITS_IN: ClockBitsIn = ClockBitsIn::MsbPos;
14const BITS_OUT: ClockBitsOut = ClockBitsOut::MsbNeg;
15
16/// FTDI I2C interface.
17///
18/// This is created by calling [`FtHal::i2c`].
19///
20/// [`FtHal::i2c`]: crate::FtHal::i2c
21#[derive(Debug)]
22pub struct I2c<Device: MpsseCmdExecutor> {
23    /// Parent FTDI device.
24    mtx: Arc<Mutex<FtInner<Device>>>,
25    /// Length of the start, repeated start, and stop conditions.
26    ///
27    /// The units for these are dimensionless number of MPSSE commands.
28    /// More MPSSE commands roughly correlates to more time.
29    start_stop_cmds: u8,
30    /// Send I2C commands faster.
31    fast: bool,
32}
33
34impl<Device, E> I2c<Device>
35where
36    Device: MpsseCmdExecutor<Error = E>,
37    E: std::error::Error,
38    Error<E>: From<E>,
39{
40    pub(crate) fn new(mtx: Arc<Mutex<FtInner<Device>>>) -> Result<I2c<Device>, Error<E>> {
41        {
42            let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex");
43
44            lock.allocate_pin(0, PinUse::I2c);
45            lock.allocate_pin(1, PinUse::I2c);
46            lock.allocate_pin(2, PinUse::I2c);
47
48            // clear direction and value of first 3 pins
49
50            lock.direction &= !0x07;
51            lock.value &= !0x07;
52            // AD0: SCL
53            // AD1: SDA (master out)
54            // AD2: SDA (master in)
55            // pins are set as input (tri-stated) in idle mode
56
57            // set GPIO pins to new state
58            let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
59                .set_gpio_lower(lock.value, lock.direction)
60                .enable_3phase_data_clocking()
61                .send_immediate();
62            lock.ft.send(cmd.as_slice())?;
63        }
64
65        Ok(I2c {
66            mtx,
67            start_stop_cmds: 3,
68            fast: false,
69        })
70    }
71
72    /// Set the length of start and stop conditions.
73    ///
74    /// This is an advanced feature that most people will not need to touch.
75    /// I2C start and stop conditions are generated with a number of MPSSE
76    /// commands.  This sets the number of MPSSE command generated for each
77    /// stop and start condition.  An increase in the number of MPSSE commands
78    /// roughtly correlates to an increase in the duration.
79    ///
80    /// # Example
81    ///
82    /// ```no_run
83    /// use ftdi_embedded_hal as hal;
84    ///
85    /// # #[cfg(feature = "libftd2xx")]
86    /// # {
87    /// let device = libftd2xx::Ft2232h::with_description("Dual RS232-HS A")?;
88    /// let hal = hal::FtHal::init_freq(device, 3_000_000)?;
89    /// let mut i2c = hal.i2c()?;
90    /// i2c.set_stop_start_len(10);
91    /// # }
92    /// # Ok::<(), std::boxed::Box<dyn std::error::Error>>(())
93    /// ```
94    pub fn set_stop_start_len(&mut self, start_stop_cmds: u8) {
95        self.start_stop_cmds = start_stop_cmds
96    }
97
98    /// Enable faster I2C transactions by sending commands in a single write.
99    ///
100    /// This is disabled by default, and currently has no effect when using
101    /// version 1 of the `embedded-hal` traits.
102    ///
103    /// Normally the I2C methods will send commands with a delay after each
104    /// slave ACK to read from the USB device.
105    /// Enabling this will send I2C commands without a delay, but slave ACKs
106    /// will only be checked at the end of each call to `read`, `write`, or
107    /// `write_read`.
108    ///
109    /// Additionally this changes the type of errors that can occur:
110    ///
111    /// * enabled: NAK errors will be reported as
112    ///   `NoAcknowledgeSource::Unknown`.
113    /// * disabled: NAK errors will be reported as
114    ///   `NoAcknowledgeSource::Address` or `NoAcknowledgeSource::Data`.
115    ///
116    /// # Example
117    ///
118    /// ```no_run
119    /// use ftdi_embedded_hal as hal;
120    ///
121    /// # #[cfg(feature = "ftdi")]
122    /// # {
123    /// let device = ftdi::find_by_vid_pid(0x0403, 0x6014)
124    ///     .interface(ftdi::Interface::A)
125    ///     .open()?;
126    ///
127    /// let hal = hal::FtHal::init_freq(device, 3_000_000)?;
128    /// let mut i2c = hal.i2c()?;
129    /// i2c.set_fast(true);
130    /// # }
131    /// # Ok::<(), std::boxed::Box<dyn std::error::Error>>(())
132    /// ```
133    pub fn set_fast(&mut self, fast: bool) {
134        self.fast = fast
135    }
136
137    fn read_fast(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error<E>> {
138        assert!(!buffer.is_empty(), "buffer must be a non-empty slice");
139
140        let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
141
142        // ST
143        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
144        for _ in 0..self.start_stop_cmds {
145            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
146        }
147        for _ in 0..self.start_stop_cmds {
148            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
149        }
150
151        mpsse_cmd = mpsse_cmd
152            // SAD+R
153            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
154            .clock_bits_out(BITS_OUT, (address << 1) | 1, 8)
155            // SAK
156            .set_gpio_lower(lock.value, SCL | lock.direction)
157            .clock_bits_in(BITS_IN, 1);
158
159        for idx in 0..buffer.len() {
160            // Bn
161            mpsse_cmd = mpsse_cmd
162                .set_gpio_lower(lock.value, SCL | lock.direction)
163                .clock_bits_in(BITS_IN, 8);
164            if idx == buffer.len() - 1 {
165                // NMAK
166                mpsse_cmd = mpsse_cmd
167                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
168                    .clock_bits_out(BITS_OUT, 0x80, 1)
169            } else {
170                // MAK
171                mpsse_cmd = mpsse_cmd
172                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
173                    .clock_bits_out(BITS_OUT, 0x00, 1)
174            }
175        }
176
177        // SP
178        for _ in 0..self.start_stop_cmds {
179            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
180        }
181        for _ in 0..self.start_stop_cmds {
182            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
183        }
184        for _ in 0..self.start_stop_cmds {
185            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
186        }
187
188        mpsse_cmd = mpsse_cmd
189            // Idle
190            .set_gpio_lower(lock.value, lock.direction)
191            .send_immediate();
192
193        lock.ft.send(mpsse_cmd.as_slice())?;
194        let mut ack_buf: [u8; 1] = [0; 1];
195        lock.ft.recv(&mut ack_buf)?;
196        lock.ft.recv(buffer)?;
197
198        if (ack_buf[0] & 0b1) != 0x00 {
199            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Unknown)));
200        }
201
202        Ok(())
203    }
204
205    fn read_slow(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error<E>> {
206        assert!(!buffer.is_empty(), "buffer must be a non-empty slice");
207
208        let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
209
210        // ST
211        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
212        for _ in 0..self.start_stop_cmds {
213            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
214        }
215        for _ in 0..self.start_stop_cmds {
216            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
217        }
218
219        mpsse_cmd = mpsse_cmd
220            // SAD+R
221            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
222            .clock_bits_out(BITS_OUT, (address << 1) | 1, 8)
223            // SAK
224            .set_gpio_lower(lock.value, SCL | lock.direction)
225            .clock_bits_in(BITS_IN, 1)
226            .send_immediate();
227
228        lock.ft.send(mpsse_cmd.as_slice())?;
229        let mut ack_buf: [u8; 1] = [0; 1];
230        lock.ft.recv(&mut ack_buf)?;
231        if (ack_buf[0] & 0b1) != 0x00 {
232            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
233        }
234
235        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
236        for idx in 0..buffer.len() {
237            // Bn
238            mpsse_cmd = mpsse_cmd
239                .set_gpio_lower(lock.value, SCL | lock.direction)
240                .clock_bits_in(BITS_IN, 8);
241            if idx == buffer.len() - 1 {
242                // NMAK
243                mpsse_cmd = mpsse_cmd
244                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
245                    .clock_bits_out(BITS_OUT, 0x80, 1)
246            } else {
247                // MAK
248                mpsse_cmd = mpsse_cmd
249                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
250                    .clock_bits_out(BITS_OUT, 0x00, 1)
251            }
252        }
253
254        // SP
255        for _ in 0..self.start_stop_cmds {
256            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
257        }
258        for _ in 0..self.start_stop_cmds {
259            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
260        }
261        for _ in 0..self.start_stop_cmds {
262            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
263        }
264
265        mpsse_cmd = mpsse_cmd
266            // Idle
267            .set_gpio_lower(lock.value, lock.direction)
268            .send_immediate();
269
270        lock.ft.send(mpsse_cmd.as_slice())?;
271        lock.ft.recv(buffer)?;
272
273        Ok(())
274    }
275
276    fn write_fast(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error<E>> {
277        assert!(!bytes.is_empty(), "bytes must be a non-empty slice");
278
279        let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
280
281        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
282
283        // ST
284        for _ in 0..self.start_stop_cmds {
285            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
286        }
287        for _ in 0..self.start_stop_cmds {
288            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
289        }
290
291        mpsse_cmd = mpsse_cmd
292            // SAD+W
293            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
294            .clock_bits_out(BITS_OUT, addr << 1, 8)
295            // SAK
296            .set_gpio_lower(lock.value, SCL | lock.direction)
297            .clock_bits_in(BITS_IN, 1);
298
299        for byte in bytes.iter() {
300            mpsse_cmd = mpsse_cmd
301                // Bi
302                .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
303                .clock_bits_out(BITS_OUT, *byte, 8)
304                // SAK
305                .set_gpio_lower(lock.value, SCL | lock.direction)
306                .clock_bits_in(BITS_IN, 1);
307        }
308
309        // SP
310        for _ in 0..self.start_stop_cmds {
311            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
312        }
313        for _ in 0..self.start_stop_cmds {
314            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
315        }
316        for _ in 0..self.start_stop_cmds {
317            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
318        }
319
320        mpsse_cmd = mpsse_cmd
321            // Idle
322            .set_gpio_lower(lock.value, lock.direction)
323            .send_immediate();
324
325        lock.ft.send(mpsse_cmd.as_slice())?;
326        let mut ack_buf: Vec<u8> = vec![0; 1 + bytes.len()];
327        lock.ft.recv(ack_buf.as_mut_slice())?;
328        if ack_buf.iter().any(|&ack| (ack & 0b1) != 0x00) {
329            Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Unknown)))
330        } else {
331            Ok(())
332        }
333    }
334
335    fn write_slow(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error<E>> {
336        assert!(!bytes.is_empty(), "bytes must be a non-empty slice");
337
338        let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
339
340        // ST
341        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
342        for _ in 0..self.start_stop_cmds {
343            mpsse_cmd = mpsse_cmd.set_gpio_lower(SCL | SDA | lock.value, SCL | SDA | lock.direction)
344        }
345        for _ in 0..self.start_stop_cmds {
346            mpsse_cmd = mpsse_cmd.set_gpio_lower(SCL | lock.value, SCL | SDA | lock.direction)
347        }
348
349        mpsse_cmd = mpsse_cmd
350            // SAD+W
351            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
352            .clock_bits_out(BITS_OUT, addr << 1, 8)
353            // SAK
354            .set_gpio_lower(lock.value, SCL | lock.direction)
355            .clock_bits_in(BITS_IN, 1)
356            .send_immediate();
357
358        lock.ft.send(mpsse_cmd.as_slice())?;
359        let mut ack_buf: [u8; 1] = [0; 1];
360        lock.ft.recv(&mut ack_buf)?;
361        if (ack_buf[0] & 0b1) != 0x00 {
362            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
363        }
364
365        for (idx, byte) in bytes.iter().enumerate() {
366            let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
367                // Bi
368                .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
369                .clock_bits_out(BITS_OUT, *byte, 8)
370                // SAK
371                .set_gpio_lower(lock.value, SCL | lock.direction)
372                .clock_bits_in(BITS_IN, 1);
373
374            // last byte
375            if idx == bytes.len() - 1 {
376                // SP
377                for _ in 0..self.start_stop_cmds {
378                    mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
379                }
380                for _ in 0..self.start_stop_cmds {
381                    mpsse_cmd =
382                        mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
383                }
384                for _ in 0..self.start_stop_cmds {
385                    mpsse_cmd =
386                        mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
387                }
388
389                // Idle
390                mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, lock.direction)
391            }
392
393            mpsse_cmd = mpsse_cmd.send_immediate();
394
395            lock.ft.send(mpsse_cmd.as_slice())?;
396            let mut ack_buf: [u8; 1] = [0; 1];
397            lock.ft.recv(&mut ack_buf)?;
398            if (ack_buf[0] & 0b1) != 0x00 {
399                return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
400            }
401        }
402
403        Ok(())
404    }
405
406    fn write_read_fast(
407        &mut self,
408        address: u8,
409        bytes: &[u8],
410        buffer: &mut [u8],
411    ) -> Result<(), Error<E>> {
412        assert!(!bytes.is_empty(), "bytes must be a non-empty slice");
413        assert!(!buffer.is_empty(), "buffer must be a non-empty slice");
414
415        // lock at the start to prevent GPIO from being modified while we build
416        // the MPSSE command
417        let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
418
419        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
420
421        // ST
422        for _ in 0..self.start_stop_cmds {
423            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
424        }
425        for _ in 0..self.start_stop_cmds {
426            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
427        }
428
429        mpsse_cmd = mpsse_cmd
430            // SAD + W
431            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
432            .clock_bits_out(BITS_OUT, address << 1, 8)
433            // SAK
434            .set_gpio_lower(lock.value, SCL | lock.direction)
435            .clock_bits_in(BITS_IN, 1);
436
437        for byte in bytes {
438            mpsse_cmd = mpsse_cmd
439                // Oi
440                .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
441                .clock_bits_out(BITS_OUT, *byte, 8)
442                // SAK
443                .set_gpio_lower(lock.value, SCL | lock.direction)
444                .clock_bits_in(BITS_IN, 1);
445        }
446
447        // SR
448        for _ in 0..self.start_stop_cmds {
449            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
450        }
451        for _ in 0..self.start_stop_cmds {
452            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
453        }
454        for _ in 0..self.start_stop_cmds {
455            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
456        }
457
458        mpsse_cmd = mpsse_cmd
459            // SAD + R
460            .clock_bits_out(BITS_OUT, (address << 1) | 1, 8)
461            // SAK
462            .set_gpio_lower(lock.value, SCL | lock.direction)
463            .clock_bits_in(BITS_IN, 1);
464
465        for idx in 0..buffer.len() {
466            mpsse_cmd = mpsse_cmd
467                .set_gpio_lower(lock.value, SCL | lock.direction)
468                .clock_bits_in(BITS_IN, 8);
469            if idx == buffer.len() - 1 {
470                // NMAK
471                mpsse_cmd = mpsse_cmd
472                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
473                    .clock_bits_out(BITS_OUT, 0x80, 1)
474            } else {
475                // MAK
476                mpsse_cmd = mpsse_cmd
477                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
478                    .clock_bits_out(BITS_OUT, 0x00, 1)
479            }
480        }
481
482        // SP
483        for _ in 0..self.start_stop_cmds {
484            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
485        }
486        for _ in 0..self.start_stop_cmds {
487            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
488        }
489        for _ in 0..self.start_stop_cmds {
490            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
491        }
492
493        mpsse_cmd = mpsse_cmd
494            // Idle
495            .set_gpio_lower(lock.value, lock.direction)
496            .send_immediate();
497
498        lock.ft.send(mpsse_cmd.as_slice())?;
499        let mut ack_buf: Vec<u8> = vec![0; 2 + bytes.len()];
500        lock.ft.recv(&mut ack_buf)?;
501        lock.ft.recv(buffer)?;
502
503        if ack_buf.iter().any(|&ack| (ack & 0b1) != 0x00) {
504            Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Unknown)))
505        } else {
506            Ok(())
507        }
508    }
509
510    fn write_read_slow(
511        &mut self,
512        address: u8,
513        bytes: &[u8],
514        buffer: &mut [u8],
515    ) -> Result<(), Error<E>> {
516        assert!(!bytes.is_empty(), "bytes must be a non-empty slice");
517        assert!(!buffer.is_empty(), "buffer must be a non-empty slice");
518
519        // lock at the start to prevent GPIO from being modified while we build
520        // the MPSSE command
521        let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
522
523        // ST
524        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
525        for _ in 0..self.start_stop_cmds {
526            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
527        }
528        for _ in 0..self.start_stop_cmds {
529            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
530        }
531
532        mpsse_cmd = mpsse_cmd
533            // SAD + W
534            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
535            .clock_bits_out(BITS_OUT, address << 1, 8)
536            // SAK
537            .set_gpio_lower(lock.value, SCL | lock.direction)
538            .clock_bits_in(BITS_IN, 1)
539            .send_immediate();
540
541        lock.ft.send(mpsse_cmd.as_slice())?;
542        let mut ack_buf: [u8; 1] = [0; 1];
543        lock.ft.recv(&mut ack_buf)?;
544        if (ack_buf[0] & 0b1) != 0x00 {
545            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
546        }
547
548        for byte in bytes {
549            let mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
550                // Oi
551                .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
552                .clock_bits_out(BITS_OUT, *byte, 8)
553                // SAK
554                .set_gpio_lower(lock.value, SCL | lock.direction)
555                .clock_bits_in(BITS_IN, 1)
556                .send_immediate();
557
558            lock.ft.send(mpsse_cmd.as_slice())?;
559            let mut ack_buf: [u8; 1] = [0; 1];
560            lock.ft.recv(&mut ack_buf)?;
561            if (ack_buf[0] & 0b1) != 0x00 {
562                return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
563            }
564        }
565
566        // SR
567        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
568        for _ in 0..self.start_stop_cmds {
569            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
570        }
571        for _ in 0..self.start_stop_cmds {
572            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
573        }
574        for _ in 0..self.start_stop_cmds {
575            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
576        }
577
578        mpsse_cmd = mpsse_cmd
579            // SAD + R
580            .clock_bits_out(BITS_OUT, (address << 1) | 1, 8)
581            // SAK
582            .set_gpio_lower(lock.value, SCL | lock.direction)
583            .clock_bits_in(BITS_IN, 1)
584            .send_immediate();
585
586        lock.ft.send(mpsse_cmd.as_slice())?;
587        let mut ack_buf: [u8; 1] = [0; 1];
588        lock.ft.recv(&mut ack_buf)?;
589        if (ack_buf[0] & 0b1) != 0x00 {
590            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
591        }
592
593        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
594        for idx in 0..buffer.len() {
595            mpsse_cmd = mpsse_cmd
596                .set_gpio_lower(lock.value, SCL | lock.direction)
597                .clock_bits_in(BITS_IN, 8);
598            if idx == buffer.len() - 1 {
599                // NMAK
600                mpsse_cmd = mpsse_cmd
601                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
602                    .clock_bits_out(BITS_OUT, 0x80, 1)
603            } else {
604                // MAK
605                mpsse_cmd = mpsse_cmd
606                    .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
607                    .clock_bits_out(BITS_OUT, 0x00, 1)
608            }
609        }
610
611        // SP
612        for _ in 0..self.start_stop_cmds {
613            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
614        }
615        for _ in 0..self.start_stop_cmds {
616            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
617        }
618        for _ in 0..self.start_stop_cmds {
619            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
620        }
621
622        mpsse_cmd = mpsse_cmd
623            // Idle
624            .set_gpio_lower(lock.value, lock.direction)
625            .send_immediate();
626
627        lock.ft.send(mpsse_cmd.as_slice())?;
628        lock.ft.recv(buffer)?;
629
630        Ok(())
631    }
632
633    fn transaction(
634        &mut self,
635        address: u8,
636        operations: &mut [Operation<'_>],
637    ) -> Result<(), Error<E>> {
638        // lock at the start to prevent GPIO from being modified while we build
639        // the MPSSE command
640        let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
641
642        // ST
643        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
644        for _ in 0..self.start_stop_cmds {
645            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
646        }
647        for _ in 0..self.start_stop_cmds {
648            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
649        }
650        lock.ft.send(mpsse_cmd.as_slice())?;
651
652        let mut prev_op_was_a_read: bool = false;
653        for (idx, operation) in operations.iter_mut().enumerate() {
654            match operation {
655                Operation::Read(buffer) => {
656                    if idx == 0 || !prev_op_was_a_read {
657                        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
658                        if idx != 0 {
659                            // SR
660                            for _ in 0..self.start_stop_cmds {
661                                mpsse_cmd = mpsse_cmd.set_gpio_lower(
662                                    lock.value | SCL | SDA,
663                                    SCL | SDA | lock.direction,
664                                )
665                            }
666                            for _ in 0..self.start_stop_cmds {
667                                mpsse_cmd = mpsse_cmd
668                                    .set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
669                            }
670                            for _ in 0..self.start_stop_cmds {
671                                mpsse_cmd =
672                                    mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
673                            }
674                        }
675
676                        mpsse_cmd = mpsse_cmd
677                            // SAD + R
678                            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
679                            .clock_bits_out(BITS_OUT, (address << 1) | 1, 8)
680                            // SAK
681                            .set_gpio_lower(lock.value, SCL | lock.direction)
682                            .clock_bits_in(BITS_IN, 1)
683                            .send_immediate();
684
685                        lock.ft.send(mpsse_cmd.as_slice())?;
686                        let mut ack_buf: [u8; 1] = [0; 1];
687                        lock.ft.recv(&mut ack_buf)?;
688                        if (ack_buf[0] & 0b1) != 0x00 {
689                            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
690                        }
691                    }
692
693                    let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
694                    for idx in 0..buffer.len() {
695                        mpsse_cmd = mpsse_cmd
696                            .set_gpio_lower(lock.value, SCL | lock.direction)
697                            .clock_bits_in(BITS_IN, 8);
698                        if idx == buffer.len() - 1 {
699                            // NMAK
700                            mpsse_cmd = mpsse_cmd
701                                .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
702                                .clock_bits_out(BITS_OUT, 0x80, 1)
703                        } else {
704                            // MAK
705                            mpsse_cmd = mpsse_cmd
706                                .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
707                                .clock_bits_out(BITS_OUT, 0x00, 1)
708                        }
709                    }
710                    lock.ft.send(mpsse_cmd.as_slice())?;
711                    lock.ft.recv(buffer)?;
712
713                    prev_op_was_a_read = true;
714                }
715                Operation::Write(bytes) => {
716                    if idx == 0 || prev_op_was_a_read {
717                        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
718                        if idx != 0 {
719                            // SR
720                            for _ in 0..self.start_stop_cmds {
721                                mpsse_cmd = mpsse_cmd.set_gpio_lower(
722                                    lock.value | SCL | SDA,
723                                    SCL | SDA | lock.direction,
724                                )
725                            }
726                            for _ in 0..self.start_stop_cmds {
727                                mpsse_cmd = mpsse_cmd
728                                    .set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
729                            }
730                            for _ in 0..self.start_stop_cmds {
731                                mpsse_cmd =
732                                    mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
733                            }
734                        }
735
736                        mpsse_cmd = mpsse_cmd
737                            // SAD + W
738                            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
739                            .clock_bits_out(BITS_OUT, address << 1, 8)
740                            // SAK
741                            .set_gpio_lower(lock.value, SCL | lock.direction)
742                            .clock_bits_in(BITS_IN, 1)
743                            .send_immediate();
744
745                        lock.ft.send(mpsse_cmd.as_slice())?;
746                        let mut ack_buf: [u8; 1] = [0; 1];
747                        lock.ft.recv(&mut ack_buf)?;
748                        if (ack_buf[0] & 0b1) != 0x00 {
749                            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
750                        }
751                    }
752
753                    for byte in *bytes {
754                        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
755                        mpsse_cmd = mpsse_cmd
756                            // Oi
757                            .set_gpio_lower(lock.value, SCL | SDA | lock.direction)
758                            .clock_bits_out(BITS_OUT, *byte, 8)
759                            // SAK
760                            .set_gpio_lower(lock.value, SCL | lock.direction)
761                            .clock_bits_in(BITS_IN, 1)
762                            .send_immediate();
763
764                        lock.ft.send(mpsse_cmd.as_slice())?;
765                        let mut ack_buf: [u8; 1] = [0; 1];
766                        lock.ft.recv(&mut ack_buf)?;
767                        if (ack_buf[0] & 0b1) != 0x00 {
768                            return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
769                        }
770                    }
771
772                    prev_op_was_a_read = false;
773                }
774            }
775        }
776
777        let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
778        // SP
779        for _ in 0..self.start_stop_cmds {
780            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value, SCL | SDA | lock.direction)
781        }
782        for _ in 0..self.start_stop_cmds {
783            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL, SCL | SDA | lock.direction)
784        }
785        for _ in 0..self.start_stop_cmds {
786            mpsse_cmd = mpsse_cmd.set_gpio_lower(lock.value | SCL | SDA, SCL | SDA | lock.direction)
787        }
788
789        // Idle
790        mpsse_cmd = mpsse_cmd
791            .set_gpio_lower(lock.value, lock.direction)
792            .send_immediate();
793        lock.ft.send(mpsse_cmd.as_slice())?;
794
795        Ok(())
796    }
797}
798
799impl<Device, E> eh0::blocking::i2c::Read for I2c<Device>
800where
801    Device: MpsseCmdExecutor<Error = E>,
802    E: std::error::Error,
803    Error<E>: From<E>,
804{
805    type Error = Error<E>;
806
807    fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error<E>> {
808        if self.fast {
809            self.read_fast(address, buffer)
810        } else {
811            self.read_slow(address, buffer)
812        }
813    }
814}
815
816impl<Device, E> eh0::blocking::i2c::Write for I2c<Device>
817where
818    Device: MpsseCmdExecutor<Error = E>,
819    E: std::error::Error,
820    Error<E>: From<E>,
821{
822    type Error = Error<E>;
823
824    fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error<E>> {
825        if self.fast {
826            self.write_fast(addr, bytes)
827        } else {
828            self.write_slow(addr, bytes)
829        }
830    }
831}
832
833impl<Device, E> eh0::blocking::i2c::WriteRead for I2c<Device>
834where
835    Device: MpsseCmdExecutor<Error = E>,
836    E: std::error::Error,
837    Error<E>: From<E>,
838{
839    type Error = Error<E>;
840
841    fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error<E>> {
842        if self.fast {
843            self.write_read_fast(address, bytes, buffer)
844        } else {
845            self.write_read_slow(address, bytes, buffer)
846        }
847    }
848}
849
850impl<Device, E> eh1::i2c::ErrorType for I2c<Device>
851where
852    Device: MpsseCmdExecutor<Error = E>,
853    E: std::error::Error,
854    Error<E>: From<E>,
855{
856    type Error = Error<E>;
857}
858
859impl<Device, E> eh1::i2c::I2c for I2c<Device>
860where
861    Device: MpsseCmdExecutor<Error = E>,
862    E: std::error::Error,
863    Error<E>: From<E>,
864{
865    fn transaction(
866        &mut self,
867        address: SevenBitAddress,
868        operations: &mut [Operation<'_>],
869    ) -> Result<(), Self::Error> {
870        self.transaction(address, operations)
871    }
872}