Skip to content

J1939Spn Class

Static helpers for extracting SAE J1939-71 SPN (Suspect Parameter Number) values from a PGN payload using configurable scale/offset (SRS FR-J1939-002).

public static class J1939Spn

Inheritance Object → J1939Spn

Remarks

SAE J1939-71 encodes each SPN as an integer field of 1..64 bits — unsigned, or two's complement for a signed SLOT — at a fixed byte (and bit) offset inside its PGN payload, with a linear transform to physical units: physical = raw * resolution + offset.

Not every bit pattern is a measurement. §5.1.1 reserves the top of each SPN's raw range for indicators — "not available", "error", reserved and parameter-specific codes — so Extract(ReadOnlySpan<byte>, int, int, int, double, double, bool) returns a J1939SpnValue that reports which of the two it found, rather than a bare Double that would turn a 16-bit 0xFFFF ("not available") into a plausible-looking 8191.875 rpm. Classify(ulong, int, bool) exposes the range check on its own.

Byte order is little-endian, matching SAE J1939-71 §5.1.3. Bit fields that start at an offset within a byte are read across byte boundaries with the low bits coming from the low-indexed byte, in line with the standard.

Methods

J1939Spn.Classify(ulong, int, bool) Method

Classifies a raw SPN field against the SAE J1939-71 §5.1.1 indicator ranges, which occupy the top of every SPN's raw range and must not be scaled into physical values.

public static CanKit.Pro.J1939.J1939SpnValueKind Classify(ulong raw, int bitLength, bool isSigned=false);

Parameters

raw UInt64

The field's raw bits, right-aligned and zero-extended (as returned by ExtractRaw(ReadOnlySpan<byte>, int, int, int)) — for a signed SPN the two's-complement pattern, not the sign-extended number.

bitLength Int32

Field size in bits (1..64).

isSigned Boolean

Whether the SPN is a two's-complement signed parameter.

Returns

J1939SpnValueKind

Exceptions

ArgumentOutOfRangeException
bitLength is outside 1..64.

Remarks

J1939-71 defines the ranges on the field's leading byte for parameters of one byte or wider — unsigned 0xFB parameter-specific, 0xFC..0xFD reserved, 0xFE error, 0xFF not available — so a two-byte SPN is "not available" over 0xFF00..0xFFFF and a four-byte one over 0xFF000000..0xFFFFFFFF. For a signed parameter the same codes sit at the top of the signed range, i.e. with the sign bit clear: 0x7B, 0x7C..0x7D, 0x7E, 0x7F.

