Every 32-bit Acorn machine has, somewhere inside it, a podule bus.  It is often treated as a 'black art', that only companies have the resources to develop for.  In fact anyone with some electronics knowledge, and possibly some experience of bus interfacing, can design and build podules without too much difficulty.  In this series I intend to outline how the podule bus works, and how to interface to it.

Preliminaries

Firstly, what does 'podule bus' mean?  Officially, it's the Acorn Expansion Bus, which has been upgraded with the advent of the Risc PC to support the Extended Acorn System Interface (EASI) and the DMA Extended Bus Interface (DEBI).  But I'll just use 'podule bus', EASI and DEBI where appropriate!  Physically, the cards normally termed 'podules' are defined in the non-Acorn world to be single-Eurocard size, with a PCB of 160x100mm and a DIN41612 connector to attach them to the podule bus.  Early machines (A300/400/5000) also support double-Eurocard size boards, but electrically they are identical - this is just a way to get more components on a podule by taking up twice the PCB area.  The A30x0/4000 minipodule slot, Risc PC/A7000 network slot and A4 econet slot are all derivatives of the basic design, and I hope to cover these in future articles.  A300/400 machines can drive external podules, and A400 series machines have the capability to support a floating point coprocessor by means of extra signals on the podule bus, but these are beyond the scope of this series.

So, you'd like to design a podule?  The first thing you'll need is Acorn's podule specification, which can be found in the datasheets area at
http://www.markettos.org.uk/riscos/techdocs.html
This document is a little, ahem, concise.  Everything you need to know is in there, as long as you already know you need to know it.  I hope in this series to expand a little on this, and design some simple podules along the way.

First, the usual disclaimer.  The podule bus is a bit less tolerant of mistakes than, say, the serial or parallel ports.  If you've only built things to hook up to the serial or parallel ports, then I'd advise a read of a book on microprocessor interfacing, such as chapter 10 of The Art of Electronics (second edition) by Horowitz and Hill and see whether you feel confident.  Usually the worst you can do is stop the machine from booting up, and removing your podule cures this, but doing silly things like putting 12V into a data line only expecting 5V can have permanent effects.  If in doubt, make sure you check your wiring carefully.  Obviously, you do all of this at your own risk.

A note on construction.  Whilst it is possible to build podules on stripboard, often the dimensions of the DIN41612 connector makes this difficult, especially having to cut tracks frequently.  Ideally a PCB would be used, but these aren't ideal for experimenting and are often expensive to make (US$26 is the best I've found for a double sided podule board).  There are a number of boards that are like stripboard but more flexible, such as Tripad (3 holes per strip) or prototyping board (where each hole has a single copper 'island' around it, and wires can be soldered between islands).  Personally I use a mix of all three.

Introduction to the podule bus

So what is the podule bus?  Well, it's really composed of three different buses, which share many of the same signals and can be accessed by reading and writing to different memory areas, known as IOC space, MEMC space and EASI space.  Podules supporting these features are known as 'simple podules', 'modules' (yes, really - that's not a typo!) and 'EASI podules' respectively - but for the sake of this series I'll refer to IOC, MEMC and EASI space where appropriate, since a podule can support any or all of these methods.

All methods are asynchronous.  That is, they are not tied to the system clock but rely on either a certain time elapsing, or a reply being received.  Whilst the bus supplies various clock signals, timing in relation to them is not to be relied upon.

IOC space is a simple asynchronous bus, quite similar to the PC's ISA bus.  The IOMD (or IOC in pre-Risc PCs) initiates a 'request' on the bus, and then a certain time later assumes the result is ready for collection.  This time can be specified as fast, medium or slow to accommodate different speeds of peripheral.  IOC space also provides a synchronous mode to support 2MHz 68xx/65xx series chips such as those used in the BBC - I shall cover this later.  The speed can be selected by the programmer by choosing a particular area of memory to read/write to or from.

Instead of assuming that the reply is ready, MEMC space allows the podule to actively tell the IOMD that the data is ready to be received, and the IOMD will wait until it hears this.  This makes it more complicated, and also incurs the danger that if the podule doesn't notify the IOMD, the machine will hang until it receives it - possibly forever!

EASI space is similar to IOC space, except is 32 bits wide, faster, provides much more address space (16Mbyte) and a variable cycle time.  This will be discussed in a future article, and ignored for the time being.  Until we get onto EASI space and DMA, everything here applies to all RISC OS machines running RISC OS 3.1 upwards (and most to Arthur and RISC OS 2 too!).

