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 003: NetSIO Protocol Specification

FieldValue
FEP ID003
TitleNetSIO Protocol
AuthorAndrew Diller, Jan Krupa
StatusDraft
TypeInformational
Created2025-04-23
Version1.0
InputJan, Mozzwald, TCH

Abstract

NetSIO is a lightweight protocol for transmitting Atari SIO (Serial Input/Output) signals and data over UDP, enabling network-based communication with peripherals like FujiNet. While no existing Atari emulator natively supports NetSIO, developers can implement direct support by writing code to handle the protocol and communicate with FujiNet devices. The netsio-hub.py reference implementation (written in Python 3) translates Altirra emulator messages into NetSIO datagrams and vice versa.

Transport: UDP, Port 9997

Current Implementations

ImplementationLanguageRepository
NetSIO HubPython 3fujinet-emulator-bridge
NetSIO Able ArcherC89dillera/atari800
NetSIO MozzableC89mozzwald/atari800

Architecture

graph LR
    A[Atari Emulator<br/>e.g., Altirra] <-->|Custom Device<br/>Interface| B[NetSIO Hub<br/>netsio-hub.py]
    B <-->|UDP Port 9997<br/>NetSIO Protocol| C[FujiNet-PC<br/>or NetSIO Device]
    C <-->|WiFi| D[Internet /<br/>FujiNet Services]

Connection Phase

The connection sequence between FujiNet-PC and the NetSIO hub proceeds as follows:

sequenceDiagram
    participant FN as FujiNet-PC
    participant Hub as NetSIO Hub

    loop Until response received
        FN->>Hub: Ping Request (0xC2)
    end
    Hub->>FN: Ping Response (0xC3)
    FN->>Hub: Device Connected (0xC1)
    Note over Hub: Hub records source IP:port<br/>as device address
    Note over FN,Hub: No explicit connection ACK<br/>Device is now registered

Key points:

  • FujiNet-PC repeatedly sends Ping Requests (0xC2) until a Ping Response (0xC3) is received
  • FujiNet-PC then sends Device Connected (0xC1) to register with the hub
  • The hub records the source IP:port of the Device Connected message as the device address
  • There is no specific connection acknowledgment from the hub back to FujiNet-PC

Protocol Messages

Message Summary

MessageIDParametersDirection
Data Byte0x01data_byte: uint8Bidirectional
Data Block0x02byte_array: uint8[]Bidirectional
Data Byte + Sync Request0x09data_byte: uint8, sync_number: uint8Atari to Device
Command OFF0x10noneAtari to Device
Command ON0x11noneAtari to Device
Command OFF + Sync Request0x18sync_number: uint8Atari to Device
Motor OFF0x20noneAtari to Device
Motor ON0x21noneAtari to Device
Interrupt OFF0x30noneDevice to Atari
Interrupt ON0x31noneDevice to Atari
Proceed OFF0x40noneDevice to Atari
Proceed ON0x41noneDevice to Atari
Speed Change0x80baud: uint32 (little-endian)Bidirectional
Sync Response0x81sync_number, ack_type, ack_byte, write_sizeDevice to Atari
Device Disconnected0xC0noneDevice to Hub
Device Connected0xC1noneDevice to Hub
Ping Request0xC2noneDevice to Hub
Ping Response0xC3noneHub to Device
Alive Request0xC4noneDevice to Hub
Alive Response0xC5noneHub to Device
Credit Status0xC6credit: uint8Device to Hub
Credit Update0xC7credit: uint8Hub to Device
Warm Reset0xFEnoneAtari to Device
Cold Reset0xFFnoneAtari to Device

With the exception of Ping, a device must first send Device Connected (0xC1) before participating in NetSIO communication.

Data Transfer Messages

Data Byte

FieldValue
ID0x01
DirectionAtari to Device, Device to Atari
Parametersdata_byte: uint8 – byte to transfer

Transfers a single SIO data byte. Used for (but not limited to) completion byte C or checksum byte.

Data Block

FieldValue
ID0x02
DirectionAtari to Device, Device to Atari
Parametersbyte_array: uint8[] – one or more bytes (up to 512)

Transfers multiple data bytes in a single message.

Data Byte and Sync Request

FieldValue
ID0x09
DirectionAtari to Device
Parametersdata_byte: uint8, sync_number: uint8

Transfers a data byte together with a request to synchronize on the next byte from Device to Atari. Atari emulation is paused waiting for the Sync Response.

Used on the last byte (checksum) of an SIO write command when Atari sends a data frame and expects an ACK/NAK within 850 us to 16 ms. The acknowledgment is delivered via Sync Response, and emulation resumes afterward. This pause-resume mechanism extends the 16 ms timing requirement for acknowledgment delivery over network connections.

Command Signals

Command ON

FieldValue
ID0x11
DirectionAtari to Device

