Wednesday 21 March 2012

The New FIGnition ROM

I've been working on a new version of FIGnition's Forth ROM and I'd like to share some of the details with you.

History

There's really two main sections to FIGnition's firmware (three if you count the bootloader). The initial 10 to 11Kb or so is the code that interfaces to the hardware: the video, the SRAM, the Flash and the keypad. It's written in a mixture of C and assembler. The inner Forth interpreter is also here; it's about 1.5Kb long and is written in assembler.

The rest of the firmware is the Forth language itself, written in Forth byte codes. My original version of this was taken primarily from Andrew Holmes' Mark 1 Forth computer's Forth ROM, because it was a Forth ROM written in Forth; and that version of the Forth ROM was taken from the 6502 assembler version of FIG-Forth, which is in the public domain.

We can see how the history of this works out using a few code snippets. The 6502 version implements most of its entire word set in 6502 code, so a command such as > is written in assembler:

L563 .BYTE $82,'>',$D2
.WORD L548 ; link to LEAVE
TOR .WORD *+2
LDA 1,X ; move high byte
PHA
LDA 0,X ; then low byte
PHA ; to return stack
INX
INX ; popping off data stack
JMP NEXT

The Mark 1 Forth computer is a true virtual machine, so Andrew had to rewrite the ROM using his core set of 32 words and since > isn't one of them he defines it as follows:

$Colon GreaterThan, '>'
DW Swap, LessThan, Exit

< in turn is:

$Colon LessThan '<'
DW Subtract, ZeroLt, Exit

Subtract isn't even a core word, it's defined as:

$Colon Subtract, '-'
DW Minus, Plus, Exit;

So, here we see a number of key changes. He's factored the code quite a lot; he's used the macro facilities of the MASM assembler to make headers easier to define and finally he's converted it all to compiled Forth expressed as words.

In FIGnition Forth's ROM it looked like this:

_Colon GreaterThan, ">",1
.byte kFigSwap
.word LessThan
.byte kFigExit

There's some minor changes. The macro definitions and word directive use as-avr syntax macros. I couldn't get the macros to properly calculate the length of the text so it's an extra parameter. In addition, in FIGnition Forth I can mix byte codes and words.

FIGnition Forth isn't a true virtual machine, since the Forth ROM and main firmware share the same code and addresses spaces. This means, for example, I can access the data stack pointer by simply declaring a constant which is the address of the register used for the stack pointer and I can then access it directly from Forth - I don't need a primitive definition to do that:

_Const GSP, "sp", 2,gDP

Means that GSP is used for the label for sp and gDP is the actual address (which is an AVR register pair). In addition, I recently added the primitive kFigNative which allows me to intersperse Forth and AVR assembler. Key for example is now:

_Colon FigKey, "key", 3
.byte kFigNative
.align 1
call Key
rjmp RomPushByteRet

FIGnition Forth Today

The Mark 1 Forth ROM is much smaller at around 4Kb than the 6502 version (at around 8Kb), because the native Forth code is more compact. In turn FIGnition's Forth ROM is more compact, because it uses byte codes - the same code becomes about 3.5Kb instead.

With FIGnition Forth I made a number of changes to the set of primitives so that it now supports shifts; internal ram access; native cmove and fill; flash block firmware access amongst others. In addition I had to add some basic missing words such as vlist, forget; list (for blocks); and of course edit. Finally I had to add definitions such as: x, so that both byte codes and execution addresses could be compiled in correctly.

FIGnition Forth Tomorrow

I've made a lot of comments about the future of FIGnition Forth on the FIGnition Google group and perhaps previous blogs, but progress is slow. The primary change is that I want FIGnition Forth to support a nice editor, written in Forth, to replace the primitive screen editor we have at the moment. The major impact for this is that I don't want to write the entire editor using .byte and .word directives, because it's just too error prone - instead I want to write it in Forth. But I also don't want to write it in Forth on FIGnition itself, because although it's going to be only 1 to 1.5Kb; I want it to integrate with a different set of lower-level string functions and compiler words; which means re-writing other parts of the FIGnition Forth ROM, which is again fairly error prone. Remember, the Mark 1 Forth ROM is basically a translation of existing (working) code; whereas this is new development.

So what I've decided to do is re-write the entire FIGnition Forth ROM in proper Forth and modify a rudimentary Forth compiler called NFC that I wrote in C around 3 or 4 years ago to generate the ROM.

This means that > for example is now defined as:

: > swap < ;


Simple!

Current Progress

So far I've re-written the entire ROM as FigRom.fth and it's much smaller, at around 1000 lines of code instead of 2300. Now I'm working on the Forth ROM Generator (FRG), which is mostly complete, but untested. This is the major reason why the most recent ROM update (which enables bitmapped graphics and sound to work together) was done by hacking the .hex files rather than modifying the actual firmware.

The first stage is to get FRG to generate the same ROM as I had before before I move on to improving it, I'm a little way from seeing that happen.

I'll blog the rest of the progress as I go along!