Floating Away with AmForth
Leon Nathaniel Maurer
Sector67 Hackerspace,
[1] UW-Madison Physics Department
Abstract
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 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. 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]
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 )
do
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. 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]
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 — 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. 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. 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
If you don’t mind compiling something, Minicom
[17] is a good way to go. 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. 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.
-
Compile am4up: gcc -o am4up am4up.c
-
Install am4up: sudo cp am4up /usr/local/bin
-
Fire up minicom in configuration mode by entering minicom -s on the terminal. If you don’t have write access to the serial ports, first add yourself to the dialout group (sudo adduser NAME dialout) and then log out and in again.
-
Select File transfer protocols and hit enter.
-
We’ll define a new setting for AmForth, so select an unused line (e.g. j).
-
You want the definition to look like amforth am4up Y U N Y N , so enter amforth, hit enter, enter am4up, hit enter, etc.
-
Return the to main menu by hitting enter and go to Serial port setup.
-
Set the correct Serial Device by hitting a and then entering it. (If you’re using a USB to serial adapter, /dev/ttyUSB0 is probably the one.)
-
Enter the Bps/Par/Bits menu by hitting e. Hit c then q to set it for 9600 8N1. Hit enter to exit this menu.
-
Make sure hardware and software flow control are off (f and g as needed). Hit enter to exit this menu.
-
Select Screen and keyboard and set Line Wrap to yes with r. Hit enter to exit this menu.
-
Save setup as amforth
-
Exit from Minicom
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
I think RealTerm
[19] is the serial terminal to use on Windows. See Fig.
2↑. It requires some setup:
-
On the Display tab, select Ansi; backspace didn’t work for me with ASCII. Also enable Scrollback, so you can see text that’s off the screen.
-
On the Port tab, make sure it’s set to 9600 Baud, no parity, 8 data bits, 1 stop bit, and no flow control. You also need to select the appropriate port. (Check the Windows Device Manager — for whatever reason, mine was Port 5.)
-
To send a file, set the delays to 10 and 100 (10ms per character and 100ms per line) on the Send tab. These may need to be tweaked since this doesn’t look at the output from AmForth, so it’s possible to send the data too quickly. See 2.2.3↓ for more information and alternatives.
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 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
else
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
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
|
1x0.10USD
|
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
|
|
|
TOTAL PRICE:
|
13.14USD
|
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, melt a
small amount of solder on your iron, touch it to a pad or two, 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. 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; older versions recognize the ATMEGA328
P, 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.
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 1⁄3 in base 10, because 10 = 5 × 2; 3 isn’t a factor. However, it’s easy to write 1⁄3 in base 3; it’s 0.1. Likewise, it’s easy to write 1⁄5 in base 10 — 0.2 — since 5 is a factor of 10. However, 5 is not a factor of 2, so writing 1⁄5 in base 2 takes an infinite number of digits — like 1⁄3 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 1⁄5 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:
-
It uses the same stack for floating-point numbers as for integers and other data. I believe this is allowed by the ANS standard, but it isn’t ideal.
-
A couple of the words were rewritten in assembly by Pito for extra speed; I’ll try to dig those up as well.
-
The plain Forth implementation isn’t that fast, but it may be faster than you think; converting text to floating-point numbers and vice versa are the slowest parts. So if you test amforth-float with something like 5.2e1 2.5 f* f., keep in mind that the actual f* is only a small fraction of the total time to execute that command. This is less of an issue when the floating point numbers are compiled.
-
There are a number of words to print out numbers. I recommend fsd., which print out the number in scientific notation using the Dragon2 algorithm.[43] This prints the numbers relatively quickly and accurately — using only as many digits as are appropriate.
-
See the amforth-float readme[5] for other words in amforth-float that may be useful but aren’t in the standard.
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.
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.
References
[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