Monday, May 27, 2013

A LED Chaser Display using SIMPL

My last post described how a LED chaser display was one of my first forays into physical computing about 30 years ago.

My recent experiments with SIMPL, have shown that it is a perfect programming tool for simple interactions with physical computing devices - so I decided to recreate a simple LED chaser display, using SIMPL.

LED chaser displays require a bunch of LEDs which you can address individually. You also need to write code that provides basic loop structures and the means to control timing.  SIMPL, which uses the Txtzyme interpreter is ideal for this task.

Txtzyme uses 1o to set a port pin high and 0o to set it low.  The port pin has to be pre-specified using the d command.  This all becomes a little unwieldy, so lets define a couple of new words to make it easier to type.

We will use H and L to set the port pins high and low respectively.  LEDs are currently fitted to digital pins 2 to 9.

Now the definitions:

:Hd1o     - sets the defined pin high

:Ld0o     - sets the defined pin low

So typing 2H will turn on the LED on pin 2, and 2L will turn it off again. This simplifies the control of outputs to two very memorable commands H and L.

Now we need to generate a loop which turns all the LEDs on in sequence. Because of the way the loop counter works in SIMPL, descending loops are easier as the loop counter k can be accessed to control the loop.

This performs a down count

10{kd1o100mkd0o}

10 - perform the loop 10 times
kd1o  - move the loop count k into d to select the pin and set it high
100m - wait 100mS
kd0o  - move the loop count k into d to select the pin and set it low

We could now substitute H for d1o and L for d0o giving the construct

10{kH100mkL}

To make an upward counting loop is a little harder and it uses the l instruction (l as in little L).

l increments the y variable each time it is executed, and the word @ allows us to move y into x so that we can print it out.

So to make a loop that counts up from 1 to 10 we first have to set y to zero using 0! (store 0 in y)

0!10{l@p}  will print out the numbers from 1 to 10.

The construct l@p increments y, moves y into x and prints it out.  To turn this into a LED chaser we need to add the H and L words to control the LEDs and a short delay to control the speed:

We start with the loop - load y with a count of 1.  The loop will start at 2, and run to 9

1!9{l@pd1o100m@d0o}

We can now replace d1o and d0o with H and L

1!9{l@H100m@L}

Remember that @ gets the current value of the increasing loop count y and puts it into x.




Sunday, May 26, 2013

Not Enough Flashing Lights or Switches

Growing up in the 1970s, a common depiction of computers, at least by Hollywood film-makers, was a room full of wardrobe sized cabinets, with innumerable flashing lights and switches and spinning tape drives.  Frequently, the plot of the movie was centred on the computer malfunctioning in some malevolent way, and chaos breaking out.  The Italian Job, Westworld and 2001 A Space Odyssey all relied on computer failures to spice up the plot.

The reality was that throughout the 1960s, computer hardware was large and cumbersome, covered in lights and switches, and you only had to point a camera at any mainframe of that era, and you had the perfect cheap shot to enhance any sci-fi movie.

By the early 1980s, computers had entered homes and schools, and teenagers, such as myself at that time, were spending countless hours typing BASIC program listings from computer magazines, into low spec home computers, with dubious keyboards and scungy TV displays. In just 5 years, the first micros of the mid 1970s had evolved from homebrew rack systems with lights and switches, to mass produced machines on sale in every high street.  In homage to the early micros, the classic example of that era, was the MITS Altair 8800, which had a role in the 1983 film "War Games".

At about the same time that Matthew Broderick was pretending to program the Altair 8800, I had invested in an 8 bit input output card for my ZX81.  At about £20, and solder it yourself, it had cost me several weeks pocket money. Here for the first time, for me, was the means to connect to the real world and make the computer do something under program control.  The first thing was to connect 8 LEDs to the pins of the output port and with some simple BASIC programs, create a whole load of different "Knight Rider"  LED chaser display effects.

Fast forward 30 years, and technology has developed by several orders of magnitude. The average Smartphone now has 1 million times as much RAM as my first ZX81 and is clocked at 1000 times the speed.  Not to mention that it has four 32 bit ARM processors acting as a quad array, plus a specialist graphics processor unit. This type of processing power and memory storage capacity in your pocket was inconceivable just a few years ago.

