Friday, February 3, 2012

Network SID Device Protocol

The Acid64 player supports playback of SID tunes via a network protocol which allows cycle-exact playback in emulators like the jsiddevice or on a real chip like in this project. I'm planning to support this protocol with the SIDboard (there will be a wrapper translating the network packages into commands that are sent via the serial port) and also within the FlowSID composer.

The main reason why I am writing this post is that I finally found a detailed description of the protocol in the jsidplay2 sources. I've extracted it for convenience:


Authors: Ken Händel, Antti S. Lankila, Wilfred Bos

JSIDPlay2 SID-emulation integration protocol. It is possible to have JSIDPlay2 take over the duty of the SID playback for a C64 emulator/player. Every jsidplay2 instance tries to open port 6581 where they will listen to connections that describe SID activity with the following protocol.


GENERAL OVERVIEW

Version 2 of the protocol is structured as a request-response protocol:

  • Requests are variable length, with minimum packet size 4 bytes. There are 3 fields and an amorphous data blob:
    • 8-bit unsigned as command.
    • 8-bit unsigned as SID number.
    • 16-bit unsigned as length of data attached to header in bytes.
    • Data (if any)
  • All commands are ACKed with a response packet that takes one of the followingforms:
    • OK means that the commands were accepted by server and can be discarded by client. No data will be appended to response.
    • BUSY means that no part of the current command was accepted due to filled queue condition, and that client should wait and retry it later. 1 millisecond could be a suitable delay before retry. Queue length is limited both by number of events and maximum time drift between playback clock and client clock. No data will be attended to response.
    • READ: successful read operation, one byte value follows that is the value read from SID.
    • VERSION: response to VERSION operation. Version number will be appended to response.
    • COUNT: number of SIDs supported by network device.
    • INFO: info packet, which contains model code and zero-padded 20-byte UTF-8 encoded string representing model name.

Maximum packet length is 64k + header length. It is suggested that only short packets are transmitted, in the order of 1k and containing no more than about 1 ms worth of events. Otherwise the client-server desync brings jitter that may have unpleasant consequences. At the limit it's possible to simply send a fixed header that describes a single write with each packet, but this is probably measurably less efficient.


COMMAND OVERVIEW

Structure of data is specific to command. Some commands require data, others will not use data even if such was provided. Some commands require specific lengths for the data packets. If data length is not correct, results are undefined.

