# BabyLIN Adapter Internals (SDK Python wrapper)

This document describes how the real hardware adapter binds to the BabyLIN SDK via the official Python wrapper `BabyLIN_library.py` and how frames move across the boundary.

## Overview

- Location: `ecu_framework/lin/babylin.py`
- Uses the SDK's `BabyLIN_library.py` (place under `vendor/` or on `PYTHONPATH`)
- Discovers and opens a BabyLIN device using `BLC_getBabyLinPorts` and `BLC_openPort`
- Optionally loads an SDF via `BLC_loadSDF(handle, sdf_path, 1)` and starts a schedule with `BLC_sendCommand("start schedule N;")`
- Converts between Python `LinFrame` and the wrapper's `BLC_FRAME` structure for receive

## Mermaid: SDK connect sequence

```mermaid
sequenceDiagram
  autonumber
  participant T as Tests/Fixture
  participant A as BabyLinInterface (SDK)
  participant BL as BabyLIN_library (BLC_*)

  T->>A: connect()
  A->>BL: BLC_getBabyLinPorts(100)
  BL-->>A: [port0, ...]
  A->>BL: BLC_openPort(port0)
  A->>BL: BLC_loadSDF(handle, sdf_path, 1)
  A->>BL: BLC_getChannelHandle(handle, channelIndex)
  A->>BL: start schedule N
  A-->>T: connected
```

## Mermaid: Binding and call flow

```mermaid
sequenceDiagram
  autonumber
  participant T as Test
  participant L as LinInterface (BabyLin)
  participant D as BabyLIN_library (BLC_*)

  T->>L: connect()
  L->>D: BLC_getBabyLinPorts()
  L->>D: BLC_openPort(port)
  D-->>L: handle/ok

  T->>L: send(frame)
  L->>D: BLC_mon_set_xmit(channelHandle, frameId, data, slotTime=0)
  D-->>L: code (0=ok)

  T->>L: receive(timeout)
  L->>D: BLC_getNextFrameTimeout(channelHandle, timeout_ms)
  D-->>L: code, frame
  L->>L: convert BLC_FRAME to LinFrame
  L-->>T: LinFrame or None

  T->>L: disconnect()
  L->>D: BLC_closeAll()
```

## Master request behavior

When performing a master request, the adapter tries the SDK method in this order:

1. `BLC_sendRawMasterRequest(channel, id, length)` — preferred
2. `BLC_sendRawMasterRequest(channel, id, dataBytes)` — fallback
3. Send a header with zeros and wait on `receive()` — last resort

Mock behavior notes:
- The provided mock (`vendor/mock_babylin_wrapper.py`) synthesizes a deterministic response for the `length` signature (e.g., data[i] = (id + i) & 0xFF).
- For the bytes-only signature, the adapter sends zero-filled bytes of the requested length and validates by length.
## Wrapper usage highlights

```python
from BabyLIN_library import create_BabyLIN

bl = create_BabyLIN()
ports = bl.BLC_getBabyLinPorts(100)
h = bl.BLC_openPort(ports[0])
bl.BLC_loadSDF(h, "Example.sdf", 1)
ch = bl.BLC_getChannelHandle(h, 0)
bl.BLC_sendCommand(ch, "start schedule 0;")

# Transmit and receive
bl.BLC_mon_set_xmit(ch, 0x10, bytes([1,2,3,4]), 0)
frm = bl.BLC_getNextFrameTimeout(ch, 100)
print(frm.frameId, list(frm.frameData)[:frm.lenOfData])

bl.BLC_closeAll()
```

## Notes and pitfalls

- Architecture: Ensure Python (x86/x64) matches the platform library bundled with the SDK
- Timeouts: SDKs typically want milliseconds; convert Python seconds accordingly
- Error handling: On non-zero return codes, use `BLC_getDetailedErrorString` (if available) for human-readable messages
- Threading: If you use background receive threads, protect buffers with locks
- Performance: Avoid excessive allocations in tight loops; reuse frame structs when possible

## Extending

- Add bitrate/channel setup functions as exposed by the SDK
- Implement schedule tables or diagnostics passthrough if provided by the SDK
- Wrap more SDK errors into typed Python exceptions for clarity
