This guide covers connecting the CoreEngine to a real external device — a piece of hardware, another system, or a network endpoint that speaks its own wire protocol.
1. The Concept: Streams and Drivers
Three distinct layers carry data between your models and a device, each with one job:
| Layer | Job |
|---|---|
| Stream | The interface with the ICD structures — translates raw bytes into ICD-compliant blocks your models and states consume, and back again. |
| Driver | The bridge between a stream and the hardware — the CDriverBase subclass a stream talks to (Send()/Recv()). |
| API layer | The actual low-level interface to the hardware vendor's SDK, built as its own shared library the driver loads at runtime. |
See Drivers and Streams for the full folder layout and the driver/API-layer split, and streams.json for how a stream and its driver are configured together.
2. Matching the Device's Memory Layout (Raw ↔ Eng)
A real external device rarely uses the same in-memory layout as your C++ structs — it may pack bits MSB-first, use a different byte order, or have no binary representation for some fields at all. APIC handles this with the raw ↔ eng conversion: every ICD block has a raw form (the exact bytes the device expects on the wire) and an eng form (the ordinary C++ value your model code uses). Your code always works with the eng side; the raw side is what actually gets sent to/received from the device.
| Convention | Use it when the device... |
|---|---|
NoRaw | ...doesn't apply — the block has no physical/binary form (internal/software-only data). |
LElsb | ...uses Little-Endian bytes with bits numbered from the LSB (the natural C/C++ convention). |
LEmsb | ...uses Little-Endian bytes with bits numbered from the MSB. |
BElsb | ...uses Big-Endian ("network order") bytes with bits numbered from the LSB. |
BEmsb | ...uses Big-Endian bytes with bits numbered from the MSB — common in avionics/MIL-STD ICDs. |
Raw2Eng()/Eng2Raw() code for you; see
Raw ↔ Eng Conversion for how these calls are used (once per LRU) inside OnRun().
3. Set It Up
- Define the device's data layout as an ICD CSV, choosing the raw convention for each block to match the device's documented format — see DBSimGenerator for how to set this up.
- Generate the DBSim code from the ICD with DBSimGenerator.
- Define the stream and its driver in streams.json.
- If a driver for this device doesn't exist yet, implement its driver and API layer — see Drivers and Streams for the folder layout and the exact pattern to follow.
- Convert raw ↔ eng in your model's
OnRun()and work with the eng-side values as usual.