Sunday, May 11, 2014

SIMPL Revisited

SIMPL

SIMPL stands for Serial Interpreted Minimal Programming Language.

It provides a quick means of programming microcontrollers for I/O interaction, using short text strings.

What this means is that a block of code or function can be invoked by sending a single serial character. Text strings are interpreted, character by character, to produce a complex program flow.

A few characters typed in to the serial terminal can be used to set output ports, read inputs or create accurately timed, complex sequences of I/O interaction. Operations can be chained together, stored in RAM and given a single uppercase alpha identity, which when typed will execute the whole sequence of instructions.

SIMPL is an interpreted language, which although this gives a minor speed disadvantage over compiled code, is fast enough for most experimentation - but to it's advantage, massively increases interactivity with the code.  Commands are easily retyped, modified and re-executed immediately, without having to go through the edit - recompile - reload process, which even on the Arduino slows down iterative development to every couple of minutes or so.

SIMPL builds up an interactive programming environment, the framework of which can be re-used from project to project, either for debugging, experimentation, or interacting with the microcontroller with the minimum of overheads.

The Arduino is essentially a serial connected device, as are many other microcontroller dev-boards, and as a simple, low overhead means of controlling the micro from a serial terminal program SIMPL provides a framework onto which more elaborate applications can be built. Blocks of code can be exercised in turn using serial commands, and debug sent to a terminal.

At the heart of SIMPL is an interpreter written in Arduino (or other microcontroller) using standard C code - for ease of portability.  I have recently ported SIMPL to the 32 bit ARM STM32F407, STM32F303, and the 16 bit MSP430 in order to illustrate it's versatility.

SIMPL is an ongoing project that was inspired by Ward Cunningham's Txtzyme interpreter.  If you want to learn more about Txtzyme - here's the link, and the Txtzyme Github page, where you can download the Arduino sketch version of Txtzyme. If you are new to this, it's worthwhile playing with Txtzyme, and studying the interpreter code to get a better understanding of it's operation.

For more background on SIMPL - please look at my blog posts from May 2013 onwards - starting here.

The Interpreter

At the centre of SIMPL is the interpreter, derived directly from Ward Cunningham's Txtzyme, which is just 90 lines of code.  It is a series of switch/case statements contained within a loop.  ASCII characters are allocated a function, which is executed by a small block of code, and then program control is returned to the main loop, to fetch the next character.

The original Txtzyme interpreter handles the following commands:

0-9    Numerical characters are enumerated to a 16 bit integer variable x
{}     Code within the braces is executed repeatedly controlled by a loop counter
m      A blocking delay of 1 millisecond
u       A blocking delay of 1 microsecond
p       Print the value contained in variable x to the serial terminal
_ _    Print the text contained within the underscores to the serial terminal
d       Allocate a digital port pin
o       output to the allocated port pin
i        read input from the allocated port pin
s       read the analogue input
k       A variable which is decremented on each iteration of the loop


Txtzyme interprets a character into an action, and that action may be controlled using a single numerical 16 bit integer parameter x.  It is the equivalent of passing an integer variable to a function in C code.

Numerical characters are enumerated into a 16 bit integer x.  The value of x is used as a control parameter for the next instruction. For example

100{}    this sets x to 100 and then repeats the commands within the braces 100 times

10m       this sets up a delay of 10mS before the next instruction is executed

13d        this allocates digital pin 13 as the one that will be handled by the next instruction

1o          Set logic high (output) on the previously allocated pin

0o          Set logic low on the allocated pin

So by combining these commands we can produce a simple LED flasher - on Arduino the LED is on digital pin 13

13d100{1o100m0o100m}  

Turn the LED on, wait 100mS, turn it off, wait 100mS and repeat this 100 times.

If however you wanted a very accurate on and off time, you could incorporate the u microsecond delay command into the above.

13d100{1o100m250u0o100m350u}

This sets the on time to 100.25mS and the off time to 100.35mS

As you can see, Txtzyme used a mix of lower case alpha characters and punctuation symbols as the instructions.  A Txtzyme interpreter running on any microcontroller, should be able to decode any string of these characters and produce the same overall action. This will give the language portability between microcontrollers. As there are only 26 lower case characters and 32 punctuation characters, this limits the scope of the language to something manageable. The alpha characters are chosen to act as mnemonics, so that the instructions are easy to remember.  This mix of lowercase alpha and punctuation characters are known as the primitives.

Txtzyme was great and a lot of fun to use, but I wanted to extend it into a more capable language, which allowed more than just a few I/O and printing operations to be performed.

I chose to add some arithmetic operators to Txtzyme, and in doing so added a second 16-bit integer variable - called y.

Then it became obvious that the ascii strings typed in via the serial terminal could be stored in RAM, and executed at any time.

I found a simple way of  allowing them to be addressed and executed, by using an upper case alpha character to act as a label to the address where the strings were stored.

This allowed the very short programs to be stored in RAM and executed just by typing a single uppercase character.  These characters could be concatenated, formed into loops, or called recursively from within Txtzyme strings. Whilst only 26 of these micro-programs were available, it is sufficient to build up some quite sophisticated operations - the sort of thing that could be used for teaching programming techniques to a young audience.

With the extensions I have added to Txtzyme, the program is still only about 260 lines of C code or just over 6.1k when compiled for the Arduino.

The main loop of SIMPL consists of just 3 functions:

txtRead
txtChk
txtEval

txtRead simply reads a character from the serial input buffer.

txtChk looks at the first character to see if it is a colon : and if so, writes the remainder of the text buffer to an area of RAM, with the store address based on the value of the uppercase alpha character that follows the colon. This takes case of colon definitions.

txtEval is the heat of the interpreter. It does one of three things:

It takes each character in turn, if it is a number it forms a 16 bit integer which it stores in variable x.

If it is a lower case alpha or punctuation character, it looks it up in a switch/case structure, and executes any code associated with it.

If it is an uppercase alpha character, it transfers the attention of the interpreter to the area of RAM addressed by that character, and continues to interpret characters from there.

I have deposited this latest version of SIMPL at this Github Gist  It compiles on Arduino 1.0.4.

FYI

There have been a few minimalist interpreted languages over the years, one notable example Mouse, was developed to operate within the acute memory limitations of an early minicomputer, intended for electronic music composition on a PDP-8. If you want to delve deeper - the full Mouse history is here.

No comments: