Floating Away with AmForth

Leon Nathaniel Maurer



Sector67 Hackerspace,[1] UW-Madison Physics Department


AmForth[2] is a Forth[3] implementation for ATmega microcontrollers with a great feature: the programming environment runs directly on the microcontroller — simplifying development. Your big computer [A]  [A] or VT-100 serves only as a serial terminal that sends text to and receives text from the microcontroller; programing the embedded system in Forth is no different than programming your big computer in Forth.
This document summarizes four things: getting started with Forth in general, getting started with AmForth in specific, the simple AmForth development board I designed (an example of rolling your own circuit),[4] and my work developing amforth-float[5] — a floating-point[6] math library for AmForth and an example of Forth’s nearly seamless extensibility. I hope this piques your interest and gets you to explore AmForth.
(Note: I use Linux almost exclusively. Perhaps using OS X is similar. I have included or linked to information for Windows where I can. I hope this document is still useful for non-Linux users.)

1 Starting Forth

Forth[3] is a flexible, stack-based programming language that is ideal for embedded use. It has an amazing power to weight ratio; it can do a lot with limited resources. Forth zealots take this as one of many signs that Forth is the One-True-Langauge. I disagree; modern desktops and laptops are so powerful that a great power to weight ratio is unnecessary. Generally I’d rather use a language with dynamic typing, automatic memory management, many libraries available, etc. [B]  [B] Yes, you could add these to Forth, but I’ve had my fun extending the language for now. However, microcontrollers don’t have cycles to burn, making Forth an appealing choice.
There’s a great introductory book for Forth, Starting Forth by Leo Brodie. IMHO, it is a top-of-the-line introductory programming book by any standard. Even better, it is legally available online for free from two sources: Forth Inc.[7] and Marcel Hendrix’s authorized reproduction.[8] I prefer the former because it has Leo Bordie’s great illustrations. Both have text updated by Marcel Hendrix to work with the ANS standard for Forth.[9] [C]  [C] Instead of the Forth 79 and 83 standards used by previous editions.
That said, be aware that all Forth implementations have their own quirks, especially in the under-the-hood parts you’d eventually want to know.
I recommend playing with Forth on a big computer first. Many implementations are available. I’m happy with GForth (GNU Forth).[10] Binaries are available for Linux and Windows.
Here’s a small view of what Forth code looks like. Below is a subroutine — a “word” in Forth parlance — that prints the first n numbers (where n is a parameter given to the word).
( This is a comment! )
: count ( n — )
  0 ( n 0 )
    i . cr
  loop ;
