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 use the same code pattern scaled to the field: the leading nibble for 4..7 bits (0xB, 0xC..0xD, 0xE, 0xF) and the leading two bits for 2..3 bits (0b10 error, 0b11 not available), matching the 4-bit and 2-bit tables in §5.1.1. Widths the standard does not tabulate (3, 5..7, and anything that is not 8/16/32 above a byte) are handled by that same leading-group rule. 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.

Because the leading group is a fixed size per width class, the indicator fraction of the range is whatever the tabulated width of that class already spends: about 2% for a byte or wider, five sixteenths for 4..7 bits, and one half for 2..3 bits. That last one is the widest reading here — a 3-bit field classifies raw 4..7 as indicators, so a parameter genuinely carrying eight states would see half of them reported as "no reading". Scaling by value instead of by leading group would cost such a field two states rather than four; J1939-71 tabulates neither, and the choice is open as issue #99. Every width above, inferred ones included, 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.