Simple Mecrisp Forth utilities May 2017
The default message shown after a reset of Mecrisp Forth is this prompt:
Mecrisp-Stellaris RA 2.3.6 for STM32F103 by Matthias Koch
Nothing else, no hint that you can start entering commands. With a
file from Embello loaded, we get an extra line with some useful status
information (and an “ok.”):
Mecrisp-Stellaris RA 2.3.6 for STM32F103 by Matthias Koch 64 KB <g6s> 32212433 ram/flash: 17024 19456 free ok.
But the fact remains that the “ok.” prompt is in a not-so-common spot, at the end of each line:
1 2 + . 3 ok. 1 ok. 2 ok. + ok. . 3 ok.
With the prompt.fs code, we can change that - yes, in Forth nearly everything can be changed:
R#0 > 1 2 + . 3 R#0 > 1 R#1 > 2 R#2 > + R#1 > . 3 R#0 >
Where “R” means we’re compiling to RAM (“F” is flash), the “#” means the number base is currently set to decimal, and the number tells us the number of items on the data stack.
The way this works is that Mecrisp calls
hook-quit after each command line.
This lets us switch to our own read-eval-print-loop, or
REPL - as this interactive
process is usually called.
Note that this interferes with Folie’s handling of the prompt and will somewhat
confuse it - it’s better to use
picocom or some other terminal emulator if you
want to alter Forth in this way.
Mecrisp Forth does not have a lot of math support built-in. But everything can
be added on top, as the
files llustrate. These were copied over from the Mecrisp
sqrt function operates on 32-bit unsigned integers, as you can see here:
1000000000 sqrt . 31622 ok. 4000000000 sqrt . 63245 ok.
cosine functions, however, operate on “32.32” fixed-point
number, i.e. a 64-bit value represented as two 32-bit words in Forth, with the
decimal point assumed to be in-between these words. In other words, fixed
32-bit integer and fractional parts. In practice, this precision (over 9 digits
each) and the range of values which can be represented is more than enough for
many use cases. The benefit of this representation, is that the operations
require no hardware floating point support and are quite efficient (more on that
in an upcoming article).
In Mecrisp Forth 32.32 fixed point values can be entered by inserting a comma in the value:
123456789,987654321 f. 123456789,98765432089567184448242187500000 ok. 123456789,987654321 9 f.n 123456789,987654320 ok.
Note the somewhat excessive printed precision with “
f.” (in case you’re
printing them out in base-2!) and how the number of decimals can be limited with
f.n”. Note also the unavoidable loss of precision when it comes to
representing a base-10 mantissa as a base-2 value:
0,1 f. 0,09999999986030161380767822265625 ok.
Back to sines and cosines. The
code also defines constants for
pi/2, but not
pi/4, so let’s add
that and verify that the sine and cosine of 45° (π/4 in radians) are almost the
pi 4,0 f/ 2constant pi/4 pi/4 sine f. 0,70710678072646260261535644531250 ok. pi/4 cosine f. 0,70710678095929324626922607421875 ok.
f/ here to divide two 32.32 fixed point values. It’s also
worth pointing out that there are no
f-, because they’re the same as
their 64-bit integer
Anyway, so much for some basic maths. Matthias has recently added the
function and some other convenience definitions. These functions all rely on the
random . -1412445179 ok. random . 1559860420 ok. random . 910593606 ok. random . -493546331 ok. random . -1177063378 ok.
To verify that the generated numbers are indeed randomly distributed, we can run a small test:
2000000 tally counts 999707 999541 1001010 1001118 999600 999359 1000272 999002 999779 1000194 999404 1000235 1000026 1000394 1000672 999687 ok.
This generates 2,000,000 random numbers of each 32-bit, cuts them up into 4-bit pieces, and counts how often each of the 0000..1111 patterns occur. If evenly distributed, all the counts will be very similar most of the time - as indeed confirmed in the above printout.