Hello World on the 65c02

TL;DR. Check wiring before blaming software.

After completing the build of my 8-bit computer based on Ben Eater’s kits, I have now started work on his 65c02 project.

I ran into some issue with the Arduino Mega, but decided to skip that bit for now. Instead, I went on to build the entire thing and proceeded with loading Wozmon on it directly.

To absolutely nobody’s surprise, that didn’t work. So; back to taking a more incremental approach.

Step 1: I built the module with the 65C02, the ROM chip and the versatile input/output adapter. Then, I customized Ben’s sample blink.s program to make it into a nice Cylon (or Knight Rider’s KITT) woosh. That worked! In case you’re interested, that bruteforce code is below. I named the file myblink.s.

Step 2: The next step was to connect up the display module and see if that worked with Ben’s hello-world.s program. No issue!

Step 3: Now on a roll, it was time to hook up the RAM and run hello-world.s again. Bingo! That worked. Next, let’s run hello-world-final.s.

And for sure, that did NOT work.

Step 4: Of course, rather than second-guessing my own build, as any good software engineer, I blamed the failure to run on somebody else faulty code.

All I needed to do was write a short test program to demonstrate that I was right. So, I decided to do just that.

Basically, I took the first four low bits of PORTA and hooked up LEDs to them. The first two bits were toggled by writing directly to PORTA. The second two used three subroutines to toggle the next two pins. That way, I can see that the program is running, and since we already demonstrated that it was fine without needing a stack, it was a good control.

Clearly, this didn’t work either. The first two LEDs toggled just fine, but the last two didn’t. Commenting out the subroutine calls confirmed that Ben’s program was fine after all; it really must have been my build instead of Ben’s code. Who would have thought?

Anyway; after carefully checking all address lines (no issue), all data lines (no issue), and the control lines, I finally identified that my read/write pin was off-by-one on the 65C02.

Running the program again quickly demonstrated that my four LEDs now were toggling nicely.

That meant that the all component involved were working (i.e., the 65c02, the RAM, the ROM, the versatile I/O adapter, and the NAND gates.

And for sure, hello-world-final.s now also worked nicely.

Step 5: All that was left now was replacing the 555-based timer with the 1MHz crystal, and we’re all good.

Lesson learned: Start troubleshooting layer 1.

Next up: Serial interfacing!

 .org $8000    

reset:
  lda #$ff
  sta $6002

  lda #$50
  sta $6000

loop:
  lda #1

ltr:
  sta $6000  ; output value
  cmp #128   ; if we are on the last bit
  beq rev    ;
  asl        ; shift left
  jmp ltr
rev:
  sta $6000
  cmp #1
  beq ltr
  lsr
  jmp rev

  .org $fffc
  .word reset
  .word $0000

ram-test.s

PORTB = $6000
PORTA = $6001
DDRB  = $6002
DDRA  = $6003

 .org $8000

reset:
  lda #%00001111        ; set least signficant bits on port A to output
  sta DDRA

loop:
  ; first try without using ram
  lda #%00000001
  sta PORTA

  lda #%00000010
  sta PORTA

  ; then try with ram
  jsr pattern1
  jsr output
  jsr pattern2
  jsr output
  jmp loop

pattern1:
  lda #%00000100
  rts

pattern2:
  lda #%00001000
  rts

output:
  sta PORTA
  rts

  .org $fffc
  .word reset
  .word $0000