Skip to content

Display & Menu System

The vacuum fluorescent display is driven through a 4-bit parallel GPIO interface using the HD44780 instruction set. The display is a 2-line × 16-character module, write-only — the R/W pin is tied to ground, so the firmware cannot read the busy flag and relies on software delays instead.

GPIO PinHD44780 SignalFunction
P0.4DB4Data bit 4 (4-bit mode, high nibble first)
P0.5DB5Data bit 5
P0.6DB6Data bit 6
P0.7DB7Data bit 7
P0.11RSRegister Select: 0 = command, 1 = data
P0.18EEnable: data latched on falling edge
R/WHardwired to GND (write-only)

The VFD driver sends each byte as two nibbles — high nibble first, then low nibble — toggling the E pin for each. The E pulse function (FUN_00003a5c) drives P0.18 HIGH, executes a short delay, then pulls it LOW. The falling edge of E is when the HD44780 controller latches the data.

The VFD init (FUN_00003d50) follows the standard HD44780 power-on procedure for 4-bit mode:

StepCommandMeaning
10x03Reset — forces 8-bit mode (HD44780 init requirement)
20x28Function set: 4-bit interface, 2 lines, 5×8 dot font
30x0CDisplay control: display ON, cursor OFF, blink OFF
40x06Entry mode: cursor increment, no display shift
50x80Set DDRAM address to 0x00 (cursor to line 1, position 0)

After initialization, the boot message is displayed:

SNAPAV EPISODE
EA500 AMPLIFIER

The string print function (FUN_00003e24) walks a null-terminated string and sends each character as a data write (RS=1). When it encounters a newline character, it sends command 0xC0 to move the cursor to line 2 (DDRAM address 0x40).

The main status display is not rendered by simple string writes. Instead, a compositor function (FUN_00007214) builds a 32-byte buffer — two lines of 16 characters each — by layering information with a priority system. The compositor runs on every VFD update call in the main loop and writes the complete buffer to the display.

The priority layers, from lowest to highest:

PriorityLayerLineContent
1Base display1" VOLUME 42 " (or " VOLUME MUTE ")
2Power mode2 (left)"TRIG" (12V trigger) or "AUTO" (audio sense) or blank (front panel)
3Night mode2 (center-left)"NIGHT" appended if enabled
4Sound mode2 (center)"MUSIC" or "MOVIE" (blank for BYPASS)
5Lock2 (left)"LOCK" — overrides power mode position
6CL FAULT2 (full)Current limit fault — overrides entire line 2
7TH FAULT2 (full)Thermal fault — overrides entire line 2

Higher-priority layers overwrite lower-priority content at the same screen positions. Under normal operation with BYPASS sound mode and FRONT PANEL power control, line 2 is blank. With 12V TRIGGER and MUSIC mode active, line 2 reads "TRIG MUSIC ". If a thermal fault occurs, line 2 becomes "TH FAULT " regardless of what was there before.

The menu system (FUN_00004e38) is a 3-state machine driven by the rotary encoder and its push button on P0.8:

StateBehavior
0 — IdleNormal status display. Encoder press enters menu. Encoder rotation adjusts volume.
1 — Menu navigationEncoder rotation scrolls through 10 menu items. Press selects current item for editing.
2 — Parameter editingEncoder rotation adjusts the selected parameter. Press confirms and returns to navigation.

The menu system has 10 items, dispatched through a jump table at address 0x5644:

#Menu ItemValue Range
1CROSSOVER40 Hz – 260 Hz in variable steps, or LFE
2SPEAKER EQFLAT, DUAL8, BSUB8, BSUB10, BSUB12, HSUB10
3PHASE0° – 315° in 45° steps (8 values, index 0-7)
4SOUND MODEBYPASS, MUSIC, MOVIE
5NIGHT MODEOFF, ON
6POWER CTRLFRONT PANEL, 12V TRIGGER, AUDIO SENSE
7IR DEVICE ID1, 2, 3, 4
8LOCKOFF, ON (special handling: hold encoder 10 sec to unlock)
9FACTORY RESETDisplays " SW V1.19 RESET>", then ">ARE YOU SURE?"
10(reserved)

The lock menu item (item 8) has special behavior: when locked, the encoder is disabled for all other menu items, and the user must hold the encoder button for 10 seconds to unlock. This prevents accidental changes in installed systems where the front panel is physically accessible but not meant to be adjusted.

The crossover display function (FUN_00005c60) reveals the actual frequency mapping. The setting byte stores an index (0-28), and the display function converts it to a frequency:

  • Index 0-12: frequency = index × 5 + 40 (gives 40, 45, 50, … 100 Hz in 5 Hz steps)
  • Index 13-28: frequency = index × 10 - 20 (gives 110, 120, 130, … 260 Hz in 10 Hz steps)
  • Index 29 (max + 1): displays “LFE” (crossover bypassed)

The maximum crossover frequency is 260 Hz, not 250 Hz as stated in the manual. The dual-resolution step scheme gives finer control in the 40-100 Hz range where subwoofer crossover points are most commonly set, and coarser 10 Hz steps above 100 Hz where the exact frequency matters less.

All user settings are stored as a byte array in SRAM and persisted to the D2-81431’s internal EEPROM via I2C:

ByteSettingDefaultMaxValidation reset
[0]Power Control010
[1]Night Mode010
[2]IR Device ID020
[4]Volume5010150
[5]Crossover28288
[6]Phase070
[7]Sound Mode020
[8]Speaker EQ050
[9]Mute011
[0xB]Lock / IR Dev ID030

The validation function (FUN_000076c4) runs at boot after loading settings from EEPROM. It range-checks every byte against the Max column — if a value exceeds its maximum, it is reset to the Validation Reset column value (which is not always the same as the default). This protects against EEPROM corruption causing out-of-range parameter values that could crash the DSP configuration functions.

Settings are not saved immediately when changed. The firmware uses a 200-tick (2-second) debounce delay:

  1. When any setting changes, settings_mark_dirty() (FUN_00003864) sets a dirty flag
  2. The auto-save function (FUN_00003884) runs every tick in the main loop
  3. If the dirty flag is set, it starts a 200-tick countdown
  4. If another setting changes during the countdown, the timer resets to 200
  5. When the countdown expires, the settings are enqueued to the I2C command ring buffer
  6. The ring buffer drains the write to the D2-81431’s EEPROM register

The 2-second debounce prevents excessive EEPROM writes when the user is scrolling through values with the rotary encoder. Without it, spinning the encoder through 20 volume steps would trigger 20 separate EEPROM write cycles. With the debounce, only the final value gets written.

The factory reset function (FUN_000049d8) resets all settings to their compiled-in defaults. The defaults represent a conservative startup state: volume at 50%, BYPASS sound mode, no night mode, FLAT EQ, phase at 0°, front panel power control, mute ON. The mute-on default is deliberate — the amp starts silent, requiring the user to unmute before audio passes.

P0.12 drives a status LED with an XOR toggle pattern. The toggle rate changes based on the amplifier’s power state:

StateToggle intervalLED period
Active (amplifier on)40 ticks400 ms (fast blink)
Standby (amplifier off)120 ticks1.2 seconds (slow blink)

The XOR toggle means the LED alternates between on and off with equal duty cycle — 200 ms on / 200 ms off in active mode, 600 ms on / 600 ms off in standby. This gives a visual indication of the amplifier’s state from across a rack room without needing to read the VFD.