Skip to main content

Overview

The Binary Stage Flight serializer extends the basic binary encoding with CRC-4 (Cyclic Redundancy Check) error detection. This provides a balance between channel density and data integrity, making it suitable for professional applications where reliability is critical.

Class: BinaryStageFlight

Namespace: Global
Implements: IDMXSerializer

Configuration Constants

blockSize
const int
default:"4"
Size in pixels of each bit block (4×4 pixels)
channelsPerCol
const int
default:"6"
Number of DMX channels encoded in each column group before adding CRC
blocksPerCol
const int
default:"48"
Total bit blocks per column (6 channels × 8 bits = 48 blocks)
CRCBits
const int
default:"4"
Number of bits used for CRC checksum (4 bits = CRC-4)

How It Works

Data Structure

Binary Stage Flight organizes data into column groups:
┌─────────────────┐
│  Channel 0-5    │  48 blocks (6 channels × 8 bits)
│  (Data Bits)    │
├─────────────────┤
│  CRC-4          │  4 blocks (error detection)
└─────────────────┘

CRC-4 Error Detection

Each column group of 6 channels gets a 4-bit CRC checksum:
  1. Channels 0-5 are serialized
  2. CRC-4 is calculated over all 6 channel values
  3. CRC bits are written below the data section
  4. Pattern repeats for channels 6-11, 12-17, etc.

Bit Endianness

Unlike the basic Binary serializer, Binary Stage Flight uses reverse bit order:
// Bit encoding for channel value 170 (0b10101010)
Bit 7: 1White block  (most significant bit first)
Bit 6: 0 → Black block
Bit 5: 1 → White block
Bit 4: 0 → Black block
Bit 3: 1 → White block
Bit 2: 0 → Black block
Bit 1: 1 → White block
Bit 0: 0 → Black block  (least significant bit last)

Methods

SerializeChannel

Encodes a DMX channel value as 8 reversed binary bits.
public void SerializeChannel(ref Color32[] pixels, byte channelValue, 
    int channel, int textureWidth, int textureHeight)
pixels
ref Color32[]
required
The pixel array to write the encoded bits to
channelValue
byte
required
The DMX channel value (0-255) to encode
channel
int
required
The DMX channel number
textureWidth
int
required
Width of the output texture
textureHeight
int
required
Height of the output texture
Process:
  1. For each of the 8 bits (reversed order, 7→0):
    • Extracts the bit value using bitwise operations
    • Calculates position with texture wrapping
    • Creates a 4×4 color block (white for 1, black for 0)
    • Writes the block to the pixel array

CompleteFrame

Generates and writes CRC-4 checksums for all column groups.
public void CompleteFrame(ref Color32[] pixels, ref List<byte> channelValues, 
    int textureWidth, int textureHeight)
pixels
ref Color32[]
required
The pixel array to write CRC blocks to
channelValues
ref List<byte>
required
All channel values for the current frame
textureWidth
int
required
Width of the output texture
textureHeight
int
required
Height of the output texture
Process:
  1. Groups channels into sets of 6
  2. For each group:
    • Calculates CRC-4 checksum using polynomial 0x03
    • Determines CRC block position below the data section
    • Writes 4 CRC bits as white/black blocks
    • Handles texture wrapping for wide layouts

DeserializeChannel

Decodes a DMX channel value from binary bits.
public void DeserializeChannel(Texture2D tex, ref byte channelValue, 
    int channel, int textureWidth, int textureHeight)
CRC verification during deserialization is marked as TODO in the source code. Currently, bits are read but CRC validation is not performed.

CRC-4 Algorithm

The CRC calculation uses a 4-bit polynomial-based algorithm:
public static byte Crc4(params byte[] data)
{
    uint crc = 0u;
    uint polynomial = 0x03;  // CRC-4 polynomial

    foreach (uint v in data)
    {
        for (int bit = 7; bit >= 0; --bit)
        {
            uint inBit = (v >> bit) & 1u;
            bool top = (crc & 0x8u) != 0u;
            crc = ((crc << 1) | inBit) & 0xFu;
            if (top) crc ^= polynomial;
        }
    }
    return (byte)(crc << 4); // Left-aligned in byte
}

CRC Properties

Polynomial
0x03
CRC-4 generating polynomial
Width
4 bits
Checksum size, can detect single-bit errors
Error Detection
Single-bit & some multi-bit
Reliably detects all single-bit errors and some multi-bit errors in a 6-channel group

Texture Wrapping

