Close
0%
0%

PCL3 raster interpreter for Kodak Diconix 150

A 1986 thermal inkjet that speaks PCL because the interpreter lives inside the printer now. Any modern host prints to it with a stock driver

Similar projects worth following
0 followers
The Kodak Diconix 150 is a battery-powered portable thermal inkjet released in 1986 by
Diconix Inc. of Dayton, Ohio.
It speaks a fixed Epson-style ESC text command set and nothing else. Which means nothing made
this century can print to it.
DiKon is a NEW PCL3 firmware that updates the old ROM within this printer so it can print from modern systems in 2026, bridging 40 years of computing.

The Kodak Diconix 150 is a battery-powered portable thermal inkjet released in 1986 by Diconix Inc. of Dayton, Ohio. Kodak bought Diconix in 1988, which is why the machine wears a Kodak badge and the stock ROM prints "A KODAK COMPANY" on its self-test page.

The board is silkscreened UK-EP01B MAIN CONTROL PWB. On it is a NEC D78C10G at 11.0592 MHz carrying a date code of 8604EK, which is to say it was made in early 1986 and has been sitting there ever since. 32 KB of ROM in a socketed Fujitsu MBM27C256-25, 8 KB of SRAM, a Centronics port, and an HP 51604A ThinkJet head. Twelve nozzles, eight of them usable per pass, 96 dpi per pass. There is no ROM checksum anywhere on the boot path, which I verified before I touched anything, and which is the entire reason this project is possible.

It speaks a fixed Epson-style ESC text command set and nothing else. Which means nothing made this century can print to it. Windows will not offer you a driver, CUPS has no queue for it, and your phone has never heard of it.

There is a second reason I wanted this machine specifically. I grew up on one. From 1989 to about 1995 a Kodak-badged Diconix was the only printer in the house, and every graphic it ever printed for me came out at about two thirds size: three quarters tall, five eighths wide. That turns out to be a grid mismatch nobody had written down. The hardware lays dots at 96 or 192 dpi horizontal by 96 dpi vertical, per HP's own service manual for the 2225 ThinkJet engine. Epson's FX graphics standard assumes 60, 120 or 240 dpi across and 72 down. Nothing in the chain rescales, so vertical always lands at 72/96 and double-density horizontal lands at 120/192. Two different fractions on two axes, which is why the aspect looked squeezed as well as small. I spent six years assuming that was just how printers were. Fixing it thirty years later by writing the printer new firmware is the shape this project took.

What I did about that

I did not write it a driver. I wrote it new firmware.

DiKon is a from-scratch PCL3 raster interpreter in uPD78C10 assembly, patched into the stock Kodak ROM in space reclaimed from the resident fonts. The interpreter runs on the printer's own 8-bit CPU. 300 dpi PCL raster goes in the parallel port and gets decoded and re-interleaved on-chip to the head's native 192 dpi vertical by 1152-dot full-carriage grid.

The whole point of putting it in there instead of on a PC is that the host then needs nothing at all. Not a converter, not a spooler, not a print processor, not an install:

  • Windows 11 - the stock in-box HP DeskJet 500 driver
  • Linux / macOS - Gutenprint pcl-500 at 300 dpi, through CUPS
  • Android - NokoPrint, "HP DeskJet 500 (Gutenprint)" or "Generic PCL4", mono 300 dpi
  • Anything else - any generic PCL 3/4 mono 300 dpi raster driver

Always 300 x 300 dpi and mono. 150 dpi prints at half scale, legible but wrong size.

The Android row is the one I care about. A phone in your pocket printing to a printer built the year Top Gun came out, over a Centronics cable, with no app written for it by anybody.

Bone-stock hardware. No board modification, no piggyback, no daughtercard. Reflash the 27C256 or drop in a doubled W27C512 and it runs.

How it works

