Saturday, 28 September 2013

SPI, IDE, and a PCB!

It's been another couple of months with no blog update. Busy busy. Anyway. In the few hours here and there (work lunch times, early morning, etc) I have managed a fair bit of progress.

Firstly I've laid out the circuit again on some fresh breadboard slabs. I'm fairly sure the breadboard I used previously had some bad links, because the circuit is now miles apart to how it previously was from a reliability point of view. I've also broken it into two halves, with the core computer on one set of breadboards and IO on the other. A bunch of ribbon cable joins the two halves, with 16 strands for address, 8 for data and a bunch more for power and the various control lines. All in all I'm very happy with the new, slightly neater, breadboard setup.

Everything was working great on the new breadboard except.... I2C. More specifically, the PCF8584, which just didn't want to work right in it's new home. Actually I was never really happy with this device in the circuit; it never quite achieved 100% reliability, and the code was always a bit strange because it didn't conform to the datasheet. In the end I decided to try something new: SPI.

SPI serves a similar purpose to I2C in that it links ICs to ICs, typically microcontrollers to memories, sensors and other devices. There are a number if differences though:
  • Generally simpler signalling because in and out are on two different wires. No pesky ACKing of bytes, or any ACKing at all for that matter, unless the programmer implements it themselves.
  • Speeds in the Mhz range, vs I2C which is a few hundred KHz, not that it makes much odds here.
  • The specification is much more "loose". SPI does not even define word length, yet alone bit ordering. There are some commonalities across devices though.
I did look for an equivalent part to the '8584 but in the end I decided to have a go at bit-banging the protocol. To do this required an I/O port ie. a parallel port with which to assert and receive the SPI signals. I had a number of options:
  • Motorola 6821 (PDF): this was the companion part to the 6850 and features two eight bit parallel ports along with some peripheral control lines.
  • MOS 6522: this part was used in many 8 bit micros. Like the 6821 it has two parallel ports, plus some counters/timers and an in and out shift register.
In the end I settled on the 6522. The timers will no doubt come in handy. Maybe the shift register too.
Bit banging SPI is fairly straightforward. In addition to the in and out serial lines, plus clock there is one enable pin per device. So half of one of the eight bit ports is occupied by the SPI. Each byte to be shifted out of the interface is sent bit by bit, with a toggling of the clock. To keep things as fast as possible, the eight bits are proceed in an unrolled loop. Just updating a counter each time a bit is sent would slow things down. Reading a byte is similar and uses the carry bit in the status register to move the read in bit into the output byte register.

To test my SPI port I would need a device to talk too. In the end I thought my computer is still going to need a clock, so after a long search - most SPI ICs are not in handy DIP format - I found what I was looking for, a DS1305 (PDF). Similar to the '1307, it is an RTC with an SPI interface. It is not completely equivalent to the '1307 though. It has more pins, but lacks the handy 1Hz output mode. Instead it has two "alarm clocks" which generate interrupts. Storage of the time is pretty much the same BCD format, and like the 1307 it has a few dozen bytes of RAM which might be useful someday.  Currently only four lines on the VIA are being used, which is obviously a big waste!

Suffice to say my computer has a nice fully working clock.  The pictures show the clock being set and then read back in, as well as a grab of the logic analyser capturing a read of the clock.



From the Logic16 screen you can easily see how long it takes to bit-bang the 10 or so bytes.  The clock rate works out at about 32Khz, or around 4KB/s.  Not exactly quick, but quick enough for the small transfers I need to do. 

And here is a picture of the new breadboard setup. One half of the Logic16 is currently attached to the data bus, allowing me to see the full contents of the data bus which is useful for seeing what data is being sent to the various ICs.  You can see this in action in the screenshot above, though nothing useful is done here with the databus signals.  The left hand breadboard is the main computer, whilst the right hand side is for IO.


A summary of the picture.  First the left hand section, from top to bottom:
  • EEPROM in its ZIF slot
  • RAM (buried under a load of wires)
  • Ribbon cable jumping off to the IO section
  • On the middle slab is the 6809 and glue logic
On the right hand set of boards we have:
  • Ribbon cables coming into the boards
  • IO decoder (1 of 8)
  • Serial port (6850)
  • Latch with 8 LEDs used for occasional debugging
  • 6522 VIA and DS1305 on the bit-banged SPI bus
In the picture (right hand side, bottom row) is one other surprise: a CompactFlash card plugged into an IDE (also known as ATA) interface! This is the latest edition to my computer.

Computers are not that useful without some form of mass storage. Having a CF port will allow me to load programs (chunks of 6809 machine code) from CF - after saving them from my linux box - without having to write them into the EEPROM. It goes along way to making the machine a "real" computer, albeit one top of the line in 1980.

IDE is great because all the cleverness is in the hard drive, or Compact Flash in my case. This makes interfacing fairly simple. Early IDE even has an 8 bit mode, though only very early (to the mid 90s) hard disks support it. But luckily most CF cards also do. Beside a direct connection to the data bus the IDE interface also has 3 address lines for accessing various registers, two Chip Select lines, a read and a write line, and thats about it. The CF card plugs into an IDE adapter which then plugs into a 40 pin header block, made up on a piece of strip board, which in turn plugs into the breadboard (phew). Hardware wise that's about it if all you need is PIO mode operation. DMA would be cool but much more complex.