Known commands are identified by small integers, starting from 0:

  • FLUSH (0): destroy queued data on all SIDs, and cease audio production.
    • sid number is ignored.
    • data packet must be 0 length.
    • should probably be followed by RESET (SID is in unpredictable state).
    • always returns OK
  • TRY_SET_SID_COUNT (1): set number of SID devices available for writing
    • sid number equals the count of SIDs wanted.
    • data packet must be 0 length.
    • returns BUSY until audio quiescent, otherwise OK.
  • MUTE (2): mute/unmute a voice on specified SID
    • data packet must contain two 8-bit unsigned bytes:
      • the voice number from 0 to 2
      • 0 or 1 to disable/enable voice
      • this command bypasses buffer and takes immediate effect.
    • always returns OK
  • TRY_RESET (3): reset all SIDs, setting volume to provided value.
    • data packet must be a 8-bit unsigned value which is written to volume register.
    • returns BUSY until audio quiescent, otherwise OK.
  • TRY_DELAY (4): inform emulation that no events have occured for a given count of cycles
    • data packet must be 16-bit unsigned value interpreted as delay in C64 clocks. 0 is not allowed.
    • allows audio generation in absence of other activity.
    • returns BUSY if there is already enough data for playback, otherwise OK.
  • TRY_WRITE (5): try to queue a number of write-to-sid events.
    • data packet must be 4*N bytes long, repeating this structure:
      • 16-bit unsigned value interpreted as delay before the write in C64 clocks. (Currently there seems to be a bug somewhere, probably in my software, that causes strange sounds (hanging bleeps, etc) unless the delay is placed after the write. However, Wilfred Bos, author of ACID64, assured me that the delay should be indeed before the write (which seems logical). I will post an update when I found out what's going on here.)
      • 8-bit unsigned SID register number from 0x00 to 0x1f.
      • 8-bit unsigned data value to write
    • returns BUSY if there is already enough data for playback, otherwise OK.
  • TRY_READ (6): reads SID chip register.
    • data packet must be a 4n+3 bytes long, where n >= 0. The protocol used for the first n packets is the same as the TRY_WRITE protocol, returning potentially BUSY if the delay implied by the READ, or the WRITEs can not yet be buffered.
    • Read packet structure trails the write packet structure:
      • 16-bit unsigned value interpreted as delay before the read in C64 clocks.
      • 8-bit unsigned SID register number from 0x00 to 0x1f.
    • returns BUSY if there is already enough data for playback, otherwise READ and a data byte, which is the read value from SID.
  • GET_VERSION (7): returns the version of the SID Network protocol.
    • sid number is ignored.
    • data packet must be 0 length.
    • returns 2 bytes: VERSION and a data byte, which is the version of the SID Network protocol.
  • SET_SAMPLING (8): set the resampling method for all SID devices.
    • sid number is ignored.
    • data packet is 1 byte long and contains:
      • 0 for pure decimator (low quality)
      • 1 for low-pass filtered decimator (high quality).
    • returns BUSY until audio quiescent, otherwise OK.
  • SET_CLOCKING (9): set the clock source speed for all SID devices.
    • sid number is ignored.
    • data packet is 1 byte long and contains:
      • 0 for PAL
      • 1 for NTSC
  • returns BUSY until audio quiescent, otherwise OK.
  • GET_CONFIG_COUNT (10): Query number of SID configurations supported by server.
  • sid number is ignored.
  • data packet is ignored and should be 0 length.
    • always returns COUNT and a 8-bit unsigned value that is 1 larger than the maximum valid configuration.
  • GET_CONFIG_INFO (11): query the name and model of the SID configuration.
    • data packet is ignored and should be 0 length.
    • returns INFO and 8-bit unsigned-value and a string in ISO-8859-1 encoding with a maximum of 255 characters excluding a null terminated byte
      • INFO code
      • Model: 0 = 6581, 1 = 8580
      • Model name (max. 255 chars + 1 null terminated byte)
  • SET_SID_POSITION (12): set sid position on the audio mix
    • data packet is 1 byte long and contains:
      • -100 to 0: audio is panned to left
      • 0 to 100: audio is panned to right
    • always returns OK.
  • SET_SID_LEVEL (13): set SID level adjustment in dB
    • data packet is 1 byte long and contains:
      • 8-bit signed dB adjustment in cB (centibels), 0 means no adjustment
    • always returns OK.
  • SET_SID_MODEL (14):
    • data packet is 1 byte long and contains:
      • 8-bit unsigned value between 0 <= value <= max_config-1
    • always returns OK.

VERSION HISTORY

  • Version 1 contains all commmands up to 7 (VERSION). There were 8 SID devices where bit 0 gave 6581/8580, bit 1 PAL/NTSC and bit 2 RESAMPLE/DECIMATE mode of operation.
  • Version 2 contains commands SAMPLING and CLOCKING. There are 4 different SIDdevices, 3x 6581 and 1x 8580. The commands SAMPLING and CLOCKING can be used to setparticular SID kind.

NOTES

The delay values do not contain the time taken to write the value to SID chip, and a delay length of 0 between writes is impossible to achieve with a true C64 system, although this emulator will accept it and execute several writes on the same clock.

At start of connection, the SID starts from RESET state with volume=0 and empty buffer.

Suitable packet size for TRY_WRITE is about 20 ms long. If TRY_WRITE returns BUSY, then client should wait about 20 ms (same as the play length of one packet) before retry.


Future expansion:

  • stereo SID support
  • select filter type in dialog
  • route chips to left, right or mono.
  • implement protocol via UDP
  • combine read and write in one data packet

1 comment:

  1. Where can I learn more about underfill? I've heard it used in conversation, but I'm not exactly sure what it is. Can you tell me more about it?

    ReplyDelete