However, just because millions carry around this sort of processing capability in their pockets or bags, does not mean that we have become a population of computer scientists.  In fact, the average citizen has no more inkling today of how a computer works, than 30 or 40 years ago, watching computers malfunction on Hollywood movies.

Fortunately, in recent years there has been an active and vocal campaign to help educate a tiny percentage of the population into the workings of computer technology.  The $20 Arduino and it's spin offs, has done more for teaching computing science, hardware, firmware and programming skills than any other device in the last 30 years.

So, in homage to those early homebrew computers with their flashing LED displays, I have connected a dozen LEDs to the pins of an Arduino, and recreated some of my light chaser memories from 30 years ago.

I have a new toy to play with, and a programming language SIMPL that lends itself to simple interactive physical computing. A few lines of SIMPL and I have a LED chaser display that demonstrates the benefits of having an interactive programming environment.

Wednesday, May 22, 2013

SIMPL - A simple programming language based on Txtzyme

SIMPL - A simple programming language based on Txtzyme

Last weekend I played around with Ward Cunningham's Txtzyme - a minimalist programming language, with an interpreter written in C so that it can be easily ported to many microcontrollers.

Txtzyme contains all the elements necessary to enable a microcontroller to interpret and execute a series of typed commands, and is an ideal example to learn the techniques employed by more sophisticated interpretive languages.

During the past week, I have written some extensions to Txtzyme and tried out a few ideas to  make Txtzyme more versatile and easier to use.

This blog post is a tutorial in Txtzyme, and it's new extensions to create more of a useful language - which I am calling SIMPL - A Serial Interpreted Minimal Programming Language.

SIMPL runs in under 6K on the standard Arduino.

A Brief Description of Txtzyme.

Txtzyme consists of an interpreter contained within a loop.  The interpreter, intended to be very simple, decodes individual ASCII characters, and executes a block of C code associated with that character. This is similar, in principle to how Forth scans through a series of Forth words and executes the code associated with them, but Txtzyme treats each ASCII character as a word, greatly simplifying the scanning process.

The interpreter steps through a string of ASCII characters, executing the associated code blocks in turn. This may be slow in speed in comparison to assembly language execution, but the user does not need to know about machine code, assembly language or even C to make the microcontroller perform simple tasks.

Numbers and Maths

Txtzyme enumerates numbers and assigns them to an integer variable x. Typing 123p into the serial terminal will set x to 123, and then print that value out when the p command is executed.

I extended Txtzyme with the use of another integer variable y.  A number can be stored in y by using the ! character. This again being borrowed from Forth.

456! will initially assign 456 to x, and then copy it into y.

The use of the second variable allows simple maths operations to be performed. Taking the simple interpreter, I added some maths operations + - * and / .

456!123+p  will set y to 456, then set x to 123, add x and y, leaving the result in x and then print out the answer 579.

I/O Commands

Txtzyme was designed to perform simple I/O operations on the pins of the microcontroller, with each operation being initiated by a serial command.  This allows ports to be set, inputs to be read and analogue inputs to be read and printed to the serial terminal.  The keywords that perform these operations are generally only single ascii characters, chosen to make the commands surprisingly human readable.

First you have to state which I/O pin you wish to use.  This is done with the d command.

For example  6d  will select digital pin 6

You may then set this selected pin to high using 1o   (where o = output)  or to low using 0o.

To read an input pin, first you have to define it eg.  8d will define digital 8. Then you use i, for input to read it's state into x. p will then print out the value.

To read the value on one of the ADC pins, you use the s command, which means analogue sample.

0sp will read the value on ADC 0 into x and print it out.

Loops

Txtzyme uses a simple loop structure, allowing commands to be executed repeatedly. It also uses the native delay functions present on the Arduino to provide simple timing functions - ideal for flashing LEDs and generating musical tones from output pins. Txtzyme can toggle output pins at up to 47kHz, a speed that is only limited by the Arduino digitalWrite function.

The loop function will execute any command contained within braces {}.  It uses x to initialise the loop counter, k to a starting value, from whence k will be decremented to zero and terminate the loop.

For example to print out ten readings from analogue pin 0

10{0sp}

To see the loop count variable k decrementing

10{kp}  will print out the numbers from 9 decrementing to 0

Txtzyme does not yet have the ability to do complete FOR/NEXT loops. This would be a very useful addition, the means to perform a loop such as

for i = x to y step z

I have added primitives @ l y and  z

y allows direct access to the variable y so typing 10y   is equivalent to y=10

@ was intended to be the equivalent of Forth's fetch, but in SIMPL it copies the value stored in y to x.

l is a loop counter.  It increments y by 1 every time

The construct l@p  increments y by 1, copies it to x and prints it out.

To print an ascending series of numbers from 1 to 10 uses this construct

0y10{l@p}

When combined with the read primitive r (see below) this can be used to read and print consecutive RAM addresses.

I/O with Loops and Timing

Loops can be used to flash LEDs or generate tones, and can be combined with the millisecond and microsecond delay functions to generate appropriate timed behaviour.

To flash a LED on pin 13 ten times, on for 500mS and off for 500mS

13d10{1o500m0o500m}

To turn this into an audible note to sound a small speaker on pin 6, we shorten the delay to say 500uS, and generate say 1000 cycles (1000 times around the loop).

6d1000{1o500u0o500u}


Creating New Definitions

The simple Txtzyme interpreter readily executes a program contained in the characters in the input buffer, but wouldn't it be great if you could store these mini programs in RAM so you could use them time over?

The mechanism to execute a program from RAM, is to point the interpreter at the location of the starting character and let it execute the characters in turn until it finds a return '\r' or newline '\n' character that marks the end of the string.

Here we have to start borrowing ideas from Forth, the concept of the "word" that signifies the start address of a block of code to execute, and the "colon definition" - a mechanism to write new words into memory.

To keep things simple, our new words will be assigned only the capital letters, allowing up to 26 new words to be defined, namely A to Z.

Additionally, to simplify the addressing of these words, and to keep the RAM usage within the limitations of the ATmega328 ( as used on the Arduino), we will allocate each word just 48 bytes of memory, with each consecutive word starting on the 48 byte address boundary.  This allows us to easily decode the ASCII value of the character, find the starting address of the associated code, and execute the word.

To create a new word, and to tell the interpreter to copy the input character string into the correct position of RAM we use the "colon definition".

We type a colon followed by the capital letter of the word we wish to create.  Suppose we liked the tone example from above and want to assign it to the letter T, we type

:T6d1000{1o500u0o500u}

The colon definition code will detect the leading : and then decode the T to 84 in decimal.  It then creates an address by multiplying 84 by the allocated permissible word length of 48 bytes, and adds this to the start address of the array assigned to hold the definitions.  I have restricted the length of the definitions to 48 bytes, because on the Arduino we are short of RAM - only having 2K to play with. Having fixed blocks of 48 characters for each definition is wasteful, but it greatly simplifies and speeds up the instruction decoding and addressing process.

This character based addressing process happens automatically and we don't have to concern ourselves about the exact address that holds T, however whenever the interpreter encounters a T, it will jump to the correct address and execute the code it finds there.

Once stored in RAM, the interpreter prints out T, to say it has been defined, and then executes the new word twice. This is a quirk of the interpreter.  So we hear the tone twice as long.

Now whenever we type T, we will get the tone.

In order to keep track of what we are doing, I have added a ? command.   This prints out the entire definition RAM, showing the commands A to Z and the code that is associated with them.  This allows a definition to be edited, by cut and paste operations from the ? listing into the input buffer, and changing what ever parameter is to be edited.  The edited definition is then automatically stored back into RAM, when you press return.

Some Prestored Definitions

Just for fun, I decided to hard code some "musical notes" into the definitions. Characters A to G play a short musical note, roughly tuned to A = 440Hz , so it's possible to play tunes just by typing the notes.  Having "musical debug" is also a great way of determining whether the program is doing what was intended.

