# 07 — Driver Compatibility Contract

*Part of **DiKon** — PCL3 raster firmware for the Kodak Diconix 150, by RND2 Labs / TheRND2 ([thernd2.com/diconix](https://thernd2.com/diconix)) — see [the repository README](../README.md).
Firmware: **M7 v5** (`d150_m7v5.bin` MD5 `fe9215abec1f8c4f4f407867302fa898`; burn image
`d150_m7v5_W27C512.bin` MD5 `2f2a10f449f522df2500effe616f5f67`). Project: TheRND2 / RND2 Labs,
thernd2.com/diconix.*

This is the contract for pointing ANY OS / driver at the modified Diconix 150. The printer is
nominally a PCL3-class inkjet; M7 implements a hardened PCL **raster** parser on top of the
stock Epson-compatible text engine. **What matters is the raster encoding a driver emits, not
the PCL level on the box.**

## The four knobs (set these and it works)
1. **Compression mode 0 (raw) or 2 (PCL TIFF/packbits)** — `ESC*b0M` / `ESC*b2M`. **Not 1 or 3.**
2. **300 dpi**, single-plane **monochrome**.
3. **Rows < 2000 bytes** each (`ESC*b<n>W`, n ≤ 2000).
4. **End the job with `ESC*rB`** — the end-of-job flush that prints the last partial band.

## WORKS (renders ink, correct layout)
Any driver whose output satisfies ALL of:
- **PCL raster framing** `ESC*r1A` (or `*r#A`) … rows … **`ESC*rB`** end. The job must end
  with `ESC*rB`.
- **Compression mode 0 or 2** (`ESC*b0M` / `ESC*b2M`).
- **Row data** `ESC*b<n>W`, n ≤ 2000 bytes.
- **Blank-line runs** `ESC*b<n>Y` — advance vertical position correctly (v5).
- **300 dpi single-plane mono** (native dot pitch after the fixed 300-dpi→carriage mapping;
  rows wider than 2304 dots are right-clipped at the carriage).
- Text, if any, via the stock Epson escape/text path (PCL raster jobs normally contain none).

**Verified WORKS:**
- **Gutenprint `pcl-500` (HP DeskJet 500)** at 300 dpi (and Draft/150 dpi*), incl. the
  `rastertogutenprint` CUPS filter — the engine used by **NokoPrint (Android)**, Linux CUPS,
  and macOS Gutenprint. (*150 dpi prints at half scale — see IGNORED.)
- **Windows DJ500 driver** (Win11, regression-tested every firmware rev).
- **Generic PCL4 mono 300 dpi** drivers (mode 0/2, no delta) — incl. NokoPrint's "Generic PCL4".

## SAFE-BUT-BLANK (consumed cleanly, prints nothing, never garbage, never wedges)
- **Compression modes 1 and 3 (delta row)** and any other `*b#M` value: rows consumed
  count-based and printed blank; vertical spacing stays correct; a later `*b0M`/`*b2M` recovers.
- **Color-plane data `ESC*b<n>V`** (uppercase V): discarded byte-exact. If the driver sends K
  as the final `W` plane, K still prints.

## IGNORED (consumed, no effect — pre-render content into raster rows)
- `ESC*p#X/#Y` cursor positioning · `ESC*t#R` resolutions ≠ 300 (dot pitch is fixed at the
  300-dpi mapping, so 150 dpi prints at half size — legible, wrong scale; use 300).
- `ESC&l…` page format, `ESC&a…` positioning, `ESC&k…`, `ESC(…` fonts/symbol sets: swallowed.
- `ESC*r#S/#T` width/height, `*r#Q/*o#Q/*o#D` quality/shingling/depletion.
- Any `ESC*<group>` with a lowercase group letter: parameters parsed and dropped; a final
  `W`/`V` payload consumed byte-exact (v5) — nothing leaks.

## AVOID / NOTES
- **Color DeskJet 500C/550C ("cDeskJet") drivers**: compact plane encoding `ESC*b#v<data>`
  (lowercase `v` carrying binary) is indistinguishable from a parameter to any grammar parser;
  the binary floods the text path as garbage glyphs and can stall the job. Use mono DJ500 or
  generic PCL4.
- **PCL5+** (macros, fonts, HP-GL/2 `ESC%#B`): untested; HP-GL/2 contains non-escape command
  text that would print as glyphs. Don't send PCL5 streams.
- **First-byte-loss race**: if the host fires the instant it opens the port while the printer
  is mid-init, the first byte can be lost (the leading `ESC` drops → its partner prints as one
  stray glyph, first band may misparse, then self-heals at the next `ESC`). **Release the job
  only when the printer is idle/ready.** This is operational, not a firmware bug.
- Always pick **300×300 dpi, mono/grayscale**. Paper eject relies on the raster band cadence
  (`ESC J` units); the `&l0H` eject is ignored, but the `*rB` flush already feeds past the last band.

**Recommended known-good setups:** Windows → HP DeskJet 500 driver. Linux/CUPS & macOS →
Gutenprint `pcl-500` @300 dpi. Android → NokoPrint "HP DeskJet 500 (Gutenprint)" (after v5) or
"Generic PCL4" (mono, 300 dpi, no delta). Anything else → any generic PCL 3/4 mono 300 dpi raster driver.

## Why "generic PCL4" works on a nominally PCL3 printer
M7 implements the raster-graphics core that PCL3 and PCL4 **share** — `*rA`/`*rB` framing,
`*b#M` mode select (0/2), `*b#W` rows, `*b#Y` blank lines — and safely ignores everything else.
What a PCL "level" adds is mostly fonts, macros and positioning that a **raster** driver never
uses: the driver pre-renders the whole page and ships it as compressed raster rows. So
compatibility is decided by the **raster encoding** (compression 0/2, row width ≤2000, mono,
300 dpi), not the PCL label. A generic "PCL4 mono" driver emitting mode-0/2 raster is, at the
byte level this printer sees, indistinguishable from the DJ500's own PCL3 output.

## Provenance
Real `rastertogutenprint.5.3` (Gutenprint 5.3.3) `pcl-500` streams at 300/150/Draft dpi,
replayed instruction-level through the audited firmware rig: 100% consumption, zero text-path
leaks, zero invariant violations; renders match ghostscript's own raster of the same page.
Gutenprint `print-pcl.c` audit: DJ500 = `PCL_PRINTER_DJ|TIFF|BLANKLINE`, mono; always
`\033*b2M` + `pcl_mode2()` rows + `\033*b%dY` blanks + `\033*rB\033&l0H\033E`; at ≥300 dpi
additionally `\033*r2Q \033*o2Q \033*o5D` (the v4b garbage source, fixed in v5). **No delta-row
encoder exists in the driver.** Windows DJ500 captures + the full adversarial corpus regressed
byte-identical to the hardware-proven v4b behavior.

*Firmware history: v4b printed Gutenprint/NokoPrint-DJ500 jobs with 4 garbage chars per page
(`2Q5D`) and collapsed blank gaps; v5 fixes both and adds binary-payload discard for unknown
groups. v4b remains the fallback chip.*
