After I was happy running GIBL (my 6502 TinyBasic) on my Ruby board, I thought about porting it – I also thought about a new project I’d like to do over the winter solstice period, so before tackling that project I set about porting it to another platform I had to-hand – the W65C134-SXB board as it has some similarities.
The W65C134
This little board uses the W65C134 microcontroller/SoC. This is a 65C02 based CPU with on-board serial and parallel ports with many options for interrupts and so on. It also has an on-board “monitor” ROM and 192 bytes of RAM. There is no on-board Flash/EEPROM.
By todays standards it’s fairly underwhelming for most modern uses but bear in-mind this was designed and released sometime in the late 1980s or early 1990s (it’s hard to know when) and as such there are no peripherals like SPI or I2C. It also lacks any PWM hardware or analog input.
My preciousssss….
The SoC uses the first 48 bytes of Zero Page for the hardware IO registers. Personally I am not a fan of this – Zero Page is precious and fast and I want all of it… The on-board 192 bytes of RAM is mirrored over page 0 and page 1 and appears from $40 through $FF and the same RAM also appears at $0100 through $1FF. It’s enough for a tiny application – such as the on-board monitor ROM… And note that this is a mask programmed ROM and not a reprogrammable flash device.
It is possible to add extra external RAM and ROM/EPROM/Flash, etc. and there are register controls to facilitate this – you lose 3 x 8-bit ports though.
The W65C134-SXB
The SXB is a board that comes with the W65C134 and 32KB of RAM and 128KB of EEPROM and a USB interface. There are ways to enable the RAM and EPROM for your own use and you can write the EEPROM in-situ. The EEPROM is split into 4 banks of 32KB each and it’s also possible to disable the internal ROM and run from the external EEPROM if required.
BASIC?
There is mention in the documentation of a BASIC available for it, (Com Log Basic) but I have searched for it, and can find nothing online…
Getting GIBL on the board was no easy task – the on-board ROM monitor is somewhat greedy with it’s use of Zero Page data and bear-in mind it’s shared with the stack in page 1. Also the data used and locations is not very well documented at all and I had to read the monitor ROM listing to get a better understanding, but I was able to move almost all my nice fast, compact zero page data into external RAM and call the ROM serial routines and I eventually got GIBL running from RAM.
Another small stumbling block – I use Linux exclusively and the WDC tools are for MS Windows only. My terminal of choice under Linux is minicom and it works well, but then another stumbling block – the monitor ROM only outputs a CR (carriage return) with no LF (line feed). So everything is all on one line. Fortunately minicom can cope with this, but it would be nice to not have to work this out.
What was more annoying was that the ROM monitor has an internal routine called CRLF – and you might think that would output both CR then LF, but no. Just CR…
Another issue: The monitor ROM echoes everything back to the screen. Not the best thing when you have a nice get line with editing facilities, so more ROM code searching and fortunately it has a way to turn it off.
I then set about using my RAM based GIBL to write the EEPROM with the intention of moving GIBL into EEPROM. It took some time – then I felt I really really wanted that zero page data back as I was only using a tiny fraction of the monitor ROM, so decided to just turn it off and poke the serial hardware directly.
Which didn’t work as planned as I could not find an easy way to poll the serial hardware – it seems it must be interrupt driven, so had to write my own tiny bootstrap to get the board going with my own serial routines using the bare minimal of zero page. Fortunately there is plenty of RAM so I was able to implement an interrupt driven serial handler with larger (128 byte) input and output buffers. This left a lot more zero page for GIBL so I could move more data back into it which reduced the code size and of-course made it run faster. I also added an interrupt driven 100Hz timer so BASIC programs had access to some simple timing facilities.
Ye Olde Bootstrap Paradox
Then there’s that bootstrap paradox again… You turn the board on and it runs the internal ROM… To get into my GIBL system I type G E000 over the serial line.
Fortunately at power-on, the ROM looks for some magic runes in a fixed area of EEPROM and if present then it does a JMP to another fixed location in the EEPROM… So that code needs to jump to more code (in the GIBL image at $E000), which disables interrupts, turns off the internal ROM, enables the external EEPROM in the ROM location ($F000) then jumps to the EEPROM initialisation code which can setup the serial port the 100Hz timer and re-enable interrupts.
And if your own code should crash then the only option is to remove the EEPROM and erase it with an external programmer and start again…
There is a way to go directly to the external EEPROM, but it involves pulling the BE signal low before you let the reset signal go high and the SXB board doesn’t support that.
Save/Load/DIR/Chain?
So we have all that EEPROM spare – what about using it for program storage? Sure, so off I went working out how best (or worst) to do it. My aim is to try to keep the bulk of the GIBL code inside the 4K window I’ve allocated myself – this is a Tiny Basic after-all… So rather than write a full filing system, I came up with a plan to split the EEPROM into fixed 4KB, 8KB and 16KB slots and used a simple numbering scheme 0-15. Things got out of hand and with bytes spare I implemented an auto-start routine and a DIR command. The DIR command works by reading the first line of code in each save slot and if it is (a) line 0, (b) starts REM then a space, then the rest of the line will be printed out. If you have a file in slot 15 and it has 0REM!BOOT then it will be loaded and auto-run at power on or reset time.
Example DIR
>DIR 0: 4K: 1: 4K: GIBL Mandelbrot 2: 4K: Chain Test 3: 4K: 4: 4K: 5: 4K: Larson2 6: 4K: Larson on P5 7: 4K: Chain Test 2 8: 8K: Calculate Pi 9: 8K: 10: 8K: 11: 8K: 12:16K: 13:16K: 14:16K: 15: 4K: Boot Test (!BOOT)
Slot 15 here has been renamed to stop it auto-starting and the DIR command tells you the size of each slot. To facilitate the auto-start I had to write 2 new commands, Chain and OLD. Tests show that power-on to running the auto-start program takes just under 10mS. The chain command doesn’t wipe variables when it starts the new program.
GPIO?
The SXB board has a number of digital IO pins/ports available to it – some appears to be somewhat haphazard in their use by the board – e.g. one pin in an otherwise free 8-bit port is used for one of the serial handshake signals when there is a spare pin in another port which also has the serial data and the other handshake signal… If that signal had been moved then the board would have had 2 fully unused 8-bit ports… Obviously if you are using the board like e.g. an Arduino Uno as a prototype means before making your own board with the CPU directly on-board then you can use whatever signals you like, but this does seems like a bit of an odd decision to make.
GIBL supports the IO in 2 ways – one is with a new command just for these boards to control the 4 LEDs (LED = n where n is a number which will be output on the 4 LEDs) and use of byte indirection – e.g. to set port 5 to all output and write the value $AA to it:
?&1F = &FF ?&1D = &AA
The ampersand (&) indicates a hexadecimal number and &1F is the data-direction register for port 5 with &1D being the data address for port 5 where you can read or write data from/to.
I made a short (8 minute) video on it all and there is a separate porting document should you wish to put GIBL on your own W65C136-SXB board.