The Verifone ZON Jr XL

Joe's Projects
DIY pressure mat

Single Board Relay Computer

Hacking the Verifone ZON Jr XL

Acoustic Delay Line Memory

Text Editor Performance Comparison


The Verifone ZON Jr XL

Long ago I tried to start a business and wanted to accept credit card transactions, so I leased a credit card terminal from CardService International.  The business went nowhere, but I leased this machine long enough so that eventually I came to own it.  I'm sure it cost me at least $1500 in lease payments.

Now, many years later, I'm ready to get rid of it.  I checked eBay: they sell for only $10- not even worth the effort to sell it.  On the other hand, they are so cheap that they could have some value if they are easy to re-purpose through hacking.  After all, they have a nice keypad and an alphanumeric vacuum fluorescent display.

It also has an 8-pin DIN connector on the back, I think for a printer:

I'd better take it apart before I dump it...

So what's inside of it?

Two screws on the back remove the back cover:

(click to enlarge)

The circuit board can then be pulled straight up (no screws).  There is a 20-pin SIP connector connecting the main board to a keypad/display board:

(click to enlarge)

A close look at the main board and key/display board reveal 80's technology: all common through-hole chips:

(click to enlarge)

(click to enlarge)

Reverse engineering is going to be easy!

Parts List

So what do we have? The main board has these chips:
  • 7.15909 MHz crystal (twice the NTSC color burst frequency)
  • Y2, a 32768 Hz crystal
  • a 74HC04 hex inverter
  • an MC1489 RS-232 receiver
  • U1, an OKI M6242 real time clock
  • U2, a 74HC942 300 baud modem
  • U3, a 74HC10 triple NAND gate
  • U4, a 27C256 32 KB EEPROM
  • U5 and U6: M5M5165P 8 KB static RAM chips
  • U7, a Z80A CPU
  • U9, a CD4052 dual 4-input analog MUX
  • U10, a 74HC138 3-bit decoder
  • U11, a Z80 CTC (Counter Timer Circuit)
  • U12 and U15: 74HC259 8-bit addressable latch
  • U13 an TL074CN quad OP-Amp
  • U14 an 74HC74 dual flip-flop
  • U16 a Z80 PIO (Parallel I/O controller)
  • U17 a UM95089 touch-tone generator
  • a L387A 5V regulator with reset generator
  • a 79L05 -5V regulator
  • Q1, Q2 and Q3: 2N3904 NPN transistors
  • A battery (dead)
