• Please review our updated Terms and Rules here

Best way to implement a 16-bit bidirectional IO port on the AT bus?

bladamson

Veteran Member
Joined
Nov 11, 2018
Messages
986
Location
Appalachia
What would be the best way to implement a 16-bit bidirectional IO port on the AT bus? Would one just use a pair of 8255s in tandem, or is there a better PPI to use for 16-bit stuff that my substandard google-fu isn't sending me to?

(I assume that a 16-bit port read on the AT bus would be about twice as fast as a pair of 8-bit reads, right?)
 
Use plain old TTL - you'll save space and money. See my comments on the PC printer port thread. You could even modernize it a bit perhaps by using an LS646 (bidirectional register); I haven't looked in detail, but certainly looks possible.
 
(I assume that a 16-bit port read on the AT bus would be about twice as fast as a pair of 8-bit reads, right?)

I would do some research on how to make that happen. My memory is very vague on this but I think if a card wants to do 16 bit wide transfers there's some kind of process the card has to do to assert that it's capable of 16 bit transfers? Maybe that's just memory transfers.

Edit: A supporting citation, maybe?
 
Last edited:
Not sure what your application is, but ATA a.k.a. IDE is literally a 16-bit bidirectional I/O interface for the AT bus...

16-bit access on the ISA bus is generally more than twice as fast as two 8-bit accesses. For 8-bit I/O, there are extra waitstates by default, to accomodate slower cards designed for 8088 systems.
 
The IBM ISA XT Printer adapter card is actually an 8 bit bidirectional port, though they didn't hardware configure it that way , but they designed it so it can work. If you change a link on this pcb, I think un-ground pin 1 IC U4 and connect it to pin 15 on U7. On the actual pcb it was set up to do it with some pads and tracks. But if you want 16 bits you could just take the data in a sequence of two bytes in your software, or send it out that way too, if your peripheral device was configured to accept it, say using a handshake line on the port. The card is helpful as its all more or less ready to go and it is a high quality card.Though I'm not sure if this applies to the AT bus, but it will probably still work with the XT card.
 
Last edited:
Hugo, I think I said something to that effect here earlier today.

You can do 16 bits parallel--it shouldn't be difficult once you get past the little bit of 16-bit ISA port gymnastics.

It really depends upon what you need the 16 bits for.
 
Last edited:
I would do some research on how to make that happen. My memory is very vague on this but I think if a card wants to do 16 bit wide transfers there's some kind of process the card has to do to assert that it's capable of 16 bit transfers? Maybe that's just memory transfers.

Edit: A supporting citation, maybe?

Indeed - the card needs to assert /IOCS16 to let the system know it is capable of and is willing to perform a 16-bit I/O cycle. This is an open collector line so it can be driven low but it should not be driven high.
 
I would do some research on how to make that happen. My memory is very vague on this but I think if a card wants to do 16 bit wide transfers there's some kind of process the card has to do to assert that it's capable of 16 bit transfers? Maybe that's just memory transfers.

Edit: A supporting citation, maybe?

You have to assert IOCS16#

The timing requirements for IOCS16# on an AT system are much more lenient than MEMCS16#. You don't have to qualify it on early (LA) address decoding.
 
Not sure what your application is, but ATA a.k.a. IDE is literally a 16-bit bidirectional I/O interface for the AT bus...

16-bit access on the ISA bus is generally more than twice as fast as two 8-bit accesses. For 8-bit I/O, there are extra waitstates by default, to accomodate slower cards designed for 8088 systems.

that's an interesting idea - just take a super basic COTS IDE card and hack it to match a different I/O port address, boom done
 
that's an interesting idea - just take a super basic COTS IDE card and hack it to match a different I/O port address, boom done

Actually not sure that adds much value, since an IDE port is pretty literally just the data portion of the AT bus with a decoded chip select in place of the full address bus. A ‘688 and a pair of ‘245s should mostly do that part. The IDE adapter doesn’t include logic for asserting IOCS16, looks like the drive does it itself.

So... in theory it should be as easy as asserting iocs16 as a mirror of chip select via an open collector buffer?

This might be a good use for a GAL like a 20v8 instead of a ‘688. It has enough inputs to decode all 10 low address lines and a few spares that might come in handy for arbitration for... whatever this is for.
 