Command asserted. Atari indicates to all connected devices the start of a command frame. The command pin uses negative logic (active = low voltage on SIO pin).

Command OFF

FieldValue
ID0x10
DirectionAtari to Device

Command de-asserted. Indicates the end of a command frame. Currently not used directly; see Command OFF and Sync Request.

Command OFF and Sync Request

FieldValue
ID0x18
DirectionAtari to Device
Parameterssync_number: uint8

Command de-asserted with a sync request. Atari expects an ACK/NAK within 16 ms of the command frame ending. The sync mechanism extends this timing requirement for network-connected devices.

Motor Signals

Motor ON / Motor OFF

SignalID
Motor ON0x21
Motor OFF0x20

Direction: Atari to Device. Controls the cassette player motor signal.

Proceed and Interrupt Signals

Proceed ON / Proceed OFF

SignalID
Proceed ON0x41
Proceed OFF0x40

Direction: Device to Atari. The device indicates to the Atari that it needs attention (e.g., data available for read). Uses negative logic.

Interrupt ON / Interrupt OFF

SignalID
Interrupt ON0x31
Interrupt OFF0x30

Direction: Device to Atari. Similar to Proceed – the device indicates it needs attention. Uses negative logic.

Speed Change

FieldValue
ID0x80
DirectionBidirectional
Parametersbaud: uint32 – 4 bytes, little-endian

Indicates that the outgoing data rate has changed. When transferring data to the emulated Atari, data bits “arrive” at the SIO Data In pin at the specified rate. In the opposite direction, the bitrate is complementary information that can be used to simulate errors when the device expects a different bitrate (e.g., toggling between standard 19200 and high speed).

Sync Response

FieldValue
ID0x81
DirectionDevice to Atari
Parameterssync_number: uint8, ack_type: uint8, ack_byte: uint8, write_size: uint16 (LSB+MSB)

Response to Command OFF + Sync Request or Data Byte + Sync Request.

  • sync_number – matches the request
  • ack_type:
    • 0 = Empty acknowledgment (device not interested in this command); other fields ignored
    • 1 = Valid acknowledgment; ack_byte will be sent to Atari
  • ack_byte – the byte Atari is waiting for (ACK = 65/A, NAK = 78/N for standard SIO)
  • write_size – non-zero means current command is SIO write and next sync is expected after this many bytes; zero means do not plan next sync

Connection Management

Device Connected / Device Disconnected

MessageIDDirection
Device Connected0xC1Device to Hub
Device Disconnected0xC0Device to Hub

Registers or unregisters a device from the NetSIO bus.

Ping Request / Ping Response

MessageIDDirection
Ping Request0xC2Device to Hub
Ping Response0xC3Hub to Device

Tests hub availability. Can be used to measure network round-trip time.

Alive Request / Alive Response

MessageIDDirection
Alive Request0xC4Device to Hub
Alive Response0xC5Hub to Device

The device must send Alive Requests at regular intervals to maintain its connection. The hub responds to confirm the connection is still active.

Flow Control (Credit System)

Credit Status / Credit Update

MessageIDDirectionParameters
Credit Status0xC6Device to Hubcredit: uint8 – remaining credit
Credit Update0xC7Hub to Devicecredit: uint8 – credit granted

The credit system provides flow control for messages that require emulator processing (data bytes, proceed, interrupt). Each message sent consumes one credit. When a device runs out of credit, it sends Credit Status and waits for Credit Update before proceeding. This prevents the emulator’s incoming message queue from being overfilled while allowing a small number of messages to be queued for processing.

Reset Notifications

Warm Reset / Cold Reset

MessageIDDescription
Warm Reset0xFEEmulated Atari performed a warm reset
Cold Reset0xFFEmulated Atari performed a cold reset (power cycle)

Direction: Atari to Device. The device may react to a cold reset by resetting itself to simulate being powered from the Atari.

Command Frame Structure

A command frame consists of three UDP packets (NetSIO messages):

  1. Packet 1: 0x11 (Command ON)
  2. Packet 2: 0x02 followed by 4 bytes of command frame data + checksum (Data Block)
  3. Packet 3: 0x81, sync_number (Sync Response expected)

Atari800 Emulator Integration

SIO Paths

The atari800 emulator has two code paths for SIO command frames:

  • SIO_SwitchCommandFrame() – traditional SIO path, called from pia.c
  • SIO_Handler() – shortcut/patch for the $E459 SIO call, handled by the emulator rather than emulated Atari code

The recommended approach for NetSIO integration uses the non-patch path:

  1. Hook SIO_PutByte() to send Data Byte messages (0x01)
  2. Hook SIO_SwitchCommandFrame() to send Command ON/OFF (0x11/0x10)
  3. Optimize by replacing single Data Byte messages with Data Block messages (0x02)
  4. Handle the response direction via SIO_GetByte()

Patch emulation can be disabled with the -nopatchall command-line switch.

See Also