gd32e2-hal 0.26.0

HAL for the GD32E23x series (Cortex-M23), currently the GD32E230
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
//! I²C master.
//!
//! 7-bit addressing. Transactions are `write`, `read` and `write_read` (the
//! last joined by a repeated START), blocking or driven by interrupts; both
//! lines must be open-drain.
//!
//! ```ignore
//! let sda = parts.pb7.into_alternate_open_drain::<1>();
//! let scl = parts.pb6.into_alternate_open_drain::<1>();
//! let mut i2c = I2c::new(&mut rcu, dp.i2c0, sda, scl, I2cMode::standard(100.kHz()));
//! ```
//!
//! # Driving a transaction by hand
//!
//! [`WriteTransfer`] and [`ReadTransfer`] are one way to do it; the primitives
//! they are built from are public, so a handler can be written instead. A
//! transaction is a sequence of phases, and the step a handler takes depends on
//! which one it is in.
//!
//! Writing: [`write_start`](I2c::write_start), then on
//! [`sbsend`](I2c::sbsend) [`write_addr`](I2c::write_addr), then on
//! [`addsend`](I2c::addsend) [`clear_addsend`](I2c::clear_addsend), then one
//! [`write_byte`](I2c::write_byte) per [`tbe`](I2c::tbe). `TBE` stays up with
//! nothing left to feed, so `unlisten(Event::Byte)` after the last one and end
//! on [`btc`](I2c::btc) with [`write_stop`](I2c::write_stop).
//!
//! Reading is the same up to `ADDSEND`, and then turns on the acknowledge:
//! [`set_acken`](I2c::set_acken) governs the byte *already* being clocked in, so
//! the NAK that ends the transaction has to be placed one byte early, and
//! [`set_poap`](I2c::set_poap) moves it one further still. Both must stand
//! before the START. Four lengths behave differently: one byte NAKs before
//! `ADDSEND` is cleared; two ride on `POAP` and are taken together on `BTC`;
//! three go straight to that tail; longer ones take bytes on
//! [`rbne`](I2c::rbne) until three remain. Getting this wrong does not fail
//! loudly — the target keeps driving the line and the bus hangs.

use core::mem::ManuallyDrop;
use core::ops::Deref;
use core::ptr;

use embedded_hal::i2c::{ErrorKind, ErrorType, NoAcknowledgeSource, Operation};

use crate::gpio::{Alternate, OpenDrain, Pin};
use crate::pac;
use crate::rcu::{Enable, Rcu, Reset};
use crate::time::Hertz;

/// Smallest `CLKC` the hardware honours.
const CLKC_MIN_STANDARD: u32 = 4;
const CLKC_MIN_FAST: u32 = 1;

/// Slowest `pclk1` each mode can be driven from, per the manual.
const MIN_PCLK1_STANDARD_HZ: u32 = 2_000_000;
const MIN_PCLK1_FAST_HZ: u32 = 8_000_000;
const MIN_PCLK1_FAST_PLUS_HZ: u32 = 24_000_000;

/// Longest SCL rise time the I²C specification allows per mode, in nanoseconds
/// (NXP UM10204) — a property of the pulled-up line, not of the controller.
const RISE_TIME_STANDARD_NS: u32 = 1000;
const RISE_TIME_FAST_NS: u32 = 300;
const RISE_TIME_FAST_PLUS_NS: u32 = 120;

/// A peripheral that [`I2c`] can drive.
pub trait Instance: Deref<Target = pac::i2c0::RegisterBlock> + Enable + Reset {}

impl Instance for pac::I2c0 {}
impl Instance for pac::I2c1 {}

/// Marks a pin usable as `SDA` for `I2C`, in the right alternate function.
pub trait SdaPin<I2C> {}
/// Marks a pin usable as `SCL` for `I2C`, in the right alternate function.
pub trait SclPin<I2C> {}