When the data exceeds texture width, Binary Stage Flight wraps to the next row:
private static void CalculateWrapping(int x, int y, out int adjx, out int adjy, 
    int textureWidth)
{
    int wrap = x / textureWidth;
    adjx = x % textureWidth;
    adjy = y + (wrap * (blocksPerCol + CRCBits) * blockSize);
}
Layout Example (narrow texture):
┌─────────┬─────────┐
│ Col 0   │ Col 1   │  Data blocks
│ Ch 0-5  │ Ch 6-11 │
├─────────┼─────────┤
│ CRC 0-5 │ CRC 6-11│  CRC blocks
├─────────┴─────────┤  Wrap boundary
│ Col 2   │ Col 3   │
│ Ch12-17 │ Ch18-23 │
└─────────┴─────────┘

Usage Example

// Create Binary Stage Flight serializer
var serializer = new BinaryStageFlight();

// Initialize frame
var channelValues = new List<byte> { 128, 64, 192, 32, 224, 96 };
serializer.InitFrame(ref channelValues);

// Serialize all channels
Color32[] pixels = new Color32[256 * 256];
for (int i = 0; i < channelValues.Count; i++)
{
    serializer.SerializeChannel(ref pixels, channelValues[i], i, 256, 256);
}

// Complete frame - writes CRC checksums
serializer.CompleteFrame(ref pixels, ref channelValues, 256, 256);

// Calculate CRC for verification
byte[] group1 = channelValues.GetRange(0, 6).ToArray();
byte crc = BinaryStageFlight.Crc4(group1);
Debug.Log($"CRC for channels 0-5: 0x{crc:X2}");

Channel Capacity

Capacity is reduced compared to basic Binary due to CRC overhead:
// Each column group:
// - 6 channels = 48 data blocks
// - 4 CRC blocks
// - Total: 52 blocks per group

// Calculate capacity
int blockWidth = textureWidth / blockSize;
int totalBlocks = textureHeight / (blocksPerCol + CRCBits);
int channelGroups = blockWidth * totalBlocks;
int totalChannels = channelGroups * channelsPerCol;

Capacity by Resolution

ResolutionChannel GroupsTotal Channels
256×25664 × 4 = 2561,536
512×512128 × 8 = 10246,144
1024×1024256 × 16 = 409624,576
These are theoretical maximums. Actual capacity may be lower depending on texture wrapping and alignment.

Advantages

Error Detection

CRC-4 detects transmission errors in channel groups

Professional Grade

Suitable for critical applications requiring reliability

High Density

Still maintains high channel density with error protection

Organized Layout

Structured column groups simplify debugging

Limitations

  • No Error Correction: CRC can detect errors but cannot fix them
  • Group-Based: Errors affect entire 6-channel groups
  • Incomplete Decoding: CRC verification not yet implemented in deserialization
  • Complexity: More complex than basic Binary serializer

Best Practices

1. Monitor CRC Failures

// Implement CRC checking during deserialization
public bool VerifyChannelGroup(byte[] channels, byte receivedCRC)
{
    byte calculatedCRC = BinaryStageFlight.Crc4(channels);
    if (calculatedCRC != receivedCRC)
    {
        Debug.LogWarning($"CRC mismatch! Expected: {calculatedCRC:X2}, Got: {receivedCRC:X2}");
        return false;
    }
    return true;
}

2. Handle Error Recovery

// Strategy for handling CRC failures
if (!VerifyChannelGroup(channelGroup, receivedCRC))
{
    // Option 1: Use previous frame's values
    // Option 2: Interpolate from adjacent channels
    // Option 3: Set to safe default values
    // Option 4: Request retransmission
}

3. Optimize Channel Grouping

Group related channels together for better error isolation:
// Good: Group fixture parameters together
Channels 0-5: Fixture 1 (pan, tilt, dimmer, R, G, B)
Channels 6-11: Fixture 2 (pan, tilt, dimmer, R, G, B)

// Poor: Mix unrelated channels
Channels 0-5: Random channels from different fixtures

Comparison with Binary

FeatureBinaryBinary Stage Flight
Block Size4×44×4
Bit OrderStandardReversed
Error DetectionNoneCRC-4
Overhead0%~8% (4 bits per 6 channels)
Use CaseMaximum densityReliable transmission
ComplexitySimpleMedium

Performance

  • Encoding: ~0.025ms per channel (includes CRC calculation)
  • CRC Calculation: ~0.005ms per 6-channel group
  • Decoding: ~0.03ms per channel
  • Memory: Minimal overhead

Future Enhancements

The source code includes a TODO comment for implementing CRC verification during deserialization. This would enable automatic error detection when receiving data.
Potential improvements:
  • Complete CRC verification in DeserializeChannel
  • Error logging and statistics
  • Automatic error recovery strategies
  • Configurable CRC polynomial
  • Reed-Solomon forward error correction

Build docs developers (and LLMs) love