Skip to content

ZIMO-Elektronik/ZUSI

Repository files navigation

ZUSI

build tests license

ZUSI is a ZIMO specific protocol for the SUSI bus. It supports ZPP updates on multiple decoders in parallel with up to 1.8MBaud. In addition, it also supports fast reading and writing of CVs for individual decoders. The protocol is currently supported by the following products:

Table of Contents
  1. Protocol
  2. Getting Started
  3. Usage

Protocol

Electrical Specification

Regarding the electrical properties, ZUSI adheres to the specifications of RCN-600, so reference is made to the standard at this point. The data transfer itself uses a combination of SPI and GPIO single bit toggles. The SPI interface must be able to use mode 1 (CPOL 0, CPHA 1) which means that data is clocked out on a rising clock edge and read on a falling clock edge. Bidirectional SPI (MOSI only) functionality is advantageous but not mandatory. All transmissions take place LSB first. The transmission speed is specified by the host; a feature request makes it possible to query the maximum speed of all participants on the bus.

Four different clock frequencies are available.

Clock Period [µs] Bit Rate [Mbps] Description
10 0.1 Resync timing
3.5 0.286 Fallback timing, slowest used for data transmission
0.733 1.364 2. fastest possible
0.5533 1.807 Fastest possible

These timings do not need to be matched precisely, it is acceptable to achieve a slightly slower data-rate.

Entry

To connect devices (decoders) to the host, the host needs to send 0x55 (or 0xAA) for at least a second with a clock period fixed at 10ms. This is necessary to allow the decoder to evaluate the signal during its normal operation.

Alternative Entry

🚧

Transmission

The transmission is generally divided into 5 phases:

The following graphic shows the transmission of a CV Read packet including response. After the command has been transmitted, including some data, a resync byte is sent. The direction of the data is then reversed and all connected devices have the opportunity to respond. This response consists of an ACK and Busy phase and, if provided for by the command, the transmission of the requested data. transmission

Command phase

During the command phase the host transmits a command including any data at the currently set transmission speed.

Resynchronization Phase

To avoid problems with the MX644, a resynchronization phase has been introduced between host transmission and device response. This phase consists of a delay of at least 10µs, followed by a transmission of the byte 0x80. The clock period for the transmission is 10µs, which corresponds to a an SPI frequency of 0.1Mbps. This asynchronous clock period is maintained for the complete feedback.

To catch asynchronous behavior, the state-machine of a decoder will be reset after 10ms of no activity on the clock. This can be used to resync all decoders.

ACK Phase

After the last bit of the host transmission (after the resynchronization phase), the host switches the data line to input. The decoder will send a two bit answer, one called ACK valid and one ACK (in this order).

ACK valid should always be low. This verifies that at least one decoder is still connected and received the command. If ACK valid is high, then the host must assume that no decoder has received the command. (wired OR).

ACK is high if all decoders have confirmed the command. If ACK is low (NAK), at least one decoder has not acknowledged the command (wired AND).

Again, there is a special workaround for the MX644. The ACK phase uses an asymmetric clock period of 10µs high to 20µs low. Both ACK valid and ACK/NAK will be set by the decoder on a rising edge on clock and can be read on the falling edge.

Busy Phase

Some commands (e.g. ZPP Erase or ZPP Write) contain a busy phase. Similar to the ACK bits, a bit is clocked by the host. The decoder waits for the clock line to be high and then pulls the data line low. While the data line is low, the decoder can execute the received command. When it is finished, it releases the data line again. This can be done asynchronously and results in a wired AND, the data line will only be high if all decoders are finished. The host clock is suspended during the busy phase.

Response Phase

During the response phase the device transmits data back to the host.

Commands

ZUSI uses a command specific frame structure. The first byte of each frame marks the used command, all subsequent bytes will be sent according to frame description.

CV-Read

Length Name Value / Limits Description
1 byte Command 0x01 Command code
1 byte Count - 1 0 - 255 (=N-1) Number of CVs to read - 1
4 byte CV address 0 - 1023 Address of the first CV
1 byte CRC CRC8 checksum
1 byte Resync 0x80 Resync byte
1 bit ACK valid
1 bit ACK
1 bit Busy
N byte CV values Values of the read CVs
1 byte CRC CRC8 checksum

CV Read is used to read CV values ​​from a decoder.

Warning

Current implementations only read one byte at a time.

CV-Write

Length Name Value / Limits Description
1 byte Command 0x02 Command code
1 byte Count - 1 0 - 255 (=N-1) Number of CVs to write - 1
4 byte CV address 0 - 1023 Address of the first CV
N byte Values (N) CV values to be written
1 byte CRC CRC8 checksum
1 byte Resync 0x80 Resync byte
1 bit ACK valid
1 bit ACK
1 bit Busy

CV Write is used to write CV values ​​into a decoder.

Warning

Current implementations only write one byte at a time.

ZPP-Erase

Length Name Value / Limits Description
1 byte Command 0x04 Command code
1 byte Security byte 0x55
1 byte Security byte 0xAA
1 byte CRC CRC8 checksum
1 byte Resync 0x80 Resync byte
1 bit ACK valid
1 bit ACK
1 bit Busy

The ZPP Erase command can be used to erase the flash in the decoder.

Warning

Deleting a NOR flash can take up to 200s depending on the manufacturer and type.

ZPP-Write

Length Name Value / Limits Description
1 byte Command 0x05 Command code
1 byte Size - 1 0 - 255 (N-1) Size of the data block - 1
4 byte Address Address of the data block
N byte Data up to 256 byte Data block
1 byte CRC CRC8 checksum
1 byte Resync 0x80 Resync byte
1 bit ACK valid
1 bit ACK
1 bit Busy

