Sunday, 10 November 2013

Hardware problems, XMODEM, and musings on programmable logic

In my last post I mentioned the problems I've been having with powering my computer. A multimeter on various ICs shows a big drop across the power pins on some of the ICs. The AY 3 8912, for instance, was getting only about 3V. I have worked around these problems by using an additional power source to counter the voltage drops. I have also bought an old computer PSU. These are nice because not only can they supply high currents, but they also have lines for pretty much any voltage I will ever need; 5V, 12V, 3.3V etc.

Sadly I have made a big blunder: in playing with the power supply I inadvertently connected the power around the wrong way, frying the 6809, RAM, EEPROM and CompactFlash. Very annoying, but completely predictable because I didn't use the correct power connector onto the breadboard. Luckily I have spares for the 6809 (at least a 4Mhz version) and memories, but will have to buy a new CompactFlash and eventually a replacement 8Mhz 6809.

In any case none of this is very satisfactory and should not be necessary either since the Apple USB power supply I am using should be well capable of powering the computer. So after reading about other peoples similar problems I have had some sucees in getting the whole computer powered by the original USB power supply.

The two tweaks I've done so far seem to have mostly fixed the voltage drop:
  • Instead of chaining the breadboards together, and making the length of power wires and number of connections larger and larger as more boards are added, the boards are instead arranged in a star.  So no board is any more then one board away from the power connection.
  • I have also added some decoupling capacitors (100uF electrolytics) to each board.
The voltage drop has now all-but disapeard.  I would still like to switch to using the PC powersupply at some point because eventually the USB power supply will reach its limit, but I'll have to make it impossible to plug in the power supply backwards first!

Since I no longer have a working CompactFlash card, I need another way to get programs into RAM if I'm going to continue working on "user" programs. Since I have the serial line, the logical thing to do is use that. There are several methods for sending files down serial lines, including XMODEM, YMODEM, ZMODEM and Kermit.  The simplest is XMODEM.  It is so simple in fact that I've implemented it in the monitor in few dozen lines of assembly.  I can now transfer files from the terminal program (minicom) into the computers RAM.  It isn't perfect though; because XMODEM file transfers are initiated by the receiving terminal, there is a small delay before the file transfer starts as the sender has to timeout.  It works well though; I can send a program from the Linux PC into the 6809 computer and run it, just as I had with the CompactFlash.  I'm of course still going to buy a new CF card so I can work on the Minix filesystem code.

Programmable Logic then.  I have wanted to try my hand at programmable logic for many years.  Ever since I found out about the ULA in the ZX Spectrum, the idea that a generic IC could be configured carry out almost any logic function seemed compelling.  And modern versions of this idea, namely CPLD (Complex Programmable Logic Devices), and FPGAs (Field Programmable Gate Arrays), are available now to the hobbyist, people like me!

In terms of uses to put to this technology my eventual aim is to implement some kind of simple custom IC for my 6809 computer. Hopefully it will contain various functions including replacing the glue logic (currently implemented in 74HC discrete logic), and some communications functions like an SPI controller, to replace the bit-banged SPI in the VIA.  There are quite a few other possibilities, like a simple display controller, or I could design my own sound interface.

But that is in the future.  I know next to nothing about this area, except some theory.  I have yet to find out anything detailed about the various HDL (Hardware Definition Languages) available, but will probably experiment with Verilog first.  I need to select which vendor to use, and select what parts from that vendor are suitable:
  • Generally it has to fit on my breadboard. Modern FPGAs have hundreds of pins and are surface mounted. 
  • It has to use 5Vs, since this is what the computer uses.  Again, modern PL devices run on 3.3V or lower.
  • Ideally the programming environment should run on OS X and should be free.
  • None of the parts should be too expensive.
So far I have narrowed my selection to Altera or Xilinx and there CPLD parts.  Both companies offer free tooling software, though unfortunately only for Windows or Linux and not OS X.  I have setup a Windows 7 virtual machine though.  So far I have installed the Xilinx tools (ISE) but the Altera software refuses to install correctly.  I will percivere but if I don't get any luck I will likely go with Xilinx anyway; the tools look good and the actual CPLDs are cheap.

Assuming I go with Xilinx my shopping list so far looks like the following:
  1. XC9572PC44-10C (PDF) (several)
  2. PLCC->DIP adapter for the breadboard
  3. PLCC socket for when I eventually use the parts in a PCB 
  4. Xilinx USB Cable Platform 
  5. PLCC extraction tool
Hopefully the whole lot shouldn't cost more then £50, which will include a couple of XC9572s.  These are 5V CPLDs with 72 macrocells and about 1,600 useable gates.  This should easily be enough to implement all the glue logic I will need, as well as a communication controller or two in a single IC.  The fact that these parts are PLCC is a bit of pain, but luckily there are DIP adapters so I can still use the breadboard.

But first up I will be happy to get something really simple, like a counter, running in the CPLD.

I have to thank the folks over at for there guidance with checking that my plan for getting into Programmable Logic wasn't completely nuts...

Tuesday, 5 November 2013

Sound, and running programs from CF

My investigation into MinixFS has revealed a nice and simple filesystem; probably the simplest filesystem which you could implement which has UNIX-like semantics.  It has inodes, permissions, and all the usual UNIX things, but (luckily for me) the first iteration of Minix-FS mostly uses 16 bit datatypes.  This means it is "fairly" easy to interpret the data structures which make up directories, superblocks and inodes.

So far the following filesystem code has been written:
  • MBR parsing reads the offset into the first partition (if there is no MBR then the entire disk is the partition).
  • From this offset, the Minix superblock is read in.  From this block, the filesystem type can be determined, and the offset into the inode table can be worked out.
  • inodes are 32bytes long, so 32 inodes can fit in a 1Kbyte block.  Inodes are stored in consective sequence following the superblock.  So to read the inode number N, N needs to be divided by 32 to work out the block number to read (with the inode start offset added), and then the remainder used to work out the starting point of the inode within the block.  This, of course, can be done with bit shifting and masking.
  • inodes contain links (block numbers) to data blocks, for both files and directories.  They also contain a 16 bit word with bits for type (file, directory, symlink etc) and permissions. Also an inode contains the file (or directory) size in bytes. Of course the filename is not in the inode, but is instead in a directory entry. A routine has been written to summarise this info, for a given inode.
  • Directory entries are 32bytes long, with the first two bytes holding the inode number, and the remaining 30 bytes containing the file or directory name, padded with null characters.
  • So to list a directory by inode, the inode needs to be read in, and the datablocks followed.  For each directory entry the name can be retrieved.  To know if the entry references a file or directory, the inode for the entry can be read in, and the type (directory, file, devnode, etc), file size and permissions can be determined.  Without following the inode pointer when listing a directory, only the filename can be known.  Linux's ls command works the same way; only if an option like -l is given will inodes be loaded for each file to be listed.  This is the "l" monitor command, which takes an inode number for the directory to list.  0001 is the root inode.
  • To read the content of a file by inode, a similar process can be followed  except that the referenced datablocks are file data and not directory entries.  This is the "f" monitor command.  It takes a starting memory location and an inode number.
So far the above has been implemented and I can list directories and read files into RAM, but only through an inode reference.  Eventually reading a fie or directory by filename will be done.  This requires string matching of the files in the directory entries, something that is not entirely trivial in 8bit assembly.

One interesting quirk of reading this data from the CompactFlash is to do with endianess.  Since the Motorola 6809 is Big Endian, all words (and longs) that are read from the CF which are things like block numbers or file sizes have to be byte swapped, because the CF is written to be a Linux PC.

The following screenshot shows the monitor being used to mount a partition, read the superblock, list the root directory, and then read a file (me.jpg at inode 2) into RAM.  When listing a directory, the inode number, type (with file mode), and file size (in hex) is shown.  Not very user friendly, but serviceable. The first 64 bytes of the file, now in RAM, at $4000 is then displayed.  You can see it is a JPG file from the first few bytes in the file.  Reading a file by filename will be much more useful then reading files by inode number!

While working on the monitor, I finally took the plunge and restructured the code for the ASxxxx assembler.  This has a number of advantages, including much friendlier ways of holding static data (including null terminated strings) in the code, and it generally has a more "modern" feel to the assembly syntax, using 0x instead of $ etc.  The monitor is now spread across half a dozen files, with a file for serial communications, a file for string handling etc.

At the same time, some of the "reusable" monitor functionality is now exported through a jump table.  Jump tables are an age-old technique for publishing APIs (in this case, through a function number) to user-level code through a table of subroutine jumps.  Thus, to execute a particular ROM routine (to output a string to the serial port, say), the user-level code meerly jumps to the table position for the routine in question.  The table, in term, is a sequence of jump instructions into the real routine.  With this technique, if the location in ROM for the real routine has to change because of implementation changes, then only the jump inside the jump table needs to change.  The position that the user level program jumps to can remain the same.  Thus the "binding" between user code and ROM code can be static and nothing needs to break when the ROM is changed.  As long as newly exported routine jump table entries are added to the bottom of the table, and not anywhere in the middle, the routines available to user code can be expanded.

None of this really matters to my little computer; I could easily rebuild user programs when the ROM is changed and just use direct jumps instead of indirect ones.  But it is satisfying to do things "properly".

With all this in mind, I have implemented two real programs which are loaded from CompactFlash and executed as user code:
  • showtime.bin: performs SPI reads and displays the time, much like the "t" command in the monitor (which has now been removed).
  • settime.bin: prompts the user to enter the time and date before performing SPI writes to set the time and date accordingly.
These programs uses the SPI APIs and does not hit the VIA directly. Thus even if I was change to hardware (to a dedicated SPI bus driver say) these programs would still work as long as the API remained the same.  Also, only PC relative addressing is used inside the user-level program.  The programs can thus be loaded into memory at any location.

