Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


A Forth VM for development boards and the PC, written in C.

BoardForth supports automatically running a user-defined word during the loop() phase of the arduino interface.

- Of course, that 'word' can be as complex as needed.
- This is done by setting DICT to the XT of the desired word.
- Similarly, setting DICT to 0 will disable automatic running.
- The easiest way to do this is to use the 'auto-run-last' and 'auto-run-off' words:
    - e.g. ... : auto-run-last LAST >BODY dict A! ;
    - e.g. ... : auto-run-off 0 dict A! ;
- The only rule is that the stacks need to end up with the same depth when done.

To build this VM for a given board:

- Open the Arduino software IDE.
- Load file bf/bf.ino.
- Select the proper COM port and target board.
- Change the following #defines in defs.h to appropriate values for the target board.
    - #define DICT_SZ (24*1024)
    - #define STK_SZ 32
    - #define TIB_SZ 0x0080
- Press the [Verify] button (<ctrl>-R).

To deploy the VM to the development board:

- Follow the steps from above, but use the [Upload] button (<ctrl>-U) instead.


- This is not an ANSI standard Forth.
- This is a work in progress. I welcome collaboration.
- Words are not case sensitive. DICT, Dict, and dict all refer to the same word.
- The data and return stack sizes are defaulted to 32 CELLS (32-bit). That can be easily changed in board.h
- To add an opcode (primitive):
    - Add a 'X("NEWOP", NEWOP, code) \' to the BASE_OPCODES list in defs.h.
    - If the code is more involved, define a function and call that.
- The development process I use is as follows:
    - Deploy the VM as above.
    - Open up Serial Monitor or PuTTY on that COM port.
    - Interactively code as usual, including defining new words as appropriate.
    - When I know what I want to keep, I update SOURCE_USER with any new code.
    - If there is anything from the interactive session I want to use, I copy it from the session.
    - Rebuild and upload the project to the board, and the new functionality is now "built-in".

To control a LED connected to pin 4, you can do this:

- : HIGH 1 swap pin! ;
- : LOW 0 swap pin! ;
- variable (led) 4 (led) !
- : led (led) @ ; 
- led output
- : led-on led HIGH ;
- : led-off led LOW ;
- led-on                  \ the LED turns on
- led-off                 \ the LED turns off

The standard 'blink' example program:

- #13 (led) ! led output
- variable (waitTime) 250 (waitTime) !
- : delay (waitTime) @ ms ;
- : blink led HIGH delay led LOW delay ;
- auto-run-last                    \ the LED starts blining with a 500 ms interval
- 100 (speed) !                    \ the led speeds up
- 500 (speed) !                    \ the led slows down
- auto-run-off                     \ the LED stops blining

To read a switch connected to pin 36, do this:

- : sw 36 ; sw input
- sw pin@ .

To read a potentiometer connected to pin 8, do this:

- : pot 8 ; pot input
- pot apin@ .

To turn on the LED depending on the value of the above switch:

- : sw->led sw pin@ led pin! ;     \ this will turn the LED on or off depending on the switch at pin 36
- auto-run-on                      \ now when you flip the switch, the LED turns on or off
- 0 auto-run                       \ the LED no longer changes when the switch is flipped


A token-threaded VM for the PC and development boards, written in C





No releases published


No packages published