Resurecting the USB Parallel Port

It's a common belief that USB parallel ports are simply not capable of bit-banging.  While this is *mostly* true, there are ways around the limitation. Based on the Prolific PL2305 chip, USB parallel devices emulate a centronics or IEE1284 protocol in hardware with no way to access the data lines programatically.   For these devices to work, a printer (or printer-like device) must be present to read the data.

So how to get around this?

Emulate a printer.

While the most direct approach for that might be to use a microcontroller, it's really not necessary.



Studying the Centronics protocol,   when data is posted,  a STROBE is asserted.  The printer then asserts BUSY until it has completed processing the data.   It then de-asserts BUSY and the process repeats.  Note that the nAck line may be ignored as some systems transfer data between host and printer by using only the STROBE* and BUSY signals.  USB parallel devices are also compatible with this.

So then STROBE must at a minimum must cause BUSY to assert, then later get de-asserted, by ... something.

I get by with a little help from my friends

So what can assert and de-assert the BUSY line?    
There are some timing constrains that must be met.   BUSY must be asserted immediately after a STROBE and then stay asserted for as long as we need to access a byte of data.    To do this is fairly simple.  A transistor inverter (because STROBE is inverted) that triggers a Thyristor/SCR can emulate this behavior easily.    But once the Thyristor/SCR is triggered, how do we turn turn it off?    Its anode must be pulsed to ground to reset it.

Fortunately a $2 USB RS232 serial cable can help with this.    With the right configuration of start and stop bits combined with a character sequence,  the TX line of  RS232 can generate a single pulse.  



Serial data is transmitted LSB first. Data '1' is the same polarity as the stop bit and data '0' is the same polarity as the start bit. So 0xf0 is transmitted as:

 0 0 0 0 0 1 1 1 1 1  

Which produces the following:




RS232 polarities are inverted.  So the data represented above will be read on the wire as:



(note I am using a very cheap "5v" rs232 usb cable.  Most USB RS232 cables are made this way as nearly all UARTS and logic made since 1980 can deal with these voltage levels. )

It's possible to generate 2 or more pulses per character as well:
	

_|~~~~~~~~~|_________ 0xF0

_|~~~~~|_____|~~~~~|_____ 0x1C

_|~|_|~|_|~|_|~|_|~|_ 0x55


Schematic


                      3 Transistor USB Parallel Port
                    Bit Bang Liberator / Printer Emulator    

                                          2x Transistors (PNP):
                                            MPSA56, 2N2907 or equiv

             .-----------------------.     1x SCR/Thyristor:
             |        Init           |      MCR100-4 or equiv
             |      (pin 16)         |
             |          +            |     1x Diode:
             |          |            |      1N4148 or equiv
   5v        |  ___   |/             |
 RS-232 o----+-|___|--|              |     3x 10k resistors       
   TX           10K   |<             |     1x 3k resistor
                        |            |
                        +--------.   |
                        |        |   |
                ___   |/         |   |
 Strobe o------|___|--|          |   |
 (pin 1)        10K   |<         V   V       
                        |  ___   -   -
                        '-|___|-/|   |
                           10K   +---+-----o Busy
                                 |          (pin 11)
                                .-.
                                | |
                                | |3K
                                '-'
                                 |
                                ===
                                GND

 ______
 STROBE asserts BUSY until cleared by falling edge of RS-232 pulse (Character 0xF0)


Each time a character of 0x0F is sent, the thyristor is reset and BUSY is de-asserted.  

So why not just use the RTS or DTR line instead?   Well you can, but then you're stuck with only one other usable output line and TX serial data.  The TX line isn't very useful for much except as a pulse generator, which is perfect for de-asserting the BUSY line.

This gives the added benefit of  freeing up the RTS and DTR lines for other purposes.  


           


Why not just use a PIC or an Arduino?

MCU's are getting cheaper, but USB Parallel devices can be had for as low as $2 with free shipping.   Also, some amount of programming and hardware development must be done with an MCU.   Another issue is device drivers. USB parallel and USB serial drivers are already written for Windows and Linux and compiled into the kernel of  many distros and even android devices.  (If you've ever tried to cross-compile android, you'll immediately appreciate this).   Also, a USB Serial and USB Parallel port requires no programming at all.   Shell scripts are all that's needed to ouput data to either device.

Demo Script Example


Android App


UsbParallelPort.apk

To use the android app,  your device must be rooted with usb parallel and usb serial drivers installed.   Newer cyanogenmod roms (4.0 and later) have at least some support for this compiled in.    PL2303-based USB serial devices should work fine, but be careful with CH341-UART.  While basicaly identical to the PL2303,  most android releases to date do no yet  include the CH341-UART driver (although this is likely to change). USB parallel devices are all some variant of the PL2305 (with various revisions).

My particular device is a kindle fire with a USB OTG cable,  and powered a USB hub.   The release is JellyBean 4.2 CM Otter SGT7,  but older releases have worked (GedeRom 4.0 for example).   When loaded, the USB serial device is at /dev/ttyUSB0 and the USB parallel device in /dev/usb/lp0   

For controlling the serial port RTS/DTR lines via ioctls from apps, see here