The Oric IDE Interface was a 1990s attempt to connect Oric micros to IDE disks. The project is obsolete in our days of cheap, gigantic (by 8-bit micro standards) SD cards, dirt-cheap microcontrollers, FPGAs and CPLDs. The whole project could be coded in VHDL or Verilog and implemented on the smallest FPGA chip available without any other integrated circuits on the board. But then, where's the fun in that? And besides, the entire Oric micro in question could probably also be implemented inside a single FPGA chip. (well, here's a fun project for the future)
Before starting, please be aware: this is tentative information! No claims on correctness are provided. The prototyped interface was in fact quite different from the one outlined below, although I couldn't give you the exact details as it's been a good while. In the text below, ‘recently’ et cetera all refer to Spring 1996, when this design was made.
This is version 0.6 of the document.
1 Abstract
This is an initial (and very sketchy) design for an IDE interface for Oric computers.
You'll find loads of errors here. Rely on it. Having said that, I think I ought to warn anyone who reads this: the interface isn't likely to work at all! You could damage your machine if you implement it. And don't come crying to me then! :-)
2 IDE Interface
IDE (also known as ‘AT-bus’) is an interface for connecting advanced peripheral memory devices (hard disk drives, CD-ROM drives, etc.) to IBM ATs and compatibles. The ‘interface’ is actually on the device itself, not on what has come to be called the ‘controller card’. An IDE device already knows how to interface with a Intel 16-bit bus and is very intelligent. Hence, the sole purpose of an IDE ‘interface’ is address decoding and buffering.
In this case, of course, we're not dealing with an Intel bus. Actually, things are even worse, because the workings of the 6502 are quite different than those of Intel CPUs. This requires a bit more ‘glue’ (interface accompanying logic). Even then, though, the interface looks pretty simple: it needs no ROM (though one would be nice), and uses a minimum of cheap, off-the-shelf discrete TTL integrated circuits. You should be able to get all the components easily.
The IDE interface consists of 40 lines, of which some are used by the master device when ‘talking’ to its slave device. Up to two devices can be connected to the IDE bus; one is a master, the other a slave. The host talks to the master device alone. The slave is only accessed by the master. This is completely transparent to the host).
Most of the other lines are used for communicating with the host. Here are the most important connections:
| Line Name | Direction | Purpose |
|---|---|---|
D0–D7 |
From/To host | Data bus, lower 8 bits. |
D8–D15 |
From/To host | Data bus, higher 8 bits. Data on these lines is not always valid
(e.g. when transmitting commands, only D0-D7 are used. When data is
being moved around, all 16 bits are used). |
-IOW |
From host to IDE | The rising edge of this inverted signal latches data from the data bus to the device. |
-IOR |
From host to IDE | The falling edge of this inverted signal latches data from the device to the data bus. |
-CS1FX, -CS3FX |
From host to IDE | These inverted lines control which set (if any) of the IDE registers is used. |
ADDR0–ADDR2 |
From host to IDE | These select which register is used in the selected register set. |
-RESET |
From host to IDE | This inverted signal cold-resets the drive. |
-DASP |
From IDE to host | Used by the slave and master devices for handshaking purposes during reset. At all other times, this inverted signal indicates that either of the IDE devices is working. |
Note on register selection:
There two sets of registers: 1 and 3 (the strange numbering comes from
their mapping on the PC I/O space at addresses 01Fx and
03Fx), hence the names of the two select lines. The IDE
bus is chip-selected when either of the two lines gets asserted. The
following table describes how to chip-select the IDE bus in detail:
-IOR |
-IOW |
-CS1FX |
-CS3FX |
Register Set selected |
|---|---|---|---|---|
| 1 | 1 | X | X | IDE bus not selected. |
| X | X | 1 | 1 | IDE bus not selected. |
| 1 | 0 | 1 | 1 | IDE bus not selected. |
| 0 | 0 | X | X | Can't happen on an Intel bus; should be avoided. |
| 1 | 0 | 1 | 0 | Host writing to register set #3. |
| 1 | 0 | 0 | 1 | Host writing to register set #1 |
| 0 | 1 | 1 | 0 | Host reading from register set #3. |
| 0 | 1 | 0 | 1 | Host reading from register set #1. |
3 The Design
Please see Figure 1 for the full circuit diagram of the interface.
The IDE Interface consists of the following parts:
- Address Decoding: decodes 6502 address lines to tell the IDE bus when we're talking to it and what register set we're addressing.
- Timing: generates the necessary signals for synchronisation with the 6502 bus.
- Data Bus Registers: since this is an asynchronous interface (more or less), we use two bus buffers eto make sure that data is there when we need it. This also includes the control logic for the registers.
- Miscellaneous: a couple of simple, easy things like a device activity indicator, etc.
3.1 Address Decoding
This is done by means of the ever so popular 74LS138, an inverting 3:8 multiplexer. This chip has the following purposes:

