Files
morningedition/fixwidth.py

113 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""
TM-T88V paper width fix tool.
Writes directly to /dev/usb/lp0, bypassing CUPS entirely.
Step 1: Direct USB test print (safe, no NV writes)
Step 2: NV paper-width reset to 80mm (writes to printer NV memory)
"""
import sys, time
ESC = b'\x1b'
GS = b'\x1d'
INIT = ESC + b'\x40'
FONT_A = ESC + b'\x4d\x00'
FONT_B = ESC + b'\x4d\x01'
SIZE_NORM = GS + b'\x21\x00'
SP_ZERO = ESC + b'\x20\x00'
# GS W 576 = full 80mm printable area (576 = 0x0240)
WIDTH_576 = GS + b'\x57\x40\x02'
# GS W 512
WIDTH_512 = GS + b'\x57\x00\x02'
CUT = GS + b'\x56\x00'
DEV = "/dev/usb/lp0"
RULER42 = "123456789|123456789|123456789|123456789|12"
RULER56 = "123456789|123456789|123456789|123456789|123456789|123456"
def write_dev(data: bytes):
with open(DEV, "wb") as f:
f.write(data)
def test_print():
"""Step 1 — safe diagnostic, no NV changes."""
body = (
"\n[DIRECT USB - Font A + GS W 576]\n"
f"{RULER42}\n"
"The quick brown fox jumps over the lazy dog\n"
"\n"
"[DIRECT USB - Font B + GS W 576]\n"
f"{RULER56}\n"
"The quick brown fox jumps over the lazy dog\n"
"\n"
).encode("ascii")
data = (INIT + SIZE_NORM + SP_ZERO + WIDTH_576 +
FONT_A + body +
b"\n\n" + CUT)
write_dev(data)
print("Test print sent directly via USB (no CUPS).")
print("Count the ruler chars on each line and report back.")
# ── NV paper-width commands ───────────────────────────────────────────────────
# GS ( E — Set customized value (persists in NV across power cycles)
# Format: GS ( E pL pH fn [data...]
# pL pH = little-endian length of (fn + data)
#
# TM-T88V firmware 30.xx:
# fn=2 : Set paper type
# data : 0x00 = 80mm/RP80, 0x01 = 58mm/RP58
#
# This writes to NV — takes effect after power cycle.
def gs_e(fn: int, data: bytes) -> bytes:
payload = bytes([fn]) + data
pL = len(payload) & 0xFF
pH = (len(payload) >> 8) & 0xFF
return GS + b'\x28\x45' + bytes([pL, pH]) + payload
NV_80MM = gs_e(0x02, b'\x00') # fn=2, param=0x00 → 80mm paper
NV_58MM = gs_e(0x02, b'\x01') # fn=2, param=0x01 → 58mm paper (for reference)
def nv_fix():
"""Step 2 — write 80mm paper width to NV memory, then test."""
print("Sending NV paper-width reset to 80mm...")
# Send the NV command alone first, then reinit and test
data = (
INIT +
NV_80MM + # set 80mm in NV
INIT + # re-init so new setting takes effect now
SIZE_NORM + SP_ZERO + WIDTH_576 + FONT_A +
(
"\n[NV SET: 80mm - if this is 42 chars wide, it worked]\n"
f"{RULER42}\n"
"The quick brown fox jumps over the lazy dog\n"
"\n"
).encode("ascii") +
b"\n\n" + CUT
)
write_dev(data)
print("NV write + test strip sent.")
print("If the ruler shows 42 chars: power-cycle the printer to confirm it sticks.")
print("If still 30 chars: the fn=2/0x00 command didn't apply; tell me and we'll try alternate byte sequences.")
if __name__ == "__main__":
cmd = sys.argv[1] if len(sys.argv) > 1 else "test"
try:
if cmd == "test":
test_print()
elif cmd == "fix":
nv_fix()
elif cmd == "fix58":
# Emergency restore to 58mm if needed
write_dev(INIT + NV_58MM + INIT + b"\n[restored to 58mm]\n\n" + CUT)
print("Restored to 58mm NV setting.")
else:
print("Usage: fixwidth.py [test|fix|fix58]")
except PermissionError:
print(f"Permission denied on {DEV}")
print(f"Run: sudo chmod a+rw {DEV} then retry")
except FileNotFoundError:
print(f"{DEV} not found — run: sudo modprobe usblp")