Zum Inhalt

Migration

Diese Seite wurde aus der AirSimTech MediaWiki migriert.

ARINC 429 Screen Buffer Pipeline

Overview

The ARINC 429 screen buffer pipeline carries MCDU page content from the McduCommandParser character writer all the way through to a UDP datagram sent to port 65520 as register 7100 payload. The key design feature is a differential XOR optimization: instead of transmitting all 312 character positions on every page render, the pipeline tracks which cells have changed since the last transmission and sends only the dirty range. A typical page refresh sends 50–100 bytes instead of the full 624-byte buffer, significantly reducing UDP bandwidth to the MCDU display hardware.

Pipeline Stages

Buffer Dimensions

The screen buffer models 13 lines of 24 columns each, giving 312 total character positions:

  • LINES As Integer = 13
  • COLUMNS As Integer = 24
  • BUFFER_SIZE As Integer = 312 (= LINES × COLUMNS)

Two parallel byte arrays hold the screen state:

  • _charBuffer(311) As Byte — 312-element array (0-based). Each element is one ARINC 429 character byte.
  • _ctrlBuffer(311) As Byte — 312-element array (0-based). Each element is a control byte encoding font and color: CByte(CType(font, Byte) Or CType(color, Byte)).

Buffer index for a given position: pos = (line * 24) + column where both line and column are zero-based.

Dirty Range Tracking

Two integer fields track the range of modified positions:

  • _firstChange As Integer = Integer.MaxValue — lowest position index modified since last reset
  • _lastChange As Integer = -1 — highest position index modified since last reset

On each WriteChar or SetControl call:

_firstChange = Math.Min(_firstChange, pos)
_lastChange  = Math.Max(_lastChange, pos)

HasChanges() returns True when _firstChange <= _lastChange.

Character Encoding

Color Codes

Defined in the McduColor enum (A320_FMGC/Inet/Arinc429Constants.vb), matching VB6 Variables_ARINC429.bas:

Color Byte Value McduCommandParser Token
Black 0 (default background, not selectable by token)
Cyan 16 ~b
Red 32 ~r
Yellow 48 ~y
Green 64 ~g
Magenta 80 ~m
Amber 96 ~a
White 112 ~w

Font Codes

Font Byte Value McduCommandParser Token
Small 0 @s
Large 128 @l

Control Byte Composition

The control byte combines font and color with bitwise OR:

_ctrlBuffer(pos) = CByte(CType(font, Byte) Or CType(color, Byte))

Example: Large (128) + White (112) = 240 (0xF0). Small (0) + Cyan (16) = 16 (0x10).

Special Character Mapping

Arinc429SpecialChars.MapSpecialChar(c As Char) As Byte maps shorthand characters used in MCDU page source strings to their ARINC 429 display byte values:

Input Char Output Byte Symbol
a 29 Square symbol
b 28 Degrees symbol
i 110 Flyover waypoint symbol
c 95 Left arrow
d 31 Right arrow
e 94 Up arrow
f 30 Down arrow
all others ASCII byte Pass-through (ASCII value AND 0xFF)

Differential XOR Transmission

BuildDifferentialMessage

BuildDifferentialMessage(isCaptain As Boolean) As Byte() produces the binary payload ready for Arinc429UdpSender.SendMessage:

  1. Returns an empty array (Array.Empty(Of Byte)()) if there are no pending changes (HasChanges() = False).
  2. Computes changeCount = _lastChange - _firstChange + 1 — the span of the dirty range.
  3. Allocates a totalLength = 18 + 2 * changeCount byte array.
  4. Writes an 18-byte fixed header (matching VB6 PageHandle.cls lines 245–256):
    • Bytes 0–1: 0x45, 0x46 ("EF")
    • Byte 2: 0x76 (118) for Captain, 0x7A (122) for FO
    • Bytes 3–13: fixed magic bytes
    • Bytes 14–15: start position as big-endian UInt16 (_firstChange)
    • Bytes 16–17: change count as big-endian UInt16
  5. Copies _ctrlBuffer[_firstChange .. _lastChange] into bytes 18 onward.
  6. Copies _charBuffer[_firstChange .. _lastChange] immediately after the control bytes.

After calling BuildDifferentialMessage, the caller invokes ResetDirtyRange() to reset _firstChange and _lastChange for the next cycle.

Bandwidth Savings

