I’ve not done too much with Ruby 6502 in the past few months, however I decided to get a PCB made up for it and I’m happy to say it’s working fine. Well, almost.
A few little notes on the PCB version:
- It’s Red. Ruby is Red…
- The clip and wire carries the 16Mhz signal from the 65C02 side to the ATmega side (Yes, I’ve still not bought another 16Mhz crystal!)
- I’m using same 64K memory module I used in the stripboard version – the yellow wire is the chip-select of the top chip.
- The SD card is on a level-shifter breakout board – which I had to extend as I oopsed the location of the ICSP header pins…
- A 65C22 VIA which has 8 LEDs connected to which replaces the single 8-bit latch that I had on the last revision of the stripboard version.
- The grey ribbon cable is the ICSP programming cable for the ATmega and the black cable is the same power and serial cable as before.
Video
I decided to give-up with the video output from the ATmega. Several reasons – one I made a simple mistake on the PCB – easy to fix with a single bodge-wire, however the main reason is that generating video took up about 70% of the CPU cycles of the ATmega so things like it’s serial port and the SD card based filing system went relatively slow. I have a plan B for video – more on that later. Not using video from the ATmega has given me 2 spare IO pins – one I’m using for the SD card “activity” LED, so I can see when the SD card is being accessed.
Filing System
This has been improved and speeded up a little. A simple block-level read only cache for some operations really helps, as did filling in some little bits like actually validating a filename… That came after a program crash left me with a file I could not delete with anything other than a disk block level editor … (so another utility needed to be written!)
The file system has a fairly standard unixy style open/read/write/close interface, so an interface shim was needed for the RubyOS/6502 side of things. It now supports most Acorn style MOS commands – OSFILE, OSFIND, OSGBPB and so on and translates these as required.
It’s not a BBC Micro!
However… What’s happened is that more or less without really intending this to happen, Ruby has become more and more BBC Micro compatible by the day. This has had some advantages, and some frustrations – I really wanted something new, however I’ve realised that writing something completely new from scratch as a little hobby project is a somewhat bigger challenge than I have the capacity for. The advantages are that I can run a lot of existing BBC Micro software – almost…
ROMs
The boffins in Acorn HQ made some brilliant decisions back then and the best one is that they separated the operating system from the “language”. The language being BASIC, Pascal, Logo, Comal, Forth and so on. These were normally in a 16K ROM and the BBC Micro had space for up to 4 ROMs plus the operating system ROM. The language (and subsequently utility and filing system ROMs) all occupied the same address space and the hardware and OS would page each ROM in as required. The term “sideways ROM” was used, and it wasn’t long before 3rd partys produced boards that could take more ROMs and even RAM which allowed loading of a ROM from disk so making it easier to load more ROMs without taking the lid off.
So a BBC Micro has 32K of RAM, 16K of paged (sideways) language or utility ROM then 12K of operating system ROM with the hardware IO tucked in there too.
Ruby currently has 64K of RAM with a small 256 byte region for hardware IO and another 256 byte region for communications with the host ATmega processor, however it works with the same memory splits and currently has space for 24K of language ROM, and just under 8K of operating system. I have assembled ehBasic to look like an Acorn language ROM image, also Applesoft and Tali Forth (which is a 24K application) The various BBC Basic ROM images “just work” completely unchanged.
Booting Ruby and entering BASIC now looks like:
Initialising Host processor systems ruFs: Filesystem initialisation [41] ram: nvr: sd0: sd1: sd2: sd3: [OK] Ruby: Host ready Press SPACE to boot 6502 or the ENTER key for interactive debug: Booting 6502 ====================================================================== Ruby 65C02 running. Loading RubyOS: OK Ruby 6502 By Gordon Henderson, 2018-2019 Ruby OS 64K * help RubyOS Commands: LS CAT DIR CD RM MV SPOOL EXEC LOAD SAVE RUN INFO UPDATE TYPE DUMP FTP MD FILL FX MODE KEY TV GO HELP BASIC ROM LARSON MEMTEST REBOOT EXIT No application loaded * basic BBC Basic ... Loading @ $8000. OK: End @ $C000 >*fx 0 Ruby 6502 2.0 >*help RubyOS Commands: LS CAT DIR CD RM MV SPOOL EXEC LOAD SAVE RUN INFO UPDATE TYPE DUMP FTP MD FILL FX MODE KEY TV GO HELP BASIC ROM LARSON MEMTEST REBOOT EXIT Application loaded: BASIC [04] (C)1984 Acorn >*cat sd0: ehBasic applesoft test >*cd /sd3 >*cat sd3: bcplRom basicRom applesoft taliForth b4 fforth120 rhBasicz ROBOT-L ROBOT bcpl.r b1 b2 basic3 ehBasic edit110 M1 mandel.txt sieve.b foo.b MOIRE mandel.bas maze.bas maze2.bas ktest.bas forth M2 M3 MANDEL.BB MANDEL-G.BB m2.txt mandelx foo >
This has been copy/pasted from a serial terminal (minicom) connected to Ruby. If you’re familiar with the BBC Micro then you may recognise some of the commands. Lines above the ==== line are generated by the ATmega and those below by the 65C02. (Note the command-list – some e.g. TV do nothing but are there because some BBC Basic programs use it)
Text? Graphics?
Without the ATmega generating graphics what do we do?
Well… Due to the above mentioned separation of operating system and language, it’s easy to isolate the screen handling calls and emulate them over a serial interface. In other 8-bit system in the late 70’s and early 80’s “poking the screen” was a popular way to put characters and graphics on the display, but before memory mapped displays there were serial terminals. The DEC VT series, Wyse, Televideo, ADM3a and so on… And before them? We had thundering mechanical monstrosities – the TTY33 and many others.
Poking the screen on the BBC Micro, while possible, it was generally frowned on – you were supposed to use the operating system (Some games did poke the screen for speed though) What was even better was that the communication between the language and operation system for graphics was for the most part done using character based control codes. This was not new then – serial terminals had their codes to move the cursor, clear the screen and so on, and advanced graphics terminals (e.g. Tektronix) could draw lines, shapes and so-on, just by sending control codes. This was the approach taken by the BBC Micro. You want to clear the screen? Print a Control-L (decimal 12). Move the cursor? Print code 31, (control underscore) followed by the X and Y character positions and so on.
So commands in BBC Basic like CLS (clear screen) were relatively simple – in this case all it had to do was send Ctrl-L (decimal 12) to the output and the screen would be cleared. not only in BBC Basic, but other languages too. Pascal, forth and so on – clear the screen? Send Control-L and the operating system did the rest.
This has proven to be very easy to implement in Ruby – the actual 6502 side really doesn’t do anything other than pass the data up to the ATmega which then interprets it and either gathers more characters or passes it up the serial line to the minicom terminal running on my Linux desktop. I have currently hard-wired the generic ANSI terminal codes into the ATmega, so when it gets a Control-L to clear the screen it sends up the relevant codes (which happen to be ESC ] 2J in this case) and the screen clears. Similarly for other codes to move the cursor (e.g. PRINT TAB(X,Y); ) and so on.
Just doing this has allowed some text based games and utilities to work with relative ease.
Graphics?
Graphics on the BBC Micro followed the same format – send control codes to the display to change colour, plot a point, line, triangle or other shapes. It may seem inefficient, but remember that in a BBC Micro this was all done in-memory rather than over a serial line, however when translated into serial commands, it’s still not that slow. There is a slight down-side though – minicom – the text-based terminal program I’m using doesn’t support graphics. It’s text only… The solution? Write a new minicom using a graphics based back-end.
Fortunately, some years back I wrote my own BASIC interpreter… For that I needed graphics and I used the SDL library to give me easy access to graphics on a Linux PC, so I used the graphical back-end to this as the basis for my new “RubyTerm” program and off I went. I made some minor changes to the ATmega code to make it recognise either an ordinary ANSI text terminal or RubyTerm so it could pass the codes transparently to RubyTerm and let that handle the decoding.
This result is quite nice and although not complete is providing a good basis for something to work on:
That demonstrates simple text output, then GCOL 0,13 selects colour 13 (Bright Magenta). The MOVE and DRAW commands draw the first line from 0,0 to 100,100 and the next MOVE and PLOT commands draw the filled triangle.
The VIA
The 65C22 Versatile Interface Adapter is a standard peripheral found in many 6502 systems (And there were 2 in the BBC Micro). It has 2 x 8-bit IO ports with handshake lines, 2 timers which can interrupt the 6502, a shift register and various other modes to make communications possible. I’m just using one port here for test it and to use it as debugging (when all else fails, light an LED!) but I have plans for some GPIO facilities using it and possibly some sort of IO backplane with I2C and SPI as well as parallel interfacing.
And that’s about all for now – I’m slowly working through and improving the graphics side and the filing system still has some work to finish it off, although it has been remarkably robust so-far.