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 diﬀerent 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.
This is an initial (and very sketchy) design for an IDE interface for Oric computers.
You'll ﬁnd 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! :-)
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 buﬀering.
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 diﬀerent 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, oﬀ-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:
||From/To host||Data bus, lower 8 bits.|
||From/To host||Data bus, higher 8 bits. Data on these lines is not always valid
(e.g. when transmitting commands, only
||From host to IDE||The rising edge of this inverted signal latches data from the data bus to the device.|
||From host to IDE||The falling edge of this inverted signal latches data from the device to the data bus.|
||From host to IDE||These inverted lines control which set (if any) of the IDE registers is used.|
||From host to IDE||These select which register is used in the selected register set.|
||From host to IDE||This inverted signal cold-resets the drive.|
||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
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:
||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.|
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 buﬀers 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.
This is done by means of the ever so popular 74LS138, an inverting 3:8 multiplexer. This chip has the following purposes:
- 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 diﬀers 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 signiﬁcant 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
the high state of
A2 pass through a 74LS173, a
quad D flip-flop. The outputs are sent directly to the
ADDR2 on the IDE bus to select registers.
I/O CONTROL line is an input to the Oric. It's
connected to the
-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.
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:
|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:
0000001111010XXX(03D0–03D7) access the MSB register (eight copies of it, due to partial decoding).
0000001111100XXX(03E0–03E7) access the registers in set #1.
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.
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
-IOW. The timing diagram below
shows how timing should work (but take this with a pinch of salt):
-IOR latches data from the IDE device to the host at its
falling edge. This, in eﬀect, 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
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.
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
SBA, DIR and
-G), the chip can
isolate the two buses (known as ports A and B), let data pass through
in a speciﬁed 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|
||Port A||Port B|
|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.
CPBAare the register clocks. The rising edge of these signals latches data from ports A and B to registers A and B respectively.
SBAare the register output enables. When
SABis high, data from register A is sent to port B (hence the name). When
SBAis 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.
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.
This 74LS646 has its B port connected to the Oric data bus. Its A port
is connected to lines
D15 of the IDE bus (wouldn't be the MSB
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.
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 deﬁnitely 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: ﬁrst 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: ﬁrst 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:
R/-Wsignal tells us the direction of data.
-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.
|0||0||1||Write to LSB.|
|0||1||0||Write to MSB.|
|0||1||1||Interface not addressed.|
|1||1||1||Interface not addressed.|
And this table shows the states of the various 74LS646 control lines
depending on the values of
-MSB. As in previous truth tables, / signiﬁes a rising edge.
|Inputs||LSB Register||MSB Register|
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
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).
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 to
CPABfor the LSB register) to provide a rising edge. Phi2 is the other NOR input. Since the 6502 makes available valid data and
R/-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 speciﬁc 74LS138 outputs drop to the low state.
Easy stuﬀ 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