Saturday, 27 April 2013

Monitor progress

So far the monitor can do four things:
  1. Dump memory contents in hex and ASCII (d command)
  2. Write memory contents in hex (w command)
  3. Exit the monitor and run arbitrary code (e command)
  4. Show the registers as they were just before the monitor was reentered (r command)
For ease of parsing each command is a single character.

Monitors are generally implemented as a big software interrupt handler. When external code needs to be run, a "rti" (return from interrupt) is performed, directly after modifying the return address ie. the Program Counter as it was just before the monitor was entered is modified to point at the external code. To return to the monitor, external code should do a "swi" (software interrupt).  This will cause the entire CPU state to be saved to the stack.

Probably the most complicated code written so far is for the ASCII to byte conversion. Each time a memory address or other data needs to be displayed, or read in, it needs to be converted. This would be trivial in C. I'm slowly gaining profficency in 6809 asm though and am enjoying the change of pace from languages a million miles away like Perl and C which I'm more used to using.

The parser, while not good at spotting every user error, is fairly flexible and will parse a stream of ASCII space-separated hex into a list of bytes and words with markers to indicate wether a byte or word, or the end of the list, was found. On the downside I'm still to implement backspace key handling.

The following screenshot shows how a trivial program is input, in machine code, at memory location $2000, dumped back out to check it was loaded successfully and ran. Finally the registers are displayed, showing what they were when the trivial program is finished and the monitor is reentered:

The program is as follows:

2000   lda #$40    86 40
       ora #$02    8a 02
       swi         4f

