Skip to content

J1939 SPN: a 3-bit field spends half its value space on indicators #99

Description

@dborgards

Split out of the #37 work (PR #98) rather than decided inside it, because it is a specification-reading question rather than a defect, and the reading it questions is the one that PR just shipped.

The rule as implemented

J1939Spn.Classify generalises the SAE J1939-71 §5.1.1 indicator tables to widths the standard does not tabulate by keeping the leading group fixed per width class: 8 bits for any field of a byte or wider, 4 bits for 4..7 bits, 2 bits for 2..3 bits. The consequence is that the indicator fraction of the range is whatever the tabulated width of that class already spends:

Width Leading group Indicator values Fraction
8, 16, 32, 64 (tabulated) 8 bits 5 of every 256 leading patterns ~2 %
12 (inferred) 8 bits same ~2 %
4 (tabulated) 4 bits 11..15 31 %
5, 6, 7 (inferred) 4 bits proportional bands 31 %
2 (tabulated) 2 bits 0b10 error, 0b11 n/a 50 %
3 (inferred) 2 bits 4..7 50 %
1 none 0 %

That is internally consistent, and PR #98 documents it. All of these are now pinned by known-answer tests, including the inferred widths, so the reading cannot drift silently.

The question

For a 3-bit field the inferred reading classifies raw 4, 5, 6 and 7 as indicators:

0,1,2,3 -> Valid      4,5 -> Error      6,7 -> NotAvailable

A 3-bit SPN that genuinely carries eight states would therefore have half its states reported as "no reading". The alternative reading — scale by value rather than by leading group, so only the top one or two raw counts indicate (7 = not available, 6 = error) — costs a 3-bit parameter two states instead of four.

Neither is written down in J1939-71. What makes this worth a second look is that Classify already declines to infer in two other places, on exactly the argument that cuts against the 3-bit choice:

A 1-bit field has no room for an indicator and is always Valid, as is a signed field narrower than a byte — J1939-71 defines no indicator codes there, and inventing some would report real measurements as missing.

The same sentence applies to 3 bits. The counter-argument is that 3 bits is closer to the 2-bit table than to nothing, and silently scaling a real 5 into a measurement is the failure mode #37 was filed about.

Two arguments that bear on the choice

Raised on the PR review thread (#98) and worth recording here so they are not lost with the PR.

1. The standard scales indicator ranges by fraction, not by absolute code count. Measured against the widths J1939-71 actually tabulates:

Width "not available" Fraction of range
2 bits 0b11 1/4
4 bits 0xF 1/16
8 bits 0xFF 1/256
16 bits 0xFF00..0xFFFF 1/256
32 bits 0xFF000000..0xFFFFFFFF 1/256

A 16-bit SPN spends 256 raw values on "not available", not one; the fraction is what stays constant from 8 bits to 32. The leading-group rule is that observation carried down to sub-byte widths. A terminal-code reading (option 4 below) would give 5-bit "not available" a 1/32 share — a fraction that appears nowhere in the tables.

2. The two readings fail in opposite directions, and only one fails safely. Classifying too widely reports a real measurement as "no reading": data loss, visible, never a wrong number. Classifying too narrowly scales an indicator into a plausible physical value — which is precisely the defect #37 was filed about (0xFFFF as 8191.875 rpm). Whichever option wins should account for the fact that the conservative error is the recoverable one.

Deciding it

Needs a real 3-bit SPN from J1939-71 or a DBC to settle rather than more reasoning from the tables. Four outcomes are defensible:

  1. Keep the leading-group rule — consistent, already tested, documented, and the fail-safe direction.
  2. Top-value scaling for 2..3 bits — a 3-bit field keeps six states.
  3. No inference below 4 bits — 3-bit fields become always-Valid, matching the 1-bit precedent, and callers that need indicator semantics there pass a wider definition.
  4. Terminal codes at every sub-byte width — the five codes stay five individual values scaled to the field top, so 5-bit becomes 27..31 and 3-bit becomes 0b110 error / 0b111 not available. Consistent with the 4-bit and 8-bit tables read as literal code lists; inconsistent with how the 8→16→32-bit ranges scale, and it is the narrowing direction, so it trades data loss for the risk of scaling an indicator.

Whichever wins, it is a behavioural change to a public classifier and belongs in its own PR with the case table updated, not folded into #98.

Refs #37, PR #98, FR-J1939-002.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions