Read docs/technical/developer-guide.md first for the current CUPS/PDF pipeline, correct crop math, and debugging checklist. This file keeps hardware/protocol facts and historical notes that are easy to misremember.
- Resolution: 203 DPI (8 dots per mm).
- Print Head Width: 576 dots (exactly 80mm).
- Protocol: It uses standard ESC/POS (
GS v 0raster bit image) but requires specific wrapper bytes:- Header:
0x02(STX),0x1B 0x40(Init),0x1D 0x76 0x30 0x00(Print Raster) +WidthL WidthH HeightL HeightH. - Footer:
0x1B 0x43 0x01,0x1B 0x6C 0x00,0x1B 0x50,0x1B 0x69(Cut),0x03(ETX).
- Header:
- NO HARDWARE MIRRORING: A raw byte test proved that the printer does not mirror the X-axis natively. Byte 0, Bit 7 (the MSB) prints on the absolute left-hand side of the paper (non-sticky edge). Byte 71, Bit 0 prints on the absolute right-hand side of the paper.
- The "Sideways" Concept: The physical roll feeds out with the sticky adhesive running continuously along the RIGHT edge. Because users hold the note with the sticky edge on the right/top, they want to read the text running along the length of the roll. Therefore, ALL text must be rotated 90 degrees Clockwise relative to the print head so that it prints Top-to-Bottom.
- Terminal /
lpron raw text: macOS often routes throughcgtexttopdf. For sticky media that filter can place glyphs in awkward relation to the page box; the driver’s auto-crop then sees little or no ink. The fun_scripts path builds PDF/PNG another way to avoid that sandbox/font pipeline. - BBEdit and most GUI apps: Do not send raw text to the filter — they spool
application/pdf. Jobs often includeColorModel=Grayin the options. Two separate issues caused “blank” output in production:- Raster: Drawing some Quartz PDFs only into DeviceGray can yield an empty first pass; the fix is DeviceRGB → flatten to gray (see developer guide).
- Crop:
CGImage.cropping(to:)uses Quartz bottom-left coordinates; buffer row 0 is the bottom of the bitmap. Applying an extra Y “flip” for crop moved the rectangle into white margins on US Letter–sized pages while body copy sat lower on the sheet — physically blank output. Correct crop usesy: minYin buffer row space (after padding/clamp), not an inverted formula.
Y-flips, scaleBy(y: -1), and “invert crop Y” snippets are context-specific. A recipe that fixes one stage can break another. When changing rotation or crop:
- Re-run
bash run_print_gates.shandbash preflight_pdf.shon a Letter-sized PDF exported from BBEdit (orcupsfilterwith-o ColorModel=Gray), not only the small built-in test PDF. - Use
NEMONIC_DEBUG_DIRand inspectrendered,cropped, andfinal-rasterPNGs when ink disappears.
The print head is exactly 576 dots (80mm) wide. If you scale text to exactly 576 dots, the top of the letters will print directly onto the sticky adhesive and get clipped by the mechanical edge of the printer.
- Always restrict
printableWidthto ~540 dots, leaving ~36 dots (~4.5mm) of pure white space on the right-hand (sticky) edge.