This is just a short follow-up to the last post; Comparing BASICs… There, I talked about the differences between BBC Basic and what was effectively a Microsoft BASIC (EhBASIC), however I decided to take a few moments and have a proper look at the published MSBASIC sources to see if I could make it work on Ruby.
And an hour or 4 later – yes. Success with the Commodore version 2.0 – obviously without the “KERNAL” part which is the Commodore equivalent of the Apple II Monitor or the Acorn MOS – what we might call a BIOS today.
The main thing that KERNAL gives a Commodore system (PET, Vic20, C64) is the screen handling – this lets you cursor up to a line, edit the line on-screen and simply hit the return key to (re) enter it into your program.
The MS sources have a simple line entry system with conditional assembly for the many different systems MS sold their BASIC to – some vendors changed it, some were supported directly. I changed it to use the RubyOS standard “getline” code which gives me line editing, history and easy access to the RubyOS star commands.
Character output was similarly changed to point to the RubyOS routines, however there appears to be some issues regarding CR+LF handling that I couldn’t quite get right, so I just edited the code to make it work.
This is MSBASIC level 2, assembled for a Commodore system running on Ruby displaying the MS “Easter Egg”:
I loaded and ran the same mandelbrot program as before – it took a few seconds longer than EhBASIC – I suspect due to it using a 5-byte floating point format, however it did work well.
Microsoft added a little “Easter egg” into the BASIC 2.0 for Commodore – if you enter
then it would print MICROSOFT! on the screen. This didn’t work initially, then after wondering why it was crashing and after looking at the code I found that it poked the characters directly into screen memory – which is at $8000 in a PET, etc. … This is where I assembled the BASIC to load and run, so I decided to change the easter egg code to simply print it to the screen. A small complication is that it uses “PETSCI” codes which are obscured in the code to make it not obvious that it was there – I ‘fixed’ that for Ruby too. the ‘a’ at the end would be an exclamation mark on a real PET/C64.
Microsoft Source code
The sources for the 6502 version of Microsoft BASIC have been published for a number of years now and it seems that Microsoft aren’t doing anything about it, however that doesn’t mean it’s in the public domain, free to use and sell. Microsoft still holds the copyright to it so while I feel it’s fine for me to use it, adapt it for my own personal use, I’m fairly sure that if I tried to sell it I’d be in a somewhat sticky position, however if anyone else wants to have a look at the sources, then I suggest starting here:
I created a new target for it, but used the CBM2 target as a template for everything to try to keep all the Commodore changes and features. (Such as the Easter egg) The one thing I’ve not looked at is the file handling and while I’m sure I could make it work with the Ruby Filing System, I’m not sure it’s really worth it for now. (And also, perhaps selfishly I am wondering why I want to use such a relatively primitive BASIC compared to BBC Basic)
Ruby 6502 has been running well on it’s PCB for some time now and interestingly enough (and curiously!) during the past few months other 8-bit projects have sprung up…
This started probably about a year back when Dave, the 8-bit guy made a video talking about what his ideal 8-bit micro might look like – which in summary is essentially a slightly better Commodore C64 with possibly a 16-bit processor (The 65C816 rather than the 65C02)
Since then, there are three project that I know of in the public eye making just such a thing. The Foenix C256, The Commander X16 and the Neon816. I’ve been following these projects and in particular te Foenix one was really interesting to me early on as I had been looking for a 65816 platform to do something for myself, but in the time it’s come to alpha board testing, I’ve gone down my own route, however…
Anyway, in the Commander X16 group (on Facebook), I had a brief discussion about BASICs and offered to do a brief video on BBC Basic vs. a typical Microsoft Basic. C64 BASIC is Microsoft BASIC 2… MS wrote 2 BASICs for the 6502, both were used at the same time with the level 2 BASIC having a higher precision floating point and a few other things. From a published version of the source code:
; These are the first eight (known) versions of Microsoft BASIC for 6502:
; Name Release MS Version ROM 9digit INPUTBUFFER extensions .define
; Commodore BASIC 1 1977 Y Y ZP CBM
; OSI BASIC 1977 1.0 REV 3.2 Y N ZP - CONFIG_10A
; AppleSoft I 1977 1.1 N Y $0200 Apple CONFIG_11
; KIM BASIC 1977 1.1 N Y ZP - CONFIG_11A
; AppleSoft II 1978 Y Y $0200 Apple CONFIG_2
; Commodore BASIC 2 1979 Y Y $0200 CBM CONFIG_2A
; KBD BASIC 1982 Y N $0700 KBD CONFIG_2B
; MicroTAN 1980 Y Y ZP - CONFIG_2C
BBC Basic was first sold in 1981 on the early BBC Micros with the latest version (v4) being in-use in 1984. The main differences are that it’s much faster (almost twice as fast), integer variables are 4 bytes long and was designed to run on a more sophisticated operating system than the typical simple monitors of early systems. (There are many more differences than that though)
So back to the Commander X16 group – I made the video and it’s about 16 minutes long and here it is:
Just an update: After 4 weeks, my post was removed from the Commander X16 group because
Keep it relevant
Posts not specifically related to the Commander X16 project will be removed, even if they’re CBM etc. Please keep all posts relevant to the X16. This group is not intended for general retro tech.
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.
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.
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…
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
Filesystem initialisation 
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
By Gordon Henderson, 2018-2019
Ruby OS 64K
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
BBC Basic ... Loading @ $8000. OK: End @ $C000
Ruby 6502 2.0
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
BASIC  (C)1984 Acorn
ehBasic applesoft test
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
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)
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 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 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.
Another software update here – this time thoughts about implementing a filing system.
It would be far too easy to get carried away and start looking at modern systems – e.g. Unix/Linux/VMS where there are a plethora of good filing systems – the down-side there is that they need CPU cycles, memory and use more disk space for metadata that I would like, at the same time, the main filing systems in the ’70s was the CP/M one and in the late 70’s, Apple DOS 3.2/3.3. The initial BBC Micro filing system (DFS) in the early 80’s was, in some respects actually worse than CP/M and Apple DOS, although the later ADFS on the Beeb did fare a little better.
The other contender from the early 80’s is Microsofts FAT. This is now an open standard but the limitations of the filename length (8+3) irritates me and while there are ways to have long filenames, I really wanted something that did it natively.
Dots and Dollars?
As my system is accidentally becoming more BBC Micro-like by the day, then it might make sense to implement something that at least had an interface that suited the BBC Micro software of the time, but I really did not like Acorns idea of $ dot DRIVE dot directory dot filename (Really? Yes, so todays hello.c was c.hello, where c was a directory!) anyway, by the 80’s I’d already been using Unix, so …
Enter Apple ProDOS.
Round about 1983 Apple developed ProDOS as an upgrade from their DOS3.3. On the Apple II it was more than just a filing system – it had hooks into BASIC and some other stuff, however the underlying filing system part was interesting and I had looked at it back in the mid-80’s when I had thoughts to implement it on my BBC Micro at the time. So I dug out my old notes and books – Beneath Apple ProDOS and refreshed the old grey cells with it’s on-disk data format/metadata.
One thing it does reasonably well is to enable file storage relatively efficiently – if your file size is under a block (normally 512 bytes) then it needs no extra on-disk storage blocks, just a single pointer in the files catalog data. I also worked out that it would be relatively easy to change the block size too – right down to 64 bytes which would favour using the 4KB NVRam in the ATmega host processor as a storage device too.
I sketched out some ideas and decided that the on-disk format would be similar to ProDOS although the actual catalog/directory structure would more reflect the BBC Micro requirements and allow me to have up to 20 characters for the filename, although the interface would be more along the Unix open/read/write/close style with a small translation layer to accommodate any existing BBC Micro software I wanted to run. I feel that this might let me run something a little more modern than that old BBC Micro software in the future.
Sizes, shapes, ?
ProDOS uses a 16-bit pointer to address the underlying disk blocks. This gives us a maximum of 65536 blocks per device, or a raw capacity of 32MB when using 512 byte blocks. The file length limitation for ProDOS is 16MB as it uses signed 16-bit value – I removed that limitation – not that it really matters.
By todays standards, 32MB is pitifully small, however this is an 8 bit device with 64KB of RAM, so the reality is that it’s going to be just fine. (And it’ll also be OK if/when I move to a 16-bit 65816 system) I’ve decided to use a standard DOS MBR partition table, giving me up to 4 partitions of 32MB each. I think that’ll do for now.
I could increase the blocks size – going from 512 to 1024 bytes would double the capacity to 64MB, but it would also double the RAM requirements for buffers and so on and in an 8-bit micro with 64KB of RAM, every byte counts.
Did I want a real floppy drive? Not really. I didn’t want to use one of the many emulators (e.g. GoTek) either. USB is too complex to implement (for now), so I looked at CF cards which essentially have an IDE interface or SD cards which have an SPI interface and settled on SD cards – also because I have many of them and have used them frequently in Raspberry Pi projects over the past 7 years or so.
One thing I’ve learned from the Raspberry Pi systems is that SD cards are actually quite fragile. The worst thing you can do is power them off during a write. Then there’s the issue of them (potentially) wearing out. For now, I’m going to treat them as disposable items and keep good backups. This is something I advise all Raspberry Pi users to do anyway.
How do you write a filing system?
What bits do you do first? It’s been an interesting journey so-far (and it’s not complete as I write this) I started with the device block drivers – seemed simple enough – although SD cards – not quite as straightforward as they may seem, however I now have basic block read/write working well and the native block-size on an SD card is 512 bytes which fits well with the block size for the filing system. for SD cards I am also using a standard DOS MBR partition table – this gives me 4 partitions of 32MB each – it’s still laughably small compared to the 8GB SD card I’m using, but it will do for now.
I also wrote some code to let me use the 4K of internal NVRam in the ATmega host processor as a drive, and up to 8KB of RAM as a small/fast RAM disk – it was also very handy for quick testing too, although I may lose it later to free up some RAM if I decide to start caching read/writes to the SD if I need a performance boost.
Directories, drives, devices, volumes?
How do you represent a filing system with multiple devices (or SD card partitions)? CP/M and MS DOS typically use a drive letter, e.g. A or C followed by a colon, then the path to the filename. Apple DOS simply uses the drive number, so filename,d1. the Unix way is to mount devices so they look like another sub directory and appear transparent to the user. This is the approach I want, although I’ll do it all at the very top level. I’ll also use forward slashes (/) as the directory separator, so a filename will look like: /sd0/path/to/filename or /ram/filename and so on. The very top-level simply being a virtual directory with the device names, so /nvr for the NV Ram in the ATmega, /ram for the ramdisk, /rom for a ROM file system (out of the internal Flash in the ATmega) and /sd0, /sd1, /sd2 and /sd3 for the 4 partitions on the SD card.
After testing the block read/write code, the format command/functions seemed naturally the first thing to write, although when developing that, I quickly wrote a block dump command for debugging… The RAM disk was proving to be a boon here too. Format involves creating all the disk allocation bitmap blocks and the first catalog block. I decided I’d create one catalog block to start with, then add more catalog blocks as needed. On a filesystem with 64-byte blocks, there is room for just one file entry per block, but on a 512 byte block-size filesystem, there is room for 12 entries. When a catalog block is full, a new one is allocated and the first one is linked to it – in a linked list fashion. Right now there is no facility to delete empty catalog blocks, (e.g. after lots of file deletion), but I may come back to that later.
Format, then the open (create file) and write functions were next, and my disk dumper was very handy here., and at this point I started working on the Acorn MOS side of it too. The Acorn MOS has a number of calls, the primary one is OSFILE. This deals with whole files at a time and is the most efficient way (from the old BBC Micro point of view) to get data to/from a disk…. However as I’ve written a Unix style filesystem with open, and write calls, a small bit of 6502 code was needed to translate OSFILE into a combination of open, write(s), and close to write a whole file out. The MOS side is all on the 6502 and the actual filing system side of it runs on the ATmega.
It started to be a bit of a grind and my envy and admiration for the people before me who did this for the computers of the 70’s and 80’s was growing….
However, it all started to come together – read was implemented, a better catalog output then realising this is just the tip of the iceberg. Testing on SD card (and the relatively slow NVRam) shows that there are optimisations to be made, caching to be done and so on. There is also a lot of “hole in my bucket” stuff happening – so e.g. opening an existing file for writing might truncate that file to zero length under Unix, and that’s more or less expected under Acorn MOS with OSFILE, so the file truncate code needs to be written (which is really part of the file delete code), and that actually leads into the seek code – which is needed for the OSFIND, OSGBPG MOS calls, etc. then there subdirectories, traversing up and down the directory paths and other questions like sparse files? It’s all possible, but just how much do I want (or need!) to do right now… To answer this, I’m doing it “on-demand”. As I test and play with more and more old BBC Micro software, I wait for it to stall and flag up something else that needs implementing, then implement it. This isn’t ideal, but it makes sure I get everything done that needs it and allows me to incrementally test it as I go along.
At this point, I have a nice little 65C02 system with 64KBytes of RAM, a little “monitor” with serial interface. I can run Applesoft, ehBasic and BBC Basic.
Well… without really trying (nor setting out to do this initially), I have more or less created a very much cut-down BBC Micro. I can load (BBC Micro) ROMs from the flash “filing system” on the host processor, I’m working on a “proper” filing system as the host has some spare RAM and NVRAM (only 8K and 4K respectively, but better than nothing!) and I’ve added a SPI access SD card. (More on the filing system later).
My ideal 8-bit system?
Right now (April 2019) prompted by a video by “the 8-bit Guy”, there are a few public projects where people are creating their “ideal” 8-bit micro system (although they’re all using the 65C816, a 16-bit chip) There is Daves one – now called The “Commander X64” and Stefany Allaires “Foenix” – these both have ideas stemmed from the Commodore 64, and Lenore Byrons “Neon816” which is fairly generic but she has indicated it’s inspired by 8-bit Daves ideal computer which is Commodore 64 based.
So, while I never initially thought about this route, I’m now wondering what my ideal 8-bit (or 16-bit) system might actually be..
Here are some thoughts: I think I want something based round mid 1980s technology and style but with a modern approach. 65C02 or 65C81 based and enough RAM to be usable and running at a good but stable speed. By the mid 80’s, my world revolved round the Apple II as a work computer (writing 6502 assembler, mostly) and I had a BBC Micro at home. I was also using the BBC Micro in a work environment writing lots and lots of BCPL. I simply didn’t get into the games side of it at all (The exception being text-based adventures and Elite)
The Apple II, while sturdy was feeling slow, although the ProDOS filing system was keeping it going. The BBC Micro was well established with a good, modern (for the 8-bit world) BASIC with named functions and procedures, local variables, a nod towards a more structured programming approach, and so on. It also had an “operating system” which was very comprehensive from an API point of view, but while it did support a command-line, there wasn’t really a command line “shell” as such. (I was also using Unix and Primos at that point) My thoughts had been to improve on the shell/command-line aspect of it with utilities loaded from “disk” as required. (and ROMs). Possibly a bit like the way CP/M works, although a very (very!) cut-down Unix would be nice…
Thinking about the underlying operating system – I came to the conclusion that the Acorn MOS would be hard to better on era-style hardware. It has a very well defined interface and although a lot is very BBC Micro specific, a lot is also very generic. For example simple character output and cursor positioning – there’s a standard call for that – which makes it very easy for me to translate those calls into standard ANSI terminal cursor movements to make a serial terminal work well, and also to a graphical video system when I build it. (I’ve yet to try some BBC Micro editor ROMs though and while I’d like to think they used the MOS, right now I don’t know!)
Bytes and Words
And so, I’ve slowly been working through the Acorn MOS calls, running a ROM or 2, seeing what they need and filling in the gaps. There are 2 main calls: OSBYTE and OSWORD. OSBYTE deals with small byte-wide data and OSWORD requires a larger parameter block. Typical OSBYTE calls may be to select output destination (e.g. printer), to read buffer status and perform keyscans, OSWORD for larger things like “read in a line of text with simple editing”. I have debug output so that when an un-implmented call happens, I get to know about it and can work out if I need to write a full implementation, or simply return with it unhanded.
The command line is something I do want to work on. Right now, I have implemented OSCLI which takes a line of text and parses and executes it. So with just a few lines of code, call the relevant OSWORD to read in a line, pass it to OSCLI and you have a very simple command-line interpreter. Ultimately I’d like to do console output redirection, similar to using the < and > functions of a typical Unix shell and this should be possible – I just write the code… And filing system…
It does leave me with a nagging thought that all I’ve done is re-create a poor-man’s BBC Micro though and I’m now thinking how I can modernise this while keeping a familiar feel to it all. One thing would be to move to using the 65C816 processor – this is the 16-bit successor to the 65C02 with a 24-bit segmented address bus (16MB of RAM in 64K banks) – however it wasn’t that well used back in the ’80’s. The Apple IIgs and the SuperNES both used it, but almost nothing else (There is the Acorn communicator, but there weren’t really aimed at the general public, sadly) However the ‘816 is almost 100% compatible with the 65C02 in emulation mode and can switch to 16-bit mode (and back again) very quickly, so it seems like a logical choice, however that’s for the next project. For now, I want the Ruby 6502 to the point where I feel it’s as good as it will get.
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 …
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)
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:
.byte "Larson 16",13,10,0
set r12,$0100 ; Sweet16 stack pointer
set r2,$00FF ; Larson data end marker value
set r8,IO_REGISTER ; Update LEDs
set r1,larsonData ; Address of the data table
ld r8 ; Copy r8 - address of LEDs into r7 because ...
ld @r1 ; Loads and increments r1
bz loop0 ; Reached the end
st @r7 ; ... store increments
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.
The 6502 (or W65C02S in our case) is really designed to have some ROM (or modern flash, etc.) to enable it to boot. At power on or reset, it reads an address out of a fixed location normally stored in ROM and jumps to it. That code then does what’s needed to make the system get going.
And here we have a small issue: The Ruby has no ROM…. So why not, and how to make it work?
One reason was to simplify the hardware. ROMs are typically, relatively slow, even by the very old 6502 standard. To make matters worse, the 6502 has a somewhat interesting way of accessing memory that means the memory has to be at least capable of responding in half the time you might expect. So for a 1Mhz 6502, you might expect a 1-microsecond access time, however it really needs just under 500nS. Take that to the maximum speed that a modern W65C02S is rated for which is 14Mhz and you need better than 70nS. In reality, you actually need better due to the latency/propagation delay of signals going from the 6502 through e.g. address decoder before it gets to the ROM chips. The same timings apply for RAMs too.
Also the 6502 only reads or writes the memory for half a clock cycle and this was taken advantage of by the various video generation circuitry of the early microcomputers such as the Apple II – 6502 runs flat-out, but does it’s RAM access in half a cycle, the video jumps in on the other half cycle and pulls data out to send to the display.
So we need (relatively) fast ROMs, and there weren’t any suitable. I was aiming for classic through hole technology too. There’s also the issue of having to reprogram them. I did this regularly over 30 years ago and it quickly becomes a chore, so I decided to go for an all RAM solution.
RAM chips are still available in through-hole technology, fast enough and with the capacity I needed, although I ended up with 2 32K x 8 bit chips as there were no suitable 64Kx8 ones.
The issue now – how to get data into the 6502 in the first place.
Enter the ATmega.
I had been experimenting with using an ATmega to generate composite video and had a system using an ATmega1284p which has 16KB of internal RAM and was generating a nice 320×240 pixel monochrome display, so I went about working out how to interface that to the memory system with the aim of using that as it’s video output. (I’ve since put that idea on hold – more on that later)
And this is where a modern version of the 6502 works well. The WDC 6502s which are still being made today have a couple of features that work well here. One is the BE or Bus Enable signal. Pull this low and the 6502 immediately tri-states all its address and data lines. The other is the Rdy signal. Pull this low and the 6502 stops at the end of the current clock cycle. So, it’s a simple matter of halting the 6502, disabling its bus, connecting the bus to the ATmega and having the ATmega fill the RAM, then reverse the process and let the 6502 boot. What could possibly go wrong …
The 6502 has a single Read/Write output pin. the RAM needs separate Read and Write inputs. There are also 2 RAM chips and I want to decode a block for some IO devices…
Enter the GAL…
A GAL is the pre-cursor to the FPGA. It’s a Generic Array of Logic. Initially one-time programmable (PALs), the GAL can be re-programmed 100 or so times. They were popular in the early 1980’s to the mid 90’s when the ULA was being used in home computers such as the BBC Micro and ZX Spectrum. In the Ruby it’s doing the job of sorting out the read and write signals, working out which enable signal to send to the RAM chips and enable some IO decoding to be performed. As a bonus I can hook up an LED or 2 to help with debugging if required.
There is a minor issue with GALs these days – Lattice stopped making them a few years ago an dsupplies from the mainstream outlets have all dried up. Atmel (now Microchip) are still making new GALs, however I lack the programmer to correctly program them and programmers that can program the Lattice ones simply won’t work, so right now I’m sourcing them from what appears to be reliable component recycles in China and so-far they’re all working perfectly.
The memory map
The 6502 divides it’s 64KB of memory up into 256 byte pages and it needs RAM in page 0 ($0000 -> $00FF) and page 1 ($0100 -> $01FF). This is for fast data storage and the stack. The reset vector (and interrupt vectors) are at the top of memory ($FFFA -> $FFFF) which is normally ROM, so I arranged the system so that the top page from $FF00 through $FFFF was the page that was shared with the ATmega. This needs 8 pins from the ATmega for the data bus and 8 for the address. Also a few more to control the 6502 Reset input, Rdy and BE signals, as well as read and write. The resulting memory map looks like:
$0000 -> $FDFF: RAM
$FE00 -> $FEFF: 256 bytes of IO space
$FF00 -> $FFFF: 256 bytes of RAM shared between the 6502 and ATmega
It’s quite simple and easy to decode inside the GAL and leaves the maximum amount of RAM for program and data usage.
On the breadboard version there was no real IO – just a pin I could connect to a ‘scope. On the stripboard version there was an 8-bit latch I could use and on the PCB version there is a WDC65C22S VIA with it’s dual parallel ports, timers and other features.
So at power on, the ATmega controls the system. It holds the 6502 in reset and pulls the BE pin low to cause the 6502 to tri-state it’s buses. It copies the minimal bootloader into the shared memory page which includes the reset vector then releases the memory (tri-states the pins used for address and data lines), lets the 6502 access the memory and takes it out of reset.
The 6502 wakes up, reads the reset vector and jumps to it. (This is $FF00 initially) That code relocates itself to a lower location in RAM then communicates with the ATmega to get more code to finish the bootstrap process.
The communication is fairly straightforward and relies on another trick of the W65C02S – the Rdy pin is bi-directional and there is a new instruction; WAI which causes the 6502 to halt, pull Rdy low then wait for an interrupt. The ATmega meanwhile has been reading the Rdy pin and when it sees it going low, it switches the bus RAM control over, reads a command and data out of the shared memory page and does whatever it’s commanded to do. For example, it might be asked to load block 5 of the bootloader, so it copies that block from it’s own internal flash to the shared memory then switches the bus control back to the 6502 and sends an interrupt to the 6502 which causes it to wake from the WAI sleep and carry on.
And that’s the key to the 6502s communications. Everything happens via the small page of shared RAM – a virtual serial port, simple ROM filing system and a full-featured filing system that can use the spare RAM on the ATmega or it’s NVRAM or an external SD card as file storage.
It’s not a million miles away from the BBC Micro, however in this case, once the 6502 has booted, it’s really the master of the system. The ATmega is a multi-function peripheral device that just helped to boot the 6502 in the first instance.
From now on, it’s 6502 code time and I’ll talk about that next.
I had a barely working 6502 prototype system on my workbench. It was a little unstable and didn’t like being moved, but it did work and demonstrated to me that the concept was viable.
Initially I didn’t know what I wanted other than “6502”… However some 30-40 years ago I did make some 6502 single board computers (SBC) and did a lot of programming on the Apple II and BBC Micro. I have also collected a few old Apple II’s and BBC Micros/Masters and one thing I had in my mind was to “re master”, or “re-imagine” what a 6502 computer system might be like with todays ideas and thoughts.
So the first task was to get a stable system and make it run BASIC.
Enter stripboard. Popular in the UK it’s been the staple of electronics hobbyists for decades. With a hand-held cutter (or in my lazy case an electric drill with suitable bit) good soldering skills and the ability to visualise your circuit you can achieve almost anything…
And so here it is:
The chip layout differs slightly from the breadboard, from left to right: ATmega1284p, RAM (more on this shortly), 6502 and below that the GAL22v10.
There is no schematic for this – I knew what I wanted, printed out the data sheets for all the chips and set about wiring it up, one wire at a time.
Now that green wire that goes from next to the can oscillator on the right over to the left… It’s carrying a 16Mhz signal. These new WDC 65C02 chips can run at 14Mhz and so when I was buying bits I bought a few oscillators for it – the 16Mhz one was really for the ATmega, but on a whim I tried it in the 6502, after going 1, 2, 4 and 8Mhz. At 16Mhz, 2Mhz over the rated maximum and on stripboard it runs at 16Mhz and passes memory tests until the cows come home. That’s not too shabby, I reckon…
And so the memory. Looks a bit odd there, perhaps? That yellow wire going over the top. Maybe this image will give a clue:
The RAM is 2 x 32KBx8 chips with one soldered on-top and it’s enable pin brought out separately. I’d not intended to do it that way, but why not – it works well and takes up less board space. I also know I’m not the first to do so either.
And for the curious, here is the back with all that lovely tin/lead solder:
But what can it do at this stage?
By this time I’ve added a little 8-bit latch and stuck my old LED board onto it. It’s running a binary count with each count representing a single pass of a simple memory test.
Next I’ll write about how it works, the memory map and exactly what the ATmega is doing.
To mark my own use and knowledge of 40 years of the 6502, I decided to build my own little single board computer (SBC) based on it.
I had a few ideas in-mind – one was to make it a little faster than the old ones (but I really didn’t mind), one was to make it suitably “retro” and try to use the sorts of components available round about my target date – so this meant through hole components rather than surface mount. I also wanted to try to keep the hardware fairly simple.
My initial aim was for a stand-alone system with video output and keyboard input. Also a serial port for software download, blinkenlights, of-course and as much RAM as possible.
And then I hit a snag. Several, actually. The first one was that the old video controller chips are no-longer being made. Plenty on ebay, but… Next was the keyboard interface – but PS/2 type keyboards are easy to come-by and relatively easy to use. Memory, and ROM/EEPROM… The 6502 has a unique (that I’m aware of!) way of accessing memory – it only accesses it on half a clock cycle rather than use a full clock cycle. The effect of this is that you actually need memory that’s twice as fast as you might first imagine. So for a 1Mhz 6502, you might think that memory with a 1 microsecond access time is OK, however the reality is that you need 500ns (or better) memory. The current 6502 chips from Western Design Centre run at speeds up to 14Mhz, so we’re looking at 70ns or better RAM. The issue there is that chips like RAM chips are moving more and more to using surface mount technology which I was trying to avoid. Fortunately I found some suitable memory chips – 32KB x 8bits, so I just needed 2 of them.
(And yes, I did say current up there – The 6502 is still being manufactured and you can buy them brand spanking new!)
EEPROMs were an issue – these days they’re big – much bigger than I need, both physically and capacity wise. Not real issue as you don’t need to use all their capacity, however they’re also not as fast as I’d have liked, so this means either slowing the clock during access or introducing wait-states to the 6502. This adds complexity – and more TTL IC’s, so more to go wrong.
At this point I had a look at what year I felt was right for my little SBC and settled on 1984. This was 6 years after the Apple II and 2 years after the BBC Micro. Programmable Logic Chips were in-use at that point – the BBC Micros (and others like the ZX Spectrum) used their fore-runner, the Ferranti ULA, so I felt that a PAL (actually a GAL – a reprogrammable PAL) might be appropriate.
I also looked at video, keyboard and thought about other peripherals like SPI and I2C an decided to build a system that had a separate IO processor to handle this – and I used an ATmega1284P. This generates the video, has a serial port and can interface to the 6502 using a shared memory system. This eliminated the EEPROM wait-state shenanigans as the system effectively became ROMless at that point – the ATmega poked the bootloader directly into the RAM of the 6502 and could control its reset line.
The ATmega has about 50 times the transistor count of the 6502 runs faster, has more and getter IO, but sometimes you have to do something new to make something old work.
And in the best traditions of make it up as you go along, I started on breadboard – and this was the barely working prototype:
The ATmega is at the top-right. Middle of the board is 32KB of static RAM, to the left of that is the 6502 and under that is the Lattice 22v10 GAL. The LEDs are mostly for debugging – the are extra outputs from the GAL.
It was a bit unreliable – using ribbon cables (“jumper jerky”) isn’t the best as they tend to pull each other out but it did work and served to prove the concept that I was after. I ran some very small bits of 6502 code with that setup and wrote a lot of the ATmega code for the video and the shared memory interface to the 6502.
Although that worked, it wasn’t really reliable enough to enable me to do much with it, so the next step was to make something a little more sturdy and for that I went back to an old favourite of mine – stripboard, and more on that design in the next post…
In 1976, Steve Wozniac wrote what’s commonly known simply as Wozmon.
Wozmon is a machine-code monitor program and for those who may not be aware, this is essentially code that starts to run in a microprocessor at initial power on. Lets be more specific, an older microprocessor system, not usually your modern Intel, AMD or ARM based system. We’re taking the old 8-bit micros here, and I’m specifically referring to the original 6502.
The monitor would let you examine and change memory. Some even had built-in disassemblers, debuggers and a whole host of tools to help you get going in a new machine. They would include subroutines that could be used by other programs, these basic input output subroutines, or BIOS as it came to be known were essential for bigger programs as it took that burden away from the programmer and helped to make programs run on different systems, or at least easier to port from one system to another.
Before the monitor there were LEDs (or even older; filament bulbs) and switches. Before that? you might have ended up soldering diodes to circuit boards. I kid you not.
Wozmon may not have been the first, but it was compact. Wozniac had 250 bytes to squeeze it all into. (6 bytes were reserved for the reset and interrupt vectors) ROMs and the means to program them were expensive in those days. He ended up with 2 bytes spare.
By todays standards Wozmon was crude. But it was also compact – if it didn’t understand what you typed then it would just print a backslash and let you start again, but however crude it may have been, it worked and let many early programmers enter code and use the computer that Wozmon ran on – the Apple 1.
After the Apple 1, there as the Apple][ (sometimes written as II, latterly as //, but rarely 2). That had more ROM space, so Wozmon was expanded and as computer got bigger and more complex eventually (we’re into the mid 1980’s now), the monitor for the various microprocessors was replaced by nothing more than the basic input/output subroutines and the BIOS as we know it today was born, although nowadays (c2018), the BIOS is bigger and more complex than an entire Apple ][ computer.
You may be wondering why I’m writing this – well, for no reason other than this year marks my 40th year of programming the 6502, I’ve built a little 6502 computer and written a monitor for it. The monitor resembles Wozmon – mostly because I used the Apple ][ variant of it back in 1978.
More to come – details of Ruby – my 40th anniversary 6502 computer.