RAM Read/Writer

Sometimes I wished I could twiddle bits remotely using an I/O port, like the parallel port. Well one day I decided to put something together to fix that. Thus was born the parallel port RAM Read Writer.

Design goals:

Since D0-D7 are the only data bits on the parallel port, it makes sense to use them for address and data. The four additional control lines can be used for multiplex. Four out of five status lines have to be used for incoming data (although they could still be used for status if the recieved data itself is multiplexed, there's no reason to do so). So it pretty much designs itself: you need two latches, one for each byte of the address (two octal D-type latches provides a cushy 16 bit address space), and those have to be clocked by control lines; to interface with the memory, which has tristate outputs, a tristate buffer is needed to prevent the memory from driving the data-out pins (this would be acceptable on a bidirectional port, however); and to select nibbles, a quad 1-of-2 selector is needed. So offhand, that's two 74LS574s, one '541 and one '157, plus the memory itself, and a couple of bypass capacitors and a regulated voltage supply. The schematic (without the analog parts) is shown below.

Schematic
Breadboard

Here's the circuit as breadboarded. As shown, it's set up for MK48Z02 NVRAMs, which have a 2kB address space. As such, most of the upper address bits are unused. Here I used 74LS273 latches (which have a funkier pinout, which isn't a big deal on a breadboard), a 74LS244 tristate buffer, and a 74LS157 selector. The big blank space is where the RAM goes. The bottom board sorts the parallel port connections, which come in from a header (the ribbon cable is wired with every-other-ground, for signal quality; it extends a regular parallel port cable).

Programming

Using the RAM Read Writer is fairly straightforward. Some simple routines can be put together to read and write bytes from a given address. In C, these are:


int readram(int address) {
    int value;

    out32(port+2, 8);               // set up ready state
    out32(port, address & 0xff);    // set address low byte
    out32(port+2, 12);              // latch it
    out32(port, (address & 0xff00) >> 8);
    out32(port+2, 1);               // latch high byte

    value = (inp32(port+1) & 0x78) >> 3;    // get low nibble
    out32(port+2, 8);
    value = value | ((inp32(port+1) & 0x78) << 1);  // get high nibble

    return value;
}

void writeram(int address, short data) {
    out32(port+2, 8);               // set up ready state
    out32(port, address & 0xff);    // set address low byte
    out32(port+2, 12);              // latch it
    out32(port, (address & 0xff00) >> 8);
    out32(port+2, 0);               // latch high byte

    out32(port, data);              // set data
    out32(port+2, 10);              // write it
    out32(port, data);
    out32(port+2, 10);              // create a little delay doing nothing...
    out32(port, data);
    out32(port+2, 8);               // ...and we're done
}

These routines use inpout32.dll, which gives user programs direct port access in WinNT. You might use other methods, such as GiveIO (I've heard of this, but it doesn't seem to be a widely known routine). The values are the same whatever I/O model you have available; it looks about the same in x86 assembly (which is how I wrote the original routines on my 8086 computer). Notice that the desired nibble is masked from the status register, then shifted into position (because, for whatever reason, they didn't feel like aligning them for us). The delay while writing isn't necessary on slower computers, and it may not be necessary at all (what does a PCI parallel port run at anyway -- is it still synchronized to the same 8MHz ISA bus clock it used to be?), but with my setup, I was finding a high error rate. This could be due to signal bounce on the extra-long, unterminated parallel cable; I don't know, I haven't scoped the circuit yet. Considering the error rate, I also recommend using a write-verify procedure.


Return to Electronics


Web page maintained by Tim Williams. All rights reserved.