The SIMPL strings for properly tuned notes are as follows, and are pasted into the RAM array when the sketch is first compiled.  They can be written over at anytime.


//  40{1o1106u0o1106u}     // A 440 Hz
//  45{1o986u0o986u}         // B 493.88 Hz
//  51{1o929u0o929u}        // C 523.25 Hz
//  57{1o825u0o825u}        // D 587.33 Hz
//  64{1o733u0o733u}        // E 659.26 Hz
//  72{1o690u0o691u}        // F 698.46 Hz
//  81{1o613u0o613u}        // G 783.99 HZ

Building Up Programs

The real power behind the colon definition is that new and more complex words can be assembled from existing definitions, and then executed as singe commands. For example, suppose we have defined three tone generating words A B and C.

We can type ABC - which will play the three tones in succession

Alternatively   5{ABC}  will play the 3 tone sequence 5 times over

We could then define a new word I as

:I5{ABC}

Whenever we type I, we get ABC played 5 times.

So from very simple definitions, quite complex operations can be performed.

This is an incredibly versatile technique. It allows you to write your own routines, assembled from other routines and then be able to use names that you can remember.

For example, you can define a word H to set the port pin high, and L to set it low.  If you have a LED connected to pin 6,  6H will turn it on, whilst 5L will set pin 5 to logic low. It becomes very easy to toggle any output pin - just with a couple of memorable keystrokes.

This ability to form new definitions is one of the fundamental and most powerful aspects of Forth - so very worthwhile to borrow it to make it adaptable to the minimal programming environment of SIMPL.

Some Other Additions

The Txtzyme interpreter is readily modified to include new functions.  This is a work in progress and I have added some simple extensions.

I now have comparison operators < and > to test whether x is less than y or greater than y.  These operations will set x to 1 if true or 0 if false.

10!5<   translates to "is 5 less than 10 ?". This is true so x is set to 1.

10!5>  translates to "is 5 greater than 10 ?". This is false so x is set to 0.

To make use of these comparisons I have introduced the jump command j.   If  x = 1 the next command is skipped, otherwise it is executed as normal.

Memory Operations.

I wanted a means to directly edit the contents of an address in RAM and read it.  These are equivalent to PEEK and POKE.

The y variable is used to hold the address  - so  723! will set the address up as 723.

The x variable is used to hold the data

To write to RAM we use w and to read we use r

So 723!65w   will write the character ASCII 65 into address 723.  You can then type ? to see that it's there. It pokes an "A" into the first location of the word defined by J.

To read a location,

723!r  will read the contents of location 723 and print it as an ASCII character.  You get your "A" back.

As this character has been poked into a definition, it has modified that definition. In this case it will cause definition J to play the tone associated with A.

Finally, I needed a means to look at a block of memory. The q command does this by printing out the desired number of characters starting at the address stored into y.

As an example, address 627 holds the start address of the H command

Typing 627!48q  will print out 48 consecutive characters, which in our case is the start-up message

_Hello World, and welcome to SIMPL_

With the loop primitive l we can also read and print successive memory locations

627y48{l@r}

This sets the address in y to 627 and reads and prints 48 consecutive locations using the r primitive.

Using the colon definition, the construct l@r could be assigned to R,   as in :Rl@r

So to read and print 33 characters from address 627 we use

627y33{L}

A Work in Progress

SIMPL and it's underlying Txtzyme interpreter is constantly evolving as new commands are added to try new ideas.

It is unlikely that it will ever be a serious language, but a novel experiment and a means to understand how an interpreter can be manipulated to execute a series of simple commands.

Many of the ideas have been borrowed from and inspired by Charles Moore's Forth as it evolved from a set of ideas into a proper language during the 1960s.

You can download a recent version of SIMPL from github gist - but be aware that it is a work in progress.

https://gist.github.com/anonymous/5648871

I hope others will get as much enjoyment as I have from tinkering with SIMPL and Txtzyme.


Sunday, May 19, 2013

More Thoughts on Txtzyme - and a musical interlude

In the last post I discussed the simple interpreted language Txtzyme and offered some ideas on how the language could be extended.

Ward Cunningham, the creator of txtzyme describes it as text that "catalyses action".  I think this is a fair description.

In summary, Txtzyme uses some very simple methods to produce an executable program and interface with the Arduino hardware. It uses the following Arduino functions to enable the interpreter to implement a simple serial interface and access the digital and analogue I/O:

Serial.read
Serial.print
digitalWrite
digitalRead
analogRead
delay
delayMicroseconds

Much of the simplicity is that a single ASCII character is interpreted to produce an action, and by stringing ASCII characters together the interpreter will handle them in turn and execute each action in order.

The interpreter allows the use of a simple loop structure, by repeating the actions enclosed within braces (curly brackets)  {.......}

Numerical characters are decoded into a decimal number and assigned to a single numerical variable   x which is used as a parameter to control some of the actions.  For example, time is handled using the two native Arduino functions delay (mS) and delayMicroseconds.

These are given the characters m and u respectively, such that

1000m  is a delay of 1000 milliseconds
500u   is a delay of 500 microseconds

These are useful to slow down program operation, such as when reading ports or ADCs and printing of for creating accurate timing loops for generating frequencies.

Extending the Ideas

My first foray into txtzyme was to enhance the simple interpreter such that it could execute a series of user routines invoked by typing their uppercase ASCII character name. The use of uppercase differentiates them from what I will call txtzyme primitive functions which are represented by lowercase characters.

I fitted a small loudspeaker to digital 6 and from it I was able to produce a series of beeps and tones, however it soon got tedious having to retype the txtzyme strings into the input buffer each time I wanted to try a new tone. This inspired me onto the next level of extension,  the means to code each txtzyme string into a named array in memory, and execute the string just by typing its name. This is an idea heavily borrowed from the idea of Forth words, but simplified to use just a single uppercase character (A-Z) as the name.

For the demonstration, I defined six user routines called A-F, each of which caused a short musical tone to be output from pin 6 of the Arduino.  The code to do this is on my github gist

https://gist.github.com/anonymous/5604829

Each uppercase character defines a txtzyme array of characters which can be interpreted as though it was typed into the serial terminal buffer.  For example, a musical note is defined by the following characters stored in the A array and will be invoked whenever the text interpreter encounters the character A.  6d selects digital port pin 6, and produces 75 cycles of tone.  The port pin is low for 708 microseconds and then high for 708 microseconds.

char A[64] = "6d75{1o708u0o708u}";

The A array has a total of 64 characters reserved for it although only 17 are used. This is not very efficient on RAM usage, but since there are only 26 user routines, less than 1700 bytes of RAM are    allocated for this storage.

I then proceeded to write similar strings for the "notes"  B through to F. Once compiled, these notes could be played just by typing ABC, or any other sequence into the serial terminal.

I then defined G by the array

char G[64] = "ABCDEFFEDCBA";

To my delight, and surprise it played the sequence of 12 notes perfectly.  Using musical tones to debug program flow is a neat trick, and a lot easier and quicker than counting flashes on a LED!

Another though was what happens if a word calls itself - using this example

char H[64] = "GH";

Typing H produced an infinite loop of tone sequence - not unsurprisingly.

Finally I tried an example that reads and prints the adc0 and plays a tune each time

char I[64] = "{0spABC}";

Notice how this is just a loop structure with no controlling parameter. This means that the number of times the loop is executed can be specified by typing that number before the I,

5I    - perform the I sequence 5 times.

Colon Definitions

The Colon Definition is a construct borrowed unashamedly from Forth.  It is the method by which new words (actions) can be defined and stored into memory. This has the advantage of not having to keep typing new stings repeatedly just to try them out, but also provides a simple means to write new code, test it and edit it until it works.

The above demonstration bypassed the need for the colon definition, by using a hard coded array of characters defined in the C code. Now it is time to bite the bullet and extend the interpreter to handle the colon definition.

The example above written as a colon definition would be written

:A6d75{1o708u0o708u};

As txtzyme ignores whitespace, this could be rewritten with spaces to make it more legible

: A 6d 75{1o 708u 0o 708u};

To handle the colon definition we need a routine that on seeing the colon, gets the next character (capital A) as the name and copies the next n characters to an array called by that name. This process ends when the interpreter encounters the semicolon.

Unfortunately, I'm not really a C programmer, so the clever use of pointers and the reference and dereference operators tends to fox me somewhat, but after an hour of some kludgy coding, I had a function that would perform the colon definition task, and assemble the definition into a named array.

In theory the name of the definition eg A, should just be an address in memory, and on typing A, the interpreter starts processing the characters that appear at that address until the newline character is encountered.

Viewing and Editing txtzyme definitions.

I also decided that the ? character would be a good way of examining the code contained within a definition, allowing cut and paste editing from the serial terminal.

So  ?A prints out the entire definition of A to the terminal

:A6d75{1o708u0o708u};


To be continued.





Saturday, May 18, 2013

Txtzyme - A minimal interpretive language and thoughts on simple extensions

Imagine a very simple programming language which could run on any microcontroller with the minimum of on chip resources. A language that could invoke complex instructions and one that could be used to exercise the basic I/O functions of the microcontroller with a simple serial command interface.

I have always been a proponent of minimalist programming languages and so it was nice to encounter something new this week. A language that consists of commands invoked by single ASCII characters which allows complex procedures to be assembled from simple arrays of characters.

It reminded me of the tiny Basics and tiny Forths that were written in the late 1970s for resource limited microcontrollers.

On Thursday evening, I attended the regular OSHUG meeting (Open Source Hardware Users Group) which is held each month at C4CC near Kings Cross.

The third speaker was Romilly Cocking, who presented a report on his quick2link project - a very simple, extensible protocol for controlling sensor/actuator networks.  quick2link provided the means to control an Arduino as the I/O subsystem of a Raspberry Pi project.

The Pi is limited in its I/O capabilities and so adding an Arduino to handle the I/O seems a sensible idea.  To allow the Pi to control the Arduino a very simple protocol is needed, and since the Arduino is essentially a microcontroller with a serial interface, a serial command interpreter seems appropriate.

Txtzyme

quick2link was inspired by the work by Ward Cunningham (creator of the first wiki) and his minimalist txtzyme command interpreter, for controlling the I/O of simple microcontrollers.

I was intrigued by txtzyme and its simplicity and having downloaded the txtzyme interpreter for the Arduino, decided to have a play. As a simple command interpreter written in C, it compiles to just 3.6k, a very low overhead for even the smallest of today's microcontrollers.

Txtzyme allows the control of the Arduino I/O, using a simple interpreted language.

The commands are reduced to single lower case ASCII characters such as i for input and o for output. Each command can be given a single numerical parameter, limited to 65535 by the unsigned integer of the C interpreter.

The interpreter, a mere 90 lines of C code, parses a serial string, evaluating numerical characters and executing the alpha character commands.

Only a few commands are implemented, leaving a lot of scope for language extensions.

0-9 enter number
p print number
a-f select pin
i input
o output
m msec delay
u usec delay
{} repeat
k loop count
_ _ print words
s analog sample
v print version
h print help
t pulse width


Whilst appearing limited, this simple command set is essentially all that is needed to get a microcontroller project up and running.

The interpreter makes use of the Arduino functions, including Serial.read, digitalWrite, digitalRead, Serial.Println, delay, delayMicroseconds and analogRead.  With these simple functions the interpreter can execute a string of commands, manipulate I/O and print results to the terminal emulator.

The hello world of the Arduino is to flash the LED. The following txtzyme string implements this efficiently:

10{1o1000m0o1000m}

This will flash the LED ten times for 1000mS on and 1000mS off.

Change the parameters a little and you can produce an audible tone to a speaker connected to an output pin.

1000{1o1m0o1m}

A quick play with the command set showed that as well as simple port manipulation, txtzyme could toggle port lines at up to 47kHz, read and display ADC channels, create tones on a piezo speaker and perform simple time delays.