The keypad / display board has these chips:
  • U3, a 10937P-40 Vacuum fluorescent driver
  • U2 a TL074CN quad OP-Amp
  • A piezo speaker
  • High voltage generator circuit for the vacuum fluorescent display (it's got to have one, plus the round inductor near the top is a dead give-away).
Cool! It's a classic Z-80 system and the datasheet for every chip is available on the web.  This is an easily hackable device.

 Memory Map

An hour poking around with a continuity checker reveals the memory map.  The 74HC10 and 74HC04 are used to make a simple address decoder for the memory space:
  • U4 27C256 EPROM: 0x0000 - 0x7FFF (32 KB)
  • U5 M5M5165P static RAM: 0xC000 - 0xFFFF (8 KB aliased twice)
  • U6 M5M5165P static RAM: 0x8000 - 0xBFFF (8 KB aliased twice)
The 74HC138 is the decoder for the I/O ports:
  • 0x00 Z80 CTC (with CS0 connected to A0 and CS1 connected to A1)
    •  The CTC is connected as follows:
      • TRG0 (pin 23) Not connected
      • TO0 (pin 7) Connected to TRG1
      • TRG1 (pin 22) Connected to TO0
      • TO1 (pin 8) Connected to clock pin of second flip-flop of the 74HC7, which drives speaker
      • TRG2 (pin 21) Not connected
      • TO2 (pin 9) Connected to TRG3
      • TRG3 (pin 20) Connected to TO2
  • 0x20 Z80 PIO (with C/~D connected to A0 and B/~A connected to A1)
    •  The PIO is connected as follows:
      • A0 (pin 15) Keypad row 0 (top row)
      • A1 (pin 14) Keypad row 1
      • A2 (pin 13) Keypad row 2
      • A3 (pin 12) Keypad row 3
      • A4 (pin 10) Transmit data to modem and DIN connector
      • A5 (pin 9) Carrier detect on 74HC942 modem
      • A6 (pin 8) To pin 6 of the MC1489.  Pin 4 is connected to the DIN connector.  My guess is that this is used for flow control.
      • A7 (pin 7) To pin 10 of the 74HC04.  Pin 11 (the input) is connected to the tape head amplifier for reading the magnetic strip.
      • ARDY (pin 18) Not connected
      • ~ASTB (pin 16) Not connected
      • B0 (pin 27) ~C1 of the touch-tone chip
      • B1 (pin 28) ~C2 of the touch-tone chip
      • B2 (pin 29) ~C3 of the touch-tone chip
      • B3 (pin 30) ~R1 of the touch-tone chip
      • B4 (pin 31) ~R2 of the touch-tone chip
      • B5 (pin 32) ~R3 of the touch-tone chip
      • B6 (pin 33) ~R4 of the touch-tone chip
      • B7 (pin 34) Receive data from modem and DIN connector
      • BRDY (pin 21) Not connected
      • ~BSTB (pin 17) Not connected
  • 0x40 U15 74HC259 (8-bit output port)
    • D input is connected to A0
    • S0 is connected to A1
    • S1 is connected to A2
    • S2 is connected to A3
    • So it means write to an even location to clear a bit or write to the next higher odd location to set it
    • The 8 output bits are connected as follows:
      • Q0 (pin 4, port 0x40) Keypad column 0 (left-most)
      • Q1 (pin 5, port 0x42) Keypad column 1
      • Q2 (pin 6, port 0x44) Keypad column 2
      • Q3 (pin 7, port 0x46) Keypad column 3
      • Q4 (pin 9, port 0x48) Goes to base of Q2.  Emitter of Q2 goes to opto-isolator U20 (I think).  This controls some part of the modem circuit.
      • Q5 (pin 10, port 0x4A) Clock signal for vacuum fluorescent display
      • Q6 (pin 11, port 0x4C) Data signal for vacuum fluorescent display
      • Q7 (pin 12, port 0x4E) Reset signal for vacuum fluorescent display.  When this bit is low, reset is asserted.
  • 0x60 U12 74HC259 (8-bit output port)
    • The 8 output bits are connected as follows:
      • Q0 (pin 4, port 0x60) to base of Q3.  Emitter of Q3 goes to opto-isolator U28.  This controls some part of the modem circuit.
      • Q1 (pin 5, port 0x62) to O/~A (Originate / Answer mode) pin of the 74HC942 modem
      • Q2 (pin 6, port 0x64) to "squelch transmitter" pin of 74HC942 modem
      • Q3 (pin 7, port 0x66) to base of Q1 which is connected to the "off hook" relay
      • Q4 (pin 9, port 0x68) to diode D3: I think something to do with the card reader
      • Q5 (pin 10, port 0x6A) to pin 10 (~preset2) of the 74HC74.  I think used to enable or disable speaker.
      • Q6 (pin 11, port 0x6C) to address A pin of CD4052 MUX
      • Q7 (pin 12, port 0x6E) to address B pin of CD4052 MUX
  • 0x80 M6242 (Real Time Clock)
  • 0xA0 unused
  • 0xC0 unused
  • 0xE0 unused


I should draw a schematic diagram for this thing, but it's so simple it's not really needed.  Instead, here is a description of each of the sub-circuits I could find:

SIP connector

Here is a pin-out of the SIP header which connects the main board to the keypad/display board.  Pin one is the one closest to the back of the machine:
  1. Keypad row 0 (top row)
  2. Row 1
  3. Row 2
  4. Row 3
  5. Keypad column 3 (right-most column)
  6. Column 2
  7. Column 1
  8. Column 0
  9. Not connected
  10. Not connected
  11. Not connected
  12. Card reader / tape head
  13. Display reset signal: active low
  14. Display data signal
  15. Display clock signal
  16. +5V
  17. Speaker
  18. -5V
  19. Speaker
  20. GND

Power Supply

It generates 5V and -5V with linear regulators.  The -5V is used to power the negative rail of the OP-AMPs.  The OP-AMP on the main board is used as a line driver for the data output pin of the DIN connector.  The OP-AMP on the keypad/display board is the tape-head amplifier for the card reader.


One half of the 74HC74 is used to divide the 7.15909 MHz oscillator (made with the crystal and some 74HC04 inverters) in half to make 3.579545 MHz for the main CPU clock and the touch-tone generator IC.


It's provided by the L387A voltage regulator.  It's connected to some chip select pins of the real time clock chip and the static RAM chips to help preserve their contents across reset.  The static RAM chips and the real time clock chip are powered (through a diode-OR gate) by both line power and battery power.


The piezo speaker is connected to the Q and ~Q outputs of second flip-flop in the 74HC74.  The ~Q output is connected to the D input, so this flip-flop is wired up as a divide by two counter.  The clock input is connected to the TO1 pin of the CTC: so you need to set up the CTC to generate the tone.  The ~preset input is connected to the Q5 output of U12.  I think the idea is to use this as an output enable bit so that you can leave the timer in the CTC always running.

Serial Port

A4 of the PIO is transmit data.  B7 is receive data.  I'm pretty sure that there was a schematic mistake with these assignments, since all of the other A pins are inputs and all of the other B pins are outputs.  Anyway, the idea is that software needs to provide a "bit-banged" UART using these pins.

These transmit and receive pins are connected to the CD4052 analog switch so that these same pins can be connected to different serial sources.  The B and A address pins of the CD4052 are connected to U12 Q6 and Q7.

  • B = 0, A = 0: serial lines connected to 74HC942 modem chip
  • B = 0, A = 1: serial lines connected to external DIN connector
  • B = 1, A = 0: serial lines connected to keypad/display board, but on this board they are wired to an unpopulated chip.  I don't know the purpose.
  • B = 1, A = 1: input line connected to an MC1489 received which is fed from an OP-AMP.  I don't know the purpose: maybe the OP-AMP is set up as a oscillator and this is some kind of test connection?  The output line is connected to an opto-isolator U18, so this has something to do with the modem, but I'm not sure what.

DIN connector

Here is the pin-out of the external connector:

  1. GND
  2. No Connect
  3. No Connect
  4. RS-232 level input to pin 4 of MC1489.  Pin 6 of MC1489 goes to A6 of PIO.  I think for flow control.
  5. RS-232 level input to pin 1 of MC1489.  Pin 3 of MC1489 goes to CD4052 MUX.  This is the serial data input.
  6. Connected to pin 7 of TL074.  Pin 6 of TL074 is connected to CD4052 MUX.  This is the serial data output.
  7. No connect
  8. Connected to 5V through a 47 ohm resistor.
The TL074 is being used as an RS-232 line driver. The output swings from 5V to -5V.


U15 pins Q0 - Q3 drive the columns.  A0 - A3 of the PIO are the row inputs.

Touch Tone Generator

B0 - B6 of the PIO are connected to the UM95089 touch tone generator chip.  This chip is designed to be connected to a telephone keypad, so the software has to simulate a key-press by asserting one row bit and one column bit (by pulling the bits low, all of the others should remain high).


To write to the display, you just send one entire line of 16 character to it.  Each character is sent as a byte in the range 0x00 - 0x3F, and the byte is serialized so that the MSB is sent first.  A falling clock edge should be provided for each bit.

From the datasheet, a reset pulse of at least 100 us needs to be provided.  After reset, you must wait another 100 us before writing any data.

The clock has a maximum high time of 20 us, so it must be kept normally low.  The minimum pulse width is 1 us.  After each byte transferred, you must wait 120 us.

The brightness of the display is controlled with the duty cycle command: 0xC0 - 0xFF, where 0xC0 is off and 0xFF is brightest.  The default brightness after reset is off, so we must send one of these commands to turn the display on.

The column to start writing to can be controlled with the commands 0xA0 - 0xAF.  The left-most column is 0xAF, next one is 0xA0, etc.

This is the character set from the data sheet:

"Hello, world!" program

We now have enough information to write our own programs for this hardware.

We could certainly write them in Z-80 assembly language, but there is a nice free C compiler available: the Small Device C Compiler: SDCC.

Here is a program to write a message to the display:

/* IoPorts for vacuum fluorescent display */
/* Note SDCC special directive to declare and locate IO ports */

__sfr __at 0x4a clr_clock;
__sfr __at 0x4b set_clock;

__sfr __at 0x4c clr_data;
__sfr __at 0x4d set_data;

__sfr __at 0x4e clr_reset;
__sfr __at 0x4f set_reset;

/* 7.54 us delay */

void delay()
        /* Do nothing: the call / ret sequence is 7.54 us */

/* At least 120 us */

void long_delay()
        unsigned char x;
        for (x = 0; x != 20; ++x)

/* Serialize one byte and send it to display */

void send_byte(unsigned char c)
        unsigned char scan = 0x80;
        do {
                if ((c & scan) != 0) {
                        set_data = 1;
                } else {
                        clr_data = 1;
                set_clock = 1;
                clr_clock = 1;  /* Falling edge when data is stable */
                scan >>= 1;
        } while(scan != 0);
        long_delay(); /* 120 us delay after each character sent */

/* Write entire line */

void send_msg(char *s)
        char x;

        send_byte(0xAF); /* Point to first digit */
        for (x = 0; x != 16; ++x) {
                if (*s != 0) {
                        send_byte(0x3F & *s++);
                } else {
                        send_byte(0x20); /* Spaces to end of line */
        send_byte(0xFF); /* Enable display, full brightness */

/* Initialize display */

void init_display()
        clr_clock = 1; /* Clock is normally low */
        clr_reset = 1; /* Assert reset */
        set_reset = 1; /* Release reset */


int main()
        send_msg("HELLO, WORLD!");
        return 0;

To compile, we use the following command:

sdcc -mz80 --xram-loc 0x8000 test.c

The '-mz80' sets the architecture to Z-80.  The '--xram-loc' sets the location of the RAM: the data section will be placed there.

The compiler will link with an included simple C startup program, "crt0.s" and generate an Intel Hex Format file which can be used in the EPROM programmer.  Crt0.s sets the stack to 0xFFFF and provides a jump instruction from the reset vector to the code.  It places "reti" instructions in the interrupt vectors.

If you have initialized global variables, they will be located in the data section (in RAM), and code will be generated to set their initial value.  This code is located along with the rest of the code in EPROM.

Old UV EPROM eraser and old MS-DOS based EPROM programmer
And here is the result:

(click to enlarge)

The '@'  at the end of the line is due to the fact that the ',' is not really a character: instead it turns out to be a modifier of the previous character.  You can see that the ',' is not using an entire character position.  So we intended to send 16 character, but really only sent 15, which left the last character left at its reset value.  Anyway, my send_msg function needs to account for this.  The '!' looks funny, but it's due to the font.