-
Notifications
You must be signed in to change notification settings - Fork 78
FEP 004
| Name | Value |
|---|---|
| FEP ID | 004 |
| Title | FujiNet Protocol |
| Author | FozzTexx |
| Status | Draft |
| Type | Informational |
| Created | 2025-Oct-6 |
| Updated | 2025-Nov-5 |
| Version | 1.1 |
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 for handling the same commands. This fragmentation means that when a bug is fixed or a new feature is added on one platform, the change rarely propagates automatically to the others — every update must be manually ported, tested, and maintained separately. Over time, this has led to divergence between platforms and made it harder to ensure consistent behavior across all FujiNet devices.
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, making it difficult to share code, test features uniformly, or extend the protocol cleanly.
With the move toward a universal FujiNet architecture — modeled on the RS-232 version — this limitation becomes more apparent. Future FujiNet devices will use a Raspberry Pi RP2040 or RP2350 as the physical bus interface, with an ESP32 or host computer (Linux/Windows/macOS) managing device emulation and network communication. In this architecture, the bus interface and the device logic are no longer necessarily on the same processor, so serialization and deserialization efficiency are critical.
By making packets self-describing, each packet will indicate the sizes of its fields so that they can be fully decoded immediately upon receipt, without requiring custom parsing logic for each command.
- Generic decoding: Packets can be parsed into C/C++ structures or classes immediately upon receipt.
- Modular command handling: Common handling can be implemented once in a base class, while device-specific logic can extend it in subclasses.
- Code reuse: Shared parsing, debugging, and validation routines can be reused across all platforms.
- Protocol introspection: Tools can decode and inspect packets without needing hardcoded command definitions.
- Forward compatibility: Future extensions can introduce new fields or data types without breaking existing implementations.
Another important consideration in designing the new protocol is legacy compatibility. While the primary architecture uses a relatively powerful ARM processor (RP2040 or RP2350) to interface with the bus, the protocol is intended to be implementable directly on older, resource-constrained systems such as the 6502, 8080, or other 8 bit processor. This ensures that FujiNet remains accessible for lightweight implementations or situations where an ARM processor is not required, while still supporting more advanced features on modern hardware.
This approach moves FujiNet from a collection of per-platform implementations toward a unified, modular, and maintainable ecosystem, where new devices and hosts can be supported with minimal reimplementation.
The new FujiNet protocol consists of two main parts:
- Packet Structure
- Packet Synchronization
Each packet consists of a fixed-length header, a variable-length field section, and an optional binary blob. The length of the binary blob does not need to be separately encoded, since the packet has an overall length and the header specifies how many fixed-size fields are present.
| Field | Size (bytes) | Description |
|---|---|---|
| Target Device | 1 | ID of the device |
| Command ID | 1 | The command to execute |
| Data Length | 2 | Total length of the data payload |
| Checksum | 1 | Simple XOR or sum |
| Data Descriptor | 1 | Byte encoding of the data fields |
The data descriptor byte defines the layout of the fixed-size fields in the data payload:
- Bit 7 (More Descriptors): If set, the following byte is an additional field descriptor byte. Multiple descriptor bytes may be used in a packet.
- Bits 6-3 (reserved): These bits are reserved and must be set to 0.
- Bits 2-0 (Field Count and size count): Number of fixed-size fields in this descriptor (1–4).
Notes on the descriptor design:
After examining all the current commands that are in use with FujiNet, there are only 8 different combinations of "aux" parameter arguments.
| Field Descriptor Value | Number of fields | Field type | Total Bytes |
|---|---|---|---|
| 0 | 0 | - | 0 |
| 1 | 1 | uint8_t | 1 |
| 2 | 2 | uint8_t | 2 |
| 3 | 3 | uint8_t | 3 |
| 4 | 4 | uint8_t | 4 |
| 5 | 1 | uint16_t | 2 |
| 6 | 2 | uint16_t | 4 |
| 7 | 1 | uint32_t | 4 |
The field types and field count can be determined either with a pair of lookup tables, or with a little bit of trickery with bitmasks.
If the field descriptor value is non-zero then the value can be decremented by 1 and then bits 2-1 can be used as a bit flag
| Bit mask | types |
|---|---|
| 0b100 | types are either uint16_t or uint32_t |
| 0b010 | type is uint32_t |
All multi-byte fields in the FujiNet protocol are transmitted in little-endian byte order.
We agree that little-endian is superior to big-endian.
In the existing protocol, packet boundaries were indicated using an out-of-band signal via an extra pin. This approach is not universally supported, and it does not work well with network or USB virtual serial interfaces.
The new protocol replaces this with SLIP-style encoding, which frames packets and allows reliable transmission over any byte stream. SLIP uses special values to mark packet boundaries and escape certain bytes:
| Description | Hex Value | Dec Value | Oct Value | Abbreviation | Notes |
|---|---|---|---|---|---|
| Frame End | 0xC0 | 192 | 300 | END | Marks the start and end of a packet |
| Frame Escape | 0xDB | 219 | 333 | ESC | Indicates that the next byte is a transposed value |
| Transposed Frame End | 0xDC | 220 | 334 | ESC_END | Replaces a data byte of 0xC0 |
| Transposed Frame Esc | 0xDD | 221 | 335 | ESC_ESC | Replaces a data byte of 0xDB |
SLIP rules:
- Packets start and end with
END(0xC0)`. - Any occurrence of
END(0xC0) in the packet payload is replaced withESC(0xDB) followed byESC_END(0xDC). - Any occurrence of
ESC(0xDB) in the packet payload is replaced withESC(0xDB) followed byESC_ESC(0xDD). - SLIP encoding is applied after the packet has been fully constructed.
- SLIP decoding is applied immediately upon reception, before processing the packet.
All reply data from FujiNet devices is also SLIP-encoded, regardless of whether it uses the full FujiNet packet format or raw payloads. This guarantees consistent framing across all transports and communication directions.
Note: Encoding and decoding are separate from the packet structure itself. This allows transports that already provide start/stop signaling to use the same packet format without modification.
While the main protocol design is largely defined, there are several issues that remain under consideration:
When the FujiNet has data to send back to the legacy system:
- Should data be wrapped in a full FujiNet packet (with header, descriptor, and checksum) or sent as a SLIP-encoded payload only, without the additional packet structure?
- If a packet is used, what is the meaning of the Device ID and Command ID?
- Do they indicate the original command being replied to, or a special “reply” type?
The protocol is command/response, but legacy systems may need to be notified when data or events are waiting (such as incoming network packets, errors, or connection closures). Challenges include:
- Many older systems have at best a single-byte serial buffer, and some may not support interrupts to process incoming bytes fast enough.
- Systems with no buffer at all cannot receive any data over serial unless they are signaled in advance. On RS232, this can be handled with an out-of-band signal line (e.g., Ring Indicator), but this approach does not generalize to all buses.
- How should the protocol provide a cross-platform method for alerting legacy computers to pending data without relying on polling or hardware-specific signals?
There may be occasions when the FujiNet needs to interact with the RP2nnn directly, such as:
- Resetting the RP2nnn to reload the initial boot program
- Uploading new firmware
Questions include:
- Should there be a special device ID in the packet header that the RP2nnn filters out?
- Potential issue: the RP2nnn would need to monitor data it normally just passes through.
- Should the RP2nnn instead expose a second virtual serial interface (e.g.,
/dev/ttyACM2) on the ESP32 or host system to handle this kind of communication?
To keep the protocol generic:
- How should the FujiNet behave when no RP2nnn is involved?
- Does the FujiNet need to detect the absence of an RP2nnn, or can it safely ignore the issue?
- How can the protocol remain flexible for both simple systems (without RP2nnn) and full-featured setups?
The protocol design outlined here captures the current thinking and rationale for a self-describing FujiNet protocol. There are several open questions (see above) that require further discussion or experimentation. Feedback, suggestions, and alternative approaches are welcome, particularly regarding:
- Signaling pending data to legacy systems
- Direct RP2nnn communication methods
- Handling systems without an RP2nnn
- Reply packet structure and semantics
Copyright 2024 Contributors to the FujiNetWIFI project.
Join us on Discord: https://discord.gg/7MfFTvD
- Home
- What is FujiNet?
- The Definition of Done
- Board bring up for FujiNet Platform.IO code
- The Complete Linux CLI Guide
- The Complete macOS CLI Guide
- Development Env for Apps
- FujiNet-Development-Guidelines
- System Quickstarts
- FujiNet Flasher
- Setting up a TNFS Server
- FujiNet Configuration File: fnconfig.ini
- AppKey Registry - SIO Command $DC Open App Key
- CP-M Support
- BBS
- Official Hardware Versions
- Prototype Board Revisions
- FujiNet Development Guidelines
- Atari Programming
- Apple Programming
- C64 Programming
- ADAM Programming
- Testing Plan
- Hacker List
- FujiNet VirtualMachine