txtzyme uses a compact syntax, but is nevertheless quite human-readable. The following command produces a short beep to a speaker connected to an output port

400{1o200u0o200u}

400 is the loop counter - so perform the instructions enclosed between the {..} 400 times

1o   -  set the designated port pin high
200u  wait 200 microseconds
0o   -  set the designated port pin low
200u  wait 200 microseconds

Extensibility

I then started thinking about how txtzyme could be extended, to include new functions, and soon had simple integer arithmetical operations working  using +  -  * and /.  There are roughly 32 printable punctuation characters in ASCII, all of which could be utilised by adding a new case statement to the interpreter and writing the code to handle each function.

The lower case characters i o m u p k s are already used in the core interpreter - so it might be sensible to reserve all lower case characters for future extensions to the core interpreter. This would leave the upper case characters to be used for User defined functions.

Txtzyme is still a rather limited language, capable of concatenating blocks of code together and performing multiple loops through code blocks.  There needs to be a simple mechanism to pass numerical parameters to the code blocks and also build the if...then construct. This will clearly need some further thought in creating useful language structures whilst keeping the syntax very simple.

What txtzyme lacks is the ability to store and retrieve these simple routines. Once you have typed return at the end of the terminal text buffer the input characters are lost forever - unless you  copy them to the clipboard first. For the language to be extensible, there needs to be an easy way to manage the storage and retrieval of these text strings.

One solution might be to borrow from the Forth community, and create a "colon definition" - giving each routine a single upper case alpha character name. That would allow for 26 unique code snippets and an easy way to manage/execute them - solely by typing their name.

Let's call the routine above "Beep"  and assign it capital B as it's name.  We could use the :   ;  structure to define the body of the routine in the same way a Forth word is defined.  So the beep word definition becomes:

:B400{1o200u0o200u};

txtzyme allocates 64 bytes of RAM to its input buffer.  A very simple addressing scheme could use the ASCII value of B, to assign a start address to the RAM segment holding the body of the code.

On encountering the first colon : the interpreter needs to switch to a colon definition compiler mode, which interprets the next character B as the start address of the buffer to hold the colon definition.  It then starts storing the characters into this buffer until it encounters the closing semi-colon ;

Once this colon definition has been stored in RAM, any occurrence of the letter B is interpreted as a pointer to the buffer, from where to start executing the commands.

Whilst wasteful of unused RAM locations, this scheme would be easy to implement and allow simple routines to be stored . Regular used routines could be stored in flash as "primitives".

After a little head-scratching, I realised that I could store the txtzyme characters that perform a function in an array, and give the array a name: For example this produces a low note on a speaker connected to digital pin 6.  (50 cycles of 2mS on, 2mS off)

char A[64] = "6d50{1o2m0o2m}";

In order to execute the function, I just had to pass the pointer of the array i.e. A to the txtEval function and include this case statement within the routine that evaluates the serial input buffer.


      case 'A':  
      txtEval(A);
      break;

I then wrote a couple of txts which produce a medium tone and a high tone, and assigned them to B and C.


char B[64] = "6d100{1om0o1m}";            // A medium tone beep
char C[64] = "6d100{1o500u0o500u}";     // A high tone beep

And then included their "names"  in the case statements of the interpreter


      case 'B':  
      txtEval(B);
      break;

      case 'C':  
      txtEval(C);
      break;  

Now it is possible to type any combination of A B and C into the serial input buffer and have the tones played in order.

These capital characters also can be inserted into loops - so to play the sequence A B C  ten times, all you need is

10{ABC}


I have created txt arrays to generate 6 musical notes A - F   - see my Github Gist for the code

https://gist.github.com/anonymous/5604829



In the same way that the native Arduino function calls are used to exercise the basic I/O, further library functions could be accessed and called by a single alpha character. For example  S for servo control and P for pwm could be invoked with a simple numerical parameter:

160S   moves the servo, connected to the nominated port pin, to 160 degrees.

128P   outputs a 50% duty cycle PWM waveform on the nominated port pin.



To be continued.