Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl GpioBitmask {
///
/// Big-endian places IO0 in the last byte's least-significant bit and
/// IO31 in the first byte's most-significant bit, so IO `n` is bit `n`
/// of the `byte_msg_payload` exactly as TC18 §13.7.4.1's Figure 24 lays
/// of the `byte_msg_payload` exactly as TC18 §13.7.4.1's Figure 25 lays
/// the payload out (msb on the left, IO23..IO0 in the low positions for
/// that figure's own 24-pin example endpoint).
//fusa:req REQ-GPIO-001
Expand Down Expand Up @@ -245,12 +245,12 @@ pub enum GpioWriteSemantics {
/// Bitwise AND the operand into the current value.
///
/// TC18 §13.7.4.1's prose words the value-changing operations as
/// "(NAND, OR, XOR)", but TC18 §13.5's Table 30 — the normative
/// "(NAND, OR, XOR)", but TC18 §13.5's Table 33 — the normative
/// per-endpoint `evt[2:0]` table — defines code `010b` as the
/// *byte_msg_payload bitwise AND current interface status*, with the
/// worked example "with a byte_msg_payload of 0xFFFF FFFE the first IO
/// pin will be reset, while other IO pins remain unchanged". This crate
/// follows Table 30's AND; §13.7.4.1's "NAND" wording contradicts it and
/// follows Table 33's AND; §13.7.4.1's "NAND" wording contradicts it and
/// is recorded as a TC18-internal inconsistency, not implemented as
/// written.
//fusa:req REQ-GPIO-021
Expand Down Expand Up @@ -852,7 +852,7 @@ mod tests {

// ── TC18 §13.7.4 spec-literal conformance checks ────────────────────────

/// TC18 §13.7.4.1 (TC18.txt line 4381): "Each GPIO endpoint can handle
/// TC18 §13.7.4.1 (TC18.txt line 4789): "Each GPIO endpoint can handle
/// up to 32 IOs." The 4-byte bitmask is exactly 32 bit positions wide,
/// so IO0..IO31 are all representable and there is no IO32.
#[test]
Expand All @@ -876,7 +876,7 @@ mod tests {
);
}

/// TC18 §13.7.4.1 / Figure 24 (TC18.txt lines 4389-4398): "Each GPIO pin
/// TC18 §13.7.4.1 / Figure 25 (TC18.txt lines 4797-4808): "Each GPIO pin
/// can be assigned to a bit position of the byte_msg_payload", laid out
/// msb-first with IO23..IO0 in the low bit positions for that figure's
/// own 24-pin example endpoint. IO `n` is therefore bit `n`, and the
Expand All @@ -890,16 +890,16 @@ mod tests {
assert_eq!(GpioBitmask(1u32 << 7).encode(), [0x00, 0x00, 0x00, 0x80]);
// IO8 opens the next byte up.
assert_eq!(GpioBitmask(1u32 << 8).encode(), [0x00, 0x00, 0x01, 0x00]);
// IO23 — the highest IO drawn in Figure 24's 24-pin example.
// IO23 — the highest IO drawn in Figure 25's 24-pin example.
assert_eq!(GpioBitmask(1u32 << 23).encode(), [0x00, 0x80, 0x00, 0x00]);
// Figure 24's whole 24-pin example EP: IO0..IO23 asserted, the
// Figure 25's whole 24-pin example EP: IO0..IO23 asserted, the
// "don't care" positions above IO23 clear.
assert_eq!(GpioBitmask(0x00FF_FFFF).encode(), [0x00, 0xFF, 0xFF, 0xFF]);
// IO31 tops out the 32-IO range.
assert_eq!(GpioBitmask(1u32 << 31).encode(), [0x80, 0x00, 0x00, 0x00]);
}

/// TC18 §13.7.4.3 (TC18.txt line 4480): "A request with data
/// TC18 §13.7.4.3 (TC18.txt line 4889): "A request with data
/// '0x0000 0000' and evt[2:0] = 0x001 (OR) results in 'no change'."
#[test]
//fusa:test REQ-GPIO-019
Expand All @@ -923,16 +923,16 @@ mod tests {
}
}

/// TC18 §13.7.4.1 (TC18.txt lines 4403-4404): "Generating a pulse for a
/// TC18 §13.7.4.1 (TC18.txt lines 4811-4812): "Generating a pulse for a
/// defined time is NOT a function of the GPIO endpoint. This either
/// needs to be managed by the Client ... by a compound or a trigger
/// operation." The endpoint's whole write surface is therefore exactly
/// TC18 §13.5 Table 30's eight `evt[2:0]` value-level codes, with no
/// TC18 §13.5 Table 33's eight `evt[2:0]` value-level codes, with no
/// ninth, duration-carrying operation.
#[test]
//fusa:test REQ-GPIO-020
fn gpio_write_surface_is_tc18_eight_codes_with_no_pulse_operation() {
// TC18 §13.5 Table 30's GPIO/PWM_OUT rows, code by code.
// TC18 §13.5 Table 33's GPIO/PWM_OUT rows, code by code.
let table_30: [(u8, GpioWriteSemantics); 8] = [
(0b000, GpioWriteSemantics::Replace),
(0b001, GpioWriteSemantics::Or),
Expand All @@ -957,21 +957,21 @@ mod tests {
}
}

/// TC18 §13.7.4.1 (TC18.txt line 4402) words the value-changing
/// operations as "(NAND, OR, XOR)", but TC18 §13.5 Table 30 (TC18.txt
/// lines 3699-3702) defines `evt[2:0] = 010b` as the byte_msg_payload
/// TC18 §13.7.4.1 (TC18.txt line 4810) words the value-changing
/// operations as "(NAND, OR, XOR)", but TC18 §13.5 Table 33 (TC18.txt
/// lines 4098-4101) defines `evt[2:0] = 010b` as the byte_msg_payload
/// *bitwise AND* the current interface status, with the worked example
/// "with a byte_msg_payload of 0xFFFF FFFE the first IO pin will be
/// reset, while other IO pins remain unchanged". This crate follows
/// Table 30's AND.
/// Table 33's AND.
#[test]
//fusa:test REQ-GPIO-021
fn gpio_evt_010b_is_bitwise_and_per_tc18_table_30_worked_example() {
assert_eq!(
GpioWriteSemantics::from_sub_opcode(0b010),
Ok(GpioWriteSemantics::And)
);
// Table 30's own worked example: every IO currently set, payload
// Table 33's own worked example: every IO currently set, payload
// 0xFFFF_FFFE -> IO0 reset, IO1..IO31 unchanged.
let current = GpioBitmask(0xFFFF_FFFF);
let payload = GpioBitmask(0xFFFF_FFFE);
Expand Down
20 changes: 10 additions & 10 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,12 +446,12 @@ mod tests {
assert!(!mode.is_ambiguous_high_speed_row());
}

// ── TC18 Table 46: i2c_mode preset wire values ──────────────────────────
// ── TC18 Table 49: i2c_mode preset wire values ──────────────────────────

#[test]
//fusa:test REQ-I2C-009
fn i2c_mode_wire_values_match_tc18_table_46_unambiguous_rows() {
// TC18 §13.7.7.2 Table 46 (TC18.txt lines 4815-4817), i2c_mode
// TC18 §13.7.7.2 Table 49 (TC18.txt lines 5226-5228), i2c_mode
// (relative address 0x0007, 8 bit R/W):
// 0: Standard Mode 100kbit/s
// 1: Fast Mode 400kbit/s
Expand All @@ -462,7 +462,7 @@ mod tests {
assert_eq!(I2cSpeedMode::Standard.to_u8(), 0);
assert_eq!(I2cSpeedMode::Fast.to_u8(), 1);
assert_eq!(I2cSpeedMode::FastPlus.to_u8(), 2);
// None of these three rows is one of Table 46's duplicated
// None of these three rows is one of Table 49's duplicated
// high-speed rows, so none may be reported as unresolved.
for mode in [
I2cSpeedMode::Standard,
Expand All @@ -476,14 +476,14 @@ mod tests {
#[test]
//fusa:test REQ-I2C-010
fn i2c_mode_value_three_is_not_resolved_to_a_single_high_speed_rate() {
// TC18 §13.7.7.2 Table 46 (TC18.txt lines 4818-4819) lists two
// TC18 §13.7.7.2 Table 49 (TC18.txt lines 5229-5230) lists two
// adjacent High-speed rows that both carry the same i2c_mode wire
// value 3:
// 3: High-speed mode 1.7Mbit/s
// 3: High-speed mode 3.4Mbit/s
// Decoding value 3 must therefore be flagged as unresolved rather
// than silently picking either bit rate.
let decoded = I2cSpeedMode::from_u8(3).expect("3 is an enumerated Table 46 i2c_mode value");
let decoded = I2cSpeedMode::from_u8(3).expect("3 is an enumerated Table 49 i2c_mode value");
assert!(decoded.is_ambiguous_high_speed_row());
assert_eq!(decoded.to_u8(), 3);
}
Expand All @@ -493,11 +493,11 @@ mod tests {
#[test]
//fusa:test REQ-I2C-011
fn i2c_byte_transfer_is_transparent_to_seven_and_ten_bit_addressing() {
// TC18 §13.7.7.3 (TC18.txt line 4830): "The byte msg payload is the
// I2C payload including the address. The I2C endpoint does not know
// whether there is a 7- or 10-bit address, since the endpoint is just
// transparent." The worked example there (Figure 29) is an I²C
// transfer with a 10-bit address and 5 bytes of data — 2 address
// TC18 §13.7.7.3 (TC18.txt lines 5241-5242): "The byte msg payload is
// the I2C payload including the address. The I2C endpoint does not
// know whether there is a 7- or 10-bit address, since the endpoint
// is just transparent." The worked example there (Figure 30) is an
// I²C transfer with a 10-bit address and 5 bytes of data — 2 address
// bytes + 5 data bytes = a 7-byte byte_msg_payload.
let ten_bit_addressed = vec![0xF2, 0x34, 0x11, 0x22, 0x33, 0x44, 0x55];
assert_eq!(ten_bit_addressed.len(), 7);
Expand Down
10 changes: 5 additions & 5 deletions src/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ impl RcServerState {
/// spec fact) given `HW_UNCONFIGURED`'s name and `0x00` encoding both
/// suggest a power-on/reset default.
///
/// TC18 §12.3 (TC18.txt line 2059) settles the surrounding rule this
/// TC18 §12.3 (TC18.txt line 2434) settles the surrounding rule this
/// default serves: "After a power cycle or restart ... the RC Server
/// shall start in the life-cycle state it is actually configured in",
/// where a device with no NVM "may incorporate default settings which
Expand Down Expand Up @@ -529,7 +529,7 @@ pub fn check_register_writable(
///
/// One of the excluded pairs is excluded by TC18 itself, not merely by
/// this crate's reading of `ROADMAP.md`: TC18 §12.3.1.1 (TC18.txt line
/// 2168) states that, from `HW_UNCONFIGURED`, "a request to advance the
/// 2544) states that, from `HW_UNCONFIGURED`, "a request to advance the
/// state directly to RCP_CONFIGURED will be rejected with an error
/// response" — the two-hop route through `HW_CONFIGURED` is the only way
/// up.
Expand Down Expand Up @@ -665,7 +665,7 @@ mod tests {

// ── TC18 §12.3: start state after a power cycle or restart ───────────

/// TC18 §12.3 (TC18.txt line 2059): "After a power cycle or restart,
/// TC18 §12.3 (TC18.txt line 2434): "After a power cycle or restart,
/// depending on the RC Server's implementation, the RC Server shall
/// start in the life-cycle state it is actually configured in.
/// Depending on the devices physical implementation it may have either
Expand All @@ -676,7 +676,7 @@ mod tests {
///
/// Both halves are asserted against literal values: the no-stored-
/// configuration default is `HW_UNCONFIGURED`/`0x00`, and each of the
/// three state names TC18 §12.3 lists (TC18.txt lines 2065-2067) can be
/// three state names TC18 §12.3 lists (TC18.txt lines 2440-2442) can be
/// restored by name as a configured start state.
#[test]
//fusa:test REQ-LIFE-015
Expand All @@ -702,7 +702,7 @@ mod tests {

// ── TC18 §12.3.1.1: no direct advance to RCP_CONFIGURED ──────────────

/// TC18 §12.3.1.1 (TC18.txt line 2168): from `HW_UNCONFIGURED`, "per
/// TC18 §12.3.1.1 (TC18.txt lines 2543-2544): from `HW_UNCONFIGURED`, "per
/// write request to the server functional configuration entry
/// svr_lifecycle_state the life-cycle state can be advanced to
/// HW_CONFIGURED. A request to advance the state directly to
Expand Down
22 changes: 11 additions & 11 deletions src/lin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@
//!
//! ## TC18 reconciliation note (§13.7.10)
//!
//! TC18 §13.7.10.3 (TC18.txt line 5304) states only that "the Byte Msg
//! Payload is the payload to be used on the Lin bus", and Figure 38 shows
//! TC18 §13.7.10.3 (TC18.txt line 5720) states only that "the Byte Msg
//! Payload is the payload to be used on the Lin bus", and Figure 39 shows
//! that payload as one undifferentiated "Lin payload" field followed by
//! padding — it defines no PID sub-field, no checksum sub-field, and no
//! per-frame length ceiling of its own. This module's split of the leading
Expand All @@ -194,13 +194,13 @@
//! recorded as explicit not-implemented requirement entries rather than
//! silently omitted: matching each received LIN message against the pending
//! read request's `byte_msg_payload` under the conditions given by
//! `evt[2:0]` and replying when `op = 0` (TC18.txt lines 5276-5277); issuing
//! `evt[2:0]` and replying when `op = 0` (TC18.txt lines 5692-5693); issuing
//! a trigger once a transmission has been finalized and the configured
//! trailing time has expired (line 5278); and the cyclic-transmission
//! trailing time has expired (line 5694); and the cyclic-transmission
//! pattern built from a repeated trigger request on the endpoint's own
//! trigger (line 5279). All three are RC-Server run-time endpoint behaviors,
//! outside this module's codec-only scope. TC18 Table 52's own
//! functional-config register layout (§13.7.10.2, lines 5287-5298) is
//! trigger (line 5695). All three are RC-Server run-time endpoint behaviors,
//! outside this module's codec-only scope. TC18 Table 55's own
//! functional-config register layout (§13.7.10.2, lines 5697-5714) is
//! likewise unimplemented — see [`LinFunctionalConfig`].
//!
//! ## Relationship to [`crate::regmap`]
Expand Down Expand Up @@ -288,7 +288,7 @@ impl LinFrameTransfer {
/// Encode this transfer to its raw wire representation: the PID byte
/// followed by `data`, unmodified and unframed.
///
/// This is the `byte_msg_payload` TC18 §13.7.10.3 (TC18.txt line 5304)
/// This is the `byte_msg_payload` TC18 §13.7.10.3 (TC18.txt line 5720)
/// calls "the payload to be used on the Lin bus": the bytes are emitted
/// verbatim, in supplied order, with nothing inserted, removed, or
/// reordered — see this module's doc comment "TC18 reconciliation note".
Expand Down Expand Up @@ -479,9 +479,9 @@ mod tests {
#[test]
//fusa:test REQ-LIN-007
fn lin_byte_msg_payload_is_carried_verbatim_onto_the_bus() {
// TC18 §13.7.10.3 (TC18.txt line 5304): "The Byte Msg Payload is the
// payload to be used on the Lin bus." Figure 38's own on-wire example
// (line 5305) carries three payload bytes with no PID/checksum
// TC18 §13.7.10.3 (TC18.txt line 5720): "The Byte Msg Payload is the
// payload to be used on the Lin bus." Figure 39's own on-wire example
// (line 5721) carries three payload bytes with no PID/checksum
// sub-structure and no length/format byte of its own, so the encoded
// form must be byte-for-byte identical to the supplied payload.
//
Expand Down
14 changes: 7 additions & 7 deletions src/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,16 +634,16 @@ mod tests {
#[test]
//fusa:test REQ-PWMI-003
fn resolve_pwm_in_read_invalidates_measurement_once_max_period_is_exceeded() {
// TC18 §13.7.6.2 Table 45, pwmi_err_on_max_period = 0b (TC18.txt
// line 4721): "if MAX PERIOD is exceeded, invalidate measurement and
// wait for new active phase of signal". pwmi_max_period (Table 45,
// relative address 0x000A, TC18.txt line 4735) is a 16-bit register,
// so 0xFFFF is the largest MAX PERIOD a conforming RC Server can be
// configured with.
// TC18 §13.7.6.2 Table 48, pwmi_err_on_max_period = 0b (TC18.txt
// lines 5129-5131): "if MAX PERIOD is exceeded, invalidate
// measurement and wait for new active phase of signal".
// pwmi_max_period (Table 48, relative address 0x000A, TC18.txt line
// 5146) is a 16-bit register, so 0xFFFF is the largest MAX PERIOD a
// conforming RC Server can be configured with.
let config = PwmInFunctionalConfig {
no_signal_timeout: 0xFFFF,
};
// TC18 §13.7.6.3 (TC18.txt line 4758): both measured values are
// TC18 §13.7.6.3 (TC18.txt line 5169): both measured values are
// 16-bit, so a valid measurement fits 0x0000..=0xFFFF.
let measured = PwmDurationPair {
period: 0x8000,
Expand Down
6 changes: 3 additions & 3 deletions src/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl AvtpTimestamp {
/// This type's rollover period, in raw ticks: the field's full 32-bit
/// width.
///
/// TC18 §11.4.1 (TC18.txt lines 1952-1953) confirms both the tick unit
/// TC18 §11.4.1 (TC18.txt lines 2328-2329) confirms both the tick unit
/// and the period: "avtp_timestamp = (AS_sec × 10^9 + AS_ns) mod 2^32
/// where AS_sec is the gPTP seconds field and AS_ns is the gPTP
/// nanoseconds field (thus rolls over every 4 seconds)" — i.e. the
Expand Down Expand Up @@ -221,7 +221,7 @@ impl MessageTimestamp {
/// This type's rollover period, in raw ticks: the field's full 64-bit
/// width — 2^32 times longer than [`AvtpTimestamp::ROLLOVER_PERIOD`].
///
/// TC18 §11.4.1 (TC18.txt lines 1954-1955) confirms both the tick unit
/// TC18 §11.4.1 (TC18.txt lines 2331-2332) confirms both the tick unit
/// and the period: "message_timestamp = (AS_sec × 10^9 + AS_ns) mod
/// 2^64 where AS_sec is the gPTP seconds field and AS_ns is the gPTP
/// nanoseconds field (thus rolls over every 584,9 years)" — i.e. the
Expand Down Expand Up @@ -609,7 +609,7 @@ mod tests {
#[test]
//fusa:test REQ-TS-007
fn rollover_periods_match_tc18_11_4_1_nanosecond_derivation() {
// TC18 §11.4.1 (TC18.txt lines 1952-1955) states both moduli and
// TC18 §11.4.1 (TC18.txt lines 2328-2332) states both moduli and
// both resulting real-world periods, with the tick unit fixed at
// nanoseconds by the `AS_sec × 10^9 + AS_ns` construction:
//
Expand Down
Loading