All trademarks and names are the property of their owners, notably (and with gratitude): Apple, Inc.; Artifex Software; American Telephone and Telegraph Company; authors prior of gdevadmp.c; Brian; Connor Taffe; Carpentier Pierre-Francois; Microsoft Corporation; NetBSD Foundation, The; Oracle; Regents of the University of California, The(;) and University of Michigan Research Systems UNIX Group.
The following guide is copyrighted 2020-2024 by Josh Moyer <JMoyer@NODOMAIN.NET.> All rights reserved.
Herein lays an outline to creating an integration between an Apple dot matrix printer and any modern UNIX or Windows system. This guide covers the following printers:
After completing the steps outlined here, you should be able to print to any of the above printers from a Windows or UNIX based host. Please note that, at present, the shipping driver for the printers only supports single-color, unidirectional printing. The soon to be released and updated driver supports color and bidirectional printing and other features.
The integration covered in this guide uses NetBSD as the Raster Image Processor (RIP) and spooler node that the printer will be connected to or driven by, depending on whether you are using a direct connection or if you are connecting with the ImageWriter II/LQ LocalTalk Option card. Other host operating systems can likely be utilized, too. However, the author noted that AppleTalk support in the Linux kernel seems to have been broken for some time now, based on experience while initially targeting Linux as the RIP and spooler node.
Apple, Inc. (née Apple Computer, Inc.) made the dot-matrix printers listed in the synopsis during the years in which that technology was viable in the market. They were all based originally on the C. Itoh (8510) mechanism and command set, both of which experienced proprietary evolutions at Apple. The Scribe, a thermal transfer printer also made by Apple, shares the same command set and some resolutions as the dot-matrix printers, but is only CMY in color mode. Eventually replaced by quieter, faster and higher quality laser and ink-jet based models, dot-matrix printers are known for their distinctive sound and also for their ability to handle multi-part forms and banners.
The author, having obtained an ImageWriter LQ from University of Washington Surplus and which was kept in storage for many years, was motivated to revive his LQ by way of his long-lived Epson Stylus Color RX500's death. Although ease was not expected, the author never anticipated the degree of difficulty encountered. Overall, it took 3-6 months of significant sustained effort to troubleshoot and integrate all of the disparate pieces -- and that was just for initial monochrome network support. Creating a color ghostscript driver from the existing sources proved very difficult and took about 3 years, due to combination of factors.
This guide is meant for users who are able to edit and manipulate files and directories and interpret diff output in a command-line environment.
To get started you'll need to have the following items:
For AppleTalk based operation (which also delivers an enhanced 230.4 kilobaud line rate versus a maximum of 19.2 kilobaud, resulting in enhanced printing speed), the following additional pieces are needed:
All of Apple's dot matrix printers are based on a common command set based on ecape sequences embedded in the output and are all backwards compatible, in theory. The non-LQ printers (at least) are all based on a family of C. Itoh print engines.
Introduced in 1982, The Apple Dot Matrix Printer featured a maximum resolution of 160x72 dpi. It also featured a parallel interface and tractor feed.
|SW1-87654321|SW2-87654321|
|------------|------------|
Introduced in late 1983, The ImageWriter featured a maximum resolution of 160x72dpi. It also featured a serial interface and tractor feed. A separate model with a 15" platen was also available.
Introduced in late 1985, The ImageWriter II featured a maximum resolution of 160x144dpi. It also featured a serial interface, tractor feed, 4 color CMYK printing, optional cut-sheet feeder and AppleTalk co-processor and interface and buffer memory cards. It won at least one award for its innovative and distinctive industrial design.
|SW1-12345678|SW2-123456|
|------------|-------*--|
* - (LocalTalk) Option Card On/Off
Introduced in mid-to-late 1987, The ImageWriter LQ featured a maximum resolution of 320x216dpi. It also featured a serial interface and tractor feed, 4 color CMYK printing, a 15" platen width, optional multi-bin cut-sheet feeder (with envelope attachment) and AppleTalk co-processor and interface and memory buffer cards. It was known for its high price ($1,399?.) Some have remarked on its (unwitnessed by the author) tendency to melt the print-head glue on large, strike-heavy jobs, as well as it's increased noise level -- as compared to the ImageWriter II.
|SW1-12345678|SW2-12345678|
|----00000110|----000*0000|
* - (LocalTalk) Option Card On/Off
Plug the printer in to a grounded outlet and make sure that you don't overload the electircal service circuit. Consult an electrician and the owner's manual for recommendations and power requirements, respectively.
Either a direct connection or a LocalTalk connector box (requires the optional Apple ImageWriter II/LQ LocalTalk Option co-processor card, with appropriate jumper settings) are supported.
In this guide we use NetBSD 9.0 (i386.)
Excellent (per-architecture) instructions already exist at the NetBSD website and, so, will not be covered here -- except to say that you should ensure you have enough free-space for the upcoming installation activities and also to make sure to install the pkgsrcs and that the network interface is configured.
Most versions (1 & 2) of the 3 ROM revisions in the ImageWriter II/LQ LocalTalk Option card have a bug in their DDP checksum calculation logic, so we gently and skillfully modify (read: brutally hack) the kernel to disable DDP checksum generation on a system-wide basis. Caveat emptor.
Download and untar the source for the kernel so that a custom kernel can be compiled with the DDP checksum verification patch.
cd /
curl http://cdn.NetBSD.org/pub/NetBSD/NetBSD-9.0/source/sets/syssrc.tgz --output syssrc.tgz
tar xzf syssrc.tgz
Apply patch to the kernel source.
/usr/src/sys/netatalk/ddp_output.c:53
Create a custom kernel configuration.
cd /src/sys/arch/i386/conf
cp GENERIC NODDPCKSUM
config NODDPCKSUM
cd ../compile/NODDPCKSUM/
Compile the kernel with the modification.
make depend ; make
Install the new kernel in the system.
mv /netbsd /netbsd-GENERIC
mv netbsd /netbsd
shutdown -r now
Ghostscript is a rendering engine for the PostScript and PDF page description languages. Certain older and more recent versions of Ghostscript contain a driver that supports all of Apple's dot matrix printers.
Review and agree to the gnu-agpl-v3.
echo "ACCEPTABLE_LICENSES=gnu-agpl-v3" >> /etc/pkg_install.conf
This took about 3 hours.
cd /usr/pkgsrc/print/ghostscript-agpl
make install
Install a ribbon, power up the printer, load some paper and use either the direct or LocalTalk connection test below -- depending on your printer's capabilities or configuration. The command-lines are only for testing.
Enter one of:
driver=appledmp # Apple Dot Matrix Printer
driver=iwlo # ImageWriter (15")
driver=iwhi # ImageWriter II
driver=iwlq # ImageWriter LQ
Enter one of:
resolution=120x72 # Apple Dot Matrix Printer
resolution=160x72 # ImageWriter (15")
resolution=160x144 # ImageWriter II
resolution=320x216 # ImageWriter LQ
Enter one of:
paperSize=letter
paperSize=legal
gs -q -dBATCH -dNOPAUSE -dSAFER -sDEVICE=$driver -sPAPERSIZE=$paperSize -dFIXEDMEDIA -dPSFitPage -r$resolution -sOutputFile=$outFile $inFile
cat $outFile > $port (on Windows, set MODE.COM %PORT%: baud=19200 parity=n data=8 stop=1 octs=on idsr=on odsr=on to set line params and use print.exe /d:%PORT%: %outFile%)
gs -q -dBATCH -dNOPAUSE -dSAFER -sDEVICE=$driver -sPAPERSIZE=$paperSize -dFIXEDMEDIA -dPSFitPage -r$resolution -sOutputFile=$outFile $inFile
pap -p $printerName:$printerType $outFile
netatalk has a dependency on Oracle's Berkeley DB (bdb) library, so you must compile and install bdb in order to use netatalk.
You will have to register for an Oracle account (if you don't have one already) and agree to their Terms and Conditions in order to download from the BerkeleyDB downloads page.
cd /usr/local/src
tar zxf db-18.1.40.tar.gz
Berkeley DB is free, but comes with conditions. Be sure to review the License Agreement to understand your usage terms and obligations.
cd db-18.1.40
Read the license
vi LICENSE
:q
cd build_unix
../dist/configure
make
make install
netatalk 2.x is both a set of kernel routines and userland programs that enable full interoperability with a wide range of AppleTalk network services, including file and print services. (netatalk 3.x does not support many of the classic AppleTalk protocols -- specifically DDP -- it has a TCP/IP-based file sharing focus.)
Save to /usr/local/src
.
cd /usr/local/src
tar xzf netatalk-2.2.6.tar.gz
The base netatalk pap(1) userland program has a bug that prevents it from working with the ImageWriter II and/or LQ in AppleTalk mode, so Connor Taffe's <cptaffe@misc.home.arpa> 0001-Fix-PAP-status-for-ImageWriter-II.patch and Carpentier Pierre-Francois' kakwa netatalk/pap.c patch must be used.
diff --git a/bin/pap/pap.c b/bin/pap/pap.c
index 0c62da4b..53221c3f 100644
--- a/bin/pap/pap.c
+++ b/bin/pap/pap.c
@@ -890,17 +890,21 @@ static int send_file(int fd, ATP atp, int lastfile)
* The stinking LaserWriter IINTX puts crap in this
* field.
*/
+ /*
if (((char *) rniov[0].iov_base)[0] != 0) {
fprintf(stderr, "Bad status response!\n");
exit(1);
}
+ */
#endif /* NONZEROSTATUS */
+ /*
if (((char *) rniov[0].iov_base)[1] != PAP_STATUS
|| atpb.atp_rresiovcnt != 1) {
fprintf(stderr, "Bad status response!\n");
exit(1);
}
+ */
if (debug) {
printf("< STATUS\n"), fflush(stdout);
@@ -931,6 +935,7 @@ static void updatestatus(char *s, int len)
{
int fd = -1;
struct iovec iov[3];
+ char error_code[len];
if (status) {
if ((fd = open(status, O_WRONLY | O_TRUNC)) < 0) {
@@ -945,7 +950,9 @@ static void updatestatus(char *s, int len)
iov[0].iov_base = "%%[ ";
iov[0].iov_len = 4;
- iov[1].iov_base = s;
+ //iov[1].iov_base = s;
+ sprintf(error_code, "%X", s);
+ iov[1].iov_base = error_code;
iov[1].iov_len = len;
iov[2].iov_base = " ]%%\n";
iov[2].iov_len = 5;
diff --git a/bin/pap/papstatus.c b/bin/pap/papstatus.c
index b113f667..3dea1743 100644
--- a/bin/pap/papstatus.c
+++ b/bin/pap/papstatus.c
@@ -44,6 +44,15 @@
#define _PATH_PAPRC ".paprc"
+#define COLOR_RIBBON_INSTALLED 0b10000000
+#define SHEET_FEEDER_INSTALLED 0b01000000
+#define PAPER_OUT_ERROR 0b00100000
+#define COVER_OPEN_ERROR 0b00010000
+#define PRINTER_OFF_LINE 0b00001000
+#define PAPER_JAM_ERROR 0b00000100
+#define PRINTER_FAULT 0b00000010
+#define PRINTER_ACTIVE 0b00000001
+
/* Forward Declaration */
static void getstatus(ATP atp, struct sockaddr_at *sat);
@@ -87,6 +96,7 @@ static char *printer = NULL;
static char cbuf[8];
static struct nbpnve nn;
+
int main(int ac, char **av)
{
ATP atp;
@@ -199,5 +209,22 @@ static void getstatus(ATP atp, struct sockaddr_at *sat)
return; /* This is weird, since TIDs must match... */
}
- printf("%.*s\n", (int) iov.iov_len - 9, (char *) iov.iov_base + 9);
+ // printf("%.*s\n", (int) iov.iov_len - 9, (char *) iov.iov_base + 9);
+ char status = rbuf[9];
+ if (status & COLOR_RIBBON_INSTALLED)
+ puts("Color ribbon installed");
+ if (status & SHEET_FEEDER_INSTALLED)
+ puts("Sheet feeder installed");
+ if (status & PAPER_OUT_ERROR)
+ puts("Out of papaer");
+ if (status & COVER_OPEN_ERROR)
+ puts("Cover open");
+ if (status & PRINTER_OFF_LINE)
+ puts("Printer offline");
+ if (status & PAPER_JAM_ERROR)
+ puts("Paper jam");
+ if (status & PRINTER_FAULT)
+ puts("Printer fault");
+ if (status & PRINTER_ACTIVE)
+ puts("Printer active");
}
--
2.41.0
CFLAGS+="-O0" (if your VAX compiler is cranky)
./configure --with-bdb=$path --without-ldap --with-ssl-dir=no --enable-ddp --disable-cups
make
make install
Why and how to install the gdevadmp device PPDs (for best results.)
This guide lives at http://jmoyer.nodomain.net/admp/ and is hosted by NODOMAIN.NET, a private, hybrid cloud run by Josh Moyer <JMoyer@NODOMAIN.NET>.