- Generates
-CS1FXand-CS3FX. - Clocks and chip-selects the MSB register (storing the high byte in 16-bit data transfers).
- Deselects the internal VIA (I don't know if this is required on the Telestrat and if it differs from the way it's done on the Oric-1/Atmos) whenever the IDE interface is accessed.
The 138 is a very handy device, especially in this case. It provides
no less than three chip select lines, which allows us to fully decode
the lower 8 bits of the Oric address bus. The most significant 8 lines
are decoded by the Oric ULA and provided as the negated line
-I/O, which gets asserted whenever the host is accessing
the hardware I/O page, page 3 (address 03xx). The mux is
enabled on the low state of -I/O and A3, and
the high state of A7.

Lines A0 to A2 pass through a 74LS173, a
quad D flip-flop. The outputs are sent directly to the
ADDR0–ADDR2 on the IDE bus to select registers.
The I/O CONTROL line is an input to the Oric. It's
connected to the CS (not -CS) line of the
VIA. A high state enables the VIA; a low state disables it. The
address decoder keeps this line at logic 1 at all times, except when
the host is addressing the IDE interface. I/O CONTROL
then drops to 0 to unmap the VIA (whose registers are otherwise mapped
to all of the I/O page).
The following table describes how address decoding is done:
| Inputs | Outputs | Comments | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
A3 |
A4 |
A5 |
A6 |
A7 |
-I/O |
-CS1FX |
-CS3FX |
-MSB |
I/O CTRL |
|
| 1 | X | X | X | X | X | 1 | 1 | 1 | 1 | Not selected. |
| X | X | X | X | 0 | X | 1 | 1 | 1 | 1 | Not selected. |
| X | X | X | X | X | 1 | 1 | 1 | 1 | 1 | Not selected. |
| 0 | 0 | X | X | 1 | 0 | 1 | 1 | 1 | 1 | Not selected. |
| 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | Not selected. |
| 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | MSB register. |
| 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | Register set #1. |
| 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | Register set #3. |
The I/O memory mapping is as follows:
- Addresses
0000001111010XXX(03D0–03D7) access the MSB register (eight copies of it, due to partial decoding). - Addresses
0000001111100XXX(03E0–03E7) access the registers in set #1. - Addresses
0000001111110XXX(03F0–03F7) access the registers in set #3.
For a discussion of the actual IDE registers rather than their mapping on memory, please see the references at the end of this document.
3.2 Timing
This might actually be tricky. I base the timing circuit on two observations:
- Z-80s don't seem to have trouble interfacing with the faster IDE interfaces, so the fact that the device is more powerful than the host is no problem (timing-wise).
- Going the other way, it's obvious that the IDE device will have no problem talking to a slower host, since the communications is asynchronous.
The only problem with timings is also a problem that has to do with
address decoding. Mainly, deciding when to assert -IOR
and -IOW. The timing diagram below
shows how timing should work (but take this with a pinch of salt):

-IOR and -IOW timing.
-IOR latches data from the IDE device to the host at its
falling edge. This, in effect, toggles data from the device
the moment phi2 goes up. I don't know if this gives enough time for
the IDE interface to enable itself. Maybe we shouldn't AND
R/-W with phi2...
-IOW latches data from the host to the IDE device at its
rising edge. This should be okay ― it more or less
matches what the 6502 does, if I'm not mistaken. The equation for this
signal is phi2 NAND (NOT R/-W).
3.3 Data Bus Registers
We have two of these; one for the lower 8 bits of the IDE data bus, and one for the upper 8 bits. Two 74LS646 bus registers are used for this purpose.
3.3.1 The 74LS646