ZPP Write is used to transfer ZPP data.

Warning

Current implementations only support a payload of exactly 256 bytes.

Features

Length Name Value / Limits Description
1 byte Command 0x06 Command code
1 byte CRC CRC8 checksum
1 byte Resync 0x80 Resync byte
1 bit ACK valid
1 bit ACK
1 bit Busy
1 byte Baud rate flags Bit7:3=1 (always)
Bit2=0 0.5533µs timing supported
Bit1=0 0.733µs timing supported
Bit0=0 3.5µs timing supported
1 byte N/A 0xFF
1 byte N/A 0xFF
1 byte Device flags Bit7=0 not compatible with other devices at the same time
Bit6:0=1 (always)

Features requests the transmission capabilities of connected devices. These capabilities consist of a baud rate and a device byte. In the baud rate byte, decoders set the bit for the fastest timing they support low. In the device byte, bit 7 pulled low indicates if they can operate simultaneously with other devices.

Warning

The CRC is missing in the response of this packet... 😢

Exit

Length Name Value / Limits Description
1 byte Command 0x07 Command code
1 byte Security byte 0x55
1 byte Security byte 0xAA
1 byte Option Bit7:2=1 (always)
Bit1=0 perform CV8 reset
Bit0=0 reboot
1 byte CRC CRC8 checksum
1 byte Resync 0x80 Resync byte
1 bit ACK valid
1 bit ACK
1 bit Busy

This will exit ZUSI and resume normal operation.

ZPP-LC-DC-Query

Length Name Value / Limits Description
1 byte Command 0x0D Command code
4 byte Developer code Developer code (see ZPP file format description)
1 byte CRC CRC8 checksum
1 byte Resync 0x80 Resync byte
1 bit ACK valid
1 bit ACK
1 bit Busy
1 byte Load code valid 0x00 Load code invalid
0x01 Load code valid
1 byte CRC CRC8 checksum

A ZPP-LC-DC query can be used to check whether the decoders contain a valid load code before deleting the flash.

Typical processes

ZPP Update

  1. Entry sequence to put devices into ZUSI
  2. Features to determine transmission speed
  3. ZPP-LC-DC-Query (optional) to check for valid load code
    • Exit on negative answer
  4. ZPP-Erase
  5. ZPP-Write
  6. Exit
  7. Leave voltage switched on for at least 1s

Getting Started

Prerequisites

  • C++23 compatible compiler
  • CMake ( >= 3.25 )

Installation

This library is meant to be consumed with CMake.

# Either by including it with CPM
cpmaddpackage("gh:ZIMO-Elektronik/ZUSI@0.9.0")

# or the FetchContent module
FetchContent_Declare(
  ZUSI
  GIT_REPOSITORY "https://github.com/ZIMO-Elektronik/ZUSI"
  GIT_TAG v0.9.0)

target_link_libraries(YourTarget PRIVATE ZUSI::ZUSI)

Build

If the build is running as a top-level CMake project then tests and a small example will be generated.

cmake -Bbuild
cmake --build build --target ZUSIZppLoad

Usage

To use the ZUSI library, a number of virtual functions must be implemented.

Receiver

In case of the receiving side it is necessary to derive from zusi::rx::Base.

#include <zusi/zusi.hpp>

class Receiver : public zusi::rx::Base {
  // Receive a byte
  std::optional<uint8_t> receiveByte() const final { return 0u; }

  // Read a CV at address
  uint8_t readCv(uint32_t addr) const final { return 0u; }

  // Write a CV at address
  void writeCv(uint32_t addr, uint8_t byte) final {}

  // Erase ZPP
  void eraseZpp() final {}

  // Write ZPP
  void writeZpp(uint32_t addr, std::span<uint8_t const> bytes) final {}

  // Return value of features query
  zusi::Features features() const final { return {}; }

  // Exit
  void exit(uint8_t flags) final {}

  // Check if the load code is valid
  bool loadCodeValid(std::span<uint8_t const, 4uz> developer_code) const final {
    return true;
  }

  // Check if the received address is valid
  bool addressValid(uint32_t addr) const final { return true; }

  // Wait till clock pin equals state with a resync timeout
  bool waitClock(bool state) const final { return true; }

  // Write data line
  void writeData(bool state) const final {}

  // Switch to SPI slave
  void spiSlave() const final {}

  // Switch to GPIO output
  void gpioOutput() const final {}

  // Optional, blink front- and rear lights
  void toggleLights() const final {}
};

Transmitter

In case of the receiving side it is necessary to derive from zusi::tx::Base.

#include <zusi/zusi.hpp>

class Transmitter : public zusi::tx::Base {
  /// Transmit byte at specific transmission speed
  void transmitBytes(std::span<uint8_t const> bytes,
                     zusi::Mbps mbps) const final {}

  // Switch to SPI master
  void spiMaster() const final {}

  // Switch to GPIO input
  void gpioInput() const final {}

  // Switch to GPIO output
  void gpioOutput() const final {}

  // Write clock line
  void writeClock(bool state) const final {}

  // Write data line
  void writeData(bool state) const final {}

  // Read data line
  bool readData() const final { return true; }

  // Delay microseconds
  void delayUs(uint32_t us) const final {}

  /// Optional, busy phase
  virtual void busy() const;
};

About

ZIMO specific protocol for the SUSI bus for ZPP updates

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •