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 board.fs 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 sqrt.fs and sine.fs files llustrate. These were copied over from the Mecrisp distribution. The sqrt function operates on 32-bit unsigned integers, as you can see here:

1000000000 sqrt . 31622  ok.
4000000000 sqrt . 63245  ok.

The sine and 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 sine.fs code also defines constants for pi and 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 same:

pi 4,0 f/ 2constant pi/4
pi/4 sine f. 0,70710678072646260261535644531250  ok.
pi/4 cosine f. 0,70710678095929324626922607421875  ok.

We’re using f/ here to divide two 32.32 fixed point values. It’s also worth pointing out that there are no f+ and f-, because they’re the same as their 64-bit integer d+ and d- counterparts.

Anyway, so much for some basic maths. Matthias has recently added the arctan function and some other convenience definitions. These functions all rely on the CORDIC algorithm.

As final item in the list of extensions which are readily available with Forth, there’s a 32-bit pseudo-random number generator (PNRG), available as random.fs in the Embello repository:

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.

Check out the ex/prompt.fs, ex/random.fs, and ex/trig.fs demos to see how it’s done in Forth.

Weblog © Jean-Claude Wippler. Generated by Hugo.