If you’re into ideological language purity, consider this. People talk about “pure” object oriented languages — whether or not everything is an object. If you consider the purity of procedural languages, Forth would take the cake; basically everything in that definition is a subroutine. : is a subroutine that starts compilation, ( is a subroutine that tells the compiler to ignore the following text -- which is a comment, 0 gets compiled into a subroutine that returns zero, do is a subroutine that starts the loop, i is a subroutine that returns the index of the loop, cr is a subroutine that prints carriage return (newline), etc.
Because of this, the language’s syntax is totally up to you — a mixed blessing.

2 Starting AmForth

IMHO, the killer feature of AmForth is that it runs on the microcontroller and can be used interactively; you develop directly on the device! Your big computer serves only as a serial terminal that sends text to and receives text from the microcontroller.
Contrast this with using C: you write the code on your big computer, compile the code on your big computer, upload the code to the microcontroller, and try running the code. If it works, that’s great. If not, you have to go through the whole process again, possibly using debugging tools.
Since AmForth can be used interactively, you just try the code, and you know right away if it works or not. Combine this with the preferred Forth coding style of breaking everything into small subroutines (that are easily tested), and you have a powerful programming tool.
The trade-off is somewhat slower execution; the code is compiled to byte-code — as with Java or Python — not to machine code. However, it’s fast enough for many things. [D]  [D] If you really need speed, an ATmega probably isn’t the right tool for the job anyway. Note that — unless you’ve defined a subroutine — the code isn’t compiled, and execution will be slower since it’s not already byte-code; AmForth has to interpret the text.

2.1 The Microcontroller

That’s all well and good, but how do you put AmForth on an ATmega microcontroller? First, you need a device to run it on — like the board described in section 3↓ or an ATmega based arduino — and a programmer — like the USBtinyISP[11] or Pocket AVR Programmer.[12] You need a programmer even if your device has a bootloader (e.g. an Arduino) because AmForth will overwrite the bootloader; they’re incompatible.[13]
AmForth User’s Manual[14] has a good guide for getting started on Windows and Linux. However, I don’t recommend that you go with their default setup. It doesn’t include a way to delete old code! Add[16]
.include "dict_wl.inc"
to a new line in dict_appl.inc. That includes several words — written in assembly — needed to get deletion working.
Even on Linux, you need Atmel’s assembler — which is made for Windows [E]  [E] Periodically, someone will email the development list saying, “OMG, why don’t you use assembler X?”, where X=gavrasm, avra, etc. AmForth’s developers aren’t stupid; if a free assembler could be used easily, it would be. If you really want to use avra, people have gotten it to work in the past for some versions of AmForth. If you get it working, power to you. — and some other files from Atmel. These can be annoying to get on Linux because the installer doesn’t work well in Wine. However, I contacted Atmel and they said I can redistribute their assembler as long as I include the license — which I’ve done. [F]  [F] It wasn’t clear if this license applied to the assembler executable, but they say it does. I’ve included them in the files for the development board described below. See section 3.2↓. That’s also a good example of the modifications needed to get AmForth working. The assembler executable also available here.[15]
Once everything is assembled, you need to upload the binary to the microcontroller — as described in the User’s Guide (with a few pointers in section 3.2↓).
However, the word that actually handles deletion — MARKER, and another word it relies on, are written in Forth, not assembly; they’re not installed when flashing the microcontroller. While short enough to enter by hand (see the page on MARKER[16] for their location), there’s an easier way...

2.2 Interacting with AmForth

Once AmForth is on a chip, you need a serial terminal to interact with it. Preferably, it should be able to send files, so you don’t have to enter them by hand. My suggestions follow. Note that by default, AmForth communicates at 9600 baud (bits per second). This can be changed before compilation. However, I know of few reasons to. [G]  [G] It’s difficult to type faster than (9600)/(8 + 1) = 1066.6 characters per second. Faster speeds could be useful if you’re using the serial connection to transfer lots of data. AmForth serial communication always uses 8 data bits, no parity bits, and 1 stop bit (often abbreviated as 8N1) without hardware or software flow control.

2.2.1 Linux Terminal

Welcome to minicom 2.6.2
Compiled on Feb 8 2013, 07:03:03.
Port /dev/ttyUSB0, 12:30:21
Press CTRL-A Z for help on special keys
5 2 + .
7  ok
> : hello ." Hello World! " cr ;
> hello
Hello World! 

Figure 1 An example Minicom session.
If you don’t mind compiling something, [H]  [H] If you do mind compiling something, what on earth are you doing here?!? Were you expecting a cat video? Minicom[17] [I]  [I] available though most Linux distributions is a good way to go. [J]  [J] Moreover, you’re not a 1337 h4x0r if you can’t use a command line serial terminal. See Fig. 1↑. Al Williams[21] released a great program, am4up,[22] that seamlessly interfaces with Minicom to upload files to AmForth. Many upload methods ignore feedback from AmForth, so text can be sent too fast for AmForth to process. [K]  [K] Computers can type (9600)/(8 + 1) = 1066.6 characters per second. am4up watches AmForth’s output and sends text as soon as AmForth is ready — which results in fast uploads without causing problems.
am4up is written in C and distributed with AmForth — located at tools/am4up.c. Instructions for the one-time setup follow.
You can start up Minicom using these settings with minicom amforth. Do this to verify everything is working. The main screen is a terminal that allows you to communicate with AmForth. Try typing something like 5 2 + . followed by enter. (See Fig. 1↑.)
The Minicom command help screen is accessed with ctrl-a z; this brings up a list of possible commands. For example it says s is for uploading files, so entering s from this menu, or ctrl-a s from the main screen will bring up the upload menu. Select amforth, and navigate to the file to upload. Two spaces enter a directory, and one space selects a file. Once a file is selected, select [Okay] at the bottom of the screen (using the left and right arrows), and hit enter. (You can define a default upload directory in Filenames and paths from the configuration menu we used — now accessible with ctrl-a o.)

2.2.2 Windows Terminal

figure RealTerm Send.png
Figure 2 An example RealTerm session, after a Hello World program file has been uploaded and ran.
I think RealTerm[19] is the serial terminal to use on Windows. See Fig. 2↑. It requires some setup:
It may also be possible to use Minicom on Windows through Cygwin.[20, 18]

2.2.3 Non-Serial-Terminal Uploaders

There’s a Python[24] script — amforth-upload.py — that works on Linux and Windows [L]  [L] although you have to install Python first and looks at the output from AmForth, so it shouldn’t send data too fast for AmForth to handle. I’ve found the script in the most recent version of AmForth (5.1) is broken. However, older, working versions are available.[23] On Linux, it’s used like
amforth-upload.py -t /dev/ttyUSB0 /path/to/file.fth
where /dev/ttyUSB0 is the correct serial port. I imagine the script is used similarly on Windows, although I haven’t tried it.
Finally, you can use the ascii-xfr command on Linux:[25]
ascii-xfr -s -c 10 -l  100  /path/to/file.frt > /dev/ttyUSB0
This doesn’t look at the feedback from AmForth. The -c option is the delay between characters and -l is the delay between lines (both in ms). 10 and 100 are the settings from the AmForth FAQ, but they may need to be adjusted.

2.3 Executing more complex code

The above examples only show simple code running on AmForth, but it can handle as complex code as you want. Here’s an example of more complicated code — composed of simple-to-understand calls to other words — that’s part of amforth-float:4↓
: >float ( n-c-addr u-length — f true | false)
 [’] string>float catch
 0= if \ was there an error?
   true \ no error — we have a float
   drop drop false \ couldn’t make a float; clear the two inputs off the stack
 then ;
This word tries to convert the string of length u-length at memory location n-c-addr to a floating-point number. If the string>float word can’t do this, it raises an error, which is caught by catch. If there is an error, false is left on the stack. Otherwise, the string can be covered to a float, so the float f and true are left on the stack.
See the amforth-float source code[5] for more examples of non-trivial code.

3 AmForth Board Design

figure fth_brd.jpg
Figure 3 My AmForth Development Board
Part Part Number Description DigiKey Link and Price
IC1 ATMEGA328-AU microcontroller 1x2.77USD
IC2 FT232RL USB to serial chip 1x4.50USD
FB MI0805K400R-10
ferrite bead to limit noise [M]  [M] 
Recommended in the FT232R datasheet.
X1 AWSCR-20.00CV-T 20MHz ceramic resonator 1x0.45USD
RX,TX APT2012EC Red LED 2x0.16USD
R1,R2 RMCF0805JT330R 330Ω resistor 2x0.03USD
C1 C0805C103K5RACTU 10nF capacitor 1x0.10USD
C2,C4 C0805C104Z5VACTU 100nF capacitor 2x0.10USD
C3 CC0805ZRY5V6BB475 4.7μF capacitor 1x0.10USD
10118194-0001LF micro B USB connector 1x0.46USD
30306-6002HB 6-pin ISP header 1x0.64USD
PCB from OSH Park[4] 3 for $10.50 3.50USD each
Table 1 Bill of Materials for my AmForth Development Board
If you just want to play around with AmForth, a pre-made board like an arduino will work fine. However, if you want to integrate AmForth into your own circuits, understanding a simple, bare-bones design is useful. To that end, I’ve made a simple board based around a ATMEGA328-AU[26] microcontroller — running at 20MHz — and a FT232R USB to serial IC.[32] See Fig. 3↑ for a view of the device and Table 1↑ for the Bill of Materials.
I’ve found the FT232R[32] — which converts USB to TTL level serial — is simple to use, and this board uses its default settings. However, a single FT232R costs $4.50 from DigiKey (as of 10/9/13) and takes up board space; if you start integrating AmForth into your designs, you probably don’t want a FT232R on every board. Instead, you could use a TTL-232R-5V[33] — a cable with an integrated FT232R. Then you would only need a 6 pin header on your board. Even better, you could make a small board with an isolator chip — like this[34] — and put that between the TTL-232R-5V (or an on-board FT232T) and your circuit. That way, if something goes wrong, you’re much less likely to fry your big computer.

3.1 Circuit Assembly

The surface mount parts may look intimidating, but they’re not too hard to solder. In fact, using a decent soldering iron with a small chisel tip, I can solder such ICs faster than their through-hole brethren. Liberally flux the board with a flux pen,[35] position the IC with tweezers, [N]  [N] The flux will help hold the IC in place. melt a small amount of solder on your iron, touch it to a pad or two, [O]  [O] Try to avoid touching the pin so that you don’t move the IC. and those pins are soldered to the pads by the miracles of surface tension and capillary action. Solder down the corners of the chip this way. Then melt a little solder on the tip of your iron, drag it across the remaining pads, and they’ll be soldered too. Melt, drag, repeat. The trick is to not put too much solder on your iron; that can lead to solder bridges between pins. Those can often be fixed by cleaning your iron then touching the bridge — drawing the solder back to the pins and to your iron. Otherwise, you’ll have to break out the solder wick. See David Jones’ great video introduction to surface mount soldering.[27] (Although, unlike him, I don’t melt solder on a corner pin before placing the chip.)
The micro USB connector can be soldered in the same way. Although the pins aren’t really accessible, if you flux and then apply solder to the pads, it’ll solder the pins. The four support posts don’t go fully though the board, but they can still be soldered from the other side by heating the through hole and feeding in solder. Be careful that you don’t apply too much solder; it can flow into the USB receptacle. This happened to me, and I was able to remove it away with solder wick.
The small parts can be soldered with the tack-and-reflow method Dave Jones describes. The resonator may look tricky, because it has three pads, but if the pads are fluxed beforehand, solder will be wicked under them.

3.2 Compiling and Programming

A good deal — but not all — of this section assumes you’re running Linux. I have not done this in Windows, which does not use a makefile. However, I imagine many of the steps are similar steps.
On Linux, the below changes are to the makefile unless otherwise noted. I’ve uploaded my amforth-5.1 folder with all the following changes already made.[31] This setup also includes the changes needed for MARKER and amforth-float (see section 4↓). The files for this board — including the hex file that can be used to flash the chip without compiling anything — is in the appl/FTH_BRD subdirectory. If you do want to compile things, this folder also includes the necessary Atmel assembler and files. [P]  [P] It wasn’t clear if avrasm2.exe could be redistributed, but I contacted Atmel who said redistribution is allowed as long as their license file is included — which I’ve done. The latter are in the Atmel/include folder — not Atmel/Appnotes2 as in the User’s Guide.
AVRDUDE[28] (AVR Downloader/UploaDEr) is used to program the microcontroller, but only version 6 and higher recognize the ATMEGA328; [Q]  [Q] Ditto for a number of other chips. older versions recognize the ATMEGA328P, which is nearly identical. As of this writing, version 6 is very new and hasn’t propagated far. There are two ways to use earlier versions of AVRDUDE: add the 328 to the AVRDUDE configuration file or force AVRDUDE to treat the 328 like the 328P by using the -F flag — i.e. AVRDUDE_FLAGS=-c $(BURNER) -p $(MCU) -F. Then you use MCU=atmega328 when compiling and MCU=atmega328p when flashing. [R]  [R] You can probably use MCU=atmega328p for both.
The BURNER=usbtiny line should be edited to match the programmer you’re using. See [29] for a list of programmers and microcontrollers supported by AVRDUDE.
Note that this design doesn’t use the default fuses since it has a 20MHz ceramic resonator. It uses the Full Swing Crystal Oscillator with the Ceramic resonator, slowly rising power 1K CK 14CK + 65ms settings. It also doesn’t use the divide by 8 clock setting. This corresponds to 0xC7 and 0xD9 for the low and high fuses [26, 30] — defined in the makefile. The clock rate requires editing template.asm so that AmForth knows we’re running at 20Mhz. Change the appropriate line to read .equ F_CPU = 20000000.
In the appl/FTH_BRD directory, you compile the code with the command make, flash the device with make install, and set the fuses with make write-fuse — only necessary once per device. (You have to add sudo to the front of those commands if you don’t have the appropriate write access.)

3.3 Sharing

The board schematics and layout[36] are yours to use in any way you please. You can order the board directly from OSH Park.[4] If you do cool stuff with this, I’d appreciate acknowledgement, but it’s not required. As a grad student, I’m used to net getting much recognition ;)

