Tuesday, March 7, 2023

Wireless printing, over a serial port!

I know printing ink onto physical pieces of paper is not exactly as popular as it once was, but I still often find it useful.  

Printouts are great!  Each page is like a tablet screen, only the information doesn't change, it's super light, and doesn't need recharging.  When I'm doing some project that requires constantly referencing different pages of information, having it all laid out at once saves me time.

Anyway, this is to explain why I wanted to be able to send print jobs from my Commodore and Amiga branded computers to my modern network laser printer.  I do have enough Commodore printers to give each machine their own, but lack the space, and the ribbons.

So what was the answer to this problem?  ....  Wait for it....



Serial WiFi Modems, of course!  Everything from the 8-bits on up to the Amiga 4000 has a serial port, and both have native kernal support for it.

The problem was on the modem side.  I knew there was no way I was going to be able to fit actual printer drivers, data converters, or anything similar into those tiny ESP chips.  I would have to look for an intermediary.


The answer was IPP and CUPS.   CUPS is a print service/daemon that can be run on a myriad of *nix like devices, from a full PC to a Raspberry Pi, all of which are likely to support a useful printer driver.  IPP is the protocol that the WiFi modem would use to communicate with the CUPS server over the network.

My first step, however, was to install a printer driver onto some device.  I won't go into that, as it will differ from person to person.  In my case, I needed a Linux driver for a HP Laser Jet, which I found here


Once that was all working,  I installed the CUPS server/daemon on the same Linux PC.   I won't go into this either, but after doing this, I made CUPS aware of my printer.  When this was done, entering   lpstat -l -e   gave me the following:


This got me half of the way there.   Other devices in my house could now send print jobs to this CUPS server, which would then queue and process the job until I had a physical piece of paper.   

Next up was to teach the Zimodem firmware, which runs in our WiFi modems, how to speak IPP.

The primary mechanism users would have to sending print jobs to their modem is via the AT+PRINT command.   This command comes in three flavors:

AT+PRINTA:<host>:<port>/<path>

AT+PRINTP:<host>:<port>/<path>

AT+PRINTR:<host>:<port>/<path>

The arguments are the actual IPP url,  In my case it looks like AT+PRINTA:192.168.1.10:631/printers/HP_ColorLaserJet_MFP_M278-M281

The three variations are for printing, respectively, A)scii data, P)etscii data, or R)aw data (typically an image, or postscript, or pdf file).

The user would type one of the command variations into their modem terminal, press RETURN, and then follow this immediately with the data they want printed.  When done, the user can use the  normal <pause>+++<pause> method to begin printing, or just wait for a timeout.

Subsequent AT+PRINT commands may omit the host/url, especially if the current modem configuration was saved to flash with AT&W.


This was enough to be immediately useful.  On my C64, I wrote a long silly BASIC program, and then printed it out by entering:


OPEN5,2,0,CHR$(8):PRINT#5,"AT+PRINTP":CMD5:LIST

So, with Commodore 8-bit printing ability out of the way, I turned my attention to the Amiga.  For awhile, I entertained the thought of writing a full blown Amiga printer driver.  The documentation I found, however, was insufficient to allow me to make much progress.

But then I discovered that the Amiga has a PostScript printer driver, especially in later AmigaOS versions.  PostScript is a type of text encoding that allows everything from documents to pictures to be rendered in a platform-independent way.  Amigas also support sending print jobs to its serial port transparently to applications.  And to cap it all off, CUPS supports this ancient encoding natively, so it was a perfect match all around.


The only problem was getting the Amiga to send the required AT+PRINTR command before each job. Not finding an easy answer there, I decided to have the WiFi modem firmware detect when a PostScript document is being dumped into the modem, and then automatically go into raw printing mode.  PostScript documents all start with something like %!PS, so that was easy enough.


The results were, as you can see, fantastic!  From the other side of my house, on a lowly Amiga 600, I was able to print these pictures directly from DPaint to my network printer.

The last platform I wanted to tackle was WYSIWYG printing via GEOS on my 8-bit C64 and C128 computers.  

Luckily, the documentation for GEOS printer drivers is fantastic and very straight forward.  

That isn't to say it was a trivial project, though.  Unlike AmigaOS, GEOS has no native support for the serial port, so RS232 bit-banging would need to be written from scratch.  An even bigger problem was the image format.  There would be no way to generate PostScript in the tiny space allowed.


To the rescue came an old SunOS image format called RAS.  The CUPS specification supports this format natively, and it is both uncompressed, and raster-based.  It's almost a wonder that GEOS didn't use this format itself, as it is absolutely perfect.


So, I coded up a new GEOS printer driver, which I called "ras4c64net", which converts GEOS bitmap printing data to the RAS format on-the-fly and sends it to the WiFi Modem at 4800 baud (making it technically faster than using the C64's own IEC port).  


The results, as you can see below, came out fantastic.


So, that wraps it up!  

Serial-based WiFi modems are often designed, built, and sold to do only one thing: connect to online BBSes.   That's such a narrow vision though!  From unix terminals, to IRC, FTP, WGET, etc clients, and now as printer interfaces, WiFi modems are wonderful tools for keeping our old machines relevant and useful!