The following screenshot shows these two programs in action.  The settime program (at inode 3) is read into location $4000, and the showtime program (at inode 4) into location $4200.  Each program is then run:

The new monitor code, as well as the two user programs have been added to github, in case anyone is interested.

Another thing implemented in the last few of weeks is sound.  I've had a couple of General Instrument AY-3-8192 chips in the parts drawer for months, and have finally got around to integrating them into my circuit.  These chips (and there variants) were amazingly popular and were used in many home micros including the Sinclair Spectrum 128K, Atari ST, and many, many arcade machines.  These ICs are a little unusual in that they were designed to integrate seamlessly into GIs slightly strange CPU bus.  This bus has multiplexed data and address lines, and instead of Chip Select, Read Write and friends has Bus Direction and two Bus Control lines.  Glue logic is needed to convert the 6809 R/W and CS signals into the BDIR and BC lines needed by the sound IC.  After playing with several glue logic schemes, I ended up using the same logic as Matt Sarnoff used in this 8bit computer.

In summary my computer now beeps when it starts! I have written some generic sound routines, but unfortunately I'm not musically talented... I might have a go at covering some sheet music later though.

In other hardware news, I am now using the PCB I made up for the core computer. Here is a picture of the top of the board:

The decoupling caps are yet to be soldiered.  Seems to work ok without them, but I'll get round to it one day.

And here is a picture of the bottom:

As can be seen there were a couple of small errors:
  • The largest and most embarrassing problem is with the rest button. Somehow when making a lovely custom PCB footprint I managed to get the orientation wrong. This required cutting a track and a small jumper wire.
  • The crystal was not given enough room. I fixed this by standing the crystal off the board by a few mm, just enough to clear the lead of a nearby resistor.
  • I really wish I'd remembered to leave room for the feet, or (better yet) include some holes for some proper mounting posts.  Next time....
The final problem is more subtle and a little unknown. It has to do with the first line of address decoding. This is done with a 1 in 4 decoder, which generates RAM, EEPROM and IO enable signals. In most of the 6809 circuits online the decoder is always enabled; the outputs will continually reflect the address bus. But I found this to cause some glitching because the address bus is not updated "atomically" so in the circuit I had made up the decoder is enabled by an inverting Q signal. I noticed this problem with the latch-drive LEDs. Sometimes activity on the serial port would flash the LEDs., which should of course never happen. Per the datasheet Q goes high when the address is on the bus. This worked well, until I added the IDE interface which only works when the address decoder is always enabled. So it is all a but tricky. Currently the circuit is in the always enabled state and everything "seems" ok but I may try other combinations of address decoder enabling. I'm getting quite good at hardware hacking with a soldering iron, so could try out some other schemes for controlling the first line address decoder, and if I do ruin that board I have four more.  It's equally possible that I'm seeing problems only because of using socketed glue logic.

I have made one other cool improvement which I'm really happy about. I have now ditched the 6850 UART in favor of a 88C681 (PDF) DUART. This is an 8 bit bus compatible version of the 68681, a DUART for the 68000 series of MPUs released by Motorola around 1985. Other then having two UARTs in one, the other big advantage is that it has an integrated baud rate generator. This allows me to divorce the system clock from the baud rate used on the console. My computer is thus now running on a 8Mhz crystal, with a 3.864Mhz crystal now driving just the DUAT. I have taken the opportunity to crank the monitor baud rate up to 115,200 baud in the process. Software wise, interfacing this chip was only moderately harder then interfacing the 6850, with just some extra registers to setup. It is still polled; interrupts are something I would like to look at soon.

Here's a picture of the PCB hooked up to the breadboard:

I jury-rigged a 3.5mm socket out of a small piece of stripboard and a socket which was salvaged from an old MP3 player.  Quite pleased with this bodge: the socket is "surface mounted" to the back-side of the strip board.  I had to splay the leads slightly to get the (non 0.1") connectors onto the stripboard track, but it seems to work well.

One small problem I'm having is with power. The various IC in the circuit consume more power then can be reliably drawn from a USB hub. While I have always wanted a bench PSU, I think I will instead buy an old PC AT power supply.  They are a damn site cheaper, and I'm unlikely to ever need anything other then 5V.  A good computer PSU will easily give me 10A at 5V, far more then my little computer will ever need, even with its inefficient NMOS parts.

And here are the two circuits. First the core computer, much as it was in the last post:

And finally the long awaited IO circuit:

Future plans now include:
  • Get filename searching working. in the filesystem code.
  • More sounds with the AY. Maybe Greensleaves because I like the tune? Or another simple tune.
  • Investigate the address decoding oddities.
  • Play with interrupts.
  • Start designing a proper SBC board incorporating the DUART and IDE interfaces, and possibly sound and the VIA.
Fun, fun, fun. :)