Skip to content

Integration Paths

The library provides one receive path per transport. Both return OscpFrame, so code downstream of reception does not depend on the transport.


Selecting a path

Variant Entry point Behavior
RS422 (stream) OscpParser Input has no message boundaries. The parser synchronizes on the 0x00 delimiter, COBS-decodes, checks the CRC and returns one OscpFrame per valid frame.
CAN-FD (framed) oscp_frame_decode() Input is one complete message. Stateless; no parser, buffer or COBS decoding.

Use the parser when the interface delivers bytes (UART/RS422). Use the decoder when the interface delivers complete payloads (FD-CAN mailbox).


Transport Examples

Bytes can be passed one at a time (e.g. drained from an ISR queue) or as a buffer. The parser returns a frame each time a valid frame is completed.

bytes ─► feed() / feed_buf() ─► sync on 0x00 ─► COBS decode ─► CRC check ─► OscpFrame

The parser holds a fixed-size buffer inside OscpParser and does not allocate. Framing, COBS, CRC and overflow errors are counted in OscpStats; they are not returned to the caller.

use oscp_imu::OscpParser;

let mut parser = OscpParser::new();

let mut buf = [0u8; 256];
loop {
    let n = uart_read(&mut buf);
    for frame in parser.feed_buf(&buf[..n]) {
        /* one OscpFrame per valid frame */
    }
}

feed_buf returns a lazy iterator

Bytes are consumed only while the iterator is advanced. A statement such as parser.feed_buf(&buf); whose result is discarded feeds no bytes. Consume the iterator with for, .for_each() or .count().

See Examples.

Each call decodes one payload. No state is kept between calls.

use oscp_imu::oscp_frame_decode;

fn on_can_message(data: &[u8]) {
    if let Ok(frame) = oscp_frame_decode(data) {
        /* frame passed length and CRC checks */
    }
}

DLC padding

CAN-FD pads a payload to the next DLC size; a 61-byte RAW frame is sent in a 64-byte message. data.len() can therefore exceed the frame length. The decoder takes the frame length from the frame type, computes the CRC over that length and ignores the remaining bytes.

See Examples.


Common output type

Both paths return the following enum:

pub enum OscpFrame {
    Raw(OscpRaw),
    Euler(OscpEuler),
    Quat(OscpQuat),
    RotMat(OscpRotMat),
    Gnss(OscpGnss),
    Debug1(OscpDebug1),
    Debug2(OscpDebug2),
    Startup(OscpStartup),
    CmdResponse(OscpFrameCmd),
}

Use match to select the variant and bind its struct, e.g. OscpFrame::Euler(e) => e.roll. Frame contents are listed in the Frame Reference.


Next: Frame reference →