4 amforth-float

amforth-float is my contribution to AmForth.[37, 38] I think it used to be distributed with AmForth, although I don’t think it still is — understandable because I didn’t update it for several years and updates to AmForth broke a couple things. It’s available[5] under the GPL from GitHub.
This isn’t just a wrapper around another floating-point library; this is my own work, written in plain Forth. Furthermore, this isn’t just a couple of routines built on top of AmForth’s preexisting floating-point capabilities — because it has none! If you enter 5.2e-3 into AmForth without amforth-float installed, you’ll just get a bunch of question marks. It has no idea what that means; it only can handle integers. This is a great example of Forth’s extensibility.

4.1 Motivation

I started this project to practice Forth. I’d say most of my code is written cleanly, but a number of the later words (like f* and f/) really need some cleanup and refactoring. It was quite an interesting project, and I learned a lot about floating point numbers along the way.
I hope to improve and extend the code further.
Here’s one thing I learned:
Do you every wonder why computers often have problems printing floats. E.g. 2e-5+2e-6 in Python is 2.2000000000000003e-05. Where did that 3 come from? Is it just a rounding error, or does it have a deeper significance?
You can’t really write 13 in base 10, [S]  [S] It would take an infinite number of digits. because 10 = 5 × 2; 3 isn’t a factor. However, it’s easy to write 13 in base 3; it’s 0.1. Likewise, it’s easy to write 15 in base 100.2 — since 5 is a factor of 10. However, 5 is not a factor of 2, so writing 15 in base 2 takes an infinite number of digits — like 13 in base 10. [T]  [T] How does this extend to more complicated numbers? 100 = 22 × 52 and both 2 and 5 are factors of 10, so you can write 1100 in base 10. Furthermore, if you can do that, you can also write 2100, 37100, etc. in base 10. 30 = 2 × 3 × 5 and while 2 and 5 are factors of 10, 3 is not, so you can’t really write 130 in base 10.
In short, there are many fractions you can write in base 10 that require an infinite number of digits to write in base 2. Since we can’t store an infinite number of digits, exactly storing numbers like 15 with binary floating numbers point is impossible.
There are complicated algorithms to work around this; they look at the binary number and try to figure out what base 10 number you really wanted. For example, see the Dragon4 algorithm.[43] Clearly, whatever method Python uses isn’t perfect — although that may be just a rounding error.

4.2 Under the Hood

This library basically implements IEEE 754[39] single-precision (32 bit), floating-point numbers — although I doubt it’s totally in compliance with the standard. It is designed to support the ANS Forth optional Floating-Point word set.[40] It implements all but one of those words[41] as well as a number of words from the ANS Forth Floating-Point extension words.[42] Most of the words for the latter are related to printing, although someone else (Pito — international man of mystery) implemented more of the math words (like FCOS, FSIN, etc.). I’ll try to dig up that up and include it.
A couple of other notes:
Extending AmForth to interpret floats works through AmForth’s recognizer framework.[44] That has a list of functions AmForth uses on text in an attempt to understand it. By default, there are three functions. The first recognizer checks if it’s a known word (subroutine). If that fails, the next recognizer checks if it’s an integer. If that fails, the last recognizer simply raises an error. amforth-float adds rec-float to this list, after the integer recognizer. So, if you enter an integer or an integer followed by a dot — e.g. 52., it’ll be recognized as a single or double integer, because the integer recognizer gets a crack at the number first.
This is a nice framework, because you can add your own recognizers to the list to extend AmForth further.

4.3 Installation

amforth-float requires more words to be included before assembly. (If you remove parts of amforth-float, you can get away without them, but it’ll reduce functionality.) Add the following to dic_appl.inc
; for maker
.include "dict_wl.inc"
; needed for place-rec
.include "words/n_to_r.asm"
.include "words/n_r_from.asm"
; needed for recognizer
.include "words/get-recognizer.asm"
.include "words/set-recognizer.asm"
; other files for amforth-float
.include "words/d-equal.asm"
.include "words/2r_from.asm"
.include "words/2to_r.asm"
Then, upload postpone.fth, marker.fth, and float.fth in that order. [U]  [U] The first two files get MARKER working.

5 The End, For Now

Have fun floating away!
I’d like to thank AmForth-lead-developer Matthias Trute and other (like Pito) on the amforth-devel mailing list[45] for their great work in general and helping me to get started and develop amforth-float.


[1] Sector67 Hackerspace http://www.sector67.org/

[2] AmForth http://amforth.sourceforge.net/

[3] Forth Wikipedia article http://en.wikipedia.org/wiki/FORTH

[4] PCB from OSH Park http://oshpark.com/shared_projects/kVCM3Rwe

[5] amforth-float GitHub page https://github.com/lnmaurer/amforth-float

[6] Floating-Point Wikipedia article http://en.wikipedia.org/wiki/Floating_point

[7] Starting Forth from Forth Inc. http://www.forth.com/starting-forth/

[8] Marcel Hendrix’s authorized reproduction of Staring Forth http://home.iae.nl/users/mhx/sf.html

[9] ANS Forth standards document http://lars.nocrew.org/dpans/dpans.htm

[10] GForth http://www.gnu.org/software/gforth/

[11] USBtinyISP http://learn.adafruit.com/usbtinyisp

[12] Pocket AVR Programmer https://www.sparkfun.com/products/9825

[13] AmForth Documentation: Hardware http://amforth.sourceforge.net/TG/Hardware.html