Sub-byte parameters carry the codes as individual values at the top of the field ("terminal codes"), matching the 4-bit and 2-bit tables in §5.1.1: 4 bits reads 0xB parameter-specific, 0xC..0xD reserved, 0xE error and 0xF not available; 2 bits reads 0b10 error and 0b11 not available. The widths the standard does not tabulate keep that shape, scaled to the field top rather than to a leading group: 5..7 bits take all five codes (5 bits: 27 parameter-specific, 28..29 reserved, 30 error, 31 not available), and 3 bits takes the two of the 2-bit table (0b110 error, 0b111 not available). Above a byte, widths other than 8/16/32 use the leading byte like the tabulated ones. 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 terminal reading for the untabulated sub-byte widths is taken from how real SPNs of those widths are defined, not from the tables (issue #99). SPN 527 "Cruise Control States" (CCVS1, PGN 65265) is a 3-bit field whose raw 4 and 5 are Resume and Set; the leading-group reading this replaced reported them as errors. SPN 527 also defines raw 6 as a state (AccelOverride), which this reading reports as an error — a rule by width cannot know a parameter's own table, and a caller that has it should decode such a field from ExtractRaw(ReadOnlySpan<byte>, int, int, int) instead. Every width above is pinned by known-answer tests so it cannot drift silently.

J1939Spn.Extract(ReadOnlySpan<byte>, int, int, double, double, bool) Method

Extracts an SPN and applies the linear transform physical = raw * + (SRS FR-J1939-002, SAE J1939-71 §5.1.3).

public static CanKit.Pro.J1939.J1939SpnValue Extract(System.ReadOnlySpan<byte> payload, int byteOffset, int bitLength, double resolution, double offset, bool isSigned=false);

Parameters

payload ReadOnlySpan<Byte>

The PGN payload bytes.

byteOffset Int32

Zero-based byte position of the first bit.

bitLength Int32

Number of bits (1..64).

resolution Double

Physical units per raw increment.

offset Double

Physical value at raw 0.

isSigned Boolean

Whether the SPN is a two's-complement signed parameter.

Returns

J1939SpnValue
A J1939SpnValue that is either a measurement or one of the J1939-71 §5.1.1 indicators. It is <b>not</b> a Double: a field reading 0xFFFF is "not available", and reporting it as 8191.875 rpm was the defect this return type exists to prevent.

Exceptions

ArgumentOutOfRangeException
Any argument is out of range or the requested field extends past payload.

J1939Spn.Extract(ReadOnlySpan<byte>, int, int, int, double, double, bool) Method

Extracts an SPN and applies the linear transform physical = raw * + (SRS FR-J1939-002, SAE J1939-71 §5.1.3).

public static CanKit.Pro.J1939.J1939SpnValue Extract(System.ReadOnlySpan<byte> payload, int byteOffset, int startBit, int bitLength, double resolution, double offset, bool isSigned=false);

Parameters

payload ReadOnlySpan<Byte>

The PGN payload bytes.

byteOffset Int32

Zero-based byte position of the first bit.

startBit Int32

Zero-based bit index within byteOffset byte (0..7). 0 = least-significant bit of the byte, as in SAE J1939-71 §5.1.3.

bitLength Int32

Number of bits (1..64).

resolution Double

Physical units per raw increment.

offset Double

Physical value at raw 0.

isSigned Boolean

Whether the SPN is a two's-complement signed parameter.

Returns

J1939SpnValue
A J1939SpnValue that is either a measurement or one of the J1939-71 §5.1.1 indicators. It is <b>not</b> a Double: a field reading 0xFFFF is "not available", and reporting it as 8191.875 rpm was the defect this return type exists to prevent.

Exceptions

ArgumentOutOfRangeException
Any argument is out of range or the requested field extends past payload.

J1939Spn.ExtractRaw(ReadOnlySpan<byte>, int, int, int) Method

Extracts an unsigned SPN raw value from payload at byteOffset starting at bit startBit (0..7) and spanning bitLength bits (1..64), little-endian.

public static ulong ExtractRaw(System.ReadOnlySpan<byte> payload, int byteOffset, int startBit, int bitLength);

Parameters

payload ReadOnlySpan<Byte>

The PGN payload bytes.

byteOffset Int32

Zero-based byte position of the first bit.

startBit Int32

Zero-based bit index within byteOffset byte (0..7). 0 = least-significant bit of the byte, as in SAE J1939-71 §5.1.3.

bitLength Int32

Number of bits (1..64).

Returns

UInt64

Exceptions

ArgumentOutOfRangeException
Any argument is out of range or the requested field extends past payload.

J1939Spn.ExtractRawSigned(ReadOnlySpan<byte>, int, int, int) Method

Extracts an unsigned SPN raw value from payload at byteOffset starting at bit startBit (0..7) and spanning bitLength bits (1..64), little-endian.

public static long ExtractRawSigned(System.ReadOnlySpan<byte> payload, int byteOffset, int startBit, int bitLength);

Parameters

payload ReadOnlySpan<Byte>

The PGN payload bytes.

byteOffset Int32

Zero-based byte position of the first bit.

startBit Int32

Zero-based bit index within byteOffset byte (0..7). 0 = least-significant bit of the byte, as in SAE J1939-71 §5.1.3.

bitLength Int32

Number of bits (1..64).

Returns

Int64

Exceptions

ArgumentOutOfRangeException
Any argument is out of range or the requested field extends past payload.

J1939Spn.FromRaw(ulong, int, double, double, bool) Method

Applies the SAE J1939-71 §5.1.1 range check and, for a measurement, the linear transform physical = raw * + to an already-extracted raw field.

public static CanKit.Pro.J1939.J1939SpnValue FromRaw(ulong raw, int bitLength, double resolution, double offset, bool isSigned=false);

Parameters

raw UInt64

The field's raw bits, right-aligned and zero-extended.

bitLength Int32

Field size in bits (1..64).

resolution Double

Physical units per raw increment.

offset Double

Physical value at raw 0.

isSigned Boolean

Whether the SPN is a two's-complement signed parameter; when true the raw bits are sign-extended before scaling.

Returns

J1939SpnValue

J1939Spn.WriteRaw(Span<byte>, int, int, int, ulong) Method

Encodes an SPN raw value back into a payload buffer, little-endian. Useful for tests and for round-tripping simulated PGN payloads.

public static void WriteRaw(System.Span<byte> payload, int byteOffset, int startBit, int bitLength, ulong rawValue);

Parameters

payload Span<Byte>

byteOffset Int32

startBit Int32

bitLength Int32

rawValue UInt64

Exceptions

ArgumentOutOfRangeException
The requested field extends past payload.