Forth

Forth on Raspberry Pi

Start the Forth interpreter with ./atlast and exit with Ctrl + d.

atlast.html and atlast.pdf is included and is an extensive ATLAST Forth manual. Read it online and read about Forth itself here  and here  (Beware that the Forth dialect in the book Starting Forth is a bit outdated compared to ATLAST Forth). Leo Brodie wrote another book, Thinking Forth, read it here and here

Adding new words
Most of the power of ATLAST Forth derives from the ease with which C coded primitives can be added to the language. In my case I will add some words for controlling my Gertboard. There is a detailed description on how to do this in the ATLAST Forth manual. And you can copy much of the word implementations from the gertboard_sw directory if you have downloaded the gertboard demo files. It is easy to add your own words, just add a "define GERTBOARD" to atlast.c around line 56.

Include gb_common.h and gb_spi.h right after include :

Then add your own word definitions at the end of the section with word definitions, around line 2704, right after #endif /* COMPILERW */ in atlast.c:

And finally, add the actual words to the Table of primitive words, right after #endif /* EVALUATE */ at line 2960 or so.

As we are using code from the Gertboard demos, copy the files gb_common.c, gb_common.h, gb_spi.c and gb_spi.h from the gertboard_sw directory to atlast-1.2 directory.

Add gb_common.o and gb_spi.o to the file Makefile in atlast-1.2. Now, save and run "make" again to recompile atlast.c.

Test the new words
Wire up the Gertboard according to the information you get when you run the command sudo ./leds in the Gertboard demo directory.

Run sudo ./atlast in the atlast-1.2 directory.

Type 1 gertboard

Type 22 1 setio and press enter, the corresponding LED will go on.

Type 22 0 setio and the LED will go off.

Type 0 gertboard

Play with it
Define your own LED demo, start the interpreter with sudo ./atlast. Define these words:

Now type:

A real Use Case
I have a kWh meter that I would like to read with the Raspberry Pi. On the meter there is a small light that blinks once per 3.6 sec at 1 kW. So I need a way to detect time between pulses. I mounted a simple LDR (2k - 20k) for around €2 over the blinking light and connected it to Gertboard Buf1 and ground. Set B1 as an input with a jumper on the board and connect GP25 to B1.

Now that you know how to add a primitive word to ATLAST, I just list the code for the word: Start the interpreter with sudo ./atlast. Test the commands Result: Jolly good, or as they say in USA, awesome! Tests shows an accuracy down to a single watt.

However, having the kW load on the command line in a terminal is not good enough, I want it online on the web or as a mobile app. If you are interested, follow me over to the Erlang page where I vill use this ATLAST Forth application as an Erlang Port  to access Gertboard from a web page.

More Fun
To play a little more with the demo I need another primary word: SLEEP that takes one item on the stack, sleep time in microseconds. This very simple word should have been the word to start with, it actually shows three fundamental things for a primary word in three lines of code. Sl(1) to make sure there is at least one item on the stack. usleep(S0) is using the top stack item S0. Pop; pops the S0 stack item off the stack when it has been used.

Add this primary word to atlast.c. Put it right after the function prim P_quit Remember to wire up the Gertboard according to the information you get when you run the command sudo ./leds in the Gertboard demo directory. Now we can do:

Now define the word leddemo:

Reflective Sensor
The edge trigger word can be used for other sensors as well, I tried it with this Reflective Sensor and it works right out of the box. Connect VCC to a digital output and the "Out" to a digital input. Gnd to Gnd. I found it more convenient to look for positive edges so here is the word for that:

Define a word COUNT to test the setup (output on the sensor is connected to Buf2 on Gertboard and VCC is connected to Buf3):

More Gertboard Words
Here are some more words for reading and writing the analog input and output (DtoA and AtoD). First GETATOD, it takes a channel on the stack and leaves a voltage.

And SETDTOA expects a channel and a voltage on the stack and sets the output accordingly.

If you would like to read a burst of values from an analog input, here's how to do it. The word GETBURST expects a channel, a delay in microseconds between samples, and the number of samples you want. It leaves the samples on stack. You may want to increase the stack length constant at line 138 like this: atl_int atl_stklen = 1000;	     /* Evaluation stack length */ And finally, add the new words to the list of primitives:

If you want a simple way to inspect the values captured with the getburst word, one way is to let ATLAST Forth create an HTML page. Here is the code for that: The word htmlcanvas takes a filename on stack. It runs getburst and writes the result as a line diagram in a canvas element.

Tellstick
In order to have a safe way to handle mains switching, a Tellstick is an excellent choice. It can control many consumer brands of wireless controlled sockets and dimmers. Implementing some words in Forth for switching mains on and off leaves the safe voltages for sensing through the Gertboard interface.

Download and install the development kit from Telldus: (UPDATE: I could not make 2.1.2 to work. Use 2.1.1 and add a line in /home/pi/telldus-core-2.1.1/common/Socket.h before you run the make command, right after line 9, see below.)

When that installation is done you can copy two files over to the ATLAST Forth directory:

Then add the lib libtelldus-core.so to the Makefile, at the top, right after -lm:

In atlast.c, add define TELLDUS right before #define MATH;

In atlast.c, include the telldus_core.h file:

In atlast.c, right after #endif /* COMPILERW */ add the following Tellstick primitives:

And finally, add the new words to the list of primitives:

Save atlast.c and re-run make to compile and you can try your new words. Remember to configure /etc/tellstick.conf according to the brands of hardware you are using, read the Tellstick documentation. First, start telldusd and then ATLAST. In the ATLAST console, type your new Forth words:

Tellstick duo
If you are fortunate enough to have a Tellstick Duo, you probably want to listen for incoming 433 MHz signals so here we go. But first follow the Tellstick instructions above, and test that they work as expected.

Add this primitive word to atlast.c. We will use it to register a callback. (A callback is an ordinary function, nothing strange, but it will be called not by you but by the Tellstick Duo when there is data coming in). Then add the callback function. This is the function that will be called. Add it around line 295, just above the line /* TOKEN  --  Scan a token and return its type. */ Finally, add the new primitive word to the list of primitives

Now, to try it out, save and re-compile with make and then start telldusd and ./atlast. Type the following in the ATLAST console: The word rawevent is executed by the callback function. You can re-define it, and it will use the latest definition. With this definition it will just type the incoming data in the console. If you take a Nexa remote control and press a few buttons, the incoming data should print as a string, for example,

"class:command;protocol:waveman;model:codeswitch;house:A;unit:1;method:turnoff;"

You can even put the three lines of Forth code in a file, for example, telldus.atl and start ATLAST like this

Websockets
With all these sensor signals coming in from Gertboard and Tellstick Duo it would be nice to be able to connect to a web server and upload data in real time. Websockets is a new way to create a full duplex communication pipe between a websocket client and a web server. Download and install noPoll http://www.aspl.es/nopoll

Add the lib nopoll to the Atlast Makefile so that the lines LIBRARIES and INCLUDE looks like this:

In atlast.c, add #define WEBSOCKETS right before #define MATH;

In atlast.c, include the nopoll.h file:

In atlast.c, right before /* TOKEN  --  Scan a token and return its type. */ add the following nopoll globals:

In atlast.c, right before /* Table of primitive words  */ add the following nopoll primitives:

And finally, add the new words to the list of primitives:

Save atlast.c and re-run make to compile and you can try your new words.

To connect to the echo server: The dot after wsconnect will print out a -1 if connected, 0 otherwise. The dot after wssend will print the number of characters sent. The dot after wsrec will print the number of characters received.

A websockets example
We have a nice temperature sensor connected to our gertboard atod channel 0 and wants to send the temp value up to a server every second. A common wire protocol for websockets communication is json. Here's some words for encoding a json object. The word jsonencode takes name-value pairs on the stack and the pair count and puts a json string in the buffer json. I have defined two names, id and voltage. You may want to increase the number of temporary string buffers in atlast.c at line 137. A temporary string buffer is a buffer not defined with size and the word string. So, the code for temperature sensor upload could be something like this: