Notes about the WizYasep protocol

A project log for WizYasep

LED screen controller over Ethernet... among others ! It's a Wiznet IP controller with a A3P250 FPGA and I/Os.

Yann Guidon / YGDESYann Guidon / YGDES 12/19/2015 at 21:220 Comments

The WizYasep (currently) implements an application-specific network protocol that is simple (hence cheap and easy to use) yet efficient and flexible. Unlike other widely used protocols, WizYasep synchronises the displays very finely to prevent "tear/shear" of moving pictures. Software can display data through the network without a complex library.


If this was not obvious before, this system uses UDP, IP and other Internet Protocols but it is not meant or designed to be connected to the WWW. It is reserved for isolated LANs to keep latency low and prevent anything from messing with it. 'K ?

Protocol design and safety considerations

The WizYasep uses a Wiznet hardware IP stack, please consult the W5300 datasheet for more details.

ARP (MAC resolution) and PING are provided in hardware by default, they are active to provide the most basic network management ("is the board alive and properly configured ?"). This is the only case where the WizYasep board emits data, the rest of the protocol over UDP does only receive data (there is no ACK to keep things simple, fast and more resilient).

The protocol is also implemented with resiliency in mind: the network stack is automatically reset if unusual conditions are detected (for example buffer overflows). At the same time it is not very restrictive and accepts certain malformed data. The worst that can happen is:

This is not a "safety critical" device, no checksum or authentication is provided. It is designed for resilience, ease of use and performance. TCP is not used because of the ACK packets overhead, particularly for the synchronisation: anti-congestion algorithms are not good for real time.

Protocol overview

For every picture/frame, all data is sent in advance to one UDP socket. Hubs and router often "store and forward" data so this transmission might be delayed and the uncertainty increases if there is other kind of traffic on the links.

The W5300 stores all the frame's data in its FIFO. 128KB is available but for practical reasons, only 56K are currently used. I haven't yet had to drive 19K LED with a single WizYasep board and if the FIFO is filled so much, something wrong is going on (buffer overflow) and the whole protocol is reset.

Note: in my tests, the W5300 does not seem to handle well UDP packets that are larger than 1200 bytes. Check the packet sizes if you don't see any output...

Pixel data are expected to be received in the right packet order. Normally, a simple LAN with a central hub should NOT reorder the packets. For this reason, packet sequence numbers are not used in the payload.

After all the data are delivered to all the WizYasep, the data source sends a small broadcast packet (2 bytes over UDP) over the control/sync port. This triggers the simultaneous display refresh for all the receiving WizYasep boards of the network. The contents of their FIFO is read and reframed to feed the attached LED strings.

The Ethernet network is the only cause of delay between screens, which is a fraction of a millisecond and no image deformation is visible.


The Ethernet link is designed for 100Mbps operation and supports 10Mbps for backward compatibility. 1000BaseT is not supported but it can be connected to a Gigabit hub/router (which will downgrade the link to 100Mbps). This can be useful if the main system controller has to drive many Wiznet boards.

The IP address/mask/port and the MAC address are configurable. Their value are stored in the onboard SPI Flash memory, which can be updated with #SPI Flasher. They can also be configured on demand, during fabrication. The usual parameters are


Any computer with a TCP/IP network stack can send data to the WizYasep.

The main display loop works this way:

  1. Set a timer (can be 20ms for 50Hz refresh)
  2. Read and process the image data (it usually takes a little time) to assemble the UDP packets
  3. Send the data
    for all the packets in a sub-frame,
    for all the receiving Wizyasep
    send the packet
    The loop organises the packets so the first packet is sent to each Wizyasep, then the second... It is better than sending all the data to one WizYasep, then all the data to the other, because it reduces congestion in the hub/router, prevents packet loss due tu buffer overflows (particularly in a Gigabit network)
  4. Wait for timer expiration
  5. Send the Sync packet to the control port
    struct {
      char signature;
      char sequence;
    } sync_payload= { 'L', 'a' };
    // 0x4C6x, only the 4 LSB of "sequence" vary,
    // so this shows in ASCII as "La" "Lb" "Lc" "Ld"..."Lp"
    (beware of Endian ;-) )
  6. goto 1

Note: Step 2 could be moved to step 4 but a tiny delay (a µs ?) is required after the sync packet is sent. This is lets the WizYasep assert how much data is contained in its FIFO. Otherwise, data from one frame could appear on another (though it's unlikely but it's not absolutely impossible, so it's safer/simpler to move the processing step just after the sync).

This delay can be removed if frame sequence numbers were contained in the data packets. The WizYasep would just stop reading when the sequence number does not match the number sent in the sync packet (yes, this one is implemented). However, due to a technical limitation of the WZ5300 FIFO, it's not possible to "unread" already read data (the W5100 is not FIFO based so the "random access" memory makes it possible, but the bus is only 8 bits wide and the capacity is too low, the W5100 can't contain enough data for a medium screen).

It's a hack but it works very well. I reserve the right to restore the sequence number once I get over a few technicalities.

Packet format

Raw LED data are sent in order, in UDP packets to port 60001. The packet size shall be even, not 0 (otherwise the stack is reset). The source can send 1200 bytes or less at a time.

A frame sequence number was added as a header (identical to the sync packet) but it was removed (this simplifies coding, just sendto() a location in memory, no need to memcpy to shift data and add the header...). This header will be restored one day.

A packet sequence number was also developed but

  1. Link/data errors are highly unlikely in practice
  2. This adds code and bugs

The protocol is reset if more than 56K bytes are received on this port.

A pair of bytes is sent to port 60000.

struct {
  char signature;
  char sequence;
} sync_payload= { 'L', 'a' };
// 0x4C6x, only the 4 LSB of "sequence" vary,
// so this shows in ASCII as "La" "Lb" "Lc"..."Lp"

BTW : beware of byte ordering ;-)

Of course, only send one per complete frame. The protocol is reset if more than 512 bytes are received on this port.

Data formatting and pixel ordering

Pixels are transmitted as RGB byte triplets.

By default, the byte ordering is preserved but the hardware can reorder (RGB, GRB, RBG, GBR, BGR, BRG)

The data for one string (output) is sent in the same order, as well. Control software must reorganise data according to the display's geometry (zig-zag etc.)

The first triplet is displayed by the first LED of the string (closest to the WizYasep or data input).

There is one channel per physical output.

Channels only work in pairs : one channel will be unused / disconnected if the display has an odd number of LED strings. This will obviously waste a bit of bandwidth but this is marginal in practical cases.

Currently the number of channels is set at fabrication time but it should be user-configurable in the future.

All channels have the same pixel count or length : if one output has less pixels, then the missing data must still be sent. Usually, displays have a balanced number of outputs so this is not a drawback.

Pixels are sent with channel interleaving: all the first pixels of the channels are sent first. Then come all the second pixels of all channels, etc. For 4 channels, the pixels are in this order:

C1 C2 C3 C4 C1 C2 C3 C4 C1 C2 C3 C4 C1 C2 C3 C4...

The WizYasep can't know how many LEDs are actually connected so more or less could be actually sent, with the obvious side effects of truncated or partial display.

Offline behaviour

The WizYasep can detect when the network is down. However, a simple timeout (after the last valid packet) also works well so the display turns black one second after the last update.

The internal configuration of the number of pixels is useful for this blanking. There is no check of the number of pixels received from the network. A higher number of pixels will not be seen, while a lower number will only blank one part of the screen.