Methodology

When building something complex like this, especially on a breadboard with an unproven design, it makes sense to build the system up with the smallest iterations possible. If you read through the Grappendorf build log, this is what he did, and I’m glad I followed in his footsteps.

  1. Build clock circuit, reset circuit
  2. Add the processor, hardwire a NOP (0xEA) on the data bus, and make sure the processor cycles the address bus.
  3. Wire in a ROM. It should have a reset vector pointing to a routine that will jump to itself in an infinite loop. You can then check the addresses being accessed to make sure the system is hitting the address you intended.
  4. Add the ACIA into the mix. This time, the reset routine should initialize the ACIA and start sending some text. (Notice that we haven’t added any RAM yet!)
  5. Add the SRAM. Add a test routine to ensure it’s working (sounds simpler than it is - research RAM testing algorithms).   Now we just have to build BIOS routines, a monitor, and a BASIC implementation and/or an Operating System!

  CNP-1 Simple

Challenges

I only ran into one serious issue - The WDC 6551 has a hardware bug causing the tx ready bit (“Transmitter Data Register Empty” bit in the Status Register) to be stuck on. What this means is that if you poll this bit to see if it is safe to write the next character, you will actually be overwriting the value as it is being shifted out and you get garbage on your terminal. Argh!

At the time I was doing this, there was no information regarding this in the 6551’s datasheet. Luckily - the 6502 forum had some info (and I had a CHEAP logic analyzer from eBay to help me know my characters were being delivered to the 6551 intact), so this wasn’t too difficult to track down. (The datasheet seems to be updated now.)

As listed in that same forum post, the fix when attempting to poll for transmit ready is to simply add a delay loop after writing to the output register of the 6551. Something like…

        lda #$d0    ; Load decimal value 208 into the accumulator
delay:  dec         ; Decrement the accumulator
        bne delay   ; If accumulator != 0, jump back to the delay label

  You’ll notice that $d0 is a carefully picked value to make the CPU (running @ 1MHz) loop long enough for the 8 bits to be shifted out at 19.2Kbps. This is obviously not ideal as we must calculate this value for each combination of CPU speed & serial baud rate.

One thing I haven’t explored yet - the forum posts regarding this topic indicate that this stuck bit causes the 6551 to constantly assert IRQ. If this is true (and you want to avoid busy-waiting), the only option left is to use the timer built into the 6522. This is as annoying as it is wasteful.

Hey, it works… CNP-1 Simple Boot Screen