Rabbit gForth Extensions

 

Loading Source Files

I use a Python terminal to help load Forth code on the ATmega. The same approach can be used on the Rabbit. Here is the Python loader modified for gForth.

 

Loading Source Files - alternates

Serial downloads of source files can be limited by the Forth compiler speed.
For now, I'm using a LOAD-READ mechanism that is similar to the one I used with eForth.
To load a source file:
     1. type LOAD <enter>
     2. use your terminal emulator to send the ASCII file. type ^Z when the transfer is complete.
     3. type READ <enter>
READ first eliminates the '\' comment to end of line and replaces those characters with spaces.
Then it does an EVALUATE on the input buffer, which compiles the un-commented source.
Note that the buffer size is 0x2000 bytes.

I use Kermit as my terminal emulator. It runs on most hosts and is very flexible.
The ^Z to terminate LOAD can be added automatically if you use:
    set transmit eof \26
and then to do the file transfer use:
    transmit /nowait filename
finally use READ to compile from the buffer.

To use Kermit with FILE:
    set transmit prompt 46
    set transmit timeout 30
and then transfer using:
    transmit filename
this compiles line by line as they are transferred.

 

Changing Baud Rate and CPU Clock Rate

CPU Clock is controlled by GCR at 0x00
                0x08 is the default (no divide)
                0x04 divides the CPU by 8, with no divide for peripherals
Clock Doubler is controlled by 0x0F
                0x5B use doubler (default).
                0x00 no doubler

Baud rate for Serial A is controlled by counter A4 at 0xA9
                at 22MHz default, 19,200 baud is 0x23 (35). 38,400 baud is 0x11 (17),
                57,600 baud is 0x0B (11). 115,200 is 0x05.

To change the baud rate to 115,200:
HEX
5 A9 p!

 

Loading a New gForth Image

You can force a new gForth image to load into an existing FS2 file system by
compiling the loader and new gForth binary to the Rabbit, then reset the Rabbit
to boot gForth and type the RESTORE command. Recall that RESTORE copies
the image from flash into the filesystem (where the working image is stored).

This will be complicated if the new image uses a different serial port!

I've successfully typed RESTORE at the old serial port, then switched to the new serial port to type Y to complete the write to flash. A better approach is to reformat the file system using this Dynamic-C program to format the file system and the binary to load with RFU.

 

Coding Words in Assembly

Assembly code can be included by wrapping the position independent opcodes
with the code for a colon definition header and ending.
For small routines use the "," word to compile opcodes into code space.
Note that the Rabbit is little endian.

: NEWDUP [ here dup cell - cell - dp ! , 0 , ]
 [ 00c5 , ]
 [ eb00 , 235e , 2356 , fdeb , dd7d , 00e4 , 20e9 , ] ;

This creates a word NEWDUP that duplicates the existing word DUP.
The words on the first line convert the colon (Forth) definition into a code (assembly) definition.
Note that HERE is defined as DP @, so the first part of the first line
adjusts the value of the variable DP (the dictionary pointer. Brodie pg 213).
The next two lines stick the opcodes into successive memory locations.
The last of those two lines is next, with a nop pre-pended.
DUP in assembly is shown in Listing 1.

0 : C5		PUSH BC
1 : ; next ,  MACRO
1 : EB		EX	HL,DE
2 : 5E		LD	E,(HL)
3 : 23		INC	HL
4 : 56		LD	D,(HL)
5 : 23		INC	HL
6 : EB		EX	HL,DE
7 : FD 7D	LD	IY,HL
9 : DD E4 00	LD	HL,(HL+0)
C : E9		JP	(HL)
D : ;		ENDM

Listing 1

Loading Assembly Words

For larger assembly routines, first load hexloader.fs. This file is Forth source. Use the LOAD-READ described above.
Then use hexload to load a hex file produced by AS, a free, portable macro cross assembler.
The assembly source for mydup is in hextest2.asm.
Use the '-cpu z180 ' switch for as.exe
Use the '-F Intel16' switch for the p2hex.exe utility that creates the hex file.
The Rabbit 2000 is similar to the Z180. 
Use DB to place opcodes for new instructions and be careful to not use deleted or changed instructions.

You can load new assembly words as an Intel hex file:
First load hexload.fs (load, read)
Then load hextest2.hex (just load, no read)
Then follow these steps:

create mydup  ok
here dup  ok
hexload  ok
' mydup !  ok
' mydup 20 dump
    4D66: 6A 4D 00 00  C5 1A 6F 13 - 1A 67 13 FD  7D DD E4 00  jM....o..g..}...
    4D76: E9 00 9B DB  BE BB F4 90 - 9A 18 37 02  5C 06 F0 11  ..........7.\...
 ok
' dup 20 dump
     42C: 30 04 00 00  C5 1A 6F 13 - 1A 67 13 FD  7D DD E4 00  0.....o..g..}...
     43C: E9 20 26 04  84 32 64 75 - 70 20 4A 04  00 00 E1 E5  . &..2dup J.....
 ok
Note that HERE still points to ' mydup 4 +
You'll want to ALLOT the number of bytes in hextest2.hex to avoid over-writing mydup.
 

Interrupt Service Routines

gForth doesn't provide access to the EIR or IIR registers that provide the upper
byte of the reset vector. I've coded Forth words for internal interrupts IIR! and IIR@.
The interrupt vector table must locate vectors in 16 byte fields. If all are used,
256 bytes are needed for the vector table and this table must start at an address
that has zero in the low byte (i.e. address mod 256 = 0).
The most efficient place to put the vector table and allocate space for the service
routine(s) and shared variables (the address of the variable must be know to both
the service routine and Forth code) is in high memory.

Here is a Dynamic-C program that uses an assembly Timer-B interrupt service routine
to toggle the pins on Port-E at 1 Hz.

Here is a gForth program that does the same thing with the assembly source and hex.
LOAD hexload.fs
READ
LOAD iir_code_words.fs
READ
LOAD r2k_int.hex
DC02 hexload
LOAD timerB_int.fs
READ

Then inspecting DC00 should show the count changing.
Running blink will toggle Port-E at 1 Hz.

Porting to other Processors

It may take less time to port gForth to different processors if an existing cross assembler
(e.g. AS) is used to code the primitives. A Perl script can be run to create prims.fs
from the assembler list file. This is primarily an advantage in embedded systems where the
Forth assembler probably won't be used on the target due to memory limitations.


| © 2005 Ken Staton