It's the software where things get interesting. So far I have simple sector reads as well as the IDENTITY command working. The code is broken down into two layers: monitor commands and low level IDE commands.

The m (for mount) command sets the IDE interface into 8 bit mode and reads the Master Boot Record, which is at the first sector of the disk. the start of the first partition is retrieved from the Master Boot Record and displayed.

The I (for identify) command performs the IDENTITY command to the drive and reads back a sector (512 bytes)containing various information. The monitor extracts the model name and some other information and outputs it. This command was implemented just to prove everything was working properly.

Finally the < (yes I'm running out of command characters) can be used to read upto 256 sectors from an arbitrary starting point. Because I only want to deal with 16 bit quantities my computer can only access the first 32 megabytes (65,536 lots of 512 byte sectors) of the compact flash. This is plenty of room for the type of storage I need.

The following screenshot shows these three commands being used. First the m command is run, then the identity command is performed before finally the first sector of the disk, the Master Boot Record is read in and displayed.


I didn't think I had a spare CompactFlash card and assumed I would have to buy one specially for this project. But after a thorough search managed to find one, which happened to be 128MB in size, in the bottom of a drawer. I had no clue what was on the card until I started doing some random reads when I realised I had found the old CF that used to be in my old Amiga 1200. Just to prove it, here is a screenshot of a random block, which I think is the AnigaGuide help file for the classic program SnoopDOS.


Of course reading raw disk blocks is only partly useful.  While it is possible to read and write raw disk blocks in a semi-structured way, the famililar way to interact with a storage device is through a file system.  Initially the focus will be on read-only access, with writes (perhaps) coming later.  I have several choices to consider:
  • FAT.  Ie. FAT16.  Everyone does FAT, so I won't.
  • Ext2/3/4.  This would be great but it is likely extremely difficult as even Ext2 is a highly complicated file system.
  • MinixFS.  This is more like it.  The first version of Minix had a fairly simple UNIX-inspired filesystem.  One of the nice aspects to it is that it only supports small (64MB ish) hard drives, which means it has 16bit data types for block pointers and the like.
Unfortunately my efforts to decode Minix are currently on hold, for a very stupid reason: I have no means of accessing a CompactFlash from my Linux PC.  This means I have no way to make a test file system on a CompactFlash, etc.  A USB reader has been ordered from good old eBay and should be with me soon.  In the meantime I'm looking into the format of Minix's superblocks, inodes, and other file system gubbins.

While all this has been going on, I have been engaged in one other area: PCB design.  Since the core of my computer is now effectively a stable design, I have decided I can forego the lefthand breadboard for a PCB, and to this end, one has been designed by yours-truely and in fact, I am now in possession of five identical boards.

In terms of software for my layout, I had a few choices but decided to stick with the gEDA suite.  To that end, I spent several days learning the imaginatively named "pcb".  I have to say the software is fair to mediocre.  Not as polished as the schematic capture tool, but good enough.  In designing a PCB layout I had to be extremely accurate in my schematic design, since the layout of the PCB flows directly from that.  To that end I spent a while getting the schematic for the core computer computer right, fixing some previous problems and adding some nice things, like decoupling caps and tieing off unused inputs.  These then map into PCB "nets".

Considering I know very little about PCB design I think I have done quite well!  First up is the schematic:


You can see everything is now documented in the schematic; even the power LED.  I have added LEDs for the BA and BS CPU signals, as well as a run/halt toggle switch, and a jumper for write enabling or write protecting the EEPROM,  There is also a 40 pin header at the right of the diagram.  This is the header which will join the core computer to the IO breadboard (and eventually PCB as well) parts.

And now a picture of the PCB design:


The dual layer PCB measure just over 10cm by 10cm, which is pretty good I think.  While the gEDA PCB software can autoroute, the results were dreadful and in fact it could not autoroute the whole circuit in "only" two layers.  In the end the whole thing was manually routed, which took probably a couple of man days of effort.  But that did include learning the software as well.

After exporting the design in the right format, I found someone on eBay to manufacture the PCB.  Total cost was about £40, and turnaround time was a little under 10 days.  Pretty impressive!  Coicidently I found the same company that made my EEPROM circuit: Botech Circuits,  I used this item on ebay.


After getting the PCBs home, of course, I noticed a few minor problems.  They should be easy to work around, hopefully.

My next tasks are, roughly:
  1. Investigate the Minix filesystem and have a go at parsing the superblock and root directory in 6809 ASM.  Eventually I hope to be able to read a file into RAM.
  2. Put the updated schematic and PCB (along with the necessary symbol and footprint files) into github.
  3. Solder up and test the CPU board!
  4. I can dream: more IO devices.  I'm especially keen on making my computer be able to make noises!
Hopefully the next post wont be 2 months away...

Links:
  1. http://www.t13.org/Documents/UploadedDocuments/project/d0948r4c-ATA-2.pdf - The spec for ATA-2, the last one to support 8 bit operation.