Address space

As I mentioned above, each type of podule access is allocated a different address space in the computer's memory map.  IOC fast/medium/slow/synchronous and MEMC space all have their own address blocks.  For example, to find out the synchronous address of podule 0, do:

SYS "Podule_HardwareAddresses",,,,0 TO sync%

On current machines this returns &033C0000.  Bits 19 and 20 determine the speed of the access:

bits 20-19	Type
00		slow
01		medium
10		fast
11		sync

MEMC space is formed from this address by clearing bits 27-16, so for this podule it starts at &03000000.  All these addresses can only be accessed in supervisor mode from RISC OS (but if you want to try them out, investigate the *Memory and *MemoryA commands).

Each podule of either type is allocated 4 Kwords of address space.  By Kwords I mean that there are 4096 address locations which either a byte or a 16-bit value can be read from (in assembler using LDRB or LDR respectively) or written to.  If you happen to have attached a 16-bit wide RAM to the bus, each address read pulls in 16 bits, so 4 Kwords * 16 bits = 8 Kbytes.  Also, since the ARM reads words on 4 byte boundaries, each address is a multiple of 4.  So the first word of the fast space for podule 0 is at &03340000 and the last word is at &03340000+((4096-1)*4) = &03343FFC.  So whilst the podule always has 16Kbytes (4Kwords * 32 bits) of address space allocated to it, only 8 or 16 bits of each 32 bit word are actually useful.  We shall see the importance of this later.

The hardware

Now, let's get down to some hardware.  First we shall consider the most basic signals on the bus.  The full pinout can be found in figure 1 - it looks fairly daunting, but we can ignore most of the signals.  Those in bold are only valid on Risc PCs, and will be covered later.  The main signals we want to look at are /PS, /IOWR, /IORD and the address and data buses (incidentally, for the purposes of notation when I use /PS I mean PS bar - that PS is active when in the low logic condition.  When I say 'asserted', I mean it becomes active - in this case goes low).

/PS is one of the few signals that are different between different podule slots.  /PS supplied to podule slot 0 is really /PS[0], and it means that when asserted that the CPU wants to access the IOC space of podule 0.  When /PS[0] is asserted, all other /PS[] lines are not.  For our purposes we can consider it as the big National Lottery finger saying 'It's You' - in other words, someone wants to talk to us and noone else.

The simplified timing diagram for a read can be seen in figure 2.  Shortly after /PS is asserted, /IORD is asserted.  This combination means the CPU wants to read from our podule.  Taking note of the relevant address lines specifying where the CPU wants to read ***from***, we must present the data to the data bus in a specified time.  The podule spec gives precise timings - for fast mode this is about 375ns.  Then the IOC will deassert /PS, and the data can be removed.

So let's build a simple circuit.  We want to put some data on the data bus when /PS and /IORD are asserted.  For the moment we're going to ignore the address bus, so a read of any address in our IOC space will get the same data.  This can be seen in figure 3.

All logic on the podule bus is powered by 5V, and it is a good idea to use CMOS logic (eg 74HC or 74AC series) to minimise bus loading.  Here we can see a 74HC244 octal buffer being used to place data on the bus by transferring from A to Y when its /G inputs are taken low, otherwise the outputs Y are high impedance (tristate).  This is done when both /PS and /IORD are low (if you are unfamiliar with the bubbles-on-input notation for the NAND gate, it means that we invert /PS and /IORD to give PS and IORD, AND them together, then invert the output again to produce the active low /G signals.  This can be simplified to another logic gate (an OR), but is shown here for clarity).

So, we've built a podule.  Doing:
*Memory b 03340000+1
will read the value on the switches and print it to the screen, if the podule is in slot 0.  You can extend this to any number of switches - for example, use 2Yx as well, or add another 74HC244 and connect it to BD8-15, so that reading a word from that location will return up to 15 bits of switches.  I say 15 bits, not 16, because it's important to keep bit 7 high whilst the machine is reset - we shall see why later on.

One last thing with this circuit - remember I said we had to produce an output within 375ns, otherwise the IOC would try to read the data before we're ready?  Well, it's always worth making sure we're going to meet the timing target.  My databook says that the propagation delay of the 74HC244 is 20ns - this is well within 375ns, so we can be confident the circuit will work correctly.

That's it for this time.  I'll leave you to play with the 15 bits of input you have - just think, it's already more than the parallel port!
