Ovladač pro RS232 tiskárny ESCPOS.
Na jaře 2025 jsem si pořídil malou pokladní termotiskárnu Sanei Electric Inc. BL112 BT s rozhranním RS232 (a BlueTooth 2.0) s úmyslem připojit ji k počítači ZX Spectrum a tisknout na ní.
Kvalita tisku není nijak oslnivá, jednak je to dáno technologií, termopapíry, které mám, nejsou příliš kontrastní. Krom toho má tiskárna najeto pravděpodobně spoustu kilometrů papíru, protože některé pixely nefungují a důsledkem toho jsou bílé pruhy ve směru posuvu papíru. Ale tiskárnu jsem koupil velmi levně, nové se prodávají za cenu mnohonásobně vyšší (víc než 20x dráž) a to se mi nechtělo riskovat, dokud jsem si nebyl jistý úspěchem. Krom toho tiskárny tisknoucí na 112mm papír jsou méně obvyklé, většina účtenkových tiskáren tiskne na 80mm papír, to je pro ZX Spectrum příliš omezující.
Pochopitelně k připojení tiskárny je potřeba sériový port, jako základ jsem zvolil standardní softwarovou RS232 na AY-3-8912 s tím, že serializovat softwarově pomocí Z80 je náročnější a ovladač pro SIF s 16C650, nebo jiné sériáky mohu vytvořit kdykoli později.
LPRINT a LLIST u ve znakovém režimu
Toto byla nejjednodušší část, protože ovladač pro tisk na obecné textové tiskárně včetně detokenizace příkazů BASICu už jsem měl hotový, pouze jsem přidal variantu vysílající data rychlostí 115200bps. Detaily a ke stažení zde.
Tiskárna BL-112 nepotřebuje žádnou zvláštní inicializaci, ASCII znaky tiskne přímo. Moje je lokalizovaná a umí znakovou sadu CP852, takže na ní lze tisknout i česky, ale ovladač pro BASIC to nevyužívá, stejně tak neumí tisknout semigrafiku a UDF, protože to by vyžadovalo tisk v grafickém režimu. To přijde na řadu možná později. Oproti grafickému tisku je tisk prostého textu mnohem rychlejší než by tomu bylo v režimu grafickém, přenáší se násobně méně dat.
Grafický tisk z programu Desktop
Tady mi pomohl ub880d svým ovladačem, v němž použil stejný podprogram pro vysílání dat, původně od Martina1, jako používáme v různých úpravách i jinde a taky v něm vyřešil seskládání bitů ze zdrojové bitmapy do osmi trojic bytů, které se do tiskárny posílají v režimu emulace 24 jehličkové tiskárny.
Ale ovladač od ub880d byl příliš zjednodušený. Neumožňoval žádné nastavení, uměl tisknout pouze 2x2 body tiskárny na jeden pixel bitmapy z Desktopu a obsahoval drobnou chybku v inicializaci. Tiskárně je totiž potřeba před tiskem nastavit nulovou mezeru mezi řádky, jinak sama přidává mezery. Tuto chybu určitě měl ub880d v jiné verzi ovladače opravenou, soudě podle k tiskárně přiložených výtisků ukrytých v roli papíru, ale ke mě se dostala nejspíš těsně předchozí verze programu.
Já jsem chtěl, aby ovladač byl v přesně stejném stylu s nastavovacím menu jako byly ovladače od Proximy s Desktopem dodávané. A při té příležitosti jsem taky chtěl, aby se dalo něco nastavit, třeba velikost tisku. Nakonec se mi povedlo umožnit nastavování XSTEP hodnoty 1,2,3, nebo 4 body tiskárny na pixel a YSTEP 2 nebo 4 body na pixel. Tyto dvě hodnoty lze libovolně kombinovat. Zvětšovat tisk více než 4x nemá smysl, pixely jsou veliké, případné větší nápisy lze snadno řešit vložením obrázku, větším písmem atd...
Omezení YSTEP na pouze 2, nebo 4 body vertikálně je dáno tím, že se do tiskárny posílá vždy sloupec 24 bodů ve třech bytech jako by tiskárna byla jehličková krát šířka tisku na řádek. Do těchto 24 bodů se musí řádek z Desktopu vysoký 12 pixelů vejít celočíselně. To znamená buď celý řádek Desktopu naráz (YSTEP=2), nebo jeho horní a pak dolní půlku do dvou samostatných řádků tiskárny (YSTEP=4), ale nelze tiskárně poslat řádek nekompletní a pak čekat na další data, ani není k dispozici místo v RAM počítače na odložení tiskových dat pro příště.
V režimu emulace 24 jehličkové tiskárny lze na jeden řádek tisknout přesně 832 bodů a do nich se musí nějak celočíselně vejít pixely z předlohy, z toho zas vyplývá omezení šířky řádku v Desktopu na 768, 416, 272 a 208 pixelů. 768px protože Desktop víc zpracovat neumí. 416px je nejbližší hodnota k Proximou preferovanému rozlišení 480px. Není to ideální, staré textové soubory by možná bylo potřeba kvůli tomu přeformátovat, kdyby je někdo chtěl tisknout zrovna na této tiskárně, ale na tiskárnu tisknoucí pouze na 112mm široký papír to není tak zlé.
A protože zároveň chceme, aby program běžel tak rychle, jak je jen možné, protože tiskárna zpracovává data rychleji než je ZX Spectrum stihne připravovat a serializovat, tak je ovladač nepěknou přehlídkou rozvinutých cyklů a kompromisů. Nicméně podařilo se, vešlo se to do 1680 bytů a funguje to.
Ovladač se do Desktopu načítá v menu pod klávesovou zkratkou EXT+SS+K (EXT + plus) a potom "LOAD utility". Pásková verze obsahuje pouze tuto možnost a skok do BASICu, disketová verze obsahuje i všechny ostatní souborové operace. Nastavovací menu ovladače se v Desktopu vyvolá EXT+I, mezerníkem se vrátí do editoru. Chování menu by mělo být identické s originálními ovladači, protože i kód je stejný, kde to dávalo smysl. Klávesou O v nastavovacím menu lze ukončit stránku, což u tiskárny používající roli znamená, že jen vynuluje počítadlo vytisknutých řádků a odřádkuje. A nakonec tisk se spouští EXT+P, kde je možné zadat více kopií než výchozí jednu. Před spuštěním tisku samozřejmě musí být nastavené okraje tiskové oblasti, to znamená od kterého řádku textu do kterého stiskem EXT+O.
Grafický tisk obrázků - screenshot
Další výzvou je pochopitelně tisk screenshotů, neboli obsahu obrazovky. Martin1 se o to už úspěšně pokusil leč ovladač ani zdrojový kód v době psaní tohoto článku nezveřejnil (resp. neviděl jsem ani jedno) a tisk provádí na šířku (v orientaci landscape), což trochu omezuje možnosti ditheringu (3x3 body tiskárny na barevný pixel) a tím i čitelnost obrázku. Krom toho, podle fotek v jeho článku, hádám, že ovladač napsal pouze pro svůj sériový port (z nějakého důvodu matoucně taky nazvaný SIF i když není s původním kompatibilní).
Já jsem si nejprve na PC vyzkoušel, že tisk na výšku (na délku papíru) je možný a vypadá o něco lépe. Do 832 bodů tiskárny se totiž 192px vysoký obrázek vejde 4x a to usnadňuje dithering, ale zvětšuje objem dat, která je nutné do tiskárny poslat. Nikoli však objem dat na jeden tiskový řádek, což je 24x768 pixelů tiskárny a to se vejde i s řídícími kódy do 2310 bytů, což znamená, že na celou obrazovku se přenese 43*2310+inicializace 7 bytů = 99337 bytů.
Ovladač je opět složen z mnoha částečně rozvinutých cyklů, abych ušetřil množství registrů, počet taktů procesoru a minimalizoval počet zbytečných operací s daty. Je to samozřejmě na úkor velikosti ovladače, ale i tak jen o málo přesáhl 2kB paměti včetně zdvojené předlohy rastrů všech 16 odstínů pro levou a pravou půlku bytu. Pro jednoduchost volání z BASICu jsem ovladač umístil na adresu 63000, ale určitě by šel posunout až na 63400 a možná ještě o pár bytů výš. Jediná podmínka je, že předloha rastrů musí být zarovnaná na násobky 256.
Volba ditheringu jednoho obrazového pixelu na 4x4 černobílé pixely tiskárny hodně program usnadnila a zrychlila. Přesto tiskárna mezi řádky krátký okamžik čeká na data z počítače a tisk na zlomek sekundy pozastavuje. To se bohužel projevuje lehounce světlejšími horizontálními (příčnými) pruhy a zřejmě bude velmi záležet na použité tiskárně i citlivosti termopapíru jestli a jak moc bude efekt výrazný. Bude-li serializovat data UART místo, aby to dělal CPU, tak se velmi pravděpodobně ušetří dost času, aby bylo i toto malé zpoždění zcela eliminováno.
Výrazné podélné pruhy jsou způsobené opotřebením tiskárny a několika nefunkčními segmenty tiskové hlavy. S tím nic udělat nedokážu, leda sehnat tiskárnu jinou, méně opotřebovanou.
Způsob převodu z barevných pixelů na monochromatický rastr viz následující obrázek.
Předloha rastru je v 8x8 pixelech, rozdělená na dvě půlky, celkem zabírá 8*16*2=256 bytů a vybírá se 1/4 z předlohy podle toho, jestli souřadnice X/Y jsou liché, nebo sudé. Z toho se sestaví 12 bytů ve kterých je ditherovaných 6 barevných pixelů a ty se pošlou do tiskárny, to celé se opakuje pro celý sloupec 6 pixelů široký a 192px vysoký. Při tisku dalšího sloupce se berou z obrazovky pixely v jiné kombinaci a to ještě dvakrát pro další sloupce 6px široké než se tisk opakuje. Po vytištění 240px se tisknou další dva sloupce 6px široké a poslední na který zbyly jen 4px a zbývající dva se nahrazují jasnou bílou. To mi dovolilo zpracovat data sekvenčně bez zbytečných podmínek a zdržujících odskoků. Víc detailů viz komentáře ve zdrojovém kódu programu.
Rastr samotný jsem získal ze screenshotu se všemi barvami z emulátoru Fuse a následným převodem na jednobitový rastr v Gimpu. Potom jsem rastr nepatrně upravil, aby nikde nebyly zřetelné přechody, mírně zarovnal a to je vše. Teoreticky by se ovladač mohl nechat přizpůsobit i změnám palety ULA+, pokud by si někdo dal práci s vytvářením rastrů podle aktuální palety (dokud se počet barev vejde do 16 zobrazených). Já to v úmyslu nemám.
Průběh a rychlost tisku ukazuje toto video: https://www.youtube.com/watch?v=Skh_QopHgXc. Myslím, že to je docela přijatelné vzhledem k možnostem počítače, způsobu přenosu a rozlišení 203dpi v emulaci 24 jehličkové tiskárny ESCPOS.
Download
- 2025-05-17_printer_driver_escpos_bl112_desktop.tar.bz2 - ovladač pro Desktop vč. zdrojového kódu
- 2025-05-17_printer_driver_escpos_bl112_screencopy.tar.bz2 - ovladač pro tisk screenshotů vč. zdrojového kódu
- datasheet_thermal_printer_BL-112_en.pdf - leták se základními parametry tiskárny
- ESCPOS_command_manual.pdf - obecná referenční příručka s popisem příkazů ESC/POS tiskáren
Historie změn článku
- 2025-05-17 - zveřejněno