This article describes how to connect a Commodore 64 compatible printer to an IBM PC compatible computer. The information originally appeared in an article that I wrote for the Tech Forum section of the March 1995 issue of Nuts & Volts magazine. This information may be used and distributed so long as proper credit is given to the author and Nuts & Volts magazine. Copyright (C) 1995 by John Keyerleber and Nuts & Volts Magazine. The problem with Commodore 64 compatible printers is that these devices use the Commodore synchronous serial interface to communicate with the C64. An IBM PC compatible printer port is a parallel interface, however it is possible to use this parallel port to emulate the C64 serial interface by constructing a special cable and writing a little bit of software. The cable is used to connect the PC DB25 pin parallel printer port to the 6 pin DIN serial port on the C64 compatible printer. The parts needed are one DB25 male connector (Radio Shack #276-1429), one 6 pin DIN plug (RS #274-020), and some six conductor cable (RS #278-874 or equivalent). Note that the cable length should be kept to less than six feet. The wiring connections and signal descriptions for this cable are given as follows: Commodore 64 DIN plug pin: Parallel printer DB25 connector pin: 1 (SRQ IN) 2 (DATA0) 2 (GND) 20 (GND) 3 (SER ATN) 3 (DATA1) 4 (SER CLK) 4 (DATA2) 5 (SER DAT) 5 (DATA3) and 11 (BUSY) 6 (RST) 6 (DATA4) The software uses the PC parallel port to emulate a C64 serial port. The example program, C64.C (Listing 1), is written in Borland's Turbo C. It reads input and sends each character to the printer. It can be used as a filter in an MS-DOS command line pipe. For example, DOS commands such as: dir | c64 would print a directory listing, or type a_file | c64 would print the contents of a file. I have also written an MS-DOS device driver which can be used to allow any PC application to print to a C64 compatible printer, and it supports multiple printers connected to a single PC parallel port. The listing for this software is too lengthy to print, however I will make this software and assembled cables available to Commodore 64 enthusiasts for a nominal charge; just write me for details. With these C64 compatible printers often selling for less than $25 at garage sales and flea markets, it's easy to add a couple of additional "scratch" printers to any PC system. John Keyerleber 26300 Chardonview Drive Cleveland, OH 44143 (216) 261-9676 E-mail: jkeyerleber@bailey.com Listing 1: #include #include #include #define PORTADR 0x378 // LPT1=0x378, LPT2 = 0x278 #define PRINTADR 0x04 // C64 compatible printer address #define SRQ 0x01 // C64 SRQ IN signal #define ATN 0x02 // C64 ATN signal #define CLK 0x04 // C64 CLK signal #define DATOUT 0x08 // C64 DAT signal (output) #define DATIN 0x80 // C64 DAT signal (input) #define RST 0x10 // C64 RST signal // function prototypes void initc64(void); void putc64(unsigned char); void puts64(char *); void putbyte(unsigned char, unsigned char); // function main() loops to read input characters and send them to the printer void main(void) { char buff[128], *ptr; initc64(); while(fgets(buff, 80, stdin)) { for(ptr = buff; *ptr; putc64(*ptr++)); } } // function init64() initializes the driver and the C64 compatible printer void initc64(void) { // set initial port output value to all bits high outportb(PORTADR, RST | SRQ | ATN | CLK | DATOUT); // set interface to output outportb(PORTADR + 2, 0x00); // initialize printer: RST=0, then RST=1 outportb(PORTADR, SRQ | ATN | CLK | DATOUT); delay(250); outportb(PORTADR, RST | SRQ | ATN | CLK | DATOUT); delay(2250); // Set printer to listener: ATN and CLK low, printer will ACK with DAT low outportb(PORTADR, RST | SRQ | DATOUT); while(!(inportb(PORTADR + 1) & DATIN)); // Send printer address (currently set for address 4) putbyte(0x20 | PRINTADR, 0); // Send printer mode putbyte(0x67, 0); } // function putc64() sends a byte of data (byteval) to the C64 compatible printer void putc64(unsigned char byteval) { // Check for upper/lower case conversion if (isalpha(byteval)) { byteval = (isupper(byteval)) ? tolower(byteval) : toupper(byteval); } // Send character putbyte(byteval, ATN); } // function putbyte clocks the actual byte to the C64 compatible printer bit by bit void putbyte(unsigned char byteval, unsigned char mode) { register int bitloop; // Set CLK high, printer will ACK with DAT high outportb(PORTADR, RST | SRQ | CLK | DATOUT | mode); while(inportb(PORTADR + 1) & DATIN); // Loop to output bits of data delay(1); for (bitloop=0; bitloop<8; bitloop++) { outportb(PORTADR, RST | SRQ | ((byteval & 1) ? DATOUT : 0) | mode); delay(1); outportb(PORTADR, RST | SRQ | CLK | ((byteval & 1) ? DATOUT : 0) | mode); delay(1); byteval >>= 1; } // Set CLK low and DAT high for end of byte, printer will ACK with DAT low outportb(PORTADR, RST | SRQ | DATOUT | mode); while(!(inportb(PORTADR + 1) & DATIN)); }