As you can see, the A register has the value $42 ($40 OR'd with $02) when the monitor is re-entered, and the progam counter has moved on to location $2005. Other registers will have fairly random values.

As it currently stands the monitor is not terribly useful, but it's getting there.

The next stage, after finally implementing backspace handling, is to implement EEPROM programming in the monitor. The rough plan for the uploading command is:
  1. Copy the whole monitor code to RAM
  2. Jump to the upload subroutine in RAM
  3. Read from the serial port 16Kbytes for the EEPROM image and write it to RAM
  4. Send the image back to the uploader machine so it can check it
  5. If the uploader isn't happy with what it received, it will output an N
  6. If its ok the uploader will send a Y and the monitor will copy the RAM image into the EEPROM
  7. Either way a reset will be performed
The reason for the convoluted copying is twofold.

First the monitor shouldn't be overwritten while its running. That way leads to madness. Second the upload should be validated before being made active, and overwriting the current EEPROM code. The idea is that if the upload was corrupt for some reason, the current monitor won't be lost. Luckily there is 32KByte of RAM available to hold the whole EEPROM image (which is 16Kbyte). Of course a plain old bug in the monitor could still cause me to reach for the EEPROM programmer, but generally this approach should mean I can improve the monitor more quickly.

Other approaches to solving this problem are possible. One way would involve using a loader program which is protected from the main program and never normally overwritten. Even if junk was uploaded it would still be available, and this loader "mini program" would always be run on reset instead of the actual monitor. This is probably more complicated then the plan outlined above, so I will choose the simpler option.

Thursday, 25 April 2013

Serial communications and the start of a "monitor"

"Monitors" were pouplar tools for debugging programs, along with other useful facilities. Some were also powerfull enough to be considered development environments in there own right. They provided the user with the ability to read memory content, modify memory contents and registers, execute external code, set breakpoints etc. Some had built in assemblers and dissasemblers. I will be writing my own, without external reference except to old books and datasheets. This will form the building blocks of the computer's software and allow me to experiment with talking to different hardware devices, as well as improve my knowledge of the 6809.
The input and output to the monitor is on RS232 via the previously described 6850 UART (PDF), so the first thing to do is get that working. No graphical display for my computer just yet!

Here I found the first big problem: baud rate generation. The 6850 is extremely basic in this regard, and lacks a proper baud rate generator. Instead it can only be configured to use the E clock asis, or divide it by 16 or divide it by 64. Since my E clock is at a quater of the crystal frequency (at 4 MHz) this leaves me with no useful baud rates: 1000000, 62500 or 15625. None of these are even close to standard rates.
There are two solutions:
  1. Use a dedicated baud rate generator circuit with its own crystal.
  2. Switch the main crystal to something more useful for baud rate generation.
Option 1 is ideal but requires extra circuitry and I have very little room as it is. As it happens a 3.6864 MHz crystal is available, which when divided down by 4 and then 16 yields a nice and standard 57600 baud rate. So I duly ordered several of these. Actually I meant to order 3 but ended up with 12 because I didn't notice that they were being sold in batches of 4!

Of course a downside of this change is that my computer is now a tiny bit slower then it was with the 4 MHz crystal. Oh well.

In addition to the UART the circuit also needs a level shifter. This is because RS233 generally uses -12V and +12V signalling levels, vs 0V and 5V used in TTL. A MAX232 IC fits the bill nicely, and only needs four electrolitic capacitors to form a complete circuit. Whilst I could have used the same USB serial port converter as on my EEPROM programmer, I feel that this is not in the spirit of the 80s tech the rest of my computer uses.

Programming the UART is fairly simple. It has four 8 bit registers:
  • Read data to receive
  • Write data to send 
  • Read status
  • Write configuration
A single Register Select pin is used in combination with the R/W pin to select which register to manipulate. Register Select is connected to A0. With the same address decoding as used on the LED output circuit, the UART is therefore at addresses:

$8000 - send and receive data
$8001 - status and configuration

The 6850 has three Chip Select lines, to aid in address decoding. But since I already have an address decoder, only the active low CS2 line is required.

The only other connections of note are the E signal and rx/tx clocking inputs. All 3 are connect to the MPU E line. (If I had an external baud rate generator it would connect to the rx/tx pins instead of using E.)

That pretty much describes the circuit:

As usual, a postscript version can be downloaded here.

Software wise, the first job is to test my understanding of the UART by running some code.  A way to do this is to write a program which can both output text to the port, and read user input. To keep things simple, polling instead of interrupts is to be used.

The 6850 is configured through the configuration register. The UART must first be reset, then the comms parameters configured.  In my case I need a divisor of 16 on the clock, and 8 databits without parity. Also interrupts should be disabled.

Sending data is as simple as polling for "transmit empty" and when it is writing a byte. Receiving is similar; poll for "receive full" and then read a byte. Subroutines for sending and receiving strings (or any other data) can be built up out of these basic blocks.

Thus the serialtest.a program was written. It will output a greeting, then wait for some input before echoing the input back to the user, before looping back to waiting for another string. It is fairly crude and does not support backspace or any input editing, but it works well. In addition, because serial terminal software does not generally echo keystrokes directly, each byte is sent back to the terminal as it us received. Thus the user can see what they are typing.

The code is on github, for anyone curious.

And here is a picture of breadboard, along with a screenshot of the program in "action". The terminal software used was minicom, running on ny linux box, which in turn was accessed over SSH on my Mac.

I have "bodged" serial input into the computer via the breadboard by removing one of the plugs from a null modem cable and soldering on three PCB pins. This is the grey lead coming onto the board at the bottom left.

The next task, which I've started, is to turn the setialtest.a program into a monitor. I doubt I will ever write an assembler, but for debugging code cross-assembled on my linux machine it should prove invaluable. One other use I plan to make of the monitor is to make the EEPROM programmable from the 6809 directly. Once this is done I can try new programs without having to move the EEPROM chip from the 6809 breadboard to my homemade programmer and back again...

[This blog post had to be rewritten due to the Android "blogger" software consuming the finished posting.  Utterly rubbish "modern" software which I have now removed from my phone. Thank you Google!]

Sunday, 14 April 2013

EEPROM progammer finished, and perspective on a 1982 progamming book

The EEPROM programmer is finished!  I soldered up the PCB, and after fixing a couple of issues it checks out.  My programmer has some very bright LEDs, and to show them off I've added a new "debugdelay" option to set how fast the programming should happen.  In the process I've removed the old "debug" option because the 8KByte flash in the ATMEGA8 is now full.  It wasn't really that useful once the code was shown to be working anyway.

Top of the programmer PCB:

Bottom of the programmer PCB:

As you can see a couple of small modifications were needed:
  • The 3.5mm jack socket was too far from the edge of the PCB, such that the plug was blocked by the edge.  Cured by hacking out a notch in the board.
  • The EEPROM socket had no power pins connected.  This was cured by the addition of some unsightly jump wires. 
Luckily I noticed the missing power connections to the EEPROM before I soldered the decoupling caps.  This meant I could use the holes meant for the capacitors for the jump leads.  The caps are just a "nice to have" really, hopefully.

Anyway, the programmer is done and works just lovely!

I'm now knee deep in learning 6809 assembly.  From a modern perspective, it's an extremely labour intensive way to write code, but it's fun.  In comparison to other 8bit MPUs the 6809 was clearly quite a way ahead, with its addressing modes and "massive" selection of registers (9, including 2 general purpose 8bit accumulators).  But it remains far behind it's 16bit big brothers, such as the 68000, in terms of ease at which it can be programmed in assembly.

Whilst there's a fair amount of info on this processor online, there's no substitute for a contemporary book on the subject.  So I bought one: Programming the 6809, by Rodnay Zaks and William Labiak, published in 1982.  As well as a useful technical resource, it's also got some fascinating insights into programming computers in the early 80s.  Some interesting quotes:
Programming also requires a strict documentation discipline. Well documented programs are understandable to others, as well as to the author.  Documentation must be both internal and external to the program.  Internal program documentation refers to the comments used in the body of a program to explain it's operation. External documentation refers to the design documents that are separate from the program including, written explanations, manuals, and flowcharts.
 This is as true today as it was in 1982, the fixaction on flowcharts perhaps notwithstanding.

Another gem, illustating the simpler times:
The representation of alphanumeric data, i.e. characters, is completely straightforward: all characters are encoded in an eight-bit code.
 If only that was still true!

Friday, 5 April 2013

We have some RAMs

The next "milestone" for the 6809-on-a-breadboard computer project is to gain some RAM.  Computers can't do very much unless they can store things.

This was fairly easy, though I did have to fix one problem with the current circuit.  I need to do some more research on this subject to understand the issue fully, but briefly...

Previously, in the EEPROM only test, I was feeding the E (Enable) output from the 6809 through to the Enable pin on the address decoder, which was then used to form the Chip Select for the EEPROM. Meanwhile the /OE and R/W line for the EEPROM came more or less directly from the R/W line on the 6809.  This works ok (but wrong) when only the EEPROM is in play, but is not sufficient or correct when RAM is added.

The adjusted circuit instead uses a tied low (always active) E pin on the decoder, and instad combines the E and R/W pins on the 6809 to form the R/W and /OE on the EEPROM (and RAM).  This is shown in the bottom left of the diagram.

The decoder's remaining two outputs are ORd (inverse logic means an AND gate, formed from a NAND and a NOT) together to form the /CS of the RAM, meaning the lower 32KByte of the 64KByte total address space is Chip Selected into the RAM chip.  I found an Aliance AS6C4008 (PDF) static RAM on eBay for a few pounds; it is a 512KByte, 32pin PDIP IC.  Obviously 512KByte requires more address lines then the 6809 has (19 vs 16).  In time I might devise a bank switching circuit to make use of this "massive" memory, but for now my circuit uses only 15 lines, yielding 32Kbyte, and ties the other four low.

The RAM is at the right.

To exercise the RAM, and prove that it is working correctly, I have made some changes to my test program:
  • It now makes use of a couple of simple subroutines (which involves the use of a stack in RAM)
  • The pattern of LEDs to show is copied from EEPROM to RAM at startup, and then shown from RAM
  • The pattern is modified (inverted) after it is shown, so the next pass through the loop will show a reversed pattern
  • The delay (speed) that the pattern is shown is held in a memory location and adjusted on each run through
The updated program (ramtest.a) is on github, as usual.

And here is a picture of the breadboard:

It's getting crowded in there!  Right of the MPU (middle row) is the 4 in 2 address decoder, NOT gates (74HC04) and NAND gates (74HC00).  The RAM is at the bottom middle.  Left of it is the unwired MC6850 UART, which will be my next addition.  That IC is the oldest on the board, dated the 18th week of 1982.  It shall be interesting to see if it still works (I would be amazed if it did not).

Today at work I received the PCB for the EEPROM programmer.  Total time to have the board made up in China and receive the board - less then 2 weeks.  Pretty impressive stuff.  Total cost, of 10 identical 10cm by 10cm boards, was about 37 pounds.  Hopefully I will get a chance to solder up the board over the weekend.  Whilst I'm happy with my stripboard programmer, the PCB version certainly looks a lot nicer.

Thanks again to Richard Gellman for turning my circuit into a PCB design!

Monday, 1 April 2013

6809 LED output test

Now that I can reliably write data into the EEPROM, the next step is to build the simplest possible working 6809 computer, in order to test my knowledge of how a system built from a 6809 should function.

After looking at how Ben Ryvers built up his Z80 based computer, I decided to borrow some of his ideas for a trivial test.   The idea is that test data - a sequence of bytes indicating which LEDs should be on and off, held in ROM - will be outputted.  Once the sequence has ended it is restarted.  As simple as can be.

My test-bed 6809 computer consists of:
  • 6809 clocked by a 4Mhz crystal
  • The 28C256 EEPROM
  • 8 bit latch which drives a 10 LED bar graph
  • Glue logic
For this test, the computer has no RAM at all.  This, of course, makes writing even a trivial test program slightly challenging, but luckily the 6809 has enough registers that temporary storage is not a problem.

The memory map for this setup is completely trivial.  When started, the 6809 reads a 16bit startup vector from memory location $fffe.  Therefore ROM has to live at the end of the memory space.  In this case, 16KByte of ROM will be available at $c000 to $ffff.  The other half of the 32KByte EEPROM isn't mapped.

It is helpful to consider the memory map in terms of the high nibble, in binary:
  • 0xxx - RAM (in the future)
  • 10xx - IO
  • 11xx - EEPROM
Each "type" of device needs to be selected from the upper 2 address lines, which are fed into a 1 in 4 decoder.  Since there isn't any RAM yet, only two decoder output lines are needed.  A typical decoder, which I've used, is the 74139, which has a pair of 1 in 4 decoders.  One generally useful aspect of the 74139 is the outputs are inverted, which is nice because memory and similar devices nearly always have an active low Chip Select (or equivalent).

To avoid the risk of the 6809 modifying the content of the EEPROM, the R/W line on the EEPROM is tied high.   The /CS line for the EEPROM is derived from the address decoding, described above, whilst the /OE line is form by the negation of the R/W signal on the 6809 (alternatively it could be held low, but this will not be useful when the EEPROM is programmed in-place).

In this simple case, "IO" consists of a single 8 bit latch - I chose a 74HC574 for this purpose.  Attached to the outputs of the latch are 10 LEDs in a bar graph (the end 2 LEDs are unused).  Since the latch is clocked on the rising edge, it is necessary to invert the IO enable signal from the address decoder.

Two push buttons, one for /RESET and one for /HALT, and a 4MHz crystal with caps complete the circuit:

You can download a postscript version.

The code, in good old fashioned assembly - such as it is, is on github.  Note the $4000 delay loop.  This sets the speed of the pattern.  This is equates to a delay of about a half of a second with the 1Mhz clock.  This program is my first crack at assembly programming since the mid to late 1980s, on the ZX Spectrum!

To turn the assembly file into a ROM image, I used a09 (available here), along with hex2bin to form the 16Kbyte ROM image, which of course is written out to the EEPROM using the upload tool previously written.

I did make a video of the "computer" in action.  Unfortunately it seems I'm unable to upload videos to this blog.  You will have to make do with a picture instead:

As you can see, the breadboard is a mess - extending the busses is going to be difficult.  Power is provided by the same IDC header used by the EEPROM programmer - only the +5V and 0V lines are used.

Amazingly the circuit worked first time.

The next step is to decide what the next step is. ;-) I can either add some RAM and play with some more advanced testing towards making the computer "useable", or I could try to get an old UART working.

I suspect I will try my hand at the RAM, since a serial port is, after all, only a "peripheral"....

Update...  Finally figured out that the way to get videos on my blog is via youtube.  So here is that video: