Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

FEP 004: FujiNet Protocol Specification

FieldValue
FEP ID004
TitleFujiNet Protocol
AuthorFozzTexx
StatusDraft
TypeInformational
Created2025-10-06
Updated2025-11-05
Version1.1

Motivation

As FujiNet expands beyond its original Atari and Apple implementations, maintaining consistency and interoperability across platforms has become increasingly difficult. Each platform currently implements the FujiNet protocol in slightly different ways, often resulting in duplicated codebases and redundant logic. When a bug is fixed or a feature is added on one platform, the change rarely propagates automatically to others – every update must be manually ported, tested, and maintained separately.

The core reason for this duplication lies in how packets are structured and parsed. The existing protocol uses fixed headers and context-dependent payloads, requiring each command handler to read its own data in a custom way. This design forces per-platform command handling logic.

Universal FujiNet Architecture

With the move toward a universal FujiNet architecture (modeled on the RS-232 version), future devices will use a Raspberry Pi RP2040 or RP2350 as the physical bus interface, with an ESP32 or host computer managing device emulation and network communication. In this architecture, the bus interface and device logic may run on different processors, making serialization and deserialization efficiency critical.

graph LR
    A[Legacy Computer] -->|Platform Bus| B[RP2040 / RP2350<br/>Bus Interface]
    B -->|Serial / SPI| C[ESP32 or Host<br/>Device Emulation]
    C -->|WiFi / Network| D[Internet]

Design Goals

By making packets self-describing, each packet indicates the sizes of its fields so they can be fully decoded immediately upon receipt:

  • Generic decoding – packets can be parsed into C/C++ structures immediately upon receipt
  • Modular command handling – common handling implemented once in a base class, device-specific logic in subclasses
  • Code reuse – shared parsing, debugging, and validation routines across all platforms
  • Protocol introspection – tools can decode packets without hardcoded command definitions
  • Forward compatibility – new fields or data types can be introduced without breaking existing implementations
  • Legacy compatibility – implementable on 6502, 8080, and other 8-bit processors

Proposed Protocol

The new FujiNet protocol consists of two main parts:

  1. Packet Structure
  2. Packet Synchronization

Packet Structure

Each packet consists of a fixed-length header, a variable-length field section, and an optional binary blob.

Packet Header

FieldSize (bytes)Description
Target Device1ID of the target device
Command ID1The command to execute
Data Length2Total length of the data payload
Checksum1Simple XOR or sum checksum
Data Descriptor1Byte encoding of the data field layout

Data Descriptor Byte

The data descriptor byte defines the layout of fixed-size fields in the data payload:

Bit(s)NameDescription
7More DescriptorsIf set, the following byte is an additional descriptor
6-3ReservedMust be set to 0
2-0Field Count/SizeNumber and type of fixed-size fields (0-7)

Field Descriptor Values

After examining all current FujiNet commands, there are only 8 different combinations of parameter arguments:

Descriptor ValueField CountField TypeTotal Bytes
000
11uint8_t1
22uint8_t2
33uint8_t3
44uint8_t4
51uint16_t2
62uint16_t4
71uint32_t4

Descriptor Decoding

For non-zero descriptor values, decrement by 1 and inspect bits 2-1:

Bit MaskMeaning
0b100Types are either uint16_t or uint32_t
0b010Type is uint32_t

This allows field types and counts to be determined with either a pair of lookup tables or simple bitmask operations, keeping the implementation lightweight for 8-bit processors.

Endianness

All multi-byte fields in the FujiNet protocol are transmitted in little-endian byte order.

Packet Synchronization (SLIP Encoding)

The existing protocol used an out-of-band signal via an extra pin to indicate packet boundaries. This does not work with network or USB virtual serial interfaces.

The new protocol uses SLIP-style encoding (Serial Line Internet Protocol) for framing:

DescriptionHexDecAbbreviationNotes
Frame End0xC0192ENDMarks start and end of a packet
Frame Escape0xDB219ESCNext byte is a transposed value
Transposed Frame End0xDC220ESC_ENDReplaces 0xC0 in payload
Transposed Frame Escape0xDD221ESC_ESCReplaces 0xDB in payload

SLIP Rules

  1. Packets start and end with END (0xC0)
  2. Any 0xC0 in the payload is replaced with ESC (0xDB) + ESC_END (0xDC)
  3. Any 0xDB in the payload is replaced with ESC (0xDB) + ESC_ESC (0xDD)
  4. SLIP encoding is applied after the packet has been fully constructed
  5. SLIP decoding is applied immediately upon reception, before processing the packet
  6. All reply data from FujiNet devices is also SLIP-encoded
graph LR
    subgraph "SLIP Framing"
        A["END (0xC0)"] --> B["Header<br/>(6 bytes)"]
        B --> C["Data Payload<br/>(variable)"]
        C --> D["END (0xC0)"]
    end

Transports that already provide start/stop signaling can use the same packet format without SLIP framing.

Complete Packet Layout

graph TD
    subgraph "FujiNet Packet"
        direction TB
        SLIP1["SLIP END (0xC0)"]
        HDR["Packet Header (6 bytes)<br/>Target Device | Command ID |<br/>Data Length (2) | Checksum | Descriptor"]
        FIELDS["Fixed-Size Fields<br/>(defined by descriptor)"]
        BLOB["Binary Blob<br/>(remaining bytes)"]
        SLIP2["SLIP END (0xC0)"]
    end
    SLIP1 --> HDR --> FIELDS --> BLOB --> SLIP2

Open Questions

Returning Data to Legacy Systems

  • Should reply data be wrapped in a full FujiNet packet (with header, descriptor, and checksum) or sent as a SLIP-encoded payload only?
  • If a packet is used, what is the meaning of the Device ID and Command ID in the reply – do they echo the original command or indicate a special “reply” type?

Signaling Data Availability

The protocol is command/response, but legacy systems may need notification when data or events are waiting. Challenges include:

  • Many older systems have at best a single-byte serial buffer and may not support interrupts
  • Systems with no buffer cannot receive unsolicited data over serial
  • RS-232 can use out-of-band signal lines (e.g., Ring Indicator), but this does not generalize to all buses
  • A cross-platform method for alerting legacy computers to pending data is needed

Direct Communication with RP2nnn

Scenarios such as resetting the RP2040/RP2350 or uploading new firmware require a communication path:

  • A special device ID filtered by the RP2nnn (requires the RP2nnn to monitor pass-through data)
  • A second virtual serial interface (e.g., /dev/ttyACM2) dedicated to RP2nnn management

Systems Without RP2nnn

The protocol should remain generic for deployments without an RP2040/RP2350:

  • Can the FujiNet safely ignore the absence of an RP2nnn?
  • How can the protocol remain flexible for both simple and full-featured configurations?

References

See Also