A full buffer transmission would be 18 + 2 × 312 = 642 bytes. A typical page refresh touches 25–50 contiguous positions, producing 18 + 2 × 50 = 118 bytes or fewer. Single-field updates (e.g., distance readout changing one value) send as few as 20–30 bytes.

UDP Output

Arinc429UdpSender wraps a single System.Net.Sockets.UdpClient instance targeting 255.255.255.255:65520 (UDP broadcast).

XOR Scrambling

Before transmission, SendMessage applies the VB6 mod_ARINC429.bas scrambling algorithm:

  1. Pad the raw message to a minimum of 24 bytes with 0x00.
  2. Generate 3 random key bytes: k0, k1, k2 (0–255 each).
  3. Compute k3 = k0 XOR k1 XOR k2.
  4. Build the scrambled output:
    • Index 0: copy as-is
    • Index 1: 0x4D ('M')
    • Index 6: 0x45 ('E')
    • Index 7: k0
    • Index 8: 0x45 ('E')
    • Index 9: k1
    • Index 10: 0x4D ('M')
    • Index 11: k2
    • Index 12: 0x01
    • Index 13: 0x01
    • All other indices: rawMessage(i) XOR k3

IDisposable and PostStop

Arinc429UdpSender implements IDisposable. The Close() method shuts down the UdpClient and sets a _disposed flag to prevent double-close. INetActor.PostStop calls _arinc429Sender.Close() to release the socket when the actor system shuts down:

Protected Overrides Sub PostStop()
    If _arinc429Sender IsNot Nothing Then _arinc429Sender.Close()
    _Logger.Info("INetActor stopped")
End Sub

Calls to SendMessage after disposal are silently discarded with a warning log.

McduActor Integration

McduActor owns one Arinc429ScreenBuffer instance per side (Captain or FO). The buffer is NOT shared between actors. The render cycle operates as follows:

  1. An input event (LSK press, scratchpad entry, periodic refresh) triggers page rendering.
  2. The active IPage implementation's HandleLsk method returns a McduCommand; separately, the Render method builds a List(Of String) of VB6 command strings into the screen buffer.
  3. McduCommandParser.ParseAndRender(commands, _screenBuffer) processes the command list:
    • "LISTCLEAR" — calls _screenBuffer.Clear() and resets parser color/font state to White/Large.
    • "LISTCOMPLETE" — no-op end marker.
    • Line content entries ("01..." through "13...") — parsed for column positions (|CC), font tokens (@s/@l), color tokens (~w/~b/~g/~y/~r/~a/~m), and character bytes.
  4. _screenBuffer.BuildDifferentialMessage(isCaptain) produces the ARINC 429 binary payload.
  5. _screenBuffer.LastCommands provides the raw VB6 command list cached during ParseAndRender — these are the original IPage commands (no binary-to-text reconstruction). ParseAndRender auto-appends LISTCOMPLETE if the page omitted it.
  6. Both outputs are passed to INetActor: _inetActor.Tell(New SendScreenBuffer(isCaptain, bytes, lstLines)).
  7. _screenBuffer.ResetDirtyRange() is called after the build.
  8. INetActor.HandleSendScreenBuffer sends via two paths:
    • Path 1 — ARINC 429 binary: delegates to _arinc429Sender.SendMessage(msg.ScreenData) for hardware MCDU displays.
    • Path 2 — INET register 5339 text: joins lstMcduLines with Chr(26), sends via INetClient1.DataTX 5339, 0, subPrefix & payload for software MCDU display. Also sends heartbeat on separate sub-address.

Source Files

  • A320_FMGC/Inet/Arinc429ScreenBuffer.vb — 13×24 buffer, _charBuffer/_ctrlBuffer, dirty range tracking, BuildDifferentialMessage, 18-byte header format
  • A320_FMGC/Inet/Arinc429Constants.vbMcduColor enum (Black=0, Cyan=16, Red=32, Yellow=48, Green=64, Magenta=80, Amber=96, White=112), McduFont enum (Small=0, Large=128), Arinc429SpecialChars.MapSpecialChar
  • A320_FMGC/Inet/Arinc429UdpSender.vbUdpClient wrapper, XOR scrambling algorithm, IDisposable, Close()
  • A320_FMGC/Inet/INetActor.vbHandleSendScreenBuffer, PostStop cleanup
  • A320_FMGC/Mcdu/McduCommandParser.vbParseAndRender, VB6 command string format, color/font token parsing
  • A320_FMGC/Mcdu/McduActor.vb — buffer ownership, render cycle, BuildDifferentialMessage call site