> Complete documentation index: [llms.txt](/llms.txt). Markdown versions of all pages are available by appending `.md` to page URLs.

# CAN-FD Bridge Mode

> An SLCAN bridge over the virtual COM port, compatible with python-can and CANable tooling. Pulsar only.

**Mode `4` · Pulsar only · Introduced in firmware v4.4.0**

CAN-FD Bridge Mode turns the Pulsar's virtual COM port into an **SLCAN**
interface: ASCII commands, one per line, terminated with `\r`. It handles both
classic CAN and CAN-FD, standard (11-bit) and extended (29-bit) IDs, with
per-frame bit-rate switching.

It is interoperable with `python-can`'s `slcan` interface and with CANable-style
terminal tools.

:::danger
**Not available on Binho Supernova.** Selecting this mode on a Supernova is
rejected with an invalid-parameter error.

:::

:::note
The COM port's baud rate is irrelevant: this is a USB CDC endpoint, not a real
UART. The **CAN bus** bitrate is set with the `S` and `Y` SLCAN commands, not by
the serial port settings.

:::

## Quick start

{% stepper %}
{% step %}
### Switch the Pulsar into CAN-FD mode

```sh
python device_settings_cli.py --device pulsar set --cdc-mode canfd
```

The tool resets the device to apply the change.
{% endstep %}

{% step %}
### Drive it from `python-can`

```python
import can

bus = can.Bus(interface="slcan", channel="COM7", bitrate=500000)

msg = can.Message(arbitration_id=0x123, data=[0xDE, 0xAD], is_extended_id=False)
bus.send(msg)

print(bus.recv(timeout=1.0))
```

The `bitrate` argument sets the nominal (arbitration) rate. The FD data phase
defaults to 5 Mbps; call `bus.set_bitrate(nominal, data)` to choose another.
{% endstep %}
{% endstepper %}

## SLCAN command set

| Command | Meaning |
| --- | --- |
| `S0`–`S8` | Select the nominal (arbitration) bitrate |
| `Y1` / `Y2` / `Y5` | Select the CAN-FD data-phase bitrate |
| `O` | Open the channel |
| `L` | Open the channel listen-only (bus monitor; transmit disabled) |
| `C` | Close the channel |
| `t` / `T` | Transmit a classic frame, standard / extended ID |
| `d` / `D` | Transmit a CAN-FD frame without bit-rate switching |
| `b` / `B` | Transmit a CAN-FD frame with bit-rate switching |
| `V` / `N` / `F` | Version, serial number, status flags |

Lowercase means a standard ID, uppercase an extended ID. Any unrecognized command
returns `\a`.

### Frame format

```text
<cmd><ID><DLC><data...>
```

The ID is 3 hex digits for standard, 8 for extended. The DLC is one hex digit,
followed by that many bytes as hex pairs. Received frames come back in the same
shape, with the leading letter indicating what arrived.

For classic CAN, DLC `0`–`8` is the byte count. CAN-FD extends it:

| DLC | Bytes | DLC | Bytes |
| --- | --- | --- | --- |
| `9` | 12 | `D` | 32 |
| `A` | 16 | `E` | 48 |
| `B` | 20 | `F` | 64 |
| `C` | 24 | | |

### Bitrates

Nominal rates: `S0` 10 kbps, `S1` 20 kbps, `S2` 50 kbps, `S3` 100 kbps,
`S4` 125 kbps, `S5` 250 kbps, `S6` 500 kbps, `S7` 800 kbps, `S8` 1 Mbps.

Data-phase rates: `Y1` 1 Mbps, `Y2` 2 Mbps, `Y5` 5 Mbps. Only these three are
offered, because they are the rates that are exact at the CAN core clock; other
digits return `\a`.

Without `S` or `Y`, the channel opens at 500 kbps nominal and 5 Mbps
data.

:::caution
Bitrate commands are captured when the channel **opens**. Always send `S` and `Y`
*before* `O` or `L`: changing them afterwards has no effect until the channel is closed and
reopened.

:::

## Limitations

* **No remote (RTR) frames:** neither transmit nor receive.
* **No receive timestamps.**
* **No error-frame or bus-state reporting** to the host.
* **No host-side acceptance filtering:** every incoming ID is accepted, standard
  and extended alike. Filter in the application.
* **`V`, `N` and `F` return fixed constants**, not live device values.
* **`s` (custom nominal bit timing) is accepted but does nothing.** Use `S`.

## Getting back out

```sh
python device_settings_cli.py --device pulsar set --cdc-mode uart_passthrough
```