macro_rules! i2c_pins {
    ( $( $I2C:ty:
        SDA: [ $($(#[$sda_cfg:meta])? $sda_p:literal $sda_n:literal : $sda_af:literal),* $(,)? ]
        SCL: [ $($(#[$scl_cfg:meta])? $scl_p:literal $scl_n:literal : $scl_af:literal),* $(,)? ]
    ),* $(,)? ) => {
        $(
            $($(#[$sda_cfg])? impl SdaPin<$I2C> for Pin<$sda_p, $sda_n, Alternate<$sda_af, OpenDrain>> {})*
            $($(#[$scl_cfg])? impl SclPin<$I2C> for Pin<$scl_p, $scl_n, Alternate<$scl_af, OpenDrain>> {})*
        )*
    };
}

// PB10/PB11 at AF1 belong to a *different* I²C depending on the chip variant
// (datasheet Table 2-14 footnotes): I2C0 on GD32E230x4, I2C1 on GD32E230x8.
// They are therefore listed in the gated blocks, not here.
//
// The `pads_ge_*` gates say the package bonds the pin at all, and match the ones in
// `gpio::Parts`.
i2c_pins!(
    pac::I2c0:
        SDA: ['A' 10 : 4, #[cfg(pads_ge_24)] 'B' 7 : 1, #[cfg(pads_ge_48)] 'B' 9 : 1, 'F' 0 : 1]
        SCL: ['A' 9 : 4, #[cfg(pads_ge_24)] 'B' 6 : 1, #[cfg(pads_ge_qfn32)] 'B' 8 : 1, 'F' 1 : 1],
);

// ---- (1) GD32E230x4 only: PB10/PB11 AF1 and PF6/PF7 AF0 are I2C0 ----
#[cfg(chip_x4)]
i2c_pins!(
    pac::I2c0:
        SDA: [#[cfg(pads_ge_48)] 'B' 11 : 1, #[cfg(pads_ge_48)] 'F' 7 : 0]
        SCL: [#[cfg(pads_ge_48)] 'B' 10 : 1, #[cfg(pads_ge_48)] 'F' 6 : 0],
);

// ---- (3) GD32E230x8 only: I2C1 exists, and PB10/PB11 AF1 belong to it ----
#[cfg(chip_x8)]
i2c_pins!(
    pac::I2c1:
        SDA: ['A' 1 : 4, #[cfg(pads_ge_lqfp32)] 'A' 12 : 5, #[cfg(pads_ge_48)] 'B' 11 : 1, #[cfg(pads_ge_48)] 'B' 14 : 5, #[cfg(pads_ge_48)] 'F' 7 : 0]
        SCL: ['A' 0 : 4, #[cfg(pads_ge_lqfp32)] 'A' 11 : 5, #[cfg(pads_ge_48)] 'B' 10 : 1, #[cfg(pads_ge_48)] 'B' 13 : 5, #[cfg(pads_ge_48)] 'F' 6 : 0]
);

/// Writes the bus timing to `CTL1`, `CKCFG` and `RT`, leaving the peripheral enabled.
///
/// `I2CCLK` takes `pclk1` in whole megahertz: `RISETIME` and the analog filter
/// are measured in real time, so the absolute frequency is needed, not a divider.
/// `CKCFG` and `I2CCLK` are only taken while `I2CEN` is clear, so the peripheral
/// is disabled for the duration.
///
/// # Panics
///
/// If `pclk1` is below the minimum the mode needs (2 / 8 / 24 MHz), or if the
/// requested frequency puts `CLKC` below what the hardware honours.
fn apply_config<I2C: Instance>(i2c: &I2C, mode: I2cMode, pclk1: Hertz) {
    let pclk1 = pclk1.to_Hz();
    let pclk1_mhz = pclk1 / 1_000_000;
    // t_rise / T_pclk1 + 1, and `1 ns × pclk1` is exactly `pclk1` in MHz.
    let risetime = |t_rise_ns: u32| (pclk1_mhz * t_rise_ns / 1_000 + 1) as u8;

    i2c.ctl0().modify(|_, w| w.i2cen().disabled());
    // SAFETY: `pclk1` in whole megahertz, which the clock tree keeps within the
    // field; a value below the mode's minimum is rejected by the asserts that
    // follow, before `I2CEN` goes back up.
    i2c.ctl1()
        .modify(|_, w| unsafe { w.i2cclk().bits(pclk1_mhz as u8) });

    match mode {
        // Both halves of the period are `CLKC` cycles long, so the period is
        // twice that.
        I2cMode::Standard { frequency } => {
            assert!(
                pclk1 >= MIN_PCLK1_STANDARD_HZ,
                "I2C standard mode needs pclk1 of at least 2 MHz"
            );
            let clkc = pclk1 / (2 * frequency.to_Hz());
            assert!(
                clkc >= CLKC_MIN_STANDARD,
                "I2C frequency too high for this pclk1"
            );
            i2c.rt()
                .write(|w| w.risetime().bits(risetime(RISE_TIME_STANDARD_NS)));
            i2c.ckcfg()
                .write(|w| w.fast().standard().clkc().bits(clkc as u16));
        }
        I2cMode::Fast {
            frequency,
            duty_cycle,
        } => {
            assert!(
                pclk1 >= MIN_PCLK1_FAST_HZ,
                "I2C fast mode needs pclk1 of at least 8 MHz"
            );
            i2c.rt()
                .write(|w| w.risetime().bits(risetime(RISE_TIME_FAST_NS)));
            write_fast_ckcfg(i2c, pclk1, frequency, duty_cycle);
        }
        I2cMode::FastPlus {
            frequency,
            duty_cycle,
        } => {
            assert!(
                pclk1 >= MIN_PCLK1_FAST_PLUS_HZ,
                "I2C fast mode plus needs pclk1 of at least 24 MHz"
            );
            i2c.rt()
                .write(|w| w.risetime().bits(risetime(RISE_TIME_FAST_PLUS_NS)));
            write_fast_ckcfg(i2c, pclk1, frequency, duty_cycle);
            i2c.fmpcfg().write(|w| w.fmpen().set_bit());
        }
    }

    i2c.ctl0().modify(|_, w| w.i2cen().enabled());
}

/// Writes `CKCFG` for the two fast modes, which share their formulas.
///
/// The duty cycle splits the period into `2 + 1` or `16 + 9` parts of `CLKC`
/// cycles each.
fn write_fast_ckcfg<I2C: Instance>(i2c: &I2C, pclk1: u32, frequency: Hertz, duty_cycle: DutyCycle) {
    let parts = match duty_cycle {
        DutyCycle::Ratio2to1 => 3,
        DutyCycle::Ratio16to9 => 25,
    };
    let clkc = pclk1 / (parts * frequency.to_Hz());
    assert!(
        clkc >= CLKC_MIN_FAST,
        "I2C frequency too high for this pclk1"
    );
    i2c.ckcfg().write(|w| {
        let w = match duty_cycle {
            DutyCycle::Ratio2to1 => w.dtcy().duty2(),
            DutyCycle::Ratio16to9 => w.dtcy().duty16_9(),
        };
        w.fast().fast().clkc().bits(clkc as u16)
    });
}

/// Ratio of the low to the high half of an SCL period (`DTCY`).
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[allow(missing_docs)]
pub enum DutyCycle {
    Ratio2to1,
    Ratio16to9,
}

/// Bus speed, and whatever else that speed implies.
///
/// Each variant has its own minimum `pclk1`: 2 / 8 / 24 MHz.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum I2cMode {
    /// Up to 100 kHz, duty cycle fixed at 1:1.
    Standard {
        /// SCL frequency.
        frequency: Hertz,
    },
    /// Up to 400 kHz.
    Fast {
        /// SCL frequency.
        frequency: Hertz,
        /// Shape of the SCL period.
        duty_cycle: DutyCycle,
    },
    /// Up to 1 MHz; also enables the stronger line driver (`FMPCFG`).
    FastPlus {
        /// SCL frequency.
        frequency: Hertz,
        /// Shape of the SCL period.
        duty_cycle: DutyCycle,
    },
}

impl I2cMode {
    /// Standard mode at `frequency`.
    pub const fn standard(frequency: Hertz) -> Self {
        Self::Standard { frequency }
    }
    /// Fast mode at `frequency`, with the given duty cycle.
    pub const fn fast(frequency: Hertz, duty_cycle: DutyCycle) -> Self {
        Self::Fast {
            frequency,
            duty_cycle,
        }
    }
    /// Fast mode plus at `frequency`, with the given duty cycle.
    pub const fn fast_plus(frequency: Hertz, duty_cycle: DutyCycle) -> Self {
        Self::FastPlus {
            frequency,
            duty_cycle,
        }
    }
}

/// An error the peripheral flagged in `STAT0` (manual Table 17-3).
///
/// [`kind`] gives the portable classification.
///
/// [`kind`]: embedded_hal::i2c::Error::kind
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error {
    /// A START or STOP arrived where the protocol allows none (`BERR`).
    Bus,
    /// Another master won the bus; this one fell back to slave mode (`LOSTARB`).
    ArbitrationLoss,
    /// A byte was overwritten before being read, or needed before being written
    /// (`OUERR`). Slave mode only, with clock stretching disabled.
    Overrun,
    /// Nobody acknowledged (`AERR`) — the ordinary answer from an empty address,
    /// which is what bus scans rely on.
    ///
    /// One flag covers both cases, so the source comes from the step that ran.
    NoAcknowledge(NoAcknowledgeSource),
    /// The received PEC does not match the one computed locally (`PECERR`).
    Pec,
    /// An `SMBus` transaction exceeded its timeout (`SMBTO`).
    SmbusTimeout,
    /// An `SMBus` device pulled the alert line (`SMBALT`).
    SmbusAlert,
}

impl embedded_hal::i2c::Error for Error {
    fn kind(&self) -> ErrorKind {
        match self {
            Self::Bus => ErrorKind::Bus,
            Self::ArbitrationLoss => ErrorKind::ArbitrationLoss,
            Self::Overrun => ErrorKind::Overrun,
            Self::NoAcknowledge(source) => ErrorKind::NoAcknowledge(*source),
            // Nothing upstream describes these three.
            Self::Pec | Self::SmbusTimeout | Self::SmbusAlert => ErrorKind::Other,
        }
    }
}

/// An I²C event that can raise an interrupt.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Event {
    /// The phase events `SBSEND`, `ADDSEND`, `ADD10SEND`, `STPDET` and `BTC`
    /// (`EVIE`). Each is cleared by the step of the transaction that acts on it.
    Protocol,
    /// The byte events `TBE` and `RBNE` (`BUFIE`), on top of the phase ones.
    ///
    /// Listening raises `EVIE` as well, `BUFIE` doing nothing without it in
    /// hardware. `TBE` is true whenever nothing is queued, so a handler feeding
    /// a buffer must `unlisten` this once the last byte is out — which leaves
    /// the phase events standing, and `BTC` then ends the transaction.
    Byte,
    /// Any of the `STAT0` error flags, which share one enable (`ERRIE`).
    /// Cleared by [`take_error`](I2c::take_error), which a handler must call —
    /// nothing else drains them.
    Error,
}

/// A configured I²C master, owning the peripheral and its two pins.
///
/// Both lines are open-drain and need a pull-up.
pub struct I2c<I2CX, SDA, SCL> {
    i2c: I2CX,
    sda_pin: SDA,
    scl_pin: SCL,
}

impl<I2CX, SDA, SCL> I2c<I2CX, SDA, SCL>
where
    I2CX: Instance,
    SDA: SdaPin<I2CX>,
    SCL: SclPin<I2CX>,
{
    /// Enables the peripheral's clock, resets it and applies `mode`.
    ///
    /// The pins must already be open-drain in this I²C's alternate function;
    /// [`release`](Self::release) hands them back.
    ///
    /// # Panics
    ///
    /// If `pclk1` is too slow for `mode` (2 / 8 / 24 MHz), or if `mode`'s
    /// frequency is unreachable from it.
    pub fn new(rcu: &mut Rcu, i2c: I2CX, sda_pin: SDA, scl_pin: SCL, mode: I2cMode) -> Self {
        let pclk1 = rcu.clocks().pclk1();
        I2CX::enable(rcu);
        I2CX::reset(rcu);

        apply_config(&i2c, mode, pclk1);
        Self {
            i2c,
            sda_pin,
            scl_pin,
        }
    }
    /// Waits for a requested STOP to reach the bus, then returns the peripheral
    /// and both pins, disabled, with its interrupts off and its clock stopped.
    pub fn release(mut self, rcu: &mut Rcu) -> (I2CX, SDA, SCL) {
        while self.i2c.ctl0().read().stop().bit_is_set() {}
        self.unlisten(Event::Protocol);
        self.unlisten(Event::Byte);
        self.unlisten(Event::Error);
        self.i2c.ctl0().modify(|_, w| w.i2cen().disabled());
        I2CX::disable(rcu);
        (self.i2c, self.sda_pin, self.scl_pin)
    }
}

impl<I2CX, SDA, SCL> I2c<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    /// Whether the bus is in use, by another master or by a transaction of this
    /// one (`I2CBSY`).
    pub fn is_busy(&self) -> bool {
        self.i2c.stat1().read().i2cbsy().is_busy()
    }
    /// START has gone out and the bus is waiting for the address (`SBSEND`).
    pub fn sbsend(&self) -> bool {
        self.i2c.stat0().read().sbsend().bit_is_set()
    }
    /// The addressed device answered; the data phase opens on
    /// [`clear_addsend`](Self::clear_addsend) (`ADDSEND`).
    pub fn addsend(&self) -> bool {
        self.i2c.stat0().read().addsend().bit_is_set()
    }
    /// `DATA` will take the next byte (`TBE`).
    ///
    /// True whenever nothing is queued, so a handler listening for it must stop
    /// once it has nothing left to send.
    pub fn tbe(&self) -> bool {
        self.i2c.stat0().read().tbe().bit_is_set()
    }
    /// The byte behind the one in `DATA` has arrived whole, and the peripheral
    /// holds SCL until software catches up (`BTC`).
    pub fn btc(&self) -> bool {
        self.i2c.stat0().read().btc().bit_is_set()
    }
    /// A received byte is waiting in `DATA` (`RBNE`).
    pub fn rbne(&self) -> bool {
        self.i2c.stat0().read().rbne().bit_is_set()
    }
    /// Blocks until the bus is free.
    ///
    /// Only the first START needs this: `I2CBSY` stays set while this master owns
    /// the bus, so waiting again before a repeated START would wait forever.
    pub fn wait_idle(&self) {
        while self.is_busy() {}
    }

    /// Raises START, which goes out as soon as the bus is free.
    ///
    /// On a bus this master already holds it is a repeated START, and the
    /// transaction continues without a STOP in between.
    pub fn write_start(&mut self) {
        self.i2c.ctl0().modify(|_, w| w.start().start());
    }
    /// Puts the address into `DATA` with `read` as its direction bit.
    ///
    /// Also the second half of clearing `SBSEND`, the first being the read of
    /// `STAT0` that observed it.
    ///
    /// # Panics
    ///
    /// If `address` does not fit in seven bits.
    pub fn write_addr(&mut self, address: u8, read: bool) {
        assert!(address <= 0x7F, "I2C address must be 7-bit");
        self.i2c
            .data()
            .write(|w| w.trb().bits(address << 1 | read as u8));
    }
    /// Puts one byte into `DATA`, which also clears `TBE`.
    pub fn write_byte(&mut self, byte: u8) {
        self.i2c.data().write(|w| w.trb().bits(byte));
    }
    /// Takes the received byte out of `DATA`, which also clears `RBNE`.
    pub fn read_byte(&mut self) -> u8 {
        self.i2c.data().read().trb().bits()
    }
    /// Releases the bus with a STOP condition.
    ///
    /// Every path out of a transaction goes through here, failures included: a
    /// skipped STOP leaves the master holding SCL, and the bus never goes idle
    /// again.
    pub fn write_stop(&mut self) {
        self.i2c.ctl0().modify(|_, w| w.stop().stop());
    }
    /// Clears `ADDSEND`, which releases the bus into the data phase.
    ///
    /// Goes down on a read of `STAT0` then a read of `STAT1`, in that order;
    /// skipping either leaves the transfer stalled.
    pub fn clear_addsend(&mut self) {
        self.i2c.stat0().read();
        self.i2c.stat1().read();
    }
    /// Acknowledges or refuses the byte currently on the wire (`ACKEN`).
    ///
    /// It governs the byte already being clocked in, so the NAK that ends a read
    /// has to stand one byte early — before `ADDSEND` is cleared on a one-byte
    /// read, and before the last `BTC` otherwise.
    pub fn set_acken(&mut self, ack: bool) {
        self.i2c.ctl0().modify(|_, w| w.acken().bit(ack));
    }
    /// Moves the acknowledge one byte further along (`POAP`), for the two-byte
    /// read where both bytes must be taken after the NAK is already placed.
    ///
    /// Like `ACKEN` it must stand before the START that begins the read.
    pub fn set_poap(&mut self, next: bool) {
        self.i2c.ctl0().modify(|_, w| w.poap().bit(next));
    }

    /// Sends START and the address, then waits for the device to answer.
    ///
    /// On a bus this master already holds, the START is a repeated one — hence no
    /// [`wait_idle`](Self::wait_idle) here. Returns with `ADDSEND` still raised:
    /// a short read has to write `ACKEN` before
    /// [`clear_addsend`](Self::clear_addsend) opens the data phase. Failures
    /// release the bus, so callers can propagate with `?`.
    fn start(&mut self, address: u8, read: bool) -> Result<(), Error> {
        self.write_start();

        while self.i2c.stat0().read().sbsend().is_no_start() {
            if let Some(err) = self.take_error_from(NoAcknowledgeSource::Unknown) {
                self.write_stop();
                return Err(err);
            }
        }
        self.write_addr(address, read);

        while self.i2c.stat0().read().addsend().is_not_match() {
            if let Some(err) = self.take_error_from(NoAcknowledgeSource::Address) {
                self.write_stop();
                return Err(err);
            }
        }
        Ok(())
    }
    /// Waits for a received byte to reach `DATA`, releasing the bus on error.
    fn wait_rbne(&mut self) -> Result<(), Error> {
        while self.i2c.stat0().read().rbne().is_empty() {
            if let Some(err) = self.take_error_from(NoAcknowledgeSource::Data) {
                self.write_stop();
                return Err(err);
            }
        }
        Ok(())
    }
    /// Waits for the byte in the shift register to finish, releasing the bus on
    /// error.
    ///
    /// While receiving, `BTC` means a byte arrived behind the one still unread in
    /// `DATA`, and the peripheral holds SCL low until software catches up.
    fn wait_btc(&mut self) -> Result<(), Error> {
        while self.i2c.stat0().read().btc().is_not_finished() {
            if let Some(err) = self.take_error_from(NoAcknowledgeSource::Data) {
                self.write_stop();
                return Err(err);
            }
        }
        Ok(())
    }

    /// Returns the first pending error, if any, clearing its flag.
    ///
    /// `source` says which step is running: one `AERR` covers both a dead address
    /// and an unacknowledged data byte.
    ///
    /// `STAT0` flags are `rc_w0`, so clearing goes through `modify` — a `write`
    /// would zero the flags it does not name and wipe them all.
    fn take_error_from(&mut self, source: NoAcknowledgeSource) -> Option<Error> {
        let stat = self.i2c.stat0().read();
        if stat.berr().is_error() {
            self.i2c.stat0().modify(|_, w| w.berr().no_error());
            Some(Error::Bus)
        } else if stat.lostarb().is_lost() {
            self.i2c.stat0().modify(|_, w| w.lostarb().no_lost());
            Some(Error::ArbitrationLoss)
        } else if stat.aerr().is_error() {
            self.i2c.stat0().modify(|_, w| w.aerr().no_error());
            Some(Error::NoAcknowledge(source))
        } else if stat.ouerr().is_overrun() {
            self.i2c.stat0().modify(|_, w| w.ouerr().no_overrun());
            Some(Error::Overrun)
        } else if stat.pecerr().is_error() {
            self.i2c.stat0().modify(|_, w| w.pecerr().no_error());
            Some(Error::Pec)
        } else if stat.smbto().is_timeout() {
            self.i2c.stat0().modify(|_, w| w.smbto().no_timeout());
            Some(Error::SmbusTimeout)
        } else if stat.smbalt().is_alert() {
            self.i2c.stat0().modify(|_, w| w.smbalt().no_alert());
            Some(Error::SmbusAlert)
        } else {
            None
        }
    }

    /// Writes `bytes` to the device at `address`, framed by START and STOP.
    ///
    /// `address` is the plain 7-bit value from the datasheet; the direction bit
    /// is appended here. Blocks until the last byte is out and acknowledged, so
    /// the bus is idle on return.
    ///
    /// # Errors
    ///
    /// [`Error::NoAcknowledge`] if nothing answers the address — with
    /// [`NoAcknowledgeSource::Address`], which is how a bus scan finds devices —
    /// or the device refuses a byte; [`Error::Bus`] or
    /// [`Error::ArbitrationLoss`] on a bus fault.
    ///
    /// # Panics
    ///
    /// If `address` does not fit in seven bits (10-bit addressing is not
    /// supported). Checked before the bus is touched.
    pub fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
        assert!(address <= 0x7F, "I2C address must be 7-bit");

        self.wait_idle();
        self.write_phase(address, bytes)?;
        self.write_stop();
        Ok(())
    }

    /// Addresses the device for writing and clocks `bytes` out, leaving the bus
    /// held: [`write`](Self::write) ends it with STOP,
    /// [`write_read`](Self::write_read) with a repeated START.
    fn write_phase(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
        self.start(address, false)?;
        self.clear_addsend();
        self.write_bytes(bytes)?;

        // With nothing sent there is no transfer to complete, and BTC never comes.
        if !bytes.is_empty() {
            self.wait_btc()?;
        }
        Ok(())
    }

    /// Clocks `bytes` out of an already addressed device.
    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
        for byte in bytes {
            while self.i2c.stat0().read().tbe().is_not_empty() {
                if let Some(err) = self.take_error_from(NoAcknowledgeSource::Data) {
                    self.write_stop();
                    return Err(err);
                }
            }
            self.i2c.data().write(|w| w.trb().bits(*byte));
        }
        Ok(())
    }
    /// Reads `bytes.len()` bytes from the device at `address`, framed by START
    /// and STOP.
    ///
    /// An empty `bytes` is a no-op: a zero-byte transfer has no acknowledge to
    /// end on.
    ///
    /// # Errors
    ///
    /// As for [`write`](Self::write); only the address can go unanswered.
    ///
    /// # Panics
    ///
    /// If `address` does not fit in seven bits.
    pub fn read(&mut self, address: u8, bytes: &mut [u8]) -> Result<(), Error> {
        assert!(address <= 0x7F, "I2C address must be 7-bit");
        if bytes.is_empty() {
            return Ok(());
        }

        self.wait_idle();
        self.read_phase(address, bytes)
    }

    /// Addresses the device for reading and fills `bytes`, ending with STOP.
    fn read_phase(&mut self, address: u8, bytes: &mut [u8]) -> Result<(), Error> {
        let n = bytes.len();
        self.read_slots(address, n, bytes.iter_mut())
    }

    /// The read phase over `n` byte slots, wherever they live: [`read`](Self::read)
    /// passes one slice, [`transaction`] spreads one run of received bytes over
    /// several buffers. `n` has to be known upfront — it decides where the NAK
    /// falls.
    ///
    /// [`transaction`]: embedded_hal::i2c::I2c::transaction
    fn read_slots<'a>(
        &mut self,
        address: u8,
        n: usize,
        mut slots: impl Iterator<Item = &'a mut u8>,
    ) -> Result<(), Error> {
        // Every `next()` below is matched against a slot counted in `n`.
        match n {
            0 => Ok(()),
            1 => {
                self.start(address, true)?;
                // The byte starts arriving the moment ADDSEND goes down, so the
                // NAK has to stand before that.
                self.i2c.ctl0().modify(|_, w| w.acken().nak());
                self.clear_addsend();
                self.write_stop();

                self.wait_rbne()?;
                if let Some(slot) = slots.next() {
                    *slot = self.read_byte();
                }
                Ok(())
            }
            2 => {
                // POAP moves the acknowledge one byte along, so the NAK lands on
                // the second byte. Must be set before START.
                self.i2c.ctl0().modify(|_, w| w.poap().next());
                let result = self.read_two(address, slots);
                self.i2c.ctl0().modify(|_, w| w.poap().current());
                result
            }
            _ => {
                self.i2c.ctl0().modify(|_, w| w.acken().ack());
                self.start(address, true)?;
                self.clear_addsend();

                // Up to the last three bytes: take each one as it lands.
                for _ in 0..n - 3 {
                    self.wait_rbne()?;
                    if let Some(slot) = slots.next() {
                        *slot = self.read_byte();
                    }
                }

                // Byte N-2 is left in DATA on purpose: once N-1 arrives behind it
                // the peripheral holds SCL, so this ACKEN cannot be late.
                self.wait_btc()?;
                self.i2c.ctl0().modify(|_, w| w.acken().nak());
                if let Some(slot) = slots.next() {
                    *slot = self.read_byte();
                }

                // Reading N-2 let the last byte in; SCL is stretched again, and
                // STOP goes out before it is read.
                self.wait_btc()?;
                self.write_stop();
                for slot in slots {
                    *slot = self.read_byte();
                }
                Ok(())
            }
        }
    }

    /// The two-byte read, split out so `POAP` is restored on every path.
    fn read_two<'a>(
        &mut self,
        address: u8,
        slots: impl Iterator<Item = &'a mut u8>,
    ) -> Result<(), Error> {
        self.start(address, true)?;
        self.i2c.ctl0().modify(|_, w| w.acken().nak());
        self.clear_addsend();

        // Neither byte is read until both have arrived, and STOP goes out before
        // either leaves DATA.
        self.wait_btc()?;
        self.write_stop();
        for slot in slots {
            *slot = self.read_byte();
        }
        Ok(())
    }

    /// Writes `write`, then reads into `read`, joined by a repeated START.
    ///
    /// This is how a register-addressed device is read: the write phase moves its
    /// pointer, the read phase takes what the pointer names. A
    /// [`write`](Self::write) then a [`read`](Self::read) puts a STOP in between,
    /// which some devices treat as the end of the register access.
    ///
    /// An empty `read` degenerates to [`write`](Self::write), an empty `write`
    /// to [`read`](Self::read).
    ///
    /// # Errors
    ///
    /// As for [`write`](Self::write), from either phase.
    ///
    /// # Panics
    ///
    /// If `address` does not fit in seven bits.
    pub fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
        assert!(address <= 0x7F, "I2C address must be 7-bit");

        self.wait_idle();
        self.write_phase(address, write)?;

        if read.is_empty() {
            self.write_stop();
            return Ok(());
        }
        // No STOP in between: the read phase's START is a repeated one.
        self.read_phase(address, read)
    }

    /// Returns the pending error, if any, and clears it.
    ///
    /// The acknowledge for [`Event::Error`]: the flag is what holds the
    /// interrupt request up, so a handler that skips this re-enters forever.
    /// One error per call — with two pending, the second survives for the next.
    /// A NACK reports [`NoAcknowledgeSource::Unknown`], the phase it arrived in
    /// being known only to whoever drives the transaction.
    pub fn take_error(&mut self) -> Option<Error> {
        self.take_error_from(NoAcknowledgeSource::Unknown)
    }

    /// Raises an interrupt on `event`, which still has to be unmasked in the
    /// NVIC.
    ///
    /// [`Event::Byte`] raises `EVIE` along with `BUFIE`, so it covers
    /// [`Event::Protocol`] too.
    pub fn listen(&mut self, event: Event) {
        match event {
            Event::Protocol => self.i2c.ctl1().modify(|_, w| w.evie().enabled()),
            Event::Byte => self
                .i2c
                .ctl1()
                .modify(|_, w| w.evie().enabled().bufie().enabled()),
            Event::Error => self.i2c.ctl1().modify(|_, w| w.errie().enabled()),
        }
    }
    /// Stops raising an interrupt on `event`.
    ///
    /// [`Event::Protocol`] takes `BUFIE` down with it: byte events cannot stand
    /// on their own in hardware. Dropping only those is
    /// `unlisten(Event::Byte)`.
    pub fn unlisten(&mut self, event: Event) {
        match event {
            Event::Protocol => self
                .i2c
                .ctl1()
                .modify(|_, w| w.evie().disabled().bufie().disabled()),
            Event::Byte => self.i2c.ctl1().modify(|_, w| w.bufie().disabled()),
            Event::Error => self.i2c.ctl1().modify(|_, w| w.errie().disabled()),
        }
    }
    /// Whether `event` is being listened for.
    pub fn is_listening(&self, event: Event) -> bool {
        let ctl1 = self.i2c.ctl1().read();
        match event {
            Event::Protocol => ctl1.evie().is_enabled(),
            Event::Byte => ctl1.evie().is_enabled() && ctl1.bufie().is_enabled(),
            Event::Error => ctl1.errie().is_enabled(),
        }
    }

    /// Starts a write of `buf` to `address`, to be driven by interrupts.
    ///
    /// Takes the peripheral with it; both come back from
    /// [`release`](WriteTransfer::release). An empty `buf` still addresses the
    /// device, which is how a bus scan probes for one. Blocks only until the bus
    /// is free, then raises START and returns.
    ///
    /// Arms the interrupts itself and keeps re-arming them as the phases change,
    /// so `listen` beforehand is neither needed nor respected.
    ///
    /// # Panics
    ///
    /// If `address` does not fit in seven bits.
    pub fn start_write(mut self, address: u8, buf: &'static [u8]) -> WriteTransfer<I2CX, SDA, SCL> {
        assert!(address <= 0x7F, "I2C address must be 7-bit");
        self.wait_idle();
        self.listen(Event::Error);
        self.listen(Event::Byte);
        self.write_start();
        WriteTransfer {
            i2c: self,
            address: address << 1,
            buf,
            pos: 0,
            state: WriteState::Sbsend,
        }
    }
    /// Starts a read of `buf.len()` bytes from `address`, to be driven by
    /// interrupts.
    ///
    /// Takes the peripheral with it; both come back from
    /// [`release`](ReadTransfer::release). An empty `buf` finishes immediately
    /// without touching the bus — a zero-byte read has no acknowledge to end on.
    /// Blocks only until the bus is free, then raises START and returns.
    ///
    /// Arms the interrupts itself and keeps re-arming them as the phases change,
    /// so `listen` beforehand is neither needed nor respected.
    ///
    /// # Panics
    ///
    /// If `address` does not fit in seven bits.
    pub fn start_read(
        mut self,
        address: u8,
        buf: &'static mut [u8],
    ) -> ReadTransfer<I2CX, SDA, SCL> {
        assert!(address <= 0x7F, "I2C address must be 7-bit");
        if buf.is_empty() {
            return ReadTransfer {
                i2c: self,
                address: address << 1 | 1,
                buf,
                pos: 0,
                state: ReadState::Done(Ok(())),
            };
        }

        self.wait_idle();
        // Both of these must stand before START: ACKEN governs the byte already
        // on the wire, and POAP moves it one further along.
        self.set_acken(buf.len() > 2);
        self.set_poap(buf.len() == 2);
        self.listen(Event::Error);
        self.listen(Event::Byte);
        self.write_start();
        ReadTransfer {
            i2c: self,
            address: address << 1 | 1,
            buf,
            pos: 0,
            state: ReadState::Sbsend,
        }
    }
}

/// Where a [`WriteTransfer`] stands: the flag it is waiting for.
#[derive(Clone, Copy)]
enum WriteState {
    /// START is out; `SBSEND` calls for the address.
    Sbsend,
    /// The address is out; `ADDSEND` opens the data phase.
    Addsend,
    /// Feeding `DATA`, one byte per `TBE`.
    Sending,
    /// Everything is fed; `BTC` says the wire is clear for STOP.
    Btc,
    /// Over, carrying the outcome the handler reached.
    Done(Result<(), Error>),
}

/// A write driven by interrupts, owning the peripheral and the buffer.
///
/// Built by [`I2c::start_write`]. The handler for both I²C vectors calls
/// [`on_interrupt`](Self::on_interrupt); the transfer is over once
/// [`is_done`](Self::is_done) says so, and [`release`](Self::release) takes it
/// apart.
#[must_use = "dropping the transfer aborts it"]
pub struct WriteTransfer<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    i2c: I2c<I2CX, SDA, SCL>,
    address: u8,
    buf: &'static [u8],
    pos: usize,
    state: WriteState,
}

impl<I2CX, SDA, SCL> WriteTransfer<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    /// Advances the transfer by one step. Call from both I²C interrupt
    /// handlers.
    ///
    /// Reads the flags itself rather than trusting which vector it was entered
    /// from, so a wakeup this step has nothing to do with is simply ignored.
    pub fn on_interrupt(&mut self) {
        if self.is_done() {
            return;
        }
        if let Some(err) = self.i2c.take_error() {
            self.i2c.write_stop();
            self.finish(Err(err));
            return;
        }

        match self.state {
            WriteState::Sbsend if self.i2c.sbsend() => {
                self.i2c.write_byte(self.address);
                self.state = WriteState::Addsend;
            }
            WriteState::Addsend if self.i2c.addsend() => {
                self.i2c.clear_addsend();
                if self.buf.is_empty() {
                    // Addressing was the whole transfer; BTC never comes.
                    self.i2c.write_stop();
                    self.finish(Ok(()));
                } else {
                    self.state = WriteState::Sending;
                }
            }
            WriteState::Sending if self.i2c.tbe() => {
                self.i2c.write_byte(self.buf[self.pos]);
                self.pos += 1;
                if self.pos == self.buf.len() {
                    // TBE stays up with nothing left to feed, so stop listening
                    // for it and wait out the byte in the shift register.
                    self.i2c.unlisten(Event::Byte);
                    self.state = WriteState::Btc;
                }
            }
            WriteState::Btc if self.i2c.btc() => {
                self.i2c.write_stop();
                self.finish(Ok(()));
            }
            _ => {}
        }
    }
    /// Whether the transfer has ended, successfully or not.
    pub fn is_done(&self) -> bool {
        matches!(self.state, WriteState::Done(_))
    }
    /// Gives back the peripheral, the buffer and the outcome.
    ///
    /// `None` means the transfer was taken apart while still running, in which
    /// case the bus is released with a STOP first.
    #[allow(clippy::type_complexity)]
    pub fn release(
        self,
    ) -> (
        I2c<I2CX, SDA, SCL>,
        &'static [u8],
        Option<Result<(), Error>>,
    ) {
        let mut this = ManuallyDrop::new(self);
        let outcome = if let WriteState::Done(result) = this.state {
            Some(result)
        } else {
            this.abort();
            None
        };
        // SAFETY: `this` is never dropped, so the field is read exactly once.
        let i2c = unsafe { ptr::read(&raw const this.i2c) };
        (i2c, this.buf, outcome)
    }
    /// Stops every interrupt and records the outcome. The bus is released by
    /// the caller, which knows whether a STOP has gone out already.
    fn finish(&mut self, result: Result<(), Error>) {
        self.i2c.unlisten(Event::Protocol);
        self.i2c.unlisten(Event::Error);
        self.state = WriteState::Done(result);
    }
    /// Cuts a running transfer short, leaving the bus idle.
    fn abort(&mut self) {
        self.i2c.write_stop();
        self.finish(Ok(()));
    }
}

impl<I2CX, SDA, SCL> Drop for WriteTransfer<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    fn drop(&mut self) {
        if !self.is_done() {
            self.abort();
        }
    }
}

/// Where a [`ReadTransfer`] stands: the flag it is waiting for.
///
/// The tail states exist because `ACKEN` governs the byte already on the wire,
/// one ahead of the one being read — the manual's "Solution B".
#[derive(Clone, Copy)]
enum ReadState {
    /// START is out; `SBSEND` calls for the address.
    Sbsend,
    /// The address is out; `ADDSEND` opens the data phase.
    Addsend,
    /// Three or more bytes to go: take each one as it lands on `RBNE`.
    Receiving,
    /// Three left. `BTC` means two of them are in, so the NAK cannot be late.
    Penultimate,
    /// Two left, both already arrived: STOP goes out before either is read.
    Tail,
    /// The one-byte read: its NAK stands, STOP is out, `RBNE` is all that's
    /// left.
    Single,
    /// Over, carrying the outcome the handler reached.
    Done(Result<(), Error>),
}

/// A read driven by interrupts, owning the peripheral and the buffer.
///
/// Built by [`I2c::start_read`]. The handler for both I²C vectors calls
/// [`on_interrupt`](Self::on_interrupt); the transfer is over once
/// [`is_done`](Self::is_done) says so, and [`release`](Self::release) takes it
/// apart.
#[must_use = "dropping the transfer aborts it"]
pub struct ReadTransfer<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    i2c: I2c<I2CX, SDA, SCL>,
    address: u8,
    buf: &'static mut [u8],
    pos: usize,
    state: ReadState,
}

impl<I2CX, SDA, SCL> ReadTransfer<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    /// Advances the transfer by one step. Call from both I²C interrupt
    /// handlers.
    ///
    /// Reads the flags itself rather than trusting which vector it was entered
    /// from, so a wakeup this step has nothing to do with is simply ignored.
    pub fn on_interrupt(&mut self) {
        if self.is_done() {
            return;
        }
        if let Some(err) = self.i2c.take_error() {
            self.i2c.write_stop();
            self.finish(Err(err));
            return;
        }

        match self.state {
            ReadState::Sbsend if self.i2c.sbsend() => {
                self.i2c.write_byte(self.address);
                self.state = ReadState::Addsend;
            }
            ReadState::Addsend if self.i2c.addsend() => {
                self.state = match self.buf.len() {
                    1 => {
                        // The byte starts arriving the moment ADDSEND goes
                        // down, so the NAK has to stand before that.
                        self.i2c.set_acken(false);
                        self.i2c.clear_addsend();
                        self.i2c.write_stop();
                        ReadState::Single
                    }
                    2 => {
                        self.i2c.set_acken(false);
                        self.i2c.clear_addsend();
                        self.i2c.unlisten(Event::Byte);
                        ReadState::Tail
                    }
                    3 => {
                        // Nothing to take before the tail: the three bytes are
                        // exactly what the last two steps handle.
                        self.i2c.clear_addsend();
                        self.i2c.unlisten(Event::Byte);
                        ReadState::Penultimate
                    }
                    _ => {
                        self.i2c.clear_addsend();
                        ReadState::Receiving
                    }
                };
            }
            ReadState::Single if self.i2c.rbne() => {
                self.buf[0] = self.i2c.read_byte();
                self.pos = 1;
                self.finish(Ok(()));
            }
            ReadState::Receiving if self.i2c.rbne() => {
                self.buf[self.pos] = self.i2c.read_byte();
                self.pos += 1;
                if self.pos == self.buf.len() - 3 {
                    // From here on the steps wait for BTC, and RBNE would only
                    // wake the handler between them.
                    self.i2c.unlisten(Event::Byte);
                    self.state = ReadState::Penultimate;
                }
            }
            ReadState::Penultimate if self.i2c.btc() => {
                // Byte N-2 stayed in DATA on purpose: with N-1 behind it the
                // peripheral holds SCL, so this ACKEN cannot be late.
                self.i2c.set_acken(false);
                self.buf[self.pos] = self.i2c.read_byte();
                self.pos += 1;
                self.state = ReadState::Tail;
            }
            ReadState::Tail if self.i2c.btc() => {
                // Both remaining bytes have arrived; STOP goes out before
                // either leaves DATA.
                self.i2c.write_stop();
                while self.pos < self.buf.len() {
                    self.buf[self.pos] = self.i2c.read_byte();
                    self.pos += 1;
                }
                self.finish(Ok(()));
            }
            _ => {}
        }
    }
    /// Whether the transfer has ended, successfully or not.
    pub fn is_done(&self) -> bool {
        matches!(self.state, ReadState::Done(_))
    }
    /// Gives back the peripheral, the buffer and the outcome.
    ///
    /// `None` means the transfer was taken apart while still running, in which
    /// case the bus is released with a STOP first.
    #[allow(clippy::type_complexity)]
    pub fn release(
        self,
    ) -> (
        I2c<I2CX, SDA, SCL>,
        &'static mut [u8],
        Option<Result<(), Error>>,
    ) {
        let mut this = ManuallyDrop::new(self);
        let outcome = if let ReadState::Done(result) = this.state {
            Some(result)
        } else {
            this.abort();
            None
        };
        // SAFETY: `this` is never dropped, so the fields are read exactly once.
        let (i2c, buf) = unsafe {
            (
                ptr::read(&raw const this.i2c),
                ptr::read(&raw const this.buf),
            )
        };
        (i2c, buf, outcome)
    }
    /// Stops every interrupt, restores `POAP` and records the outcome. The bus
    /// is released by the caller, which knows whether a STOP has gone out
    /// already.
    fn finish(&mut self, result: Result<(), Error>) {
        self.i2c.set_poap(false);
        self.i2c.unlisten(Event::Protocol);
        self.i2c.unlisten(Event::Error);
        self.state = ReadState::Done(result);
    }
    /// Cuts a running transfer short, leaving the bus idle.
    fn abort(&mut self) {
        self.i2c.write_stop();
        self.finish(Ok(()));
    }
}

impl<I2CX, SDA, SCL> Drop for ReadTransfer<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    fn drop(&mut self) {
        if !self.is_done() {
            self.abort();
        }
    }
}

impl<I2CX, SDA, SCL> ErrorType for I2c<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    type Error = Error;
}

/// Whether two operations run in the same direction, and so belong to one
/// addressed phase.
fn same_direction(a: &Operation<'_>, b: &Operation<'_>) -> bool {
    matches!(
        (a, b),
        (Operation::Read(_), Operation::Read(_)) | (Operation::Write(_), Operation::Write(_))
    )
}

impl<I2CX, SDA, SCL> embedded_hal::i2c::I2c for I2c<I2CX, SDA, SCL>
where
    I2CX: Instance,
{
    /// Per the trait's contract: neighbouring operations of the same direction
    /// join into one addressed phase, a change of direction inserts a repeated
    /// START, and only the end carries a STOP.
    ///
    /// # Panics
    ///
    /// If `address` does not fit in seven bits, or if a `Read` is followed by
    /// further operations — ending a read early needs a repeated START in place
    /// of its STOP, which the read sequences here do not express. `[Write.., Read]`
    /// works.
    fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
        assert!(address <= 0x7F, "I2C address must be 7-bit");
        if operations.is_empty() {
            return Ok(());
        }
        let phases = operations.chunk_by(same_direction).count();

        self.wait_idle();
        for (i, phase) in operations.chunk_by_mut(same_direction).enumerate() {
            let last = i + 1 == phases;
            match phase.first() {
                Some(Operation::Write(_)) => {
                    self.start(address, false)?;
                    self.clear_addsend();
                    let mut sent = false;
                    for op in phase.iter() {
                        if let Operation::Write(bytes) = op {
                            self.write_bytes(bytes)?;
                            sent |= !bytes.is_empty();
                        }
                    }
                    if sent {
                        self.wait_btc()?;
                    }
                    if last {
                        self.write_stop();
                    }
                }
                Some(Operation::Read(_)) => {
                    assert!(last, "I2C read must be the last operation of a transaction");
                    let n = phase
                        .iter()
                        .map(|op| match op {
                            Operation::Read(buf) => buf.len(),
                            Operation::Write(_) => 0,
                        })
                        .sum();
                    let slots = phase
                        .iter_mut()
                        .filter_map(|op| match op {
                            Operation::Read(buf) => Some(buf),
                            Operation::Write(_) => None,
                        })
                        .flat_map(|buf| buf.iter_mut());
                    self.read_slots(address, n, slots)?;
                }
                None => {}
            }
        }
        Ok(())
    }

    fn read(&mut self, address: u8, bytes: &mut [u8]) -> Result<(), Error> {
        self.read(address, bytes)
    }
    fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
        self.write(address, bytes)
    }
    fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
        self.write_read(address, bytes, buffer)
    }
}