The stock ESC dispatch table at 0x196A gets its ESC* entry repointed at my parser at 0x2800. ESC& and ESC( are pointed at a swallow routine, because they are free on the plain 150 and harmless to consume. Six patched bytes in the table. Every other ESC handler stays stock, so the printer's native text path is untouched. The rest of DiKon is one blob living at 0x2800 to 0x2F28, in a ROM window that was proven unreferenced rather than merely looking empty.

The pipeline is:

ESC*  ->  M7STAR parser  ->  DISPATCH  ->  PROCESS_ROW  ->  column buffers  ->  EMIT  ->  stock ring                                          (decode + bit)   COLSA / COLSB     (walk-back)   THR / DTHR throttle

It never buffers a page. It processes one 16-row band at a time into 8 KB of RAM.

The interleave is the part I am proudest of. The head prints 8 usable rows per pass at 96 dpi. A band...

Read more »

02-memory-map.md

markdown - 7.70 kB - 08/21/2026 at 23:24

Download

07-driver-compatibility.md

markdown - 5.97 kB - 08/21/2026 at 23:24

Download

d150_dikon_v5i.ips

ips - 2.09 kB - 08/21/2026 at 23:23

Download

apply_patch.py

x-python - 6.71 kB - 08/21/2026 at 23:23

Download

MD5SUMS.txt

plain - 417.00 bytes - 08/21/2026 at 23:23

Download

  • 1 × Kodak Diconix 150 portable thermal inkjet printer (1986)
  • 1 × NEC D78C10G (uPD78C10) 8-bit MCU, QFP-64
  • 1 × HP 51604A ThinkJet printhead cartridge
  • 1 × Fujitsu MBM27C256-25 32 KB EPROM, DIP-28 (stock ROM)
  • 1 × Winbond W27C512 64 KB EEPROM, DIP-28 (recommended reflash chip)

View all 7 components

  • Why every picture came out two thirds size

    TheRND219 hours ago 0 comments

    Posting the thing that started this project, because it is the oldest open question I had and it took until now to answer it properly.

    I grew up on one of these. From 1989 to about 1995 a Kodak-badged Diconix was the only printer in the house: school papers, cards, Print Shop banners. Every single thing with a graphic in it came out at roughly two thirds size. Not cropped, not clipped, just small, floating in a sea of white margin. Plain text was fine. Anything else was two thirds, and the aspect always looked faintly squeezed on top of that.

    I was nine. I assumed that was just how printers were.

    The answer is in HP's own service manual for the ThinkJet 2225, which is the same print engine under a different badge. This family lays its dots on a fixed grid:

    96 or 192 dots per inch horizontal. 96 dots per inch vertical.

    Epson's FX graphics standard assumes something else entirely: 60, 120 or 240 dpi horizontal depending on which density command the software sends, and 72 dpi vertical, because an Epson 9-pin fires eight pins across a ninth of an inch. The printer faithfully places every dot it is handed, on its own grid, and nothing anywhere in the chain rescales.

    • Vertical: 72 requested into 96 actual = 3/4 height. Always, no exceptions.
    • Horizontal, double density, which was the common software choice: 120 into 192 = 5/8 width.

    Two different fractions on two axes. That is the two-thirds page, and that is also why the aspect looked wrong rather than merely small.

    DiKon does not emulate anything. It takes 300 dpi PCL3 raster and does the interleave to the head's native grid on-chip, so the geometry is correct by construction instead of by accident. Which means the specific annoyance that made me pick this project up is now a thing the firmware handles, thirty years after it first bothered me.

    Side-by-side prints of the same file, stock Epson mode versus DiKon, to follow.

  • The fix was already sitting in Kodak's firmware

    TheRND22 days ago 0 comments

    <p>After the brick, the self-test still printed garbage in four of its six sliding-ASCII diagnostic rows, because those rows render out of the two fonts my blob is sitting on.</p>
    <p>Turns out the stock ROM already ships a DIP-selected quality lock at 0x0ACB that forces every font class to one of the two fonts I did not touch. Making it unconditional is one byte, <code>0x0ACE: JR -> NOP</code>.</p>
    <p>Forty years later and whoever wrote this thing had already left me the exact lever I needed. v5i then puts the visual variety back a different way, by rewriting the class-to-parameter-block pointer table at 0x0AFF so every class resolves to an intact font base while the metrics still differ.</p>

  • How I bricked a printer with a self-test page

    TheRND22 days ago 0 comments

    The v5f banner ran to 0x3018. I had cleared that window two ways, an instruction-operand scan and a runtime read-watch, and both said it was free. Both were wrong.

    The font base addresses that reach into it live as data inside parameter blocks behind a pointer table at 0x0AFF, so no operand scan will ever see them, and my test jobs only ever selected the two font classes that do not point there. I had written over live glyph cells for @, A and B.

    Result: constant BUSY on every interface, a crash-reset loop every few seconds, garbage on the rare moments it held still. A dead scan plus an incomplete test equals a bricked printer.

    Nothing goes at or above 0x3000 now, and the build asserts it rather than trusting me to remember.

  • A single carriage return wedged the printer, and the simulator never noticed

    TheRND22 days ago 0 comments

    I prepended one carriage return to the emit path to force column-zero anchoring. On hardware that CR hit the stock CR handler at 0x1B48, which checks motion-in-flight before it checks buffer-empty, queued a pending print on an empty buffer, and made the next ESC L abort after its header. 224 raster bytes leaked into the text path and hard-wedged the machine.

    My stubbed simulator was perfectly happy with all of it. I had to build an unstubbed audit rig before I could see the thing at all, and then it reproduced instruction for instruction. One character.

    v3d and v3e both carry it. Do not burn either one.

View all 4 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates