SIMPL Archives Part 1 - monsonite/SIMPL GitHub Wiki

The SIMPL Archives

An Archive of Blog Posts on SIMPL.

Postings about SIMPL have appeared regularly on my blog for almost the last 3 years.

Here's a copy of all those posts - in one huge digest covering May 2013 to October 2015. If you wish to see the original posts - plus accompanying photoos - please check out my blog starting here

http://sustburbia.blogspot.co.uk/2013/05/txtzyme-minimal-interpreter-and.html

This note is a compilation of blogposts from May 2013 to October 2015 that describe the evolution of the SIMPL programming language. I intended to edit it into a series of chapters to describe this evolving language. For the moment, however, just recording the various developments in a single document is a good first step.

Tuesday, October 27, 2015

SIMPL Revisited - Again, but this time it's personal

In May 2013, I learned about Ward Cunningham's Txtzyme language - a very simple serial command interpreter which allowed basic control of microcontroller function using a serial interface.

I wrote about it here:

Tytzyme was about as easy as a "language" could get, it offered digital input and output, analogue input, rudimentary timing in uS and mS and simple repetitive loops. It was so simple, and offered so many opportunities for extension, that I decided to write some new functions - and called the extended language SIMPL - serial interpreted minimal programming language.

In late May 2013, I described the extensions here:

In the last 30 months I have ported SIMPL to Arduino, ARM and FPGA soft core processors. I have also used the Txtzyme interpreter to help to create assembly language for an entirely new soft core FPGA cpu.

Very often, during initial deveopments, we need a low level human interaction with a new microcontroller, and SIMPL seems to provide that coding framework to allow more complicated applications to be tested and coded.

SIMPL is coded in C - which allows good portability between micros, but recently I have been wondering whether SIMPL would be better coded in Forth, and act as a human interface layer between a Forth virtual machine and the human programmer.

Forth can be a difficult language to master - partly because it involves considerable manipulation of the data stack, and the need to keep track of the stack presents quite a challenge to the new programmer.

Standard Forth consists of a vocabulary of about 180 compound words, which can be entirely synthesised from about 30 primitives. When ported to a FPGA soft core CPU, optimised for Forth, most of those 30 primitives are actual native instructions. That makes it fast in execution, but still not the easiest of languages to grasp.

Can we use SIMPL to access a sufficient subset of the Forth vocabulary to allow real programs to be written, but without having to tie our brains in knots over keeping track of the stack?

The beauty of Forth, is that you can compile a new word and give it any name you wish. In SIMPL terms, this name would be a single alpha or punctuation character. Small alpha characters are reserved for the keywords, whilst capital letters can be used for User defined words.

This gives us access to

26 lower case primitives 26 Upper case User words 33 punctuation characters

This gives us a subset of 85 possible words - which has reduced the scope and complexity of the standard Forth language by a factor of 2.

Forth text entry consists solely of words and whitespace. This is intentional because it makes it more readable from a human point of view, and the spaces between words allows the compiler to know where one word ends and the next begins. The carriage return is usually used to denote the end of a line, and thus signal the compiler to start compilation of the contents of the input buffer.

SIMPL borrows from these ideas, but attempts to simplify by removing the whitespace. In fact a space character (ascii 32) may have it's own unique meaning to the SIMPL interpreter.

Numbers also present a burden to the traditional Forth interpreter - which has to search the dictionary only to find that a number is not listed, and then assume that it is a number. In SIMPL we assume that numbers are all decimal unless prefixed with a character that changes the base to hexadecimal.

As the compiler is only dealing with 85 possible input characters, the dictionary is simplified to an address lookup. For example if the interpreter encounters the character J, it looks up the address associated with the function called J, executes that code and then returns so as to interpret the next character in the buffer.

There are only 85 characters to interpret - so only 85 action routes to execute.

Here are some of the primitives

  •       ADD
    
  •        SUB
    
  •        MUL
    

/ DIV

& AND | OR ^ XOR ~ INV

@ FETCH ! STORE

< LT = EQ

       GT

j JMP z JPZ : CALL ; RET

LIT

% MOD £ DEC $ HEX

( Push R >R \ R@ ) Pop R R> [ ] {
} " '

? Query _ Text String

a ALLOT b BEGIN c CONSTANT d DO e ELSE f FOR g
h i IF k l LOOP m n o OVER p PRINT q
r REPEAT s SWAP t THEN u UNTIL v VARIABLE w WHILE x
y

Monday, September 21, 2015

How SIMPL Can You Get?

In the last post, I explained how I had slimmed down the kernel of SIMPL - at the same time removing much of the Arduino specific code so that it would fit into 2Kbytes of Flash plus a lower RAM requirement. This also makes it highly portable to other microcontrollers.

My intention was to be able to put an image of SIMPL onto any microcontroller target system that I happened to be working on at the time - and give myself a friendly, predictable environment with which to exercise the hardware. In some cases, SIMPL could even be loaded into the bootloader space of a processor - so that it was always accessible.

SIMPL fundamentally allows interaction with the microcontroller, because of it's interpreted nature. The interpreter is flexible enough to form the basis of a series of simple tools, such as cross assemblers, debuggers and simulators. It is, whatever you want it to be - you have absolute control over what action the cpu performs in response to your key strokes.

Kernel Functionality

SIMPL communicates with a PC using a serial UART interface. It can be driven from any terminal application.

It really only needs getchar() and putchar() routines that interface with the on-chip UART.

These together with a printnum() function which prints out a 16 bit unsigned number are all that is needed to communicate with the PC in a meaningful manner. It's old-school, but it works - and easy to set up, on almost any microcontroller or SoC device.

SIMPL is a low overhead program - a kind of interactive tiny OS, that only takes a few Kbytes, yet provides all the means of accessing and controlling the micro.

A brief list of functionality.

The digital I/O is limited to the writing to or reading from a single I/O pin. In most cases this will be one that supports a LED. The I/O functions can be extended to whatever is needed by the application - for example in one application - an LED chaser display I needed to write a 13 bit number to an array of LEDs each connected to an output pin of the Arduino.

Analogue Input (ADC) and output PWM functions may be ennabled if required - but these will add approximately a further 600 bytes to the kernel code.

The kernel uses the delay() and delayMicroseconds() functions to allow accurate timing of I/O operations. With these the microcontroller can generate pulse sequences (up to 100kHz on Arduino), generate musical tones, sound effects or animate LED displays.

As well as the functions that interact with the hardware peripherals, SIMPL also has a range of arithmetic and bitwise logic operators to allow simple integer maths and logical decision making.

There is a simple looping function which permits a block of code to be repeated - up to 32K times.

Recently added functions allow the printing of strings and the manipulation of ascii characters.

Extend-ability

On top of the 2K kernel core is some further code which allows the user to define their own functions and store them in RAM. Up to 26 user functions can be defined under the current system. It's not exactly Forth - but borrows a whole lot of ideas from that remarkable language.

The system could be extended to include SPI or I2C functions to exercise specific peripheral chips or access a microSD card for program storage.

One of my designs "WiNode" is an Arduino compatible target board but with 433MHz wireless module, external SRAM, RTC, motor driver/ speaker driver, and microSD card. SMPL may be used to exercise and interact with all of these peripherals.

32bit Math Extensions

This was remarkably easy to implement. By re-type-ing the x and y variables to long - it forced all of the arithmetic routines to 32 bit. Whilst this pushed the code size up by about 900 bytes - some of this was offset by rewriting the printnum() function as a 32 bit printong() and deleting the original printnum(). The code now stands at 4826 bytes and can be found on this GitHub Gist

This means that SIMPL can do 32 bit integer maths - straight form the can.

Whatever Next?

SIMPL has been an ongoing project for over 2 years, and as it has developed - so have my C coding skills. As the code becomes larger, things become easier - as the switch from 16 bit to 32 bit integer maths has proven - it was literally a 10 minute hack.

I am very aware that SIMPL is not yet a fully fledged language - it can flap its wings and tweet a bit - but is not ready to leap out of the nest and fly. Perhaps I am a bad mother bird - too eager to experiment with new ideas rather than concentrate on the basics. Time will tell.

I have ported SIMPL to STM32Fxxx ARM microcontrollers and seen a 25X increase in speed. Now their are ARMs that run at 240 and 300MHz (Atmel SAM E7) that will give even more of a performance boost.

The final intention is to create a SIMPL virtual machine (SVM) that can be hosted on nearly any micro - including FPGA soft core stack proessors - such a James Bowman's J1b. With these we hope to see a large leap in performance.

In the meanwhile, I still have an Arduino plugged into my laptop - as my preferred development platform - if it will run on Arduino - it will run on everything else a whole lot better!

Next Time - more uses for the SIMPL Interpreter.

Monday, September 21, 2015

A Closer Look at the SIMPL Interpreter

Keeping it SIMPL

Since May 2013, I have been slowly developing a tiny interpreted language that can be used to initialise and exercise hardware when developing with a new processor.

SIMPL is primarily intended to be a very low overhead language, requiring only a serial uart (or bit banged serial) for communication to a PC hosted terminal program.

Commands are in plain, human readable ascii text - with an emphasis on being easy to remember.

SIMPL is based on Ward Cunningham's Txtzyme interpreter - originally for Arduino - but ported onto several other microcontrollers - as it is written mainly in C.

The kernel or SIMPL interpreter needs only a few resources:

2K bytes of program memory (Flash) 35 bytes of RAM UART getchar and putchar functions microsecond delay millisecond delay

On the Arduino these delays are provided by the delay() and delayMicroseconds() functions but can be provided with simple delay loops.

Once you have this 2K of code on-board, you can then start to add it more functionality - that is tailored to your particular application.

Slimming Down the Interpreter Kernel.

As originally written, Ward Cunningham's Txtzyme compiles to 5032bytes of flash and 209 bytes of RAM. (The exact number of compiled bytes may vary on what version of the Arduino IDE you are using).

As it made use of several of the high level functions available in Arduino - such as Serial.print, digitalWrite etc, - it was certainly not optimised for codesize.

I rewrote and enhanced the interpreter - so that now it fits into just short of 2048 bytes, and is written in more generic standard C for easier porting to other processors.

I have also added more functions including arithmetic, bitwise logic and memory operations.

I am sure that if the routines were handcoded in AVR assembly language, that further reductions in codesize could be achieved. However, I wanted a useful kernel that would fit in 2K and was easy to understand.

I have placed the SIMPL kernel here as a Github Gist.

Growing the Kernel

It has long been my intention to make SIMPL an extensible language, and so for this approach I have chosen to use some of the ideas used in Forth.

The kernel can easily be extended from some 30 basic functions to about 85, just by extending the switch/case statement that forms the basic subroutine calling mechanism at the heart of the kernel.

I keeping with Charles Moore's philosopy of "Problem Oriented Languages" the kernel of SIMPL may be extended in whatever way needed for solving the problem, and should as such be considered to be a minimum common starting point - for any cpu.

Once the 2K core of the kernel was established, it was time to add in the extra functionality that allows users to add their own functions. This is done in the spirit of Forth - but with certain limitations to keep the code size down. However, with the added functionality - the code grew from 2Kbytes to 3982 bytes. The main difference is in the amount of RAM that is used - the extra code allocates a User RAM array of 1248 bytes.

If you would like to look at the code and try it out on an Arduino - I have created a Github Gist here.

If you are using a standard Arduino with the LED on Pin 13 change line 64 to:

int d = 13; // d is used to denote the digital port pin for LED operation

As this is a work in progress - more details will emerge in a later post.

Sunday, September 06, 2015

Extending SIMPL

In the earlier post "Building form the ground up" I wrote about how Forth could be used to provide a low level development environment for an unfamiliar processor for which a C compiler was either not available, or not desirable to use.

The first task is to write a simple virtual machine for the target processor, and then use this VM to run your application code. This is similar to what Java bytecode does.

The virtual machine need only have a handful of instructions, including basic arithmetic, logical operations and the ability to access and manipulate memory. From these primitive instructions, all subsequent instructions may be synthesised.

This is the approach described in "The Elements of Computer Systems" (TECS) which is also known as "From Nand to Tetris". The simple machine described, consists of little more than an ALU, a program counter, two registers and a memory interface capable of accessing a 64K x 16 bit address space.

Designing a Virtual Machine

If it is possible to code up a simple virtual machine, on any choice of microcontroller, or softcore CPU FPGA - then it becomes practical to program the virtual machine using the same machine language.

The virtual machine will be a stack machine, and will support a data stack and a return stack. These stack structures will probably be created in RAM on the virtual machine. If this was then implemented in FPGA hardware, the stacks would be separate RAM blocks, with a means of fast access, without having to go through main memory.

The ALU has access to the top and second items of the stack, and will conduct arithmetic and logical operations on these elements, leaving the result on the top of the stack. If operands are required from memory, they will first have to be loaded into the top and 2nd stack locations.

Assume that the virtual machine ALU can perform the following operations. The arithmetic and logical operations are performed on the top 2 members of the data stack, returning the result to the top.

ADD SUB MUL DIV

Multiply and Divide can be synthesised from shift and add/sub - but are time consuming without additional specialist hardware.

AND Bitwise AND OR
XOR NEG

SLL Shift Left Logical SRL Shift Right Logical

@ Fetch a word from memory and place on the top of stack ! Store a word from the top of stack to memory

BRZ Branch if zero JMP Unconditional Jump CALL Call subroutine RET Return from subroutine

LIT Put a literal number onto the stack

So with approximately 20 instructions, we have the basis of a stack machine that can do useful work.

The virtual machine to perform these operations can be written in a high level language - such as C, or actually implemented as a soft core on a FPGA. One such stack processor that lends itself to this is James Bowman's J1 Forth CPU. This compact, no thrills CPU can be defined in under 100 lines of C, or synthesised in FPGA hardware using under 200 lines of Verilog code.

The J1 is a practical CPU, designed for simplicity and optimised for high speed execution of stack based languages. It offers most of the instructions outlined above and forms the basis of an exploration into stack based CPUs. Initially it can be simulated on any processor in C code for experimentation and later blown into real high speed FPGA logic.

Even though the instruction set is very small, the 16 bit instruction word length does not lend itself to easy or memorable coding in machine language. It has several instruction fields, and these have to be populated with the correct bit pattern if we are to make any progress off the starting blocks. The instructions to however map very well onto the Forth language, but there are other alternatives which could be explored.

At the bare minimum, we need an assembler to synthesise the instruction words from the various fields, and once we have a list of 16bit hex instructions we need to load them into RAM and have the simulator step through them.

An assembler typically scans through a text file containing instruction mnemonics, such as ADD, JMP, CALL etc and converts these into the instruction opcodes. It also looks for numerical constants, variables and addresses and assembles these into the instruction. Additionally, it looks for labels that identify subroutine addresses for jumps and includes these in the code.

A relatively simple program: Mnemonics in - machine language out

Another Option

However there might be a different way to do this - in a more interactive nature - and this is where Forth or one of it's near cousins will come in. For the purpose of my exploration, I want to see if the SIMPL interpreter can be used as a means to perform this assembly step.

As we know, the SIMPL interpreter will read a series of characters from a buffer, one at a time, and execute code associated with that character.

So to add 2 numbers (say 45 and 63) in SIMPL and print out their sum

45 63+p

45 is interpreted as a literal to be pushed onto the stack The space is used in SIMPL to push the stack down 63 can then be pushed onto the stack

  • adds the top two members of the stack leaving the result on the top p prints the result to the serial terminal

This is almost Forth, except in SIMPL there is only a limited stack structure and the space is needed to command the stack to push down to accept another number.

Instead of executing the SIMPL instructions directly, we can hijack the SIMPL interpreter to synthesise the assembly language and the machine language needed for the virtual machine.

So 45 63+p is translated to assembly language

LIT 45 LIT 63 ADD CALL PRINT

Where PRINT is a subroutine that outputs the top of stack contents as a printed integer to the serial port

But the translation to standard traditional assembly language with 3 letter mnemonics is an un-required middle step. The SIMPL interpreter can easily produce the instruction fields and generate the machine language directly:

802D LIT 45 803F LIT 63 6200 ADD 5100 CALL 100 (PRINT is at 0x0100)

So by this process of translation, the SIMPL language is the Assembly Language - we can find enough of the SIMPL character set to map directly onto the J1 instruction set, and any of the other command characters (like p) will invoke calls to subroutines.

It might be remembered that SIMPL uses small letters and punctuation characters as primitives, numbers are enumerated as literals and capitals are reserved for the application words. This means that our little language can have approximately 60 primitive instructions, which is enough to do real work, yet takes up a fraction of the space used by the 170 words used in a typical Forth system. Less words, less typing, yet still more readable than assembly language or machine code.

So lets look at the primitive words and how it might map onto the assembly language

  • ADD
    
  •  SUB
    
  •  MUL
    

/ DIV % MOD & AND | OR ^ XOR ~ INV

LIT

@ FETCH ! STORE

: CALL ; RET

< LT = EQ

GT

j JMP z JPZ

I find Stack manipulations are never easy to remember in Forth - words like DUP, OVER, SWAP, NIP, DROP etc but as these are an essential part of the language, they need to have a syntax to code them into the assembly language. Perhaps it might be possible to express the top two stack items as a two member array between parenthesis.

DUP (1,1) OVER (2,1) SWAP (2,1) NIP (x,y) DROP (2,3)

Text Editor and Assembler

In order to start writing code for our new processor, we need a few simple tools to help us. We need a means of entering and displaying text - usually a serial terminal interface, so that we can enter machine instructions into memory and have the virtual machine execute them.

In the early days of microprocessors development kits there was often a hexadecimal keypad, 7 segment display for address and data, and a monitor program. This allowed the machine instructions to be entered directly into memory, and then the means to run code from a certain address. It was quite primitive, frustrating and subject to a lot of human typing mistakes. Nowadays, we can use the power and resources of a laptop to help get new systems up and running.

The first tool we need is a simple text editor. This will take in text from the keyboard, display it in a terminal window and allow basic editing, listing and text file storage and retrieval.

Secondly, no-one wants to code in machine language, so a very basic assembler that converts text mnemonics and numbers - one a line by line basis - to machine language would also be an asset.

For this we need simple text parsing - and in traditional Forth this was done by looking for individual words or numbers separated by spaces.

Forth would take each new word and look it up in the dictionary for a match. The match was based on the first three characters of the word, and it's length. This is quick to do and suitable for most purposes.

Numerical input, which includes integers up to 65535 were generally not stored in the dictionary, and would be converted from ASCII to integer and then placed on the stack.

The text editor and assembler can exist as one program - as they share a lot of features. Principally we will need the means to parse through the entered text looking for keywords and numbers. As there are only 20 or so keywords required to implement the instruction set of the virtual machine, the task of programming these into the assembler is not too difficult.

I have chosen mnemonics that simplify this task - the first 2 characters are unique to each mnemonic, and no mnemonic is more than 4 characters long. We can combine the first two characters to produce a unique number, and then use this number in a series of Switch-Case statements to perform the action needed.

The 16 bit virtual machine can handle integer numbers up to 65535. We need a means of detecting a number within the entered text string, and converting the ASCII characters to an integer. In a similar way to how we uniquely defined the mnemonics by the first 2 characters, we can do a quick test on the string to see if it is a number.

The assembler will convert our inputed mnemonics on a one by one basis into the machine instructions of the virtual machine. More detail on how the assembler should operate is outlined in Chapter 6 of "TECS".

Sometimes it is easier working in binary or hexadecimal, so additional assembler directives, for example BIN, HEX and DEC, could be used to instruct the assembler which base to use to interpret the numerical strings.

Assemblers make use of other directives such as ORG, and labels, to refer to points in the listing. Assemblers can be single pass or two-pass. A single pass assembler will require you to keep track of your own labels, which can be quite difficult if the assembly listing is rich in subroutines. So this is possibly one reason why Forth evolved as a language, it has it's roots in assembly language programming, but the Forth system of "words", provided an efficient and automated means of keeping track of labels and subroutines - it had to, as Forth is composed almost entirely of subroutines.

Charles Moore, created Forth to be an efficient and automated way of creating a common programming environment on each of the wide variety of mainframe machines that he encountered during the 1960s-70s. His virtual machine had to be first coded in the native machine language of the processor, but with the availability of C compilers, the VM can be coded in C.

Moore realised that the tasks of text editor, assembler, compiler and interactive interpreter could be bundled up into one efficient package, which he called Forth. How exactly this was done was at first fairly obscure, and Moore initially kept much of it to himself, before branching out around 1970 and sharing the inner secrets of Forth within the Radio Astronomy community.

If the primitive assembler can only accept valid mnemonics and numbers, then any other unrecognised text string could be considered to be a new word. A word that cannot be found in the dictionary, is treated as a new definition and is composed from the primitive instructions.

This is similar to the use of a macro label within a (two pass) assembler listing. Once a macro has been encountered and given an address, it can be used again.

So the combination of a simple text editor and line assembler will help us to build up the various Forth word definitions from the primitives. Whilst this C program is not a complete Forth system, it is a tool that helps us create the Forth system.

Expressing Time of Day, Day of Week as a 16 bit Integer

This is a throwback to the requirement to control equipment at specific times during the day, and on specific days of the week.

It allows very simple code to be used to determine the time and day, and decide whether an action route should be executed.

By reducing the time and the day of the week to an unsigned 16 bit integer, simple comparison operations can be done to decide the program flow.

In applications such as central heating control, there is no need to resolve to the nearest second, when 10 second accuracy is perfectly acceptable. It also allows the table that schedules operations to be condensed into an array of 16 bit integers.

Let's invent a new measure of time - the decond. A decond is 10 seconds and there are 6 deconds in a minute.

1 hour = 360 deconds 1 day = 8640 deconds 1 week = 60480 deconds (less than 65536 - so can be expressed as a 16 bit unsigned integer).

As there are less than 10000 deconds in a day, the most significant digit of the 16 bit number can represent the day of the week between 0 (Sunday) and 6 (Saturday)

Midnight on Saturday is 00000, midnight Sunday is 10000 and so on. On reaching 8639 the time counter is reset and 10,000 added.

To turn something on for an hour, you just need the start time, and then keep comparing that with (start_time + 360)

In addition, the Arduino millis() function can be used for timing, and incrementing the decond counter. 10000 millis in a decond, and 60000 millis in a minute. Both of these will nicely fit into a 16bit unsigned integer.

When applied to SIMPL, we have a command for programming the RTC with the current time, and also triggering a function to run, when a certain RTC match is achieved.

The SIMPL Files

Preface

On the evening of May 16th 2013, I attended the OSHUG (Open Source Hardware User's Group) monthly meeting in London. Here I heard a presentation by Romily Cocking about a minimalist language called Txtzyme for controlling microcontrollers. I was intrigued by the concept and decided to explore it further. In the next year, I extended the language and experimented with it as a means of controlling electronic hardware.

Txtzyme is the brainchild of Ward Cunningham. He developed the concept of a simple interpreter contained within a loop and implemented it in C, so that it could be run on a variety of microcontrollers.

I have taken Ward's concept and extended it so that it can be used for exercising hardware based on various 8 bit and 32 bit microcontrollers and soft cores running on FPGAs.

During this journey of discovery, I have borrowed ideas from other programming languages including Mouse - by Dr. Peter Grogono, Forth - by Charles H. Moore and Bitlash by Bill Roy. It also includes some ideas inspired by various Tiny Basics, and Sweet16 - an interpreted bytecode language by Steve Wozniak.

The journey is not yet over, there is still plenty to do to refine the language and develop applications. I have taken this opportunity to pause for thought, and collate all of my previous thoughts into one document.

Introduction

As a Hardware Engineer, the first time you manage to flash an LED on a new microcontroller project board, is the equivalent of your first child's first steps. It is the first positive sign that you have breathed life into an inanimate object, that you are in control and from there on, things will be generally simpler.

Achieving this first step, can often be difficult, especially with a new unfamiliar processor, so it's best to set about this journey equipped with tools that you know and trust, that will make the whole process a whole lot simpler and less painful.

My personal journey began in the summer of 1978, when my school acquired a Research Machines 380Z - as part of an early scheme to put microcomputers into schools. Over the intervening years I've worked with most of the major families of microcontroller and microprocessor and recently ventured into the new territory of soft-cores running on FPGAs.

Along the way, you might happen upon some good ideas, which generally make the road a little less rocky. One notable "good idea" was the Arduino project (2004), which virtually single handedly has revolutionised the access to microcontrollers and programmable digital hardware.

Building on the strength of Arduino, we have seen considerable inroads into making digital hardware more accessible and generally lowering the bar sufficiently to allow anyone to achieve great things with physical computing devices.

The first computer I built - a ZX81 kit cost me a week's wages back in 1983 - about £40. Now I can purchase a 32 bit microcontroller on a credit card sized development board for under a fiver or a complete computer for less that the cost of a pub-meal for two. (Raspberry Pi 2 - about £25).

We live in exciting times - with new hardware appearing almost continuously. At times, it may seem difficult to keep up, but with a few well chosen skills, it is easier to remain on top of the situation. The ability to program in C seems to me to be a fundamental necessity, and it is a pity that I left it so late in life to gain a beginner's proficiency. However. I generally have worked alongside very competent work colleagues, to whom I hand over a mostly debugged hardware pcb - and they then work their firmware magic, and breathe life into it.

So this document - compiled from various blog posts, is a description of how to manage the first few steps of a new hardware project. A means of exercising the hardware to the point that you have confidence that all your pcb tracks are wired correctly and take the design to the point where you may hand it over to your colleague without a bunch of issues.

At the time I wrote the various posts - I was developing some ideas for a new dc motor control board, initially testing some of the basic functionality with an Arduino before moving over to a 32bit STM32F407 ARM M4 cortex microcontroller. Despite the fact that the ARM had approximately 40 times the processing throughput of the Arduino, the principles were exactly the same, and code tested on the Arduino was readily ported across to the ARM with little difficulty.

Some while ago, I read the History of the C Programming Language - which started with Ken Thompson's desire to set up a stable, workable programming environment, when he encountered a new computer (A PDP 7). Similarly, Charles Moore, in an autobiographical document, talks about the early history of Forth, where he moved from machine to machine, each time taking his card deck and known good routines with him. Nearly 50 years on, things haven't fundamentally changed so much, despite the huge advances in processing power, you still need a few familiar routines to bring a system up from scratch.

Beginnings

In the summer of 1983, I wrote some Z80 code to control a microfilm reader. It was hard, repetetive work, hand assembling the various op-codes in hexadecimal, and then programming them into an Eprom, only to find that a bug prevented the code from running at all. It took, at best, about 20 minutes to find the bug, fix it and re-blow an eprom - and so progress was generally fairly slow.

With modern tools, and flash memory, this iterative cycle has been reduced to under a minute, but it's still not instant gratification. Following Charles H. Moore's lead, I wanted a simple tool to be able to quickly test out prototype hardware, and one that could be applied to any microcontroller or device that supports a C compiler. The answer was a simple interpreted language that could be used to execute simple routines to exercise the microcontroller and it's peripherals.

I had previously written a "command interpreter" for the Arduino, which would take a single alpha command and a single numerical parameter, which when entered from a serial terminal was cause a block of test code to be executed. For example, in my dc motor control design F100 would move the motor forwards the equivalent of 100mm. The simple construct of a memorable alphabetical character and an integer parameter was a powerful tool to control the hardware.

One of the first steps in bringing up a new design, is to flash a LED. This proves that the microcontroller is being correctly programmed and that your code actually works. It's the "Hello World" of microcontroller hardware. The next step is to get a UART working so that you can get serial characters in and out of the mcu, and from then you use a simple program, such as a command interpreter to systematically test the rest of the peripheral hardware. For complex processors - such as the ARM, with it's myriad of peripherals, it can take a considerable time to exercise everything - a timescale in the order of weeks.

So to simplify this process with the ARM, I thought about writing some code to make the ARM look like an Arduino, and then I could use the old favourite functions - such as DigitalRead, DigitalWrite to test out the various GPIO ports. It was about this time, that I encountered, through a third party, Ward Cunningham's Txtzyme, and realised that this simple program was just what I had been looking for.

The "language" had to be very compact, and human readable. It also had to have a small set of memorable commands, that form the basis of the language, and an easy way of extending the language so that it could perform modestly complicated high level functions. Charles Moore's FORTH, was a strong influence - as I have dabbled in forth for almost all of my programming career. However, I didn't want the complexity of a stack and reverse polish notation, and I couldn't immediately see how FORTH would fit in well to a C environment.

SIMPL is intended to "be close to the hardware". It's primary use is to be a conveniently simple tool to test the function and exercise new hardware. Many of the "alpha" instructions call directly on Arduino functions - allowing data to be moved between peripherals and memory. Examples include Digital input and output, serial operations, ADC and PWM, and bit shifting.

Further functions may be written to exercise additional hardware, such as servos, shift registers, SPI and I2C connected devices. Many ICs are supported by Arduino Libraries, and SIMPL can be used as the glue, to bind these library functions together with the hardware in an interactive manner. In this way, small applications can be developed.

Ward Cunningham's Txtzyme was a godsend. It essentially extended and automated my command interpreter program and did it in a very simple yet extendable fashion. In just 90 lines of C code, written for an Arduino platform, Ward had created the heart of a new language.

Ward's interpreter consisted of just two routines contained within a loop:

  1. Get the next character from a buffer
  2. Evaluate the character with a switch-case function and execute the block of code associated with it.

Lower case characters (or primitives) would cause some block of code to be executed, and numbers would be converted into a single integer parameter which was passed to the function to control it in some manner.

I took the Txtzyme interpreter and extended it to perform additional functions - such as memory access (equivalent to peek and poke) and also used the FORTH concept, of allowing a word to execute a block of code. In my case, words were actually single uppercase characters. Words and their definitions could be stored in memory (either Flash or RAM) allowing code to be executed from memory - and not just a serial text string.

Layers of Abstraction

Arduino comes with a rich set of helper functions that sit upon the hardware and act as a hardware abstraction layer. It is this abstraction process which makes Arduino a great platform for newcomers. There is no need to get involved with the hardware at register level. The GPIO and other peripherals are provided with simple driver routines, which in principle could be ported to be specific for any microcontroller platform. Indeed various flavours of Arduino have been ported to the MSP430, the STM32F103 ARM, the Freescale version of the ARM M4 in Teensy and now the ZPUino - a 32 bit 100MHz soft core that runs on FPGA hardware - such as the Papilio boards.

With this basic set of "Arduino" helper functions present, Txtzyme can then easily be ported to any microcontroller - as I managed with the STM32407 ARM Cortex M4.

As my journey of discovery continued with the Txtzyme code, I decided to give it a new name - SIMPL, which is an acronym for serial interpreted microcontroller programming language. It was my objective from the start to keep it simple and small, so that it could be easily ported to the most minimal, or the most complex hardware.

What SIMPL Can Do

  1. Exercise GPIO lines
  2. Produce audio tones and square waves
  3. Read the ADC channels
  4. Generate PWM
  5. Peek and Poke to Memory
  6. Print serial strings
  7. Execute code with millisecond and microsecond timing
  8. Execute sequentially a set of serial commands
  9. Combine commands and parameters to make new definitions
  10. Control simple hardware such as shift registers, servos and stepper motors
  11. Execute a complex program function from a minimal command.

SIMPL can be extended to mach the peripheral resources available on the microcontroller - for example on the ARM there are many timer channels that can be used for quadrature encoders. Further extensions could allow file access to eeprom and SD cards, and I2C and SPI data transfers.

A complete SIMPL program consists of a few serial characters, or can be reduced to a single uppercase alpha character. This makes SIMPL program ideal to be passed from one device to another, for example in the form of a text string or packet of characters. This compactness allows SIMPL packets to be sent via SMS, BLE or packaged in the URL of web browsers. It can be sent over any communication interface such as SPI, UART, USB or wireless. Whilst compact, SIMPL is still definitely human readable.

Monday 16th February 2015

SIMPL - A Quick Start Guide

Serial Interpreted Microcontroller Programming Language

SIMPL is a small language resource that resides in flash memory on the target microcontroller. It contains an interpreter that allows the user to have control and interactive access to the memory and peripherals of the mcu without placing an unnecessary burden on its limited resources.

SIMPL can be used as a development tool to exercise new hardware, or as a compact and efficient programming environment that may be ported to virtually any microcontroller or FPGA soft core, that supports a C compiler.

SIMPL can be implemented in Arduino ++ code, or in standard C code. It compiles to under 10Kbytes on most systems so can reside alongside the user application program.

SIMPL defines a 16 bit integer virtual machine. With this VM present on the target microcontroller, the user need not get involved with the machine specifics of a particular microcontroller.

The Advantage of SIMPL

SIMPL is a minimalist interpreted language for direct control of microcontroller hardware, via a communications link. This may take the form of wired serial connection, a wireless or Bluetooth Low Energy link. SIMPL can be run on virtually any microcontroller, or FPGA that supports a C compiler. It's instruction set is small, just 50 commands, and designed to be human readable. Snippets of SIMPL code are compact and can be embedded into communications packets or even web URLs (such as REST), for commanding remote devices.

SIMPL reduces program code down to a few lower case alphabetical and punctuation characters - which each character representing a function or block of functions, which are stored in the flash memory of the microcontroller. These operations can be further reduced to a concatenated block of code that is represented by a single upper case character, however these operations are stored in RAM, and can be updated and modified at run time.

In this way, a microcontroller device, containing the SIMPL interpreter in flash, will execute commands sent to it via a communications link - such as serial, or BLE UART link, or wireless packet protocol conveyed over low power wireless - for example RFM12B and Jeenodes. It can also be reprogrammed remotely.

A Brief Outline.

SIMPL uses a very small interpreter, that sequentially scans through characters stored in a buffer, decodes the character, and executes a small block of code from flash, that is associated with each character.

The interpreter looks at each character in turn, checking if it is a number (0-9), a lowercase character (a-z), a punctuation character, or an uppercase character (A-Z). Depending on the type of character encountered, the interpreter follows a different strategy. Non-printable ASCII characters (less than 32 or greater than 128) are currently ignored by the interpreter.

Numbers 0-9 are decoded into a 16-bit integer variable called x.

Lowercase and punctuation characters, known as primitives, and are decoded in a series of Switch-Case statements to execute small blocks of code.

Uppercase characters, known as Definitions, force the interpreter to jump to a given address in RAM, and execute the string of characters found there, rather than the input buffer.

SIMPL uses a very simple, 16 bit virtual machine model for its operation. This model fits nicely with C code and 16 bit integer maths.

It contains two 16 bit registers, x and y into which the operands are loaded. These registers are used as a pair of operands for all arithmetic, comparison and logic operations, with the result being placed in x. In this respect, x may be considered to be analogous to the accumulator in other systems.

x is also used as the data source and destination register for any memory or I/O operation. The y register is used to supply the address for memory operations.

In addition to x and y, there is a loop counter variable k. This is decremented each time a loop is executed and is used to force the interpreter to exit the loop when k reaches zero.

Implementation in C and Arduino

Whilst the SIMPL interpreter is written in C code ( and C++ on Arduino) for portability, it could be ported to run under the native machine language of any specific processor, if much greater execution speed were needed. However with mcu clock speeds now 10 to 100 times faster than early 8 bit processors, resorting to machine code may seldom be needed.

However, there is a case to warrant the use of direct register manipulation - especially for the digitalRead and digitalWrite commands as used in Arduino. These can be sped up by a factor of 10 using direct port manipulation.

Instruction Set

Alpha Primitives

a Analogue Write - set a PWM value on a pin b c d Define a digital port pin e f for-next structure g h Set a pin High i Read an input pin j Jump k The loop counter operand l Set a pin Low m A blocking delay in milliseconds n Write an 8 bit number to an output port
o Write to an output pin p print x to the serial device as an integer number q Send an 8 bit word out to a shift register using the ShiftOut function r Send a 16 bit word out to a pair of cascaded shift registers using the ShiftOut function
s Get an ADC sample t Read an input word from a shift register (Test)
u A blocking delay in microseconds v
w While structure x The primary data (Accumulator) operand y The secondary (Address) operand z Sleep - a non-blocking pause for x zeconds - whilst still monitoring UART and I/O

Maths Group

  •                 Add x and y and put the result in x              
    
  •                  Subtract  x from y and put the result in x
    
  •                 Multiply x and y and put the result in 32 bit pair [y:x]
    

/ Divide y by x and put the result in x, and remainder in y % Calculate y modulo x and put the result in x

space Move the number just entered to y (allows for 2nd variable)

Comparison Group

                 Is y greater than x, put result in x (equiv to x = y-x)

< Is y less than x, put result in x (equiv to x = y-x) = Is y equal to x, put result in x (equiv to x = y-x)

Logical Group

& Bitwise AND of y and x | Bitwise OR of y and x ^ Bitwise XOR of y and x ~ Bitwise Complement of x

Memory Group

@ Fetch the data into x from the memory address defined by y (equivalent to PEEK) ! Store the data in x to the memory address defined by y (equivalent to POKE)

Definition Group

: A Start a colon definition of A ; End a colon definition

Block Group

{.................} Loop the code contained within the braces whilst loop variable is +ve (................ .) Conditionally execute (or skip) the code contained within the round brackets [,,,,,,,,,,,,,,,,,,] Create an array of comma separated elements within memory (enumerate and store) Print String Print the string contained within the underscores "Store String" Store the string between the quotes in memory at address x .A. Print the code characters assigned to A 'A' Retrieve the string from memory stored at address A

Control and Miscellaneous

? Print out the contents of the program stored in RAM (LIST) , A separator between elements stored within memory - store and increment \ Escape from interpreter - stop all commands £ Restart interpreter $ Load x with the ASCII value of next character - do not interpret/execute

Send a number as a bit pattern to a device, such as port register or shift register

Timing, Sleeping, Pauses and Delays

Much of what a microcontroller does is to synchronise events with time. This might be as simple as flashing a LED once per second, or toggling a square wave from a port pin at a given frequency. Arduino has been equipped with the millis() and micros() functions, and the delay() and delayMicroseconds() functions to make time synchronised coding simpler.

The delay functions are blocking - in that the microcontroller cannot execute any other code until the delay period has elapsed. This is OK for short periods, up to about a second, but it prevents the system from responding to external events, such as a change on an input pin, or the User trying to stop the program. For this reason, SIMPL has been given a non-blocking delay command z, which allows it to pause for a while, whilst still monitoring the UART Rx buffer for certain characters - such as the \ escape character, or for a change in status of any input lines, which might signify an external event.

z - is often associated with sleeping, so appropriate for a command that effectively allows the microcontroller to take a nap, until something happens to wake it up.

I also propose at this point the zecond - that is a non-blocking nap for a second. This allows for naps of 1 zecond up to 18.2 hours to be defined.

Waiting for External Events

This is a common use for While statements for in C.

while(some condition is met) { Execute this block of code, and continue to test condition}

This simple construct needs to be efficiently coded into SIMPL.

For example - wait for a value to be exceeded on an ADC input, say 600 on ADC 5.

600 5s>(............)

600 is first loaded into x, and the space character transfers it to y. Then we read ADC 5 (into x) and compare it with the value in y. If the result in x is positive - we execute the code in contained between the round brackets. This code could just be an idle loop or a pause - non-blocking delay. After this code is executed, we need to test again.

To code this into SIMPL we need to have a mechanism to repeatedly perform the test, and a means to execute an idle loop.

We can make this distinction using the two flavours of brackets. The code to test for the condition is enclosed in round brackets, and the code for the tasks to be done whilst idling is enclosed in the curly brackets (braces). This makes our code as close as possible to the C construct.

We then have the general form, where w defines the while statement

w(...condition..){...idle loop.....}

or as in the example

w(600 5s>){loop here until condition returns zero or less}

This is a kind of conditional form of the general loop, which decrements the loop counter k each time around the loop, until zero is reached.

Can we use the same constructs to implement for-next loops?

General form in C

for(i=0; i<=10; i++)

Here we have a loop variable i, which is initialised to zero, tested against an upper limit (to execute a conditional block of code) and then incremented (or modified) each time around the loop.

Let' use f to designate a for loop. We need to supply 3 parameters

initial value, test condition, modifier

We could do this by setting up the initial value and modifier outside of the test condition - by using x an y

Lets run from 0 to 100 with a modifier of +1

0 1f(100<){ loop}

A better method might be to borrow the loop counter k, so that 3 parameters can be entered into the conditional statement.

Using the space as a stack pushdown, the sequence

10 11 12 puts 10 into k, 11 into y and 12 into x.

The Decimalisation of Time- A SIMPL means to handle regular events.

This comes as a result of the need to control equipment at specific times during the day, and on specific days of the week.

It allows very simple code to be used to determine the time and day, and decide whether an action routine should be executed.

By reducing the time and the day of the week to a 16 bit integer, simple comparison operations can be done to decide the program flow.

In applications such as central heating control, there is no need to resolve to the nearest second, when 10 second accuracy is perfectly acceptable. It also allows the table that schedules operations to be condensed into an array of 16 bit integers.

Let's invent a new measure of time - the decond. A decond is 10 seconds and there are 6 deconds in a minute.

1 hour = 360 deconds 1 day = 8640 deconds 1 week = 60480 deconds (less than 65536 - so can be expressed as16 bit unsigned integer).

As there are less than 10000 deconds in a day, the most significant digit of the 16 bit number can represent the day of the week between 0 (Sunday) and 6 (Saturday)

In addition, the Arduino millis() function can be used for timing, and incrementing the decond counter. 10000 millis in a decond, and 60000 millis in a minute. Both of these will nicely fit into a 16bit unsigned integer.

More Applications for SIMPL.

A few notable things have happened since I was last using SIMPL to control stepper motors and LED arrays using shift registers. I have developed a new compact RFM12/69 wireless I/O breakout board for the Raspberry Pi in association with my friends at Open Energy Monitor and I have invested in a couple of FPGA dev boards - launched via Kickstarter.

Both of these developments can benefit from using the SIMPL language to exercise them and try out ideas on new hardware.

The RFM-Pi board is a compact I/O board (33 x 28mm) fitted with an RFM12/69 wieless module and ATmega328P, running Arduino with the Jeenodes wireless protocol. The pcb plugs into the I/O header of the Model B+ and Pi 2, where it picks up 3V3 power, Rx and Tx from the Pi's UART and a GPIO line for reset. This is a very simple way of providing Jeenodes/RFM12 wireless communications for the Pi, so that it can be used as a basestation for the series of wireless energy monitoring products developed by OpenEnergyMonitor.

However, in the latest version of the RFM-Pi, I chose to make available most of the I/O pins of the ATmega328 - so that in effect, this board may also be used as a I/O expander for the Pi - providing up to 8 analogue input channels and 5V tolerant I/O pins.It can be used as an Arduino compatible wireless I/O extender for the Raspberry Pi. It breaks out 12 digital I/O pins and 8 analogue pins from the ATmega328 SMD package, giving almost complete Arduino functionality in a small form factor.

Additionally, the board may be used as a plug in module, providing RFM12 wireless and Arduino functionality for some other project. It can act as an analogue sensor interface, or hardware controller and be controlled remotely from distances in excess of 100m using the Jeenodes wireless library. It is compatible with the other products in the Open Energy Monitor Range - and could form the basis of a new form of sensor. It requires a 3V3 supply - which could be provided from a coin cell or from a larger lithium cell- such as these 2250mAh common size 18650CA cells.

By running the SIMPL interpreter in the background, the RFM-Pi board can execute SIMPL commands via a 250m range wireless link.

SIMPL is also great way of getting the Pi to drive the I/O board - by a series of easy serial commands. This would open up the Pi to driving LED arrays, stepper motors and indeed, anything that the Arduino can do - just with a few high level commands. The Arduino has 5V tolerance, so best to have it take the knocks when experimenting with I/O - rather than frying a more expensive Pi.

A SIMPL Compiler?

Having "lifted the hood" again on SIMPL, I have been thinking about the possibility of a SIMPL compiler. There might be a way in which C code source could be compiled into an interpreted SIMPL program. A machine compiler would help with more complex programs and reduce human errors in coding.

SIMPL has a number of primitive operators, that are mapped into machine language, using an interpreter written in C. Lower case alpha and punctuation characters limit the primitives to just 58 instructions. This ensures that a microcontroller that runs SIMPL - has a memorable and easily managed reduced instruction set. For future implementations it means that a machine could run SIMPL from a 6 bit instruction.

This would allow more complex SIMPL programs to be machine generated from C source code, and reduced to an interpreted text file to be run on any micro. It's kind of like the Java Bytecode idea where common code can run on a variety of different platforms - provided that they have the interpreter. Imagine what sort of a SIMPL program could be conveyed in a 140 character text message - sent to a remote device by SMS.

Better Branching

For this to happen, SIMPL needs some further augmentation to allow easier branching and decision making - in what I call "If this - then that" or IFTTT- popularised by a recent new IoT service.

Ideally, and in its simplest form, a parameter needs to be tested against a number (using subtraction) and then branch if the result is positive, negative or zero. The branch would be to either execute the next character (code block) or skip it. This would allow the popular constructs of If-Then-Else and While loops to be generated.

I have implemented a simple > or < test, but it's a little clunky and also needs an equality test as to be included as well.

The round brackets (.....) represent a block inline of code that should be executed on the outcome of a test or skipped. This would allow While and For-Next constructs to be programmed.

The square brackets [....] could be used for a switch-case construct to be generated.

Whilst I am running out of lower case characters for the primitive commands - only e,f,g, t and v remain, there is loads more scope for expansion by using some of the remaining printable punctuation characters - a total of 32. Some such as +, -, *, / ,>,<, {, }, :, ;,@, !, _ and ? have already been defined leaving about 18 for later. Logical operators such as &, (AND) | (OR) are an obvious extension leaving a few like £, $, %, ^, ~, # to acquire some meaning - probably similar to their meaning in a C context.

So in theory, SIMPL can have a maximum of (26+32) primitive commands plus 26 user defined words - as defined by uppercase alpha characters.

Better Arithmetic

SIMPL currently has an x variable and a y variable that can be set to the previously entered value of x using the @ (fetch) and ! (store) operators. This is a bit clunky and a better way of handling multiple variables would probably be by using a stack. I want to try to keep the interpreter simple, and not implement the full stack logic. As most microcontrollers only combine 2 variables in their math operations, just x and y will be sufficient to handle this.

In FORTH, numbers are automatically put on the stack, but in SIMPL, they always go into x, unless stored to y using the ! operator. A neat idea would be to use the space character (instead of !) to inform the interpreter that another number is expected immediately, and so that x should be stored to y, so that x is free to accept the second number.

This would make the math operations a whole lot more readable - just by separating the variables with a single space.

123 456+p would add 123 and 456 and print it out.

As well as the math operators, the logical operators would also benefit from this increased flexible notation. The space operator implies - push the top of the stack down to make room for another parameter - allowing constructs such as

123 456+ 23-p so the interim sum of 123+456 is pushed down by the 2nd space, allowing room for the 23 and the subtraction operation. This makes it a lot more FORTH like and very much improved readability for numerical operations involving two variables.

Rule: A space following a number implies that the number is automatically copied from x (top) to the y (next) variable.

More Operators

& Bitwise AND | Bitwise OR ^ Bitwise XOR ~ NOT (invert)

$ String operator % modulo operator (...) Conditionally execute this block of code [...] Use x to select an option from the list contained within the square brackets £ Invoke SIMPL interpreter

, separate a list of integers . Pop x and print it (FORTH compatibility) ? Print out the current set of definitions \
" '
: Start of colon definition ; End of colon definition _ Text string identifier

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.

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};

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

Txyzyme 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. This process happens automatically and we don't have to concern ourselves about the exact address that holds T.

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.

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, June 02, 2013

Extensions to SIMPL

In the last week I have been thinking about the user interfaces used on minicomputers of the 1960s, in particular the PDP-8, and wondering if a similar front LED and switch panel could be created cheaply as a nostalgic retro accessory shield for the Arduino.

I have added some LEDs to the 12 available digital I/O pins of the Arduino, so that I can recreate LED chaser and "vintage computer" style displays.

I've extended the SIMPL command set so that I can more easily address each LED in turn, or alternatively treat all twelve as a binary numerical display, to display address or data numbers in the range 0 to 4096.

The latest version of SIMPL can be found here on Github Gist:

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

Just download the Gist and compile it as an Arduino sketch. You can then start typing SIMPL commands using the serial monitor window at 115200 baud. Make sure that you have selected the "Both NL and CR" option for the serial monitor.

Output Commands

In order to gain more immediate access to the I/O, I have added some new commands:

a - sends an analog.Write value to a pin previously named with d b - prints out the current value of the milliseconds counter, allowing loop timing to be calculated c - prints out the current value of the microseconds counter

h - sets a digital pin high eg 6h l - sets a digital pin low eg 13l n - decodes a number up to 4095 and displays it on digital pins 2 to 13 eg 1234n

n can be thought of as a very simple binary display. It has a fast response time and allows the user a simple visible means of checking that a program is executing.

The n command can be useful to examine the characters stored in RAM. Here it is used to output 1000 characters to the LEDs, starting at RAM address 256. The characters are sent every 100mS and also printed to the terminal.

255!1000{y@rn100m}

255! Store 255in y as the starting RAM address 1000{ Perform the loop 1000 times y Increment y each time around the loop @ Move y into x r read the contents of RAM into x n Send the value to the LED display 100m 100mS delay to slow things down to a sensible speed } End of the loop

Decision Making

SIMPL currently lacks the if, then, else decision making, or the switch case structure. This would be a useful addition and I am currently working on some ways of implementing it.

It might be possible to test the x value against certain constants and then execute one of the upper case routines if the test was equal.

Other SIMPL Commands

SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter, which recognises the following:

a Send an analog write (PWM) value to a pin b print out the current milliseconds count c print out the current microseconds count d define a digital port pin e f g h set pin high i read an input j skip next instruction k access the loop counter l set pin low m define a delay in milliseconds n display a number on a line of LEDs o set an output p print the x variable to the terminal q query a block of RAM locations ( as character) r read from RAM s read an analogue input t u define a delay in microseconds v w write to RAM x increment x y increment y (as used in incrementing loop structures)

{} loop the code contained within the braces

@ copy y to x ! store x in y ? Dump the contents of RAM to show the existing words

/ <

Numbers can be typed in the range 0 to 65535 and are stored in the x variable and used to control the above instructions.

eg. 6d define digital port pin 6 100m define a delay of 100mS 10{....} go around a loop 10 times 20p Print 20 to the terminal

To these basic instructions I added a y variable, so that I could do simple maths. You can store a number in y by using the store symbol !

  20!          Stores the value of 20 into y (by transferring it from x)

To get the contents of y back, we use the fetch symbol @

 20!@p      Prints the value of 20 from y

We can do simple addition, subtraction, multiplication and division on x and y

 20!5+p      Adds 20 to 5 and prints result       (x=x+y)

 5!30-p      Subtracts 5 from 30 and prints result  (x=x-y)

 16!8*p     Multiplies 8 by 16 and prints result     (x = x*y)
 
 6!30/p       Divides 30 by 6 and prints result      (x=x/y)

Downloading the SIMPL sketch from Github Gist and programming it into a standard Arduino is the first step to discovering a new way to control physical computing devices.

Saturday, June 01, 2013

Extending SIMPL and flashing a few LEDs

I have been experimenting with SIMPL, and have added a few new commands to give it greater functionality.

I've wired Digital outputs 2 to 13 to a line of 12 LEDs, to give a very simple means of displaying numerical values. It also allows LED chaser displays to be tinkered with.

I have added a command to allow the analogWrite function to control an output pin.

Name the pin first, e.g. 6d and then the PWM value such as 127a This sets the PWM to about 50% duty cycle.

I've also been investigating how fast the commands run, so added a couple of timing commands b and c. b prints the current value of the millisecond counter millis(), so typing b before and after a list of instructions will allow you to calculate how many milliseconds it took to execute. c does the same, but uses the microseconds counter micros().

By timing 10000 cycles of a loop, I can show that SIMPL will add two 16 bit integers in about 6 microseconds.

I have added some commands for easier control of the I/O. h and l are now used to set a port pin high or low eg. typing 6h and 5l will immediately set those pins high and low.

After my experiments with LED chaser displays, I also wanted a way to immediately write an 8 bit number to 8 consecutive LEDS. So the "n" command displays a number on a row of LEDs.

Typing 255n will turn all the LEDs on Digital 2 to Digital 9.

To make incrementing loops easier, the command "x" now increments x and "y" increments y.

0!10{y@p}

This prints out the numbers from 1 to 10. 0! sets y to zero, y increments the y variable.

The q, r and w commands have been used to access the RAM.

300r will print the character stored at address 300.

SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter. SIMPL now recognises the following lower case instructions:

a Send an analog write (PWM) value to a pin b print out the current milliseconds count c print out the current microseconds count d define a digital port pin e f g h set pin high i read an input j skip next instruction k access the loop counter l set pin low m define a delay in milliseconds n display a number on a line of LEDs o set an output p print the x variable to the terminal q query a block of RAM locations ( as character) r read from RAM s read an analogue input t u define a delay in microseconds v w write to RAM x increment x y increment y (as used in loop structures)

{} loop the code contained within the braces

@ copy y to x ! store x in y ? Dump the contents of RAM to show the existing words

  •   Add x and y
    
  •    Subtract x and y
    
  •   Multiply x and y
    

/ Divide x and y < Is y < x

  Is y > x

Saturday, December 28, 2013

SIMPL on the STM32F4xx Discovery Board

Back in the summer, I posted some musings about a very small programming language that I named SIMPL - Serial Interpreted Micro Programming Language. It's an extended version of Ward Cunningham's Txtztme, described as a Nano Interpreter - which is documented here.

Well over the period of the Christmas break, I have had the opportunity to port SIMPL, which is written in fairly standard C, across to the STM32F4 ARM Discovery board. It is now working to the point where I can program simple I/O operations and loops on the Discovery board.

SIMPL is fast on the STM32F4x you can create a pulse as short as 200nS, or toggle a pin on and off at 372kHz. By comparison on the Arduino (using digitalWrite) the pulse time is 10uS and 47.8kHz maximum frequency, though better could be achieved by direct port manipulation.

Ward Cunningham has ported txtzyme to the Teensy board, as a means of controlling hardware over a USB connection, and from a remote server. Ward is using txtzyme to control hardware remotely as part of his Federated Wiki project. A video explaining the project with some demos is here, and well worth a watch for some interesting background.

I've chosen to follow a slightly different route to Ward's project, to use SIMPL more as a programming language, but as the txtzyme interpreter is common to both the Teensy and my ARM implementation, then either hardware can interpret txtzyme strings.

Although SIMPL started off life on an Arduino, it seemed a natural choice to port over to the ARM Discovery board. The additional RAM and program space allow far more elaborate programs to be written, and as the ARM runs at 10 times the clock speed of the Arduino Uno, - the code is blistering quick.

You might recall that SIMPL is based on an interpreter, which interprets serial character strings and decodes them into functions which are executed in turn.

SIMPL generally uses a mix of small characters and punctuation marks as the primitive command set, and then a capital letter can be used in a similar way to a Forth word, to execute a sequence of commands.

Small characters, maths symbols and punctuation marks are used as the primitives. When encountered by the interpreter, they are used to call a function directly, such as p to print a character, or h to set a port line high. The maths symbols are used, obviously to allow maths operations to be executes, such as + - * / and tests such as < and >. The overall simplicity of using a single ascii character as a command, means that the entire interpreter can be coded as a simple switch-case statement in C. For example when h is encountered:

  case 'h':                               // set bit high
  digitalWrite(x, HIGH);
  break;

Where the interpreter encounters a number character 0 to 9, these are scanned in, and accumulated into variable x with the correct decimal place shift, for as long as the next character in the buffer is a number. The following few lines of C perform this number interpretation

  x = ch - '0';
  while (*buf >= '0' && *buf <= '9') {
    x = x*10 + (*buf++ - '0');
  }

Punctuation marks are used to help program flow. For example the open and close brace structure defines a portion of code to be repeated as in a loop. Suppose we want to loop some code 10 times, for example print 10 Green Bottles. The Green Bottles will be printed if it is written thus Green Bottles and the loop structure uses a loop index k, which is decremented each time around the loop. kp will print the current value of k, each time decrementing.

10{kp_Green Bottles_}

Unfortunately p also introduces a newline character, so the output is not quite as desired :-(

Words

In this interpretation scheme, I have reserved the upper case letters to represent "words" - in the Forth sense. In order to maintain the same simplicity in the interpreter, single characters are decoded as calls to the code stored in the word definition. This may sound confusing, so to illustrate with an example.

Suppose I liked the "Green Bottles" code so much, that I wanted to preserve it and use it again, and again. Well I can do this by making it into the form of a colon definition (again borrowed from Forth), such that I can assign it to a memorable word, say B for bottles.

The colon : tells the interpreter that the next character will be a word, followed by the code that will be executed when the word is called

:B 10{kp_Green Bottles_}

This will place the code 10{kp_Green Bottles_} at a location in memory that can be accessed everytime that the interpreter sees the letter B. Instead of interpreting the contents of the keyboard buffer, the interpreter is now pointed to a word buffer, containing the code body that makes up B.

This process can be extended by adding together words to make new words

:A 10{B}

This defines A as ten iterations of B, or about 100 Green Bottles!

The word definitions are stored in a RAM array, and the ? command can be used as a means of listing all the current word definitions.

SIMPL is now starting to take the form of a very concise language. It can handle numbers, character commands from the terminal and perform simple maths. It can perform loops and output numbers and text to the terminal. The next thing is to allow it to access the peripherals and I/O.

SIMPL has been developed to be "close to the hardware". As almost all microcontrollers have a mix of on chip peripherals, such as timers, ADCs, DACs and general purpose I/O, SIMPL has primitive commands designed to exercise this hardware directly.

For example, suppose you have an output port on Port D13 controlling a LED, then the command 13h will turn the LED on and 13l will turn it off, h and l being the commands to set the named port 13, either high or low.

For analogue input from an ADC channel, the command s for "sample" is used. So to read the ADC channel 10 and print to the terminal, we enter 10sp.

Commands can be repeated within loops using the { } loop structure.

To read the ADC channel 10, ten times and print the result to the terminal, we use:

10{10sp}

or to slow this down to once a second, we can delay with the millisecond delay m command which puts a 1000mS pause in the loop.

10{10sp1000m}

We can now put a few of these commands together so as to flash the LED for 100mS each time we take an ADC reading

10{10sp900m13h100m13l}

Note that we are still looping 10 times, reading ADC channel 10 and printing it out, pausing for 900mS, setting LED 13 high, pausing for 100mS, setting the LED low, returning to the start of the loop.

So it's quite easy to build up complex commands, just by concatenating a few primitives together.

What if you were to write this in C? It would be somewhat longer, about 8 to 10 lines of code, and then need to be compiled, tested, and if you weren't happy, edited and compiled again. SIMPL breaks us out of the edit, compile, test cycle, and allows ideas to be tested quickly and easily, straight from the terminal.

This was exactly what Forth language pioneer, Charles Moore realised in the mid-1960s. He too wanted to break free from the edit-compile-test cycle, in order to improve his efficiency in coding, as computer time was expensive back then, and also to make himself no longer reliant on compilers and assemblers that he had no control over. He wanted to develop a self-written, self-contained programming environment that could easily be moved from one system to another, and require few and simple resources to get it running.

If you are interested in the early history of Forth, Charles "Chuck" Moore describes the early development of the language here:

History of Forth

Whilst SIMPL is not Forth, and never will be, there are several nice techniques borrowed from Forth, which are used to enhance SIMPL.

We have come a long way since the early development of the computer languages, such as C and Forth, which were often hosted on very primitive machines, with limited RAM and tiny disks by today's standards.

One early machine, the PDP-8, was of a simple enough architecture, that it has often formed the basis of study in computer science courses. Additionally, the PDP-8 has been implemented in many different technologies over the years, including TTL, VLSI and as a FPGA implemented in Verilog or VHDL.

The reason for interest in the PDP-8, is that whist primitive by machine standards now, it represented a revolution in architecture simplification, such that the whole system could be sold for $18,000 back in 1965. It was the first of the true minicomputers, available at a tenth of the cost of competing systems.

Additionally, the PDP-8, is comparable in resources to those that we find on a low cost microcontroller, costing a few dollars. So the practices used in the 1960s to write code for the early minicomputers has significant relevance these days.

Whilst generally we use open source C compilers, such as GCC, and integrated design environments (IDEs) to develop programs, there is no reason why a simple interpreted language, running in the background would not make sense, when developing applications on a new microcontroller. It puts the control of the hardware, directly at your fingertips and allows quick experimentation.

Modern 32 bit microcontrollers, such as the ARM range of cores, are now rapidly replacing 8-bit devices in a range of applications, at very little additional extra cost. The resources and peripherals available on a typical ARM device, are vast compared to 8-bit processors, and with clock speeds roughly ten times faster, a huge amount of processing power is available, compared to only a few years ago.

With clock speeds in the 100-200MHz range, it's now perfectly possible to host an interpreted language on the microcontroller, and have it run at speeds only previously available through the compiled language route.

SIMPL consists of an interpreter running within a loop. The interpreter is written in about 300 lines of standard C, and additionally includes several I/O and memory functions, which are tailored to the particular microcontroller, to create a standardised machine model.

To the Arduino user, these I/O routines will be familiar:

digitaRead Read the state of a digital input digitalWrite Write a digital output high or low analogRead Read the value of an ADC channel analogWrite Write a value to an analogue PWM or DAC channel delayMilliseconds generate a delay in mS delayMicroseconds generate a delay in uS printNum print an integer number to the terminal putChar print an ASCII character to the terminal getChar read an ASCII character from the keyboard or terminal input buffer

All microcontrollers for embedded applications should have the hardware means to execute these routines, and although setting up the I/O and peripherals may take a bit of time on an unfamiliar hardware device, once done the basic routines will be used frequently in any application that may be developed.

delayMilliseconds can simply be derived from 1000 times around the delayMicroseconds loop, or can be derived from a hardware timer, depending on the device.

Whilst putChar would normally send a character to the UART transmit buffer, it might instead be used to bit-bang an output pin, if no UART is available. Fortunately most microcontrollers have one or more UARTs available these days, so bit-banged serial comms is less of a requirement.

printNum is just a convenient means of getting integer numerical output from the microcontroller. It will use the C routine "integer to ASCII" and putChar to send an integer to the terminal.

getChar is intended to read in a character at a time either directly from the keyboard or from the terminal input buffer.

With these routines, you can now interface to a serial terminal, read and write to I/O lines, read analogue inputs and control PWM or DAC outputs. With the ability to specify accurate delays to give a sense of timing to the program flow, there is little else that the micro needs to do, except perhaps for memory operations.

Thanks for the Memory

In bygone days, when microcontrollers had very little memory, it was easy to get obsessed about the placement of code and data within memory. Memory was a precious commodity, and it was necessary to squeeze your program and your data into what little memory was available. Every byte was precious, so clever tricks were devised to pack data into as few bytes as possible.

These days, this is not so much of a problem. The STM32F407 has a 1Mbyte flash for program and storage of constant data, and 196Kbytes of SRAM, 4Kbytes of which can be battery backed and made non-volatile. Other STM32F4xx family members have 2Mbyte of flash and 256Kbytes of SRAM. This might not seem much by PC standards, but for an embedded application it is more than plenty.

Friday, May 02, 2014

A little bit shifty

Experimenting with Shift Registers and Arduino

Shift registers are probably the least understood class of devices used in microcontroller and hardware design, yet they are central to so many common interfacing techniques, so I thought I would spent a few evenings getting to know how to use them.

There are some very good online tutorials regarding the use of shift registers, so I will not try to improve upon the wealth of good material that is already available, instead I will attempt to document some of my recent findings, in the hope that someone finds it useful. Everyone can type Arduino and shift register into Google and come up with a whole bunch of useful information.

My experiments have been done with an Arduino, or rather a low cost clone that uses the ATmega328P microcontroller, but could equally be applied to any other microcontroller, as the firmware is written in C or C++.

Here are 10 facts about shift registers that make them very useful.

  1. They convert serial data to parallel, and parallel data to serial.
  2. They can be easily chained together, generally 8 bits at a time to make longer wordlengths.
  3. They are cheap and readily available - about £0.30 for an 8 bit shift register.
  4. They can be used for storing data
  5. They are used in UARTs for serial communication
  6. They are used in I2C and SPI interfaces
  7. They can be used to extend the simple I/O capabilities of small pin-limited microcontrollers
  8. They can come with power drivers stages for driving lamps, relays and stepper motors
  9. They are ease to wire up, using few pins and easy to control with simple firmware
  10. They often form the basis of many segment LED drivers

I will be looking at some very common types:

74HC595 - this is the ubiquitous 8 bit series to parallel shift register, used for outputing parallel data. It requires just 3 pins on the Arduino to control it, and can be chained together to make much larger word sizes. It is available as a breadboard friendly 16 pin DIP, but also as compact SOIC, TSSOP and QFN packages. As a HC device is is compatible with both 3V3 and 5V logic and can be powered from 2V to 6V. Each output can supply 20mA - which is ideal for driving LEDs with a suitable series resistor. Available from several manufacturers the world over. Datasheet here

74HC165 - this performs the complimentary function to the '595 which is parallel to series conversion. It also requires 3 pins to drive, can be chained to make larger word sizes and is very often used to provide additional input lines on small microcontrollers. These are very useful for reading switches (such as DIP switches used for configuration), or any other parallel input data. Again the HC logic allow a wide range of supply voltages, and available in a 16 pin DIP or several other compact packages. Datasheet here

TPIC6B595 - this is an 8-bit serial to parallel shift register followed by a DMOS power driver stage, capable of 500mA of drive. It can be used for driving higher current, inductive loads directly such as relays, solenoids and small stepper motors. Available as a 20 pin DIP (or smaller) package, it can be used to replace the popular combination of a 74HC595 followed by a ULN2803 octal darlington driver. If you are short of pcb space - this device is worth considering. About £1 each in 10 off quantity. A typical application would be driving a "fruit machine" where a few hundred lamp drivers are needed.Datasheet here

If you follow the links to the datasheets, you will see that 2 of them are via the Sparkfun site, showing the popularity of shift register devices amongst hobbyists. Indeed, shift registers are available on breakout boards and Arduino Shields, like this 48 Channel Output shield that uses six of the 74HC595 devices.

My experiments are slightly less ambitious. I decided to breadboard two 74HC595 devices and two 74HC165 devices to make a 16 bit output LED display, and a 16-bit switch input in order to expand the capabilities of the Arduino. Additionally I wanted to explore the use of the TPIC6B595 device as a means of driving a pair of small stepper motors - as the basis of some robotics and automation projects.

Wiring Up

74HC595 Output

Connecting a pair of shift registers on a breadboard to make a 16 bit word size is fairly straightforwards - here is a circuit from a French tutorial. It has nice clear diagrams of the breadboard layout too.

You will need 3 spare pins on the Arduino, referred to as latch, data and clock. If you use the Arduino ShiftOut() function, these can be any three spare pins, but I chose to use 8,9 and 10 in order to leave 11,12 and 13 spare for future SPI work. If you follow the tutorial above and the code example provided it is very simple, and you will be up and running in no time.

I wanted to speed up the time that the latch signal was present, so in order to lower the latch I substituted the usual digitalWrite() function for the direct port command

PORTB &= ~_BV(0); // This lowers digital pin 8

and to raise it

PORTB |= _BV(0); // This raises digital pin 8

Doing this small code change allows the shift register to be updated at about 8000 times per second.

74HC165 Input

Wiring this up was also fairly straightforward. Again you will need 3 lines to control the shift registers. I used digital lines 5,6 and 7 - again to avoid the SPI pins. Again this French wiki provides nice neat circuit diagrams in EagleCAD format. However, I used pull down resistors, rather than pull-ups, and I used the Arduino shiftIn() function. At first I noticed some very odd behaviour, where the register appeared to be multiplying the input number by 2. I had had a past experience of this, and realised that it was caused by clocking on the wrong edge of the clock. This was easily corrected by making sure that the clock line is raised after the shiftIn(), so that it idles in the HIGH state, not the low state.

Code

Now we look at the code to combine the reading of the input shift registers with writing to the output registers. First we need to define the 6 various pins that carry the control signals:

int sinPin = 5; // Serial input pin from 74HC165 int sclkPin = 6; // Clock pin to 74HC165 int loadPin = 7; // Parallel load pin of 74HC165
int latchPin = 8; // Pin connected to ST_CP of 74HC595 int dataPin = 9; // Pin connected to DS of 74HC595 int clockPin = 10; // Pin connected to SH_CP of 74HC595

and then within setup() - set them up as INPUT or OUTPUT

pinMode(d,OUTPUT);
pinMode(loadPin, OUTPUT);
pinMode(sclkPin, OUTPUT);
pinMode(sinPin, INPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(sclkPin,HIGH);    // initialise the clock HIGH

Once you have set up the pins it's just 4 lines of code to read the inputs

// Read incoming word from 74HC165

digitalWrite(loadPin, LOW); digitalWrite(loadPin, HIGH); int incoming = shiftIn(sinPin, sclkPin, MSBFIRST); digitalWrite(sclkPin,HIGH);

and 3 lines of code to write to the outputs

// and write it out to 74HC595

PORTB &= ~_BV(0); shiftOut(dataPin, clockPin, MSBFIRST, incoming); // shift out the bits: PORTB |= _BV(0);

This sketch is available in full at this Github Gist

Once the signals have been defined and initialised, the code to read and write to the registers is really very trivial. Whilst I have used the shiftIn() and shiftOut() functions provided by Arduino, these functions are also fairly simple and can readily be substituted for routines that directly control the I/O pins - if additional speed is needed.

In the next part I will look at how this shift register functionality can be incorporated into real applications such as stepper motor driving.

More Information

Nick Gammon's tutorial on using the '595

Nick Gammon's tutorial on using the '165

These outline using the shift registers with the SPI bus. This is the next step if you need the fastest speed data transfer.

The flawed Arduino tutorial - do not connect the 1uF capacitor there!! It's supposed to be a 100nF capacitor across the 5V and 0V power pins!

Friday, May 02, 2014 A little bit shifty Experimenting with Shift Registers and Arduino

Shift registers are probably the least understood class of devices used in microcontroller and hardware design, yet they are central to so many common interfacing techniques, so I thought I would spent a few evenings getting to know how to use them.

There are some very good online tutorials regarding the use of shift registers, so I will not try to improve upon the wealth of good material that is already available, instead I will attempt to document some of my recent findings, in the hope that someone finds it useful. Everyone can type Arduino and shift register into Google and come up with a whole bunch of useful information.

My experiments have been done with an Arduino, or rather a low cost clone that uses the ATmega328P microcontroller, but could equally be applied to any other microcontroller, as the firmware is written in C or C++.

Here are 10 facts about shift registers that make them very useful.

  1. They convert serial data to parallel, and parallel data to serial.
  2. They can be easily chained together, generally 8 bits at a time to make longer wordlengths.
  3. They are cheap and readily available - about £0.30 for an 8 bit shift register.
  4. They can be used for storing data
  5. They are used in UARTs for serial communication
  6. They are used in I2C and SPI interfaces
  7. They can be used to extend the simple I/O capabilities of small pin-limited microcontrollers
  8. They can come with power drivers stages for driving lamps, relays and stepper motors
  9. They are ease to wire up, using few pins and easy to control with simple firmware
  10. They often form the basis of many segment LED drivers

I will be looking at some very common types:

74HC595 - this is the ubiquitous 8 bit series to parallel shift register, used for outputing parallel data. It requires just 3 pins on the Arduino to control it, and can be chained together to make much larger word sizes. It is available as a breadboard friendly 16 pin DIP, but also as compact SOIC, TSSOP and QFN packages. As a HC device is is compatible with both 3V3 and 5V logic and can be powered from 2V to 6V. Each output can supply 20mA - which is ideal for driving LEDs with a suitable series resistor. Available from several manufacturers the world over. Datasheet here

74HC165 - this performs the complimentary function to the '595 which is parallel to series conversion. It also requires 3 pins to drive, can be chained to make larger word sizes and is very often used to provide additional input lines on small microcontrollers. These are very useful for reading switches (such as DIP switches used for configuration), or any other parallel input data. Again the HC logic allow a wide range of supply voltages, and available in a 16 pin DIP or several other compact packages. Datasheet here

TPIC6B595 - this is an 8-bit serial to parallel shift register followed by a DMOS power driver stage, capable of 500mA of drive. It can be used for driving higher current, inductive loads directly such as relays, solenoids and small stepper motors. Available as a 20 pin DIP (or smaller) package, it can be used to replace the popular combination of a 74HC595 followed by a ULN2803 octal darlington driver. If you are short of pcb space - this device is worth considering. About £1 each in 10 off quantity. A typical application would be driving a "fruit machine" where a few hundred lamp drivers are needed.Datasheet here

If you follow the links to the datasheets, you will see that 2 of them are via the Sparkfun site, showing the popularity of shift register devices amongst hobbyists. Indeed, shift registers are available on breakout boards and Arduino Shields, like this 48 Channel Output shield that uses six of the 74HC595 devices.

My experiments are slightly less ambitious. I decided to breadboard two 74HC595 devices and two 74HC165 devices to make a 16 bit output LED display, and a 16-bit switch input in order to expand the capabilities of the Arduino. Additionally I wanted to explore the use of the TPIC6B595 device as a means of driving a pair of small stepper motors - as the basis of some robotics and automation projects.

Wiring Up

74HC595 Output

Connecting a pair of shift registers on a breadboard to make a 16 bit word size is fairly straightforwards - here is a circuit from a French tutorial. It has nice clear diagrams of the breadboard layout too.

You will need 3 spare pins on the Arduino, referred to as latch, data and clock. If you use the Arduino ShiftOut() function, these can be any three spare pins, but I chose to use 8,9 and 10 in order to leave 11,12 and 13 spare for future SPI work. If you follow the tutorial above and the code example provided it is very simple, and you will be up and running in no time.

I wanted to speed up the time that the latch signal was present, so in order to lower the latch I substituted the usual digitalWrite() function for the direct port command

PORTB &= ~_BV(0); // This lowers digital pin 8

and to raise it

PORTB |= _BV(0); // This raises digital pin 8

Doing this small code change allows the shift register to be updated at about 8000 times per second.

74HC165 Input

Wiring this up was also fairly straightforward. Again you will need 3 lines to control the shift registers. I used digital lines 5,6 and 7 - again to avoid the SPI pins. Again this French wiki provides nice neat circuit diagrams in EagleCAD format. However, I used pull down resistors, rather than pull-ups, and I used the Arduino shiftIn() function. At first I noticed some very odd behaviour, where the register appeared to be multiplying the input number by 2. I had had a past experience of this, and realised that it was caused by clocking on the wrong edge of the clock. This was easily corrected by making sure that the clock line is raised after the shiftIn(), so that it idles in the HIGH state, not the low state.

Code

Now we look at the code to combine the reading of the input shift registers with writing to the output registers. First we need to define the 6 various pins that carry the control signals:

int sinPin = 5; // Serial input pin from 74HC165 int sclkPin = 6; // Clock pin to 74HC165 int loadPin = 7; // Parallel load pin of 74HC165
int latchPin = 8; // Pin connected to ST_CP of 74HC595 int dataPin = 9; // Pin connected to DS of 74HC595 int clockPin = 10; // Pin connected to SH_CP of 74HC595

and then within setup() - set them up as INPUT or OUTPUT

pinMode(d,OUTPUT);
pinMode(loadPin, OUTPUT);
pinMode(sclkPin, OUTPUT);
pinMode(sinPin, INPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(sclkPin,HIGH);    // initialise the clock HIGH

Once you have set up the pins it's just 4 lines of code to read the inputs

// Read incoming word from 74HC165

digitalWrite(loadPin, LOW); digitalWrite(loadPin, HIGH); int incoming = shiftIn(sinPin, sclkPin, MSBFIRST); digitalWrite(sclkPin,HIGH);

and 3 lines of code to write to the outputs

// and write it out to 74HC595

PORTB &= ~_BV(0); shiftOut(dataPin, clockPin, MSBFIRST, incoming); // shift out the bits: PORTB |= _BV(0);

This sketch is available in full at this Github Gist

Once the signals have been defined and initialised, the code to read and write to the registers is really very trivial. Whilst I have used the shiftIn() and shiftOut() functions provided by Arduino, these functions are also fairly simple and can readily be substituted for routines that directly control the I/O pins - if additional speed is needed.

In the next part I will look at how this shift register functionality can be incorporated into real applications such as stepper motor driving.

More Information

Nick Gammon's tutorial on using the '595

Nick Gammon's tutorial on using the '165

These outline using the shift registers with the SPI bus. This is the next step if you need the fastest speed data transfer.

The flawed Arduino tutorial - do not connect the 1uF capacitor there!! It's supposed to be a 100nF capacitor across the 5V and 0V power pins!

Monday, May 05, 2014

A little more shifty....

Recap

In the previous post, I quickly reviewed the techniques for interfacing shift registers to Arduino based hardware and highlighted some simple code for reading and writing to the external shift registers.

Whilst to some, this may have appeared to be a whistle-stop tour, there is however a wealth of similar information available online and I felt that it would have been of little overall value just repeating the excellent examples and documentation provided by others.

Instead I wanted to get something up and running quickly which would extend the Arduino and act as the basis of a variety of projects, requiring additional input output devices such as LEDs, switches, and actuators such as stepper motors and hobby servos.

I am using the SIMPL language to control the shift registers. If you have not come across SIMPL yet - please see my related blog post, and those going back to May of 2013.

Output to Shift Registers

With my recent experiments with shift registers, I wanted to send a 16 bit word out to a pair of output shift registers to selectively illuminate an array of LEDs.

In SIMPL, I chose the lower case ascii character "r" to represent this output to register function using the following Arduino code:

  case 'r':            // Send an 16 bit byte to the shift register using shiftOut

  PORTB &= ~_BV(0);
  shiftOut(dataPin, clockPin, MSBFIRST, x,8);      // shift out the high bits:
  shiftOut(dataPin, clockPin, MSBFIRST, x);        // shift out the low bits: 
  PORTB |= _BV(0);
  break;

To use this function, you need to supply the 16 bit integer x immediately preceding the r character,

so 0r will turn off all the LEDs and 65535r will turn them all on.

Light Chasers

These are very simple to set up just by turning on the LEDs in a sequence. SIMPL is ideal for this.

We have a SIMPL command "r" which does a 16 bit write to the pair of shift registers.

128r will turn on LED 7, 64r will turn on LED 6 and so on. We can use the millisecond command m, to keep the LEDs lit for, say 100mS.

128r100m64r100m and so on.

So let's define a LED sequence that counts down from the left - ie moves to the Right. We do this using the colon to start a definition - called R

:R 128r100m64r100m32r100m16r100m8r100m4r100m2r100m1r100m

And similarly a LED sequence that moves to the Left

:L 1r100m2r100m4r100m8r100m16r100m32r100m64r100m128r100

Now you can use L and R to make chase sequences

10{LR} - 10 iterations of the Left-right chaser sequence

Stepper Motors

From creating a moving light chaser display, it is a very simple step to controlling the motion of a stepper motor. Rather than turning the LEDs on in a sequence, it is simply a matter of energising the windings of the stepper motor in the correct sequence.

The hardware we will use is available cheaply on ebay, and consists of a small unipolar 5V stepper motor with 64:1 reduction gearbox, and a small circuit board that contains a power driver IC (ULN2003) and usually 4 LEDs.

The stepper motor coils are energised in the following sequence for forwards motion. This sequence of 8 steps is known as a half step sequence :

1 1 and 2 2 2 and 3 3 3 and 4 4 4 and 1

So let's code these into a number sequence that can be sent to the shift register and driver.

1 3 2 6 4 12 8 9

Now let's define a Pause statement, so that we don't have to keep changing the 100m delay when we want to change speed. 100mS may be OK for testing, so as you can see what is going on, but for the real miniature stepper motors, this delay should only be about 1mS.

:P 1m

Now let's code these numbers into definitions F, for Forwards and B for Backwards

:F 1rP3rP2rP6rP4rP12rP8rP9rP

:B 9rP8rP12rP4rP6rP2rP3rP1rP

So we can now use a sequence of F or B to provide forwards or backwards motion

512{F} will produce one complete turn of the motor shaft, because there are 512 steps to a full rotation of the gearbox shaft, and each iteration of "F" produces 4 steps.

At the end of each sequence t might be wise to send a 0r - in order to turn off all of the windings whilst the stepper is idle.

There are other sequences of coil energisation, which are used, sometimes when more torque is needed. A useful link here.

step-fig-3-1.gif (5087 bytes)

step-fig-4-1.gif (10593 bytes)

Input from Shift Registers

To complement the output command q, I wrote a short function to read the input shift registers. Command "t" is used to test the input registers and put the resultant value into x.

In order to display the value x, you need the print command p. So the following construct was used

tp test the input register and print the value to the serial monitor

tq test the input register and display the value on the output LEDs

The code behind the "t" function is as follows:

 case 't':     // test the inputs from 74HC165 shift registers

  digitalWrite(loadPin, LOW);
  digitalWrite(loadPin, HIGH);
  x = shiftIn(sinPin, sclkPin, MSBFIRST);  // Read incoming word from 74HC165
  digitalWrite(sclkPin,HIGH);

  break;

In the next part, I'll be looking at the high power TPIC6B595 and using it to control a pair of stepper motors using SIMPL.

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.

Sunday, June 02, 2013 Extensions to SIMPL In the last week I have been thinking about the user interfaces used on minicomputers of the 1960s, in particular the PDP-8, and wondering if a similar front LED and switch panel could be created cheaply as a nostalgic retro accessory shield for the Arduino.

I have added some LEDs to the 12 available digital I/O pins of the Arduino, so that I can recreate LED chaser and "vintage computer" style displays.

I've extended the SIMPL command set so that I can more easily address each LED in turn, or alternatively treat all twelve as a binary numerical display, to display address or data numbers in the range 0 to 4096.

The latest version of SIMPL can be found here on Github Gist:

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

Just download the Gist and compile it as an Arduino sketch. You can then start typing SIMPL commands using the serial monitor window at 115200 baud. Make sure that you have selected the "Both NL and CR" option for the serial monitor.

Output Commands

In order to gain more immediate access to the I/O, I have added some new commands:

a - sends an analog.Write value to a pin previously named with d b - prints out the current value of the milliseconds counter, allowing loop timing to be calculated c - prints out the current value of the microseconds counter

h - sets a digital pin high eg 6h l - sets a digital pin low eg 13l n - decodes a number up to 4095 and displays it on digital pins 2 to 13 eg 1234n

n can be thought of as a very simple binary display. It has a fast response time and allows the user a simple visible means of checking that a program is executing.

The n command can be useful to examine the characters stored in RAM. Here it is used to output 1000 characters to the LEDs, starting at RAM address 256. The characters are sent every 100mS and also printed to the terminal.

255!1000{y@rn100m}

255! Store 255in y as the starting RAM address 1000{ Perform the loop 1000 times y Increment y each time around the loop @ Move y into x r read the contents of RAM into x n Send the value to the LED display 100m 100mS delay to slow things down to a sensible speed } End of the loop

Decision Making

SIMPL currently lacks the if, then, else decision making, or the switch case structure. This would be a useful addition and I am currently working on some ways of implementing it.

It might be possible to test the x value against certain constants and then execute one of the upper case routines if the test was equal.

Other SIMPL Commands

SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter, which recognises the following:

a Send an analog write (PWM) value to a pin b print out the current milliseconds count c print out the current microseconds count d define a digital port pin e f g h set pin high i read an input j skip next instruction k access the loop counter l set pin low m define a delay in milliseconds n display a number on a line of LEDs o set an output p print the x variable to the terminal q query a block of RAM locations ( as character) r read from RAM s read an analogue input t u define a delay in microseconds v w write to RAM x increment x y increment y (as used in incrementing loop structures)

{} loop the code contained within the braces

@ copy y to x ! store x in y ? Dump the contents of RAM to show the existing words

/ <

Numbers can be typed in the range 0 to 65535 and are stored in the x variable and used to control the above instructions.

eg. 6d define digital port pin 6 100m define a delay of 100mS 10{....} go around a loop 10 times 20p Print 20 to the terminal

To these basic instructions I added a y variable, so that I could do simple maths. You can store a number in y by using the store symbol !

  20!          Stores the value of 20 into y (by transferring it from x)

To get the contents of y back, we use the fetch symbol @

 20!@p      Prints the value of 20 from y

We can do simple addition, subtraction, multiplication and division on x and y

 20!5+p      Adds 20 to 5 and prints result       (x=x+y)

 5!30-p      Subtracts 5 from 30 and prints result  (x=x-y)

 16!8*p     Multiplies 8 by 16 and prints result     (x = x*y)
 
 6!30/p       Divides 30 by 6 and prints result      (x=x/y)

Downloading the SIMPL sketch from Github Gist and programming it into a standard Arduino is the first step to discovering a new way to control physical computing devices.

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, December 29, 2013 The Elements of Language Charles H. Moore is one of my all time computer heroes. He has to be up there amongst Kernighan, Ritchie and Thomson for his contribution to computer languages.

In the 1960s, computer programmer Charles H. Moore developed a new programming language that he called FORTH.

He was convinced that there must be an easier and more productive way to program and interact with a computer and he wanted to create the language tools to do it. Computers at that time were generally mainframes which required the vast resources of assembler, compiler and linker, plus the costly time of specialist computer operators just to generate a program and run it. Moore wanted to develop a self contained programming environment, over which he had complete control, that would allow him to become a more productive programmer. Better programming efficiency would mean less time spent paying for expensive mainframe time.

Moore went on to port FORTH to many different computer systems, and it was also adopted by the homebrew computer community. In the 80's, Moore turned his attention to using FORTH as a machine language, which was executed directly by the microcontroller. He wrote CAD software in FORTH to help him design new ICs, and now in his mid 70's he is still working on state of the art multi-processor arrays which execute a dialect of FORTH.

It is in this spirit that I have spent the last few days tinkering with SIMPL and have borrowed some of the ideas from FORTH. I make no claims that it is a fully fledged programming language, but it does contain all the elements which allow simple programs to be written and run, edited and re-run from the a serial terminal without having to constantly edit and re-compile C code in order to make changes. It allows the user a greater level of interaction with the program so that ideas can quickly be tried out and changes made with just a few keystrokes.

SIMPL is based on a tiny interpreter called txtzyme written by Ward Cunningham. Ward initially wrote txtzyme to run on the Arduino, but as it is written in bog-standard C, it can easily be ported across to other micros. During this Christmas week, I have ported my version of SIMPL across to a STM32F4xx ARM Discovery board.

The original Arduino version of txtzyme only has 9 commands, and allows access to basic input, output and looping and timing functions. The core interpreter is only 90 lines of C code - taking up about 3.6K when compiled for an Arduino. The language is easily extended, as we shall see later.

As stated above, Moore wanted to develop a self contained, comfortable programming environment which involved less typing and a more direct involvement in the program application, rather than the mechanics of compiling and assembling it.

In the same way, SIMPL allows you to perform simple I/O operations directly from the serial terminal, without having to go through the edit-compile-upload cycle every time you wish to make a slight change. Whilst this interactive serial interface makes it easier to experiment directly with the hardware from a serial terminal, the simple character interpreter at the core of txtzyme has much more powerful tricks up it's sleeve.

By way of illustration, I'd like to mention at this stage Java and the Java virtual machine. Basically any computer, be it PC, MAC or Linux, can be programmed to emulate the Java virtual machine. By sending this virtual machine programs in Java bytecode, any platform can be made to run the same software. Whilst this may be an over simplification of Java, it serves to illustrate how vastly differing platforms can be made to run the same programs.

So now apply this to a range of microcontroller hardware platforms. Give them the means to interpret a common language, and then you can get them to run the same programs. If this language is an efficient character based language like txtzyme, then programs can be conveyed to the hardware devices using strings of just a few characters, served from a browser interface. We now have a common language to implement the internet of things, small enough to run on the simplest of 8-bit microcontrollers for the most trivial of applications.

A remote device that is executing one particular program, could easily be reprogrammed with a text string of just a few characters, to execute an entirely different program. This text string could come from a server directly, or via SMS or Twitter or be embedded in a web page or wiki document.

Here, Ward Cunningham explains this concept in a short video

Txtzyme is not only a simple language for microcontrollers to interpret, it is easy to read, write and understand by humans. With each character representing an entire function, a lot can be written in a very short text string.

Take the classic Blinking LED program - say from Arduino, to flash a LED on pin 13, 10 times, for 500mS on and 500mS off. Here it is in C

for(i==0; i<=10; i++) { digitalWrite(13, HIGH); delay(500); digitalWrite(13, LOW); delay(500); }

In txtzyme this becomes just 16 characters:

10{1o500m0o500m}

If you want it to read an ADC channel 5 and print it to the terminal the txtztme is now just three more characters

10{1o500m0o500m5sp}

In C, you would have had to add the following line, recompile and upload again

Serial.println(analogRead(6));

So, to sum up, it's easy to implement the txtzyme interpreter on any micro. It's already available for Arduino, Teensy 1 and 2 and now the STM32F4 Discovery board. Once a micro can interpret txtzyme strings it may be controlled from any browser or from a Wiki, using the txtzyme plug-in.

To be continued.......

Saturday, December 28, 2013 SIMPL on the STM32F4xx Discovery Board Back in the summer, I posted some musings about a very small programming language that I named SIMPL - Serial Interpreted Micro Programming Language. It's an extended version of Ward Cunningham's Txtztme, described as a Nano Interpreter - which is documented here.

Well over the period of the Christmas break, I have had the opportunity to port SIMPL, which is written in fairly standard C, across to the STM32F4 ARM Discovery board. It is now working to the point where I can program simple I/O operations and loops on the Discovery board.

SIMPL is fast on the STM32F4x you can create a pulse as short as 200nS, or toggle a pin on and off at 372kHz. By comparison on the Arduino (using digitalWrite) the pulse time is 10uS and 47.8kHz maximum frequency, though better could be achieved by direct port manipulation.

Ward Cunningham has ported txtzyme to the Teensy board, as a means of controlling hardware over a USB connection, and from a remote server. Ward is using txtzyme to control hardware remotely as part of his Federated Wiki project. A video explaining the project with some demos is here, and well worth a watch for some interesting background.

I've chosen to follow a slightly different route to Ward's project, to use SIMPL more as a programming language, but as the txtzyme interpreter is common to both the Teensy and my ARM implementation, then either hardware can interpret txtzyme strings.

Although SIMPL started off life on an Arduino, it seemed a natural choice to port over to the ARM Discovery board. The additional RAM and program space allow far more elaborate programs to be written, and as the ARM runs at 10 times the clock speed of the Arduino Uno, - the code is blistering quick.

You might recall that SIMPL is based on an interpreter, which interprets serial character strings and decodes them into functions which are executed in turn.

SIMPL generally uses a mix of small characters and punctuation marks as the primitive command set, and then a capital letter can be used in a similar way to a Forth word, to execute a sequence of commands.

Small characters, maths symbols and punctuation marks are used as the primitives. When encountered by the interpreter, they are used to call a function directly, such as p to print a character, or h to set a port line high. The maths symbols are used, obviously to allow maths operations to be executes, such as + - * / and tests such as < and >. The overall simplicity of using a single ascii character as a command, means that the entire interpreter can be coded as a simple switch-case statement in C. For example when h is encountered:

  case 'h':                               // set bit high
  digitalWrite(x, HIGH);
  break;

Where the interpreter encounters a number character 0 to 9, these are scanned in, and accumulated into variable x with the correct decimal place shift, for as long as the next character in the buffer is a number. The following few lines of C perform this number interpretation

  x = ch - '0';
  while (*buf >= '0' && *buf <= '9') {
    x = x*10 + (*buf++ - '0');
  }

Punctuation marks are used to help program flow. For example the open and close brace structure defines a portion of code to be repeated as in a loop. Suppose we want to loop some code 10 times, for example print 10 Green Bottles. The Green Bottles will be printed if it is written thus Green Bottles and the loop structure uses a loop index k, which is decremented each time around the loop. kp will print the current value of k, each time decrementing.

10{kp_Green Bottles_}

Unfortunately p also introduces a newline character, so the output is not quite as desired :-(

Words

In this interpretation scheme, I have reserved the upper case letters to represent "words" - in the Forth sense. In order to maintain the same simplicity in the interpreter, single characters are decoded as calls to the code stored in the word definition. This may sound confusing, so to illustrate with an example.

Suppose I liked the "Green Bottles" code so much, that I wanted to preserve it and use it again, and again. Well I can do this by making it into the form of a colon definition (again borrowed from Forth), such that I can assign it to a memorable word, say B for bottles.

The colon : tells the interpreter that the next character will be a word, followed by the code that will be executed when the word is called

:B 10{kp_Green Bottles_}

This will place the code 10{kp_Green Bottles_} at a location in memory that can be accessed everytime that the interpreter sees the letter B. Instead of interpreting the contents of the keyboard buffer, the interpreter is now pointed to a word buffer, containing the code body that makes up B.

This process can be extended by adding together words to make new words

:A 10{B}

This defines A as ten iterations of B, or about 100 Green Bottles!

The word definitions are stored in a RAM array, and the ? command can be used as a means of listing all the current word definitions.

SIMPL is now starting to take the form of a very concise language. It can handle numbers, character commands from the terminal and perform simple maths. It can perform loops and output numbers and text to the terminal. The next thing is to allow it to access the peripherals and I/O.

SIMPL has been developed to be "close to the hardware". As almost all microcontrollers have a mix of on chip peripherals, such as timers, ADCs, DACs and general purpose I/O, SIMPL has primitive commands designed to exercise this hardware directly.

For example, suppose you have an output port on Port D13 controlling a LED, then the command 13h will turn the LED on and 13l will turn it off, h and l being the commands to set the named port 13, either high or low.

For analogue input from an ADC channel, the command s for "sample" is used. So to read the ADC channel 10 and print to the terminal, we enter 10sp.

Commands can be repeated within loops using the { } loop structure.

To read the ADC channel 10, ten times and print the result to the terminal, we use:

10{10sp}

or to slow this down to once a second, we can delay with the millisecond delay m command which puts a 1000mS pause in the loop.

10{10sp1000m}

We can now put a few of these commands together so as to flash the LED for 100mS each time we take an ADC reading

10{10sp900m13h100m13l}

Note that we are still looping 10 times, reading ADC channel 10 and printing it out, pausing for 900mS, setting LED 13 high, pausing for 100mS, setting the LED low, returning to the start of the loop.

So it's quite easy to build up complex commands, just by concatenating a few primitives together.

What if you were to write this in C? It would be somewhat longer, about 8 to 10 lines of code, and then need to be compiled, tested, and if you weren't happy, edited and compiled again. SIMPL breaks us out of the edit, compile, test cycle, and allows ideas to be tested quickly and easily, straight from the terminal.

This was exactly what Forth language pioneer, Charles Moore realised in the mid-1960s. He too wanted to break free from the edit-compile-test cycle, in order to improve his efficiency in coding, as computer time was expensive back then, and also to make himself no longer reliant on compilers and assemblers that he had no control over. He wanted to develop a self-written, self-contained programming environment that could easily be moved from one system to another, and require few and simple resources to get it running.

If you are interested in the early history of Forth, Charles "Chuck" Moore describes the early development of the language here:

History of Forth

Whilst SIMPL is not Forth, and never will be, there are several nice techniques borrowed from Forth, which are used to enhance SIMPL.

We have come a long way since the early development of the computer languages, such as C and Forth, which were often hosted on very primitive machines, with limited RAM and tiny disks by today's standards.

One early machine, the PDP-8, was of a simple enough architecture, that it has often formed the basis of study in computer science courses. Additionally, the PDP-8 has been implemented in many different technologies over the years, including TTL, VLSI and as a FPGA implemented in Verilog or VHDL.

The reason for interest in the PDP-8, is that whist primitive by machine standards now, it represented a revolution in architecture simplification, such that the whole system could be sold for $18,000 back in 1965. It was the first of the true minicomputers, available at a tenth of the cost of competing systems.

Additionally, the PDP-8, is comparable in resources to those that we find on a low cost microcontroller, costing a few dollars. So the practices used in the 1960s to write code for the early minicomputers has significant relevance these days.

Whilst generally we use open source C compilers, such as GCC, and integrated design environments (IDEs) to develop programs, there is no reason why a simple interpreted language, running in the background would not make sense, when developing applications on a new microcontroller. It puts the control of the hardware, directly at your fingertips and allows quick experimentation.

Modern 32 bit microcontrollers, such as the ARM range of cores, are now rapidly replacing 8-bit devices in a range of applications, at very little additional extra cost. The resources and peripherals available on a typical ARM device, are vast compared to 8-bit processors, and with clock speeds roughly ten times faster, a huge amount of processing power is available, compared to only a few years ago.

With clock speeds in the 100-200MHz range, it's now perfectly possible to host an interpreted language on the microcontroller, and have it run at speeds only previously available through the compiled language route.

SIMPL consists of an interpreter running within a loop. The interpreter is written in about 300 lines of standard C, and additionally includes several I/O and memory functions, which are tailored to the particular microcontroller, to create a standardised machine model.

To the Arduino user, these I/O routines will be familiar:

digitaRead Read the state of a digital input digitalWrite Write a digital output high or low analogRead Read the value of an ADC channel analogWrite Write a value to an analogue PWM or DAC channel delayMilliseconds generate a delay in mS delayMicroseconds generate a delay in uS printNum print an integer number to the terminal putChar print an ASCII character to the terminal getChar read an ASCII character from the keyboard or terminal input buffer

All microcontrollers for embedded applications should have the hardware means to execute these routines, and although setting up the I/O and peripherals may take a bit of time on an unfamiliar hardware device, once done the basic routines will be used frequently in any application that may be developed.

delayMilliseconds can simply be derived from 1000 times around the delayMicroseconds loop, or can be derived from a hardware timer, depending on the device.

Whilst putChar would normally send a character to the UART transmit buffer, it might instead be used to bit-bang an output pin, if no UART is available. Fortunately most microcontrollers have one or more UARTs available these days, so bit-banged serial comms is less of a requirement.

printNum is just a convenient means of getting integer numerical output from the microcontroller. It will use the C routine "integer to ASCII" and putChar to send an integer to the terminal.

getChar is intended to read in a character at a time either directly from the keyboard or from the terminal input buffer.

With these routines, you can now interface to a serial terminal, read and write to I/O lines, read analogue inputs and control PWM or DAC outputs. With the ability to specify accurate delays to give a sense of timing to the program flow, there is little else that the micro needs to do, except perhaps for memory operations.

Thanks for the Memory

In bygone days, when microcontrollers had very little memory, it was easy to get obsessed about the placement of code and data within memory. Memory was a precious commodity, and it was necessary to squeeze your program and your data into what little memory was available. Every byte was precious, so clever tricks were devised to pack data into as few bytes as possible.

These days, this is not so much of a problem. The STM32F407 has a 1Mbyte flash for program and storage of constant data, and 196Kbytes of SRAM, 4Kbytes of which can be battery backed and made non-volatile. Other STM32F4xx family members have 2Mbyte of flash and 256Kbytes of SRAM. This might not seem much by PC standards, but for an embedded application it is more than plenty.

To be continued.

Saturday, June 01, 2013 Extending SIMPL and flashing a few LEDs I have been experimenting with SIMPL, and have added a few new commands to give it greater functionality.

I've wired Digital outputs 2 to 13 to a line of 12 LEDs, to give a very simple means of displaying numerical values. It also allows LED chaser displays to be tinkered with.

I have added a command to allow the analogWrite function to control an output pin.

Name the pin first, e.g. 6d and then the PWM value such as 127a This sets the PWM to about 50% duty cycle.

I've also been investigating how fast the commands run, so added a couple of timing commands b and c. b prints the current value of the millisecond counter millis(), so typing b before and after a list of instructions will allow you to calculate how many milliseconds it took to execute. c does the same, but uses the microseconds counter micros().

By timing 10000 cycles of a loop, I can show that SIMPL will add two 16 bit integers in about 6 microseconds.

I have added some commands for easier control of the I/O. h and l are now used to set a port pin high or low eg. typing 6h and 5l will immediately set those pins high and low.

After my experiments with LED chaser displays, I also wanted a way to immediately write an 8 bit number to 8 consecutive LEDS. So the "n" command displays a number on a row of LEDs.

Typing 255n will turn all the LEDs on Digital 2 to Digital 9.

To make incrementing loops easier, the command "x" now increments x and "y" increments y.

0!10{y@p}

This prints out the numbers from 1 to 10. 0! sets y to zero, y increments the y variable.

The q, r and w commands have been used to access the RAM.

300r will print the character stored at address 300.

SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter. SIMPL now recognises the following lower case instructions:

a Send an analog write (PWM) value to a pin b print out the current milliseconds count c print out the current microseconds count d define a digital port pin e f g h set pin high i read an input j skip next instruction k access the loop counter l set pin low m define a delay in milliseconds n display a number on a line of LEDs o set an output p print the x variable to the terminal q query a block of RAM locations ( as character) r read from RAM s read an analogue input t u define a delay in microseconds v w write to RAM x increment x y increment y (as used in loop structures)

{} loop the code contained within the braces

@ copy y to x ! store x in y ? Dump the contents of RAM to show the existing words

  •   Add x and y
    
  •    Subtract x and y
    
  •   Multiply x and y
    

/ Divide x and y < Is y < x

  Is y > x

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

Txyzyme 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. This process happens automatically and we don't have to concern ourselves about the exact address that holds T.

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 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.

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.

⚠️ **GitHub.com Fallback** ⚠️