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
// Pure eUSCI_B I2C **slave-mode** register math for the `i2c` module.
//
// Like `rtc_alarm.rs` and `mpu_seg.rs`, this file is intentionally
// dependency-free (pure `core` integer arithmetic, no PAC/HAL types) so the
// exact same source can be `include!`d by the host-side test crate in
// `unit_tests/`. The `i2c::I2cSlave` driver is a thin wrapper over these
// conversions — a regression here (a shifted `UCOAEN` bit, an accepted
// reserved address, a transposed IV slot) fails the host tests without a
// board on the desk. Do not add external `use`s. (Regular `//` comments, not
// `//!`, so the file can be `include!`d mid-crate.)
//
// # The hardware's own-address model (SLAU367P, eUSCI_B I2C mode)
//
// A slave answers the addresses programmed into `UCBxI2COA0..3`. This driver
// uses only `I2COA0`: bits 9:0 hold the address, bit 10 (`UCOAEN`) enables
// matching, and — on `I2COA0` only — bit 15 (`UCGCEN`) additionally answers
// the I2C general call (address 0x00). The other three own-address registers
// and the `ADDMASK` range-matching stay at their reset values (disabled /
// match-all-bits) so exactly one address is answered.
//
// # The interrupt-vector table (UCBxIV)
//
// The `USCI_B0` vector demuxes through `UCBxIV`, whose read atomically clears
// the served (highest-priority pending) flag. The slot values below are TI's
// `USCI_I2C_*` constants from `msp430fr5969.h`. **They are not yet verified
// on hardware** — and this project has already caught one vendor-table
// discrepancy the hard way (the RTCIV alarm slot, documented 0x08, observed
// 0x06), so treat `decode_iv` as the documented-table reference that the
// eventual hardware fixture must confirm slot by slot.
/// `UCOAEN` — own-address-enable bit in `UCBxI2COA0..3` (bit 10).
pub const OA_ENABLE: u16 = 0x0400;
/// `UCGCEN` — general-call-enable bit, `UCBxI2COA0` only (bit 15).
pub const OA_GENERAL_CALL: u16 = 0x8000;
/// Reasons a 7-bit own address is rejected.
/// Validate a 7-bit own address and encode the `UCBxI2COA0` register word:
/// the address in bits 9:0, `UCOAEN` set, and `UCGCEN` when the slave should
/// also answer the general call (address 0x00).
// ---------------------------------------------------------------------------
// UCBxIV decode
// ---------------------------------------------------------------------------
// TI's USCI_I2C_* interrupt-vector values (msp430fr5969.h). The eUSCI_B I2C
// IV is priority-ordered: bus errors first, then framing, then the four
// receive/transmit pairs from own-address 3 down to own-address 0, then the
// byte counter and timeout sources.
pub const IV_NONE: u16 = 0x00;
pub const IV_ARBITRATION_LOST: u16 = 0x02; // UCALIFG
pub const IV_NACK: u16 = 0x04; // UCNACKIFG
pub const IV_START: u16 = 0x06; // UCSTTIFG (own address + R/W received)
pub const IV_STOP: u16 = 0x08; // UCSTPIFG
pub const IV_RX3: u16 = 0x0A; // UCRXIFG3
pub const IV_TX3: u16 = 0x0C; // UCTXIFG3
pub const IV_RX2: u16 = 0x0E; // UCRXIFG2
pub const IV_TX2: u16 = 0x10; // UCTXIFG2
pub const IV_RX1: u16 = 0x12; // UCRXIFG1
pub const IV_TX1: u16 = 0x14; // UCTXIFG1
pub const IV_RX: u16 = 0x16; // UCRXIFG0 (data received, own address 0)
pub const IV_TX: u16 = 0x18; // UCTXIFG0 (TXBUF empty, own address 0)
pub const IV_BYTE_COUNTER: u16 = 0x1A; // UCBCNTIFG
pub const IV_CLOCK_LOW_TIMEOUT: u16 = 0x1C; // UCCLTOIFG
pub const IV_NINTH_BIT: u16 = 0x1E; // UCBIT9IFG
/// A decoded `UCBxIV` value, from the slave's point of view.
/// Decode a `UCBxIV` read. Total (any `u16` maps to something), so an ISR can
/// log an off-table value instead of misattributing it.