Actually not sure that adds much value, since an IDE port is pretty literally just the data portion of the AT bus with a decoded chip select in place of the full address bus. A ‘688 and a pair of ‘245s should mostly do that part. The IDE adapter doesn’t include logic for asserting IOCS16, looks like the drive does it itself.
it adds the value of a pre-built PCB with a hard gold edge connector, and having the bus transceivers already in place - seems like a good place to start to me

you're right about needing extra logic for the IOCS16# assertion, I forgot the drive does it for IDE
So... in theory it should be as easy as asserting iocs16 as a mirror of chip select via an open collector buffer?
yeah that should work just fine for I/O ports, MEMCS16# would be substantially more complex
 
... I guess without knowing more about what the application is we don’t know if there is any requirement for this host adapter to actually latch-and-hold incoming/outgoing data or if just a buffered I/O decode is enough.
 
it adds the value of a pre-built PCB with a hard gold edge connector, and having the bus transceivers already in place - seems like a good place to start to me

I just don’t know how common cards that would trivially allow you to change the address to something arbitrary really are. IDE host adapters were shrunk down into ASICS pretty quickly.
 
Yeah, I'll need to latch and hold data. I am trying to figure out the highest throughput way to interface a raspberry pi gpio header to an ISA IO port, without getting too awfully complicated.

Thanks for the advice, guys.
 
Huh. I think you might be better off looking at PPI-category devices again if you want some kind of handshake and latching. It might be *just* within the Raspberry Pi's powers to respond in real-time fast enough to keep up with an ISA bus posing as a dumb peripheral but it's going to be a stretch.

My uneducated guess would be that handshaking and latching is also likely to slow things down enough it's not going to matter a lot if it's 8 or 16 bits wide. Are you thinking the sort of handshaking that a parallel port does, where you have to check a status bit to see if the partner can take a byte, generate a strobe, wait for an ack, etc?
 
I was thinking that a more pragmatic approach would be to use a serial protocol, such as SPI or I²C. Less wire, yet pretty simple to implement. The RPi can speak either.
 
The other day I bookmarked an interesting design for using a 6522 VIA to do SPI with its built-in shift register; unfortunately it's not exactly plug-and-play because of a misfire in how MOS implemented that part of the chip. Does anyone make an easy off-the-shelf 8-bit parallel-to-SPI part?
 
Huh. I think you might be better off looking at PPI-category devices again if you want some kind of handshake and latching. It might be *just* within the Raspberry Pi's powers to respond in real-time fast enough to keep up with an ISA bus posing as a dumb peripheral but it's going to be a stretch.

My uneducated guess would be that handshaking and latching is also likely to slow things down enough it's not going to matter a lot if it's 8 or 16 bits wide. Are you thinking the sort of handshaking that a parallel port does, where you have to check a status bit to see if the partner can take a byte, generate a strobe, wait for an ack, etc?

If all goes according to plan, I'll have the software on the Pi side running on bare metal, so RT operation will hopefully be less of a concern. My main reason for wanting to use Pi Zero is the cost. :p

I was thinking that a more pragmatic approach would be to use a serial protocol, such as SPI or I²C. Less wire, yet pretty simple to implement. The RPi can speak either.

You are probably right, but I am afraid that if I try to run SPI fast enough to do what I want (I'm wanting to synchronize a block of memory in the pi with the host computer's video RAM at least 20 times per second, among other things that aren't nearly as intense) that I'll have to start paying more attention to my wiring to keep the noise down, whereas if I'm transferring 8 or 16 bits at a time at ISA speeds things will be a little more calm. And I think I2C would be too slow. But then again, I am just a hobbyist and I don't really know what I am doing most of the time, so maybe I am on the wrong track heh. (Another thought I had was using a dual-port SRAM and mapping it into upper memory somewhere, but I think that may be beyond my ability at this juncture; and DMA most certainly is).
 
How is interrupt latency on the raspi? Could you have the falling edge of /IOW generate an interrupt, and then poll the data port until it goes high again? Maybe that would effectively latch the data at the rising edge.

For data to run in the other direction, the raspi could just write new data when it sees /IOR go low. I'm assuming it has its own output registers for its I/O pins.
 
Back
Top