[14] AmForth User’s Manual http://amforth.sourceforge.net/UG/amforth_user.html

[15] avrasm2.exe downloadshttp://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=859&showinfo=1

[16] Un-Doing Definitions http://amforth.sourceforge.net/TG/recipes/Forget.html

[17] Minicom Wikipedia article http://en.wikipedia.org/wiki/Minicom

[18] Cygwin homepage http://www.cygwin.com/

[19] RealTerm Homepage http://realterm.sourceforge.net/

[20] Minicom for Cygwin http://www.xantius.com/articles/minicom.php

[21] Al Williams’ Site http://www.hotsolder.com/

[22] am4up source code https://sourceforge.net/p/amforth/code/HEAD/tree/releases/5.1/tools/am4up.c

[23] Working version of amforth-upload.py https://sourceforge.net/p/amforth/code/HEAD/tree/releases/4.4/tools/amforth-upload.py

[24] Python programming language homepage http://www.python.org/

[25] AmForth FAQ: How do I send forth code to the system? http://amforth.sourceforge.net/faq.html#how-do-i-send-forth-code-to-the-system

[26] ATmega328 http://www.atmel.com/devices/atmega328.aspx

[27] EEVblog #186 - Soldering Tutorial Part 3 - Surface Mount http://www.youtube.com/watch?v=b9FC9fAlfQE

[28] AVRDUDE Homepage http://savannah.nongnu.org/projects/avrdude

[29] AVRDUDE Option Descriptions http://www.nongnu.org/avrdude/user-manual/avrdude_4.html

[30] Engbedded AVR Fuse Calculator http://www.engbedded.com/fusecalc

[31] My complete AmForth 5.1 folder https://mywebspace.wisc.edu/lnmaurer/web/FloatingAway/amforth-5.1.tar.gz

[32] FT232R USB UART IC Webpage http://www.ftdichip.com/Products/ICs/FT232R.htm

[33] TTL-232R-5V USB to serial cable http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm

[34] SI8622EC-B-IS 2 channel digital isolator http://www.silabs.com/Support%20Documents/TechnicalDocs/Si861x-2x.pdf

[35] Rosin flux pen http://www.digikey.com/product-detail/en/835-P/473-1033-ND/949475

[36] Eagle CAD schematic and board files for the development board https://mywebspace.wisc.edu/lnmaurer/web/FloatingAway/FTH_BRD_design.zip

[37] 19.9.2010: release 4.2http://pages.citebite.com/g2y1n7x1r6ips

[38] AmForth 5.1 Readme http://sourceforge.net/p/amforth/code/HEAD/tree/releases/5.1/readme.txt

[39] IEEE Standard for Floating-Point Arithmetic (IEEE 754) Wikipedia article http://en.wikipedia.org/wiki/IEEE_floating_point

[40] ANS Forth chapter 12: The optional Floating-Point word set http://lars.nocrew.org/dpans/dpans12.htm

[41] ANS Floating-Point words http://lars.nocrew.org/dpans/dpans12.htm#12.6.1

[42] ANS Floating-Point extension words http://lars.nocrew.org/dpans/dpans12.htm#12.6.2

[43] How to print floating-point numbers accurately http://dl.acm.org/citation.cfm?id=93559

[44] Recognizer — Dynamically Extend The Forth Interpreter http://amforth.sourceforge.net/pr/Recognizer-en.pdf

[45] amforth-devel mailing list https://sourceforge.net/mailarchive/forum.php?forum_name=amforth-devel

Creative Commons License
Floating Away with AmForth by Leon Nathaniel Maurer is licensed under a Creative Commons Attribution 3.0 Unported License.