The 646 is a very useful chip for asynchronous bus applications: it
has two 8-bit registers. Depending on the state of the control lines
(CPAB, SAB, CPBA,
SBA, DIR and -G), the chip can
isolate the two buses (known as ports A and B), let data pass through
in a specified direction, store data in one of the two registers, and
allow one part of the bus to read the other part's register, so we can
access data even if we can't have control of the other end of the bus.
The following table describes the operation of the chip depending on the control inputs. States are described as 1, 0, X (don't care), 1/0 (high or low, but no transition allowed), or / (rising edge):
| Control Inputs | Data I/O | Function | ||||||
|---|---|---|---|---|---|---|---|---|
-G |
DIR |
CPAB |
CPBA |
SAB |
SBA |
Port A | Port B | |
| 1 | X | 1/0 | 1/0 | X | X | Input | Input | Isolation. |
| 1 | X | / | X | X | X | Input | Input | Port A to Reg A. |
| 1 | X | X | / | X | X | Input | Input | Port B to Reg B. |
| 0 | 1 | X | X | 0 | X | Input | Output | A to B (Real Time). |
| 0 | 1 | / | X | 0 | X | Input | Output | Port A to Reg A. |
| 0 | 1 | 1/0 | X | 1 | X | Input | Output | Reg A to Port B. |
| 0 | 1 | X | X | 1 | X | Input | Output | Port A to Reg A and Port B. |
| 0 | 0 | X | X | X | 0 | Output | Input | B to A (Real Time). |
| 0 | 0 | X | / | X | 0 | Output | Input | Port B to Reg B. |
| 0 | 0 | X | 1/0 | X | 1 | Output | Input | Reg B to Port A. |
| 0 | 0 | X | X | X | 1 | Output | Input | Port B to Reg B and Port A. |
The control inputs do the following tasks:
-Gis the output enable signal. A low state enables the chip's selected port (either A or B) to output data. At the high state, the 646 can only input data to its twin registers.- DIR is the data flow direction. When DIR is high, data flows from A to B. When DIR is low, the direction is from B to A.
CPABandCPBAare the register clocks. The rising edge of these signals latches data from ports A and B to registers A and B respectively.SABandSBAare the register output enables. WhenSABis high, data from register A is sent to port B (hence the name). WhenSBAis high, register B is sent to port A.
This makes the chip extremely useful in this case. Unfortunately, we need quite a bit of control logic for all those lines, as described below.
3.3.2 The LSB Register
The LSB register is accessible by addressing either of the two sets of IDE interface registers, as decoded by the address decoding part.
The 74LS646 used for this purpose has its A port attached to the IDE
bus. Its B port is the 6502 bus. Hence, DIR is the same as the 6502's
R/-W line: when in the high state, direction is from IDE (A) to 6502
(B); when in the low stgate, direction is from 6502 (B) to IDE (A).
The following two cases are taken care of:
- When reading data from this register, IDE data are copied to the 646's register and output to the 6502 bus. Data are retained in the register in case the 6502 needs the data bus valid for more time than the IDE interface is willing to hold (hence we're using asynchronous communication).
- When writing to the register, 6502 data are latched to the register and output to the IDE device. Data are retained in the register for the same reasons as before.
3.3.3 The MSB Register
This 74LS646 has its B port connected to the Oric data bus. Its A port
is connected to lines D8 to D15 of the IDE bus (wouldn't be the MSB
register otherwise!).
The MSB register is addressed in a lot of cases:
- When the LSB register is read from, data is also clocked to the MSB register from the IDE device. This is done because, when reading from the LSB register, we might need to read 16 bits instead of just 8.
- When the LSB register is written to, data from the MSB register is also sent to the IDE device. This allows us to send 16 bits to the device.
- When the MSB register is read from, data is not clocked from the IDE device: this has already been done (when we read the LSB register). Instead, the 646's A register is sent to its B port (the 6502 bus). Asynchronous communication in all its glory, eh?
- When the MSB register is written to, data from the Oric is clocked into the B register, to be output to the IDE device when next data is written to the LSB register.
3.3.4 Data Bus Register Control Logic
This clearly complicates things quite a lot. Of course, since an IDE device is always 16 bit and the Oric is 8-bit, we can't really escape this. Some drives support full 8-bit operation, but definitely not enough of them (and all of them are brand new EIDE devices ― I wouldn't try to connect a new 1.6 GB hard drive to my Oric just because it supports 8-bit data transfers, all things considered...)
Because of all this, the software will have to be slightly careful of accessing the drive. Accesses to the MSB register do not clock data from/to the device. Only the LSB register can do this. Hence, to work with this scheme, we have to do the following:
- When writing a word: first store the MS byte onto the MSB register. Nothing is sent to the IDE device by the interface yet. Then store the LS byte onto the LSB register. This now clocks the device. The interface makes both bytes available to it at this time.
- When reading a word: first read the LSB register to clock the drive. 16 bits of data are copied to the two 646 registers, and the low-order byte is read by the 6502. Then we read the MSB, which contains the high order byte of the previous operation.
Figure 3 depicts the four kinds of accesses needed to interface the Oric to an IDE 16-bit data bus.
The data bus registers use three signals to tell what to do with themselves:
- The
R/-Wsignal tells us the direction of data. -REG= --CS1FXAND-CS3FX=CS1FXANDCS3FX. The-REGsignal goes to a low state whenever the host is accessing either register set #1 or #3. This is used to tell when the LSB register is accessed, since both register sets are 8 bits wide.-MSB, as output from the address decoding part of the interface, is used to detect accesses to the MSB register.
The following truth table shows what happens depending on the states of the three lines.
R/-W |
-REG |
-MSB |
Action |
|---|---|---|---|
| 0 | 0 | 0 | Can't happen. |
| 0 | 0 | 1 | Write to LSB. |
| 0 | 1 | 0 | Write to MSB. |
| 0 | 1 | 1 | Interface not addressed. |
| 1 | 0 | 0 | Can't happen. |
| 1 | 0 | 1 | Read LSB. |
| 1 | 1 | 0 | Read MSB. |
| 1 | 1 | 1 | Interface not addressed. |
And this table shows the states of the various 74LS646 control lines
depending on the values of R/-W, -REG and -MSB. As in previous truth tables, / signifies a rising edge.
| Inputs | LSB Register | MSB Register | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
R/-W |
-REG |
-MSB |
CPAB |
CPBA |
SAB |
SBA |
-G |
CPAB |
CPBA |
SAB |
SBA |
-G |
| 0 | 0 | 0 | Never happens. | |||||||||
| 0 | 0 | 1 | 0 | / | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | / | 1 | 1 | 0 |
| 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | Never happens. | |||||||||
| 1 | 0 | 1 | / | 0 | 1 | 1 | 0 | / | 0 | 1 | 1 | 1 |
| 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 |
| 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
To ease the implementation of this table into hardware, I use another 74LS138 inverting multiplexer to decode the three input lines. Then it's trivial to tap desired output lines to get the equation we want.
And behold explanations for each case:
- All four
SAB/SBAlines are pulled up. Since this is asynchronous communication, we'll want to make registers available at all times (when the register chips are selected, of course). CPAB/CPBAlines have to be rising edges. Thus, I use a NOR gate for each output line (three of them:CPABfor the MSB register is always equal toCPABfor the LSB register) to provide a rising edge. Phi2 is the other NOR input. Since the 6502 makes available valid data andR/-Wbefore phi2 goes high, the address decoder provides the 74LS138 with its required values, and hence the two 74LS646 registers get a rising edge on their respective clock inputs after addresses and data has stabilised. This is a pretty narrow time constraint: I don't know if it'll work.-Gis asserted whenever it's needed. For the LSB register, this value is tapped from the-REGline. For the MSB register, logic is used such that-Gis high whenever any of three specific 74LS138 outputs drop to the low state.
3.4 Miscellaneous
Easy stuff here. This only consists of an activity LED fed from the -DASP line and a
-RESET line which is pulled up so that the drive stops resetting as soon as it gets
power. :-)





Add new comment