VFD hacking (again)

By | October 24, 2018

Three years ago I have posted an article about reverse engineering a large surplus VFD module that had no documentation available. Well, it is time to do some more hacking!

I have attended the HAM radio meetup at La Louvière, Belgium this year again. Lot of people, lots of all kinds of gear there but what has caught my eye was a box full of display modules pulled out of some equipment:

The display modules – the bottom darker one seems to be a newer revision

Closer look revealed the following:

  • Noritake iTron 2×16 character VFD module with a 14 pin connector that looked very much like the one used by the common cheap LCD character displays using the Hitachi HD44780 controller.
  • ATMega128 MCU with an unusual 7.3728MHz crystal
  • A serial interface with a transciever chip, likely RS485
  • Some LEDs, 5 buttons set up as a navigation cross
  • 5€ for each module – a steal. The VFD alone is worth like 20€ and the ATMega128 costs around 8-9€ in quantity.

Board Inventory

These modules seem to be custom jobs, the silkscreen shows the company name Livetools Technology – a Swiss company building video and audio gear for television. The older module is labeled “DIX-V100”, the newer one “DIX-V120” but Google doesn’t show anything relevant. The boards seem to come from an older obsolete product, possibly an older version of this, likely made around 2004 and 2006, based on the date codes.

This is what is on the boards (differences between the revisions will be specifically noted):

  • Noritake iTron CU16025ECPB-W6J VFD module (datasheet)
  • ATMega128L microcontroller, in a TQFP64 package (datasheet), the lockbits are set, so there is no way to reverse engineer the original communication protocol
  • 7.3728MHz SMD crystal (frequency is perfectly divisible by the common serial baudrates!)
  • MAX3075 (or SP3075EE) RS485/RS422 transciever connected to one of the MCU UARTs.
  • Adjustable voltage regulator, in a SOT-23 package, set to 3.3V
  • 5 buttons, hardware debounced using an RC filter, active low
  • 4 LEDs (three on a side labeled “Err”, “Warn”, “OK”, one next to the buttons labeled “C” – the later revision boards don’t have this one populated), LEDs are active low.
  • 6 pin 0.05″ (1.27mm) pitch ISP connector (through hole on the older revision, SMD on the new one)
  • 4 pin 0.05″ (1.27mm) pitch connector for power and the serial line
  • 10 pin 0.05″ (1.27mm) pitch expansion connector (unpopulated on the newer revision)
Backside of the board
Running module

From the design of the board it is quite obvious that cutting BOM costs was not really an issue here – the board is 4 layers, the ATMega128L is a huge overkill for the task, the VFD module is not cheap neither.

There are however some odd design choices. The MCU is powered from the 3.3V rail (and thus not 5V tolerant!) but the VFD is a 5V part (even though it works at 3.3V already). Also the LEDs are powered from the 5V rail – the consequence is that when the MCU pin is set high, the LED will still faintly glow (5V – 3.0V = 2V voltage difference across the LEDs, enough to turn it on). That may not be too healthy for the MCU nor for the voltage regulator that suddenly has to sink current. No idea why the 3.3V regulator was needed – everything on that board is 5V capable.

Also the RS485 is quite an overkill for what this has likely been used for but maybe they needed a multidrop bus. I have desoldered the transciever using hot air on one of my modules and bridged the pads directly across to be able to use it with a normal serial port.

Making it useful again

The board is very easy to use, there is plenty of memory available in the MCU for any kind of project. The simplest and fastest way is to write a new firmware using Arduino – it is bloated but performance and used flash are really not a concern here.


  • Arduino 1.8.7
  • MegaCore (install through the Arduino board manager as described here, regular Arduino doesn’t support ATMega128)
  • LiquidCrystal library (standard part of Arduino)

MegaCore doesn’t support the atypical clock frequency used by this board, so a new entry in the boards.txt file for the MegaCore needs to be made.

In Linux:


In Windows:

C:\Documents and Settings\<username>\Local Settings\Application Data\Arduino15\packages\MegaCore\hardware\avr\2.0.1\boards.txt


C:\Users\<username>\Local Settings\Application Data\Arduino15\packages\MegaCore\hardware\avr\2.0.1\boards.txt

Add the following text:

128.menu.clock.7_3728MHz_external=7.328 MHz external

Now it should be possible to select the ATMega128 board and the correct clock speed from the menu. I haven’t tried to burn the bootloader, it is possible that farther modifications are needed for that.

Programming notes

  • The VFD works with the standard LiquidCrystal library. After the initialization, it is necessary to wait for about 200ms before sending data to it or part of the data will be missed.
  • As mentioned above, the LED are powered from the 5V rail so even if the MCU pin is high, they will still glow. Set the pin to input instead.
  • The serial port used is Serial1


The following tables indicate both the Atmel pin names and also the Arduino pin numbers, as used by the MegaCore:

MegaCore pinout for ATMega128

Board connections

MCU connections on the board (larger version)

ISP connector

1 Vcc

Serial connector

3Differential data
4Differential data

Expansion connector

PinMCU pin (Arduino pin)
2PF0 (45)
3PF1 (46)
4PF2 (47)
5PF3 (48)
6PF4 (49)
7PF5 (50)
8PF6 (51)
9PF7 (52)

VFD connections

PinSignalMCU Pin (Arduino pin)
4RSPG0 (26)
5R/WPG1 (27)
6EPG2 (36)
7D0PC0 (28)
8D1PC1 (29)
9D2PC2 (30)
10D3PC3 (31)
11D4PC4 (32)
12D5PC5 (33)
13D6PC6 (34)
14D7PC7 (35)

Other MCU connections

MCU Pin (Arduino pin)
PA0 (44)
LED WrnPA1 (43)
LED ErrPA2 (42)
LED CPA3 (41)
Button LeftPE4 (4)
Button UpPE5 (5)
Button RightPE6 (6)
Button DownPE7 (7)
Button EnterPD1 (19)
RxPD2 (20, RXD1)
TxPD3 (21, TXD1)
RxE (RS485 transciever bus control)PD4 (22)
TxE (RS484 transciever bus control)PD5 (23)

Leave a Reply

Your email address will not be published. Required fields are marked *