Bring-up testing the 6502

Testing the Ruby 6502

After making it on breadboard, I was already relatively confident that it would work on stripboard and my initial testing went well. I could access the shared RAM from the ATmega, write test patterns into it, read them back and the initial bring-up of the 6502 went well. I wrote a tiny program to take the reset vector and loop to itself which let me probe some data and address lines to see that it was all working, and it was, so next step was to make it do something more useful …

Traditionally…

Most old (and old-style!) 8-bit micros had some sort of “monitor” program that ran at boot time.An early example is WozMon. This would let you edit memory, maybe load programs from a punched tape or audio tape and provide a way for programs to print and take keyboard input. The Apple 1 worked like this.

Often it was hidden away and all it really was was a set of basic input/output subroutines (what we might now call a BIOS) which were used by the main BASIC ROM to communicate with the outside world.

The Apple II, PET (and Vic20/C64), TRS-80, ZX Spectrum, and many others all worked in a similar manner to this

The Apple II did have another trick up its sleeve… It had a full-blown “monitor” that could let you display and alter and move memory, disassemble 6502 instructions, a mini one-line at a time assembler as well as a few more features like some floating point subroutines and a pseudo 16-bit interpreter.

The BBC Micro was slightly different again – come 1981 and some ideas had changed, so it had what we might now recognise as an operating system with well-defined ways to call functions inside the OS to perform text input and output, graphics, sound, disk (and network) filing systems and so on. There was a command-line interface to this Machine OS (MOS), but for the most part, you’d turn the computer on, and half a second later, like most of the other micros of the day, a beep then you were in BASIC. The command-line interface was commonly accessed from BASIC (and other languages) by typing a star (*) then the command, so the phrase “star command” was popular.

The main alternative to this style of computer startup was CP/M. More popular on 8080 and Z80 systems. This loaded from disk and provided a set of basic input and output subroutines (ie. BIOS) and a command-line driven interface. Almost all commands were then loaded from disk into RAM to be executed. Many modern day systems work like this.

What do I do for Ruby?

After initial bring-up testing and writing some basic routines to talk back to the ATmega host processor via the shared memory interface, I started with an Apple II style of monitor. I wrote a somewhat simplified version which let me do things like dump and modify memory, memory tests, poke short bits of code and execute them. I made this with a well-defined interface for character IO and a few utility routines, so that other programs could use it for keyboard and screen input and output and so on.

This worked (and still works!) well. I can use it to run ehBasic and Applesoft BASIC and I’ve also had Apple Integer BASIC running under it too, as well as a few of my own programs. I also wrote a new implementation of Woz’s Sweet16 for it too – to make it go a little faster and remove a (re)location issue it has. (I have plans for a project that will need some 16-bit data manipulation so I thought this might be handy)

This is an example of it in operation:

GMon v1.0. Ready
Copyright (c) 2018, Gordon Henderson
% 0.ff   // Dump RAM from $0000 to $00FF
0000: 4C 3C C4 4C 3A CB 00 00  | L< L:    |
0008: 00 00 4C 99 D1 22 00 6B  |   L  " k |
0010: 00 00 00 04 00 00 00 00  |          |
0018: 00 00 00 00 00 00 00 00  |          |
0020: 00 00 00 00 00 00 00 00  |          |
0028: 00 00 00 00 00 00 00 00  |          |
0030: 00 00 FF DD 00 00 00 00  |          |
0038: 00 00 00 00 00 00 00 00  |          |
0040: 00 00 00 00 00 00 00 00  |          |
0048: 00 00 00 00 00 00 00 00  |          |
0050: 00 F0 55 52 00 07 50 C3  |   UR  P  |
0058: 00 00 00 00 00 00 38 CE  |       8  |
0060: 0A DD 78 00 00 00 03 01  |   x      |
0068: 08 65 09 6C 09 6C 09 00  |  e l l   |
0070: C0 00 C0 00 C0 C8 FF C8  |          |
0078: 00 62 00 00 00 00 08 00  |  b       |
0080: 00 01 82 00 00 00 00 00  |          |
0088: 88 00 05 00 6E 09 00 03  |     n    |
0090: 4C 01 00 00 6C 08 65 08  | L   l e  |
0098: 00 00 00 00 00 90 00 00  |          |
00A0: F0 00 00 00 00 84 F0 00  |          |
00A8: 00 00 00 00 00 0C C3 65  |        e |
00B0: 09 E6 B8 D0 02 E6 B9 AD  |          |
00B8: 08 02 C9 3A B0 0A C9 20  |    :     |
00C0: F0 EF 38 E9 30 38 E9 D0  |   8 08   |
00C8: 60 80 4F C7 52 00 00 00  | ` O R    |
00D0: 00 00 00 00 00 00 00 00  |          |
00D8: 00 00 00 00 00 00 00 00  |          |
00E0: 00 00 00 00 00 00 00 00  |          |
00E8: 00 00 00 00 00 00 00 00  |          |
00F0: 00 01 00 00 00 00 00 00  |          |
00F8: F8 00 00 00 00 00 00 00  |          |
% ?

Unknown command: "?"
% 400:a9 47 20 03 f0 60    // Enter small program to print 'G'

% 400.40f

0400: A9 47 20 03 F0 60 60 B9  |  G   ``  |
0408: 00 FF 99 00 04 C8 D0 F7  |          |
% 400g

Go @0400
G%

Load up Applesoft:

-> Applesoft ... Loading @ $C000. OK: End @ $E880

Remember to set CAPS-LOCK to use BASIC

]PRINT 1/3
.333333333

]

At this point I typed in a program (actually copy & paste as I don’t have any Applesoft filing operations working yet)

]LIST

10 MAXITER = 20
20  LET C$ = " .,'~!^:;[/<&?oxOX#  "
30  FOR Y =  - 21 TO 21
40  FOR X =  - 21 TO 21
50 CREAL = X / 11
70 CIMAG = Y / 11
80 ZREAL = CREAL
90 ZIMAG = CIMAG
95 CT = 1
100 ZM = ZREAL * ZREAL
105 ZN = ZIMAG * ZIMAG
107 ZL = ZM + ZN
110  IF ZL > 4 THEN  GOTO 170
120 Z2 = ZM - ZN + CREAL
130 ZIMAG = ZREAL * ZIMAG * 2 + CIMAG
140 ZREAL = Z2
150 CT = CT + 1
160  IF CT < MAXITER THEN  GOTO 100
170  PRINT  MID$ (C$,1 + CT,1);
180  NEXT X
185  PRINT ""
190  NEXT Y
200  END 




]RUN
...............,,,,,,,,,,,,,...............
............,,,,,,,,,,,,,,,,,,,............
..........,,,,,,,,,,,,,,,,,,,,,,,..........
.........,,,,,,,,,,,,,,,,,,,,,,,,,.........
........,,,,,,,,,,,,,,,,,,,,,,,,,,,........
......,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,......
.....,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.....
.....,,,,,,'''''''''',,,,,,,,,,,,,,,,,.....
....,,,,'''''''''''~'''',,,,,,,,,,,,,,,....
...,,,,'''''''''~~! !~~'',,,,,,,,,,,,,,,...
..,,,'''''''''~~~!![[ ~~~'',,,,,,,,,,,,,,..
..,,'''''''''~~~!!:/O:!~~~'',,,,,,,,,,,,,..
.,,''''''''~~~~!!^<   ^!!~''',,,,,,,,,,,,,.
.,''''''''~~~~!^:;<  o;^^!~''',,,,,,,,,,,,.
.''''''''~~~!!; <     O/[ !'''',,,,,,,,,,,.
,'''''''~!!!!^;          <!~''',,,,,,,,,,,,
''''''~^^!!^^;           [^~'''',,,,,,,,,,,
'''~~!!<;;[:;o            <~'''',,,,,,,,,,,
'~~~!!^;#O  /#            :~~''',,,,,,,,,,,
~~~!!!;                   :~~''',,,,,,,,,,,
~~!^:;OO                  ^~~''',,,,,,,,,,,
                         ;!~~'''',,,,,,,,,,
~~!^:;OO                  ^~~''',,,,,,,,,,,
~~~!!!;                   :~~''',,,,,,,,,,,
'~~~!!^;#O  /#            :~~''',,,,,,,,,,,
'''~~!!<;;[:;o            <~'''',,,,,,,,,,,
''''''~^^!!^^;           [^~'''',,,,,,,,,,,
,'''''''~!!!!^;          <!~''',,,,,,,,,,,,
.''''''''~~~!!; <     O/[ !'''',,,,,,,,,,,.
.,''''''''~~~~!^:;<  o;^^!~''',,,,,,,,,,,,.
.,,''''''''~~~~!!^<   ^!!~''',,,,,,,,,,,,,.
..,,'''''''''~~~!!:/O:!~~~'',,,,,,,,,,,,,..
..,,,'''''''''~~~!![[ ~~~'',,,,,,,,,,,,,,..
...,,,,'''''''''~~! !~~'',,,,,,,,,,,,,,,...
....,,,,'''''''''''~'''',,,,,,,,,,,,,,,....
.....,,,,,,'''''''''',,,,,,,,,,,,,,,,,.....
.....,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.....
......,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,......
........,,,,,,,,,,,,,,,,,,,,,,,,,,,........
.........,,,,,,,,,,,,,,,,,,,,,,,,,.........
..........,,,,,,,,,,,,,,,,,,,,,,,..........
............,,,,,,,,,,,,,,,,,,,............
...............,,,,,,,,,,,,,...............

]

And that works well. I ran a few versions of this under Applesoft and ehBasic and use it as a sort of system soak test.

IO IO, it’s off to work I go …

The final thing to test was my single bit of IO decoding. I wrote a program, connected an oscilloscope to it and the scope trace wiggled as I expected it to. (Actually, not first time, I went through an iteration or 2 of my GAL programming to get it right). I hooked the signal up to an 8-bit latch with the inputs connected to the 8-bit address bus, then I could light up some LEDs.

This video is incrementing a counter each time it finishes a simple memory test:

Blinkenlights are always a good thing and a traditional Larson Scanner was written. (In Sweet 16)

Here is the code:

        jsr     strout
        .byte   "Larson 16",13,10,0

        goSweet16

        set     r12,$0100       ; Sweet16 stack pointer
        set     r2,$00FF        ; Larson data end marker value
        set     r8,IO_REGISTER  ; Update LEDs

loop0:
        set     r1,larsonData   ; Address of the data table
loop1:
        ld      r8              ; Copy r8 - address of LEDs into r7 because ...
        st      r7

        ld      @r1             ; Loads and increments r1
        cpr     r2
        bz      loop0           ; Reached the end
        st      @r7             ; ... store increments

        bs      delay
        br      loop1

delay:
        set     r3,$0800
sub1a:
        dcr     r3
        bnz     sub1a
        rs
        .setcpu "65c02"

And data:

; larsonData:
;       Bit patterns for a 3-bit wide scan, there and back again.
;********************************************************************************

.export larsonData
larsonData:
        .byte   %00000000
        .byte   %00000001
        .byte   %00000011
        .byte   %00000111
        .byte   %00011100
        .byte   %00111000
        .byte   %01110000
        .byte   %11100000
        .byte   %11000000
        .byte   %10000000
        .byte   %00000000
        .byte   %00000000
        .byte   %10000000
        .byte   %11000000
        .byte   %11100000
        .byte   %01110000
        .byte   %00111000
        .byte   %00011100
        .byte   %00001110
        .byte   %00000111
        .byte   %00000011
        .byte   %00000001
        .byte   %00000000
        .byte   $ff

 

But I wanted more…

After the Apple II, I would consider the BBC Micro to be my next favourite 8-bit micro system. Although they really tie for top place for many reasons. It was easy to say (back in the day) that the Beeb was better, faster, etc. but it also had 3 or 4 years advantage – and back then, 3 years was a long time and technology was changing really fast!

Anyway, after another “how hard can it be” moment I started to look at getting BBC Basic running. Fortunately a lot of hard work has already been done by others on this and Jonathan Harston in particular (See: http://mdfs.net/) so it was relatively easy. I had to write just 3 Acorn MOS “OSBYTE” calls to make a text-only BBC BASIC run.

Well, not quite – there was slightly more to it than that – mostly to do with IRQ/BRK handling, however I can now run BBC BASIC on Ruby and I’ll write about that soon..

Although before I close this one, just a note to say that once it was on stripboard and I’d written the code to do some memory tests and BASICs I decided to see how fast I could get it to run at… the W65C02 is rated to 14Mhz and I had been hoping I might get it up to 8Mhz – I did use some good fast memory but otherwise I didn’t really put much effort into the stipboard layout, and so once it was happy at 1Mhz, I tried 2Mhz, then 4 and 8Mhz crystals. At 8Mhz it was just as stable as 1Mhz and as I didn’t have any more crystals, I decided for a bit of fun to go for broke and tried the 16Mhz crystal I was using for the ATmega and just run a wire over the board. (See the green wire with a knot in it in the video above) I was quite amazed that it worked. And it continues to work just fine at 16Mhz although to save wires flying all over the board, I’m currently running it at 8Mhz.

Back to the main Ruby index page

Comments are closed.