lin: Local Interconnect Network frames
| (require lin) | package: lin |
The "lin" package implements the frame layer of LIN (Local Interconnect Network, ISO 17987) — the low-cost single-wire bus that sits under CAN in every vehicle for window lifts, seats, mirrors and other slave devices.
Everything is implemented in pure Racket. The 64-entry protected-ID table and the checksum vectors (including the LIN specification 2.2A §2.8.3 example calculation) are frozen from the public stm8-lin-checksum implementation as test fixtures.
1 Quick start
> (protected-id 1) 193
> (protected-id 60) 60
> (checksum-classic (bytes 74 85 147 229)) 230
> (checksum-enhanced 191 (bytes 74 85 147 229)) 39
> (define f (frame (protected-id 17) (bytes 74 85 147 229))) > (frame-bytes f) #"U\21JU\223\345\325"
> (parse-frame (frame-bytes f)) (lin-frame 17 #"JU\223\345" 213 'enhanced)
2 Protected identifiers
A LIN frame is addressed by a 6-bit ID; on the wire it carries two parity bits in the high positions: P0 = ID0^ID1^ID2^ID4 (even) and P1 = !(ID1^ID3^ID4^ID5) (odd).
procedure
(protected-id id) → (integer-in 0 255)
id : (integer-in 0 63)
procedure
(frame-id pid) → (integer-in 0 63)
pid : (integer-in 0 255)
procedure
(pid-valid? pid) → boolean?
pid : (integer-in 0 255)
3 Checksums
The LIN checksum is an inverted 8-bit sum with carry folding: each overflow adds 1 back to the low byte, and the final sum is inverted. The classic form (LIN 1.x) covers the data bytes only; the enhanced form (LIN 2.x) starts from the protected ID. Diagnostic frames (IDs 60/61) always use the classic form.
procedure
(checksum-classic data) → (integer-in 0 255)
data : bytes?
procedure
(checksum-enhanced pid data) → (integer-in 0 255)
pid : (integer-in 0 255) data : bytes?
procedure
(checksum-valid-classic? cksum data) → boolean?
cksum : (integer-in 0 255) data : bytes?
procedure
(checksum-valid-enhanced? cksum pid data) → boolean?
cksum : (integer-in 0 255) pid : (integer-in 0 255) data : bytes?
4 Frames
struct
pid : (integer-in 0 255) data : bytes? checksum : (integer-in 0 255) kind : (or/c 'classic 'enhanced)
procedure
(frame pid data #:kind kind #:checksum checksum) → lin-frame? pid : (integer-in 0 255) data : bytes? kind : (or/c 'classic 'enhanced) checksum : (or/c (integer-in 0 255) #f)
procedure
(frame-bytes f) → bytes?
f : lin-frame?
procedure
(parse-frame bs [#:kind kind]) → lin-frame?
bs : bytes? kind : (or/c 'classic 'enhanced) = 'enhanced
procedure
(frame-bits data-length) → exact-nonnegative-integer?
data-length : exact-nonnegative-integer?
5 Diagnostic frames
IDs 60 (master request) and 61 (slave response) always carry 8 data bytes: NAD, PCI, SID/RSID and payload; the PCI of a single-frame diagnostic is 0x0N with N the number of bytes after the PCI.
procedure
(diagnostic-request nad sid payload) → lin-frame?
nad : (integer-in 0 255) sid : (integer-in 0 255) payload : bytes?
procedure
(diagnostic-response nad rsid payload) → lin-frame?
nad : (integer-in 0 255) rsid : (integer-in 0 255) payload : bytes?
procedure
(diagnostic-parse data)
→
(list* exact-nonnegative-integer? exact-nonnegative-integer? (listof exact-nonnegative-integer?)) data : bytes?
6 License
MIT. Test fixtures derive from stm8-lin-checksum (MIT).