Showing posts with label SIMPL. Show all posts
Showing posts with label SIMPL. Show all posts

Wednesday, March 09, 2016

Porting SIMPL to the MSP430FR4133 Launchpad.

For the last few days I have been using the entry level, MSP430G2553 Launchpad for my code development.

This was fine to begin with for basic experimentation with functions, but ultimately I knew that my proposed application would probably use on of the larger FRAM based parts, with built-in segment LCD controller.

The MSP430FR4133 Launchpad is excellent value at about $16 and it comes with a 6-digit multi-segment display,  similar break-out headers to the entry level Launchpad and the means to monitor the mcu power consumption - using Energy Trace Technology.

My final application is a hand-held, battery powered instrument with LCD - so the MSP430FR4133 target is a good hardware match to the final device.

The MSP430FR4133 has 15360 bytes of FRAM memory for program storage, plus an additional 512 bytes for Information (calibration data, Identity etc). There is also 2Kbytes of RAM.

The extra RAM means that SIMPL can be run easily in the RAMspace without having to use the external RAM - most of the time.   This makes the user interaction with SIMPL a lot easier, and also allows more functionality to be included.


Porting SIMPL to MSP430FR4133

The following steps had to be performed to get SIMPL to run on the '4133 Launchpad.

1.  Increase the RAM allocation to make ful use of the 2Kbytes of RAM
2.  Convert the uart routines to work with USCA0
3.  Convert the spi routines  to work with USCB0
4.  Modify the ADC initialisation code to work with the onchip ADC_10
5.  Correct the interrupt timer routines so that millis() and micros() work correctly
6.  Make use of the LCD by diverting some printout to it


The code is still a work in progress, with 1, 2 & 3 above, working, and a little progress on 6  - but I have posted the latest code here on this Github Gist.

Monday, March 07, 2016

SIMPLEX - Part 2 - Running SIMPL Code out of External RAM

Running SIMPL Code out of External RAM

In part 1 I looked at the bulk access to the RAM chip using streaming mode - which takes about 3uS to access a byte.  With single byte access, there is the significant overhead of setting up the read instruction and the 24 bit address - making an access about 100uS.

For this reason, I propose a block access mode which loads in a block of 32 bytes into the SIMPL input buffer and executes the code at full speed from there.

Reading in 32 bytes in streaming mode will take around 100uS and then the code will execute at full speed out of internal RAM.

Writing some Commands

A   Assemble
B   Block Read
C   Compile
D   Decimal Dump
E    Execute (Read and Go combined)
F    File
G   Go
H   Hex Dump

We need a simple routine to load a block from RAM - based on the existing bulk read.

I use the  B command to signify a Block Read - and it takes a integer block number and loads the block into a temporary internal RAM buffer called block_array[]

Once the data is in the block_array buffer, it's a simple case of pointing the interpreter at the start of that buffer and letting it execute the code.

To initiate this process, I use the G  (Go) command.

The great thing about SIMPL is that the commands can be concatenated along a line  so to load and run Block 0 you just need to type  0BG.  You can then string these together so that multiple blocks are executed one after another  0BG1BG3BG2G  etc

We could now dispense with the BG construct, and just call it E for Execute.

SIMPL has grown a lot today - and even as I author it, there's a lot of new information and excitement to take in.  It's been a long but rewarding day getting the external RAM to work with SIMPL.

The latest code - with the ability to run code out of SRAM is on this github gist

In the next part, I look at data entry into the RAM and making a simple line editor.




Sunday, March 06, 2016

SIMPL meet SIMPLEX - Part 1 - Putting it Together



SIMPLEX - the EXtended Version Of SIMPL

So I took SIMPL running on a LaunchPad, and added a 23K256 RAM chip with 6 jumper wires and a 10K resistor:



Overall View

I'm probably infringing a whole bunch of trademarks but the EXtended version of SIMPL which uses the EXternal SPI RAM will be called SIMPLEX. 

Now that's what I call subtle! With a touch of irony.

With the RAM expansion comes the need to examine and modify its contents, and so I have written a bit of code to allow the contends of the RAM to be dumped to the screen in both decimal and hexadecimal formats, with ASCII equivalent in a separate column.

Whilst the SIMPL kernel code fits into 2Kbytes - and as such may be considered as a smart interactive bootloader, the high level routines to manipulate the RAM extend this limit quite considerably.

The code I have produced is "quick and dirty"  C, and I am sure it could be written more succinctly at a later date.

The decimal-dump D and hex-dump H commands are the start of a new group of high level commands to handle external memory, editing etc.

30 or so years ago, "monitor" programs were common place on the early 8-bit micros. They allowed for the direct editing of data within the RAM space of the memory map - and were a means of entering programs - one hex byte at a time.  It was a welcome step up from toggle switches!

The "Editor"  will use the first 8 commands of the User Words, signified by letters A through to H, each representing a high level operation.  One allocation of these is as follows:

A           Assemble
B           Block
C           Compile
D           Decimal Dump
E           Edit
F           File
G          Go   (execute from RAM)
H          Hex Dump

Several of these are really just place-holders for yet to be written command functionality.

The first task of being able to examine the RAM contents has been undertaken, now its time to start looking at the process of getting code into the RAM area and then executing it from RAM.

The 23K256 has a page size of 32 bytes, which is a useful size for a phrase of SIMPL code.

Looking at the Block B and File F commands above, the block command can be used to manipulate the memory 32 bytes at a time - effectively a line of SIMPL code, whilst the File command can be used for handling multiple blocks. 

The hexadecimal conversion is used both for 2 digit (<= 255) and 4-digit (256 <=  x <= 65535) conversions.

I have includes a SIMPL primitive   $  which takes an integer x and converts it to either 2 digit or 4 digit hex.

The dump formats make use of the modern wider terminal screen.  1K of RAM can be dumped to a single screen - of 32 lines of 32  hex bytes.


The Hex -Dump as it appears on Termite Screen. 1K bytes of RAM data shown per screen



I have put the code for SIMPLEX_1 on this Github Gist  Please note that the UART is running at a non-standard 100Kbaud instead of 115200.  This is to be investigated later. 

In the next post, I'll look at more RAM operations plus actually running SIMPL code out of the external SPI RAM.




SIMPL for Beginners - Part 1

It's almost 3 years since I started on the SIMPL project, it has come a long way since it's early beginnings.

This first post, in a series,  is a "catch-up" for those that have come late to the party.

Introduction to SIMPL

0. SIMPL stands for Serial Interpreted Minimal Programming Language. It is intended as a common, interactive hardware exercising language that will run on almost any low-end, resource limited, microcontroller.

So far it has been implemented on the following microcontroller platforms

Arduino
ATmega328
ATmega1284P

Nucleo
RFDuino         nRF51822  Cortex M0
STM32F103  Cortex M3
STM32F373  Cortex M4F
STM32F407  Cortex M4F
STM32F746  CCortex M7

LaunchPad
MSP430G2553
MSP430FR5969
MSP430FR5739

Teensy 3.0, 3.1, 3.2
MK20DX256

Future development will include PIC16Fxxxx and PIC32MX devices too - made accessible using Pinguino - an Arduino-like IDE for PICs.

1. SIMPL is based, unashamedly on Ward Cunningham's excellent Txtzyme "Nano-Interpreter".  You can find his work on his Txtzyme Github   This should be the starting point of any SIMPL development. First you port the C code of Txtzyme across to whatever microcontroller you wish to use.  Once you have Txtzyme working on your mcu, you can then start to extend it's functionality to include the whole SIMPL featureset.

2. SIMPL is a text-based interpretive tiny language, which interacts with the onchip hardware allowing simple applications to be developed for a variety of very low cost microcontrollers. It fits into about 2Kbytes of Flash and requires a minimum of 512bytes of RAM - so it will work on the smallest of RAM limited microcontrollers.  It needs a uart connection to a PC terminal program - for text input and output. It is primarily aimed at 14 -28 pin low end microcontrollers - but of course, will run on larger parts.

3. SIMPL originally ran on Arduino. It makes use of the Arduino "Wiring" functions - such as digitalRead, digitalWrite, analogRead, analogWrite, millis, micros, delay, delayMicroseconds and Serial. Provided that your microcontroller can offer similar functions to these, SIMPL will work. SIMPL also runs on the Teensy series of mcu boards.

4. SIMPL can be developed for other microcontrollers - including ARM, MSP430, RFDuino, ESP8266 etc using the "Arduino-like" IDEs  such as STM32Duino or Energia for MSP430 and Pinguino for PIC devices. These alternative IDEs will help you with the various "Wiring" functions.

5. SIMPL has been written in C, to make it portable between various microcontrollers. It uses standard Arduino functions to interact with the hardware - which are perhaps not always the smallest or fastest.  These functions can be rewritten for a particular microcontroller to make them both smaler in codesize, more efficient and faster.

6. SIMPL is not a polished final product, but it offers a framework for experimentation and education.  As new hardware or ideas come along, SIMPL can be extended to incorporate them.  The core ideas of SIMPL are easy to understand, and it gives a good insight into how computer languages are written to interact with the hardware.

7.  SIMPL has been developed with the same methodology as some of the tiny languages from the mid-1970s - when computing resources were very limited.  Tiny BASIC, and FORTH grew out of this period.

8. SIMPL can be easily extended to allow for external SPI or I2C peripherals - such as SRAM, sensors.

9. SIMPL needs almost no tools to develop code.  Just IDE with serial terminal.

10. Enjoy SIMPL, extend and modify it if you wish - most of all, have fun!


The Command Set

SIMPL uses single ASCII characters for its commands and integer numbers for arithmetic - this makes the command interpreter a lot easier to write.

Lower Case characters are used for the core primitive functions which are generally built into Flash, and should be present for every implementation of SIMPL.

Punctuation characters and arithmetical symbols are also used as part of the kernel of  primitives.

The choice of primitives was made to make the language memorable and more human readable.

Upper Case characters are "User Words"  - these you can write yourself, test interactively, modify and store in RAM.  On some microcontrollers - they may be stored in non-volatile ferro-electric memory FRAM (MSP430FR series)  or in non-volatile EEprom.

Originally Txtzyme offered just these commands - see Ward Cunningham's Read Me:

a-f      Select an I/O port
h        help - a summary of commands
i         input
k        a loop counter - which decrements each time around the loop  see {}
m       millisecond delay
o       output
p       print the value of variable x followed by carriage return/line feed
s       sample an ADC channel
u       microsecond delay
x       a 16 bit integer variable
{}     code between these braces is repeated as a loop
_ _    characters between the underscores are printed to the terminal

Once you have got Txtzyme ported across to your microcontroller, and have experimented with it, you are well on your way to working with SIMPL.

In the next part I look at how Txtzyme is extended to include the SIMPL framework.

It is likely that this series will be included on a SIMPL wiki - so that all the information is accessible in one place.

Monday, February 01, 2016

A Review of Tiny Languages - Part 3

Last time I explained how to add more functionality to Txtzyme to build up a more versatile language that I call SIMPL.

In this post I look at a couple of ways to perform program flow control.

The latest version of SIMPL is located at this Github Gist  - and includes the code below.

The 16 bit maths version compilese to 2268 bytes, whilst the 32 bit version, with it's more complicated 32bit maths routines adds a further 624 bytes.


Program Flow Control

So far, SIMPL lacks many of the usual program flow control constructs:

IF-THEN-ELSE

FOR-NEXT

DO-WHILE

SWITCH - CASE


1. Simple Loop

SIMPL has a simple loop construct - where a block of code can be repeated k times before exiting the loop.

10{kp_ Green Bottles_}

This initialises the loop counter k to 10, and prints it out along with the text Green Bottles, decrementing k each time it goes around the loop.

This is similar to C's    while(k)      // k>0
                                 { some task;
                                  k-- ;
                                 }

When executed, you will get this screen output:

9 Green Bottles
8 Green Bottles
7 Green Bottles
6 Green Bottles
5 Green Bottles
4 Green Bottles
3 Green Bottles
2 Green Bottles
1 Green Bottles
0 Green Bottles

ok

It is also reminiscent of the old Z80 instruction DJNZ, in which the B register was decremented and a relative jump to a label if it was non-zero.  In SIMPL we effectively have 26 labels - the capital letters A to Z so this could be quite a useful feature.   Loop can be used for any repetitive output task - such as flashing LEDs or playing musical tones.

The next construct required is the conditional jump.  Here the number on the top of the stack, x should be compared against a constant y and a call to a block of code executed whilst the comparison remains true.

We have the means to perform logical and comparison operations on the top value of the stack.

AND   &
OR      |
XOR   ^

These perform bitwise logic on the x and y operands.

AND may be used to check if  x != 0   as it returns 1 for any value of x other than zero
OR can check if x = 0
XOR  can check if x != y

Greater Than  >   if  x > y  return 1
Less Than      <   if x  < y  return 1

Any of these operations may combined with a skip operation - skipping over the next operation if the result is true.

Here's the C implementation of the  SIMPL comparison and jump operators:

// Comparison Test and conditional Group
   
      case '<':
      if(x       break;
   
      case '>':
      if(x > y){x=1;}      // If x > y x= 1 - can be combined with jump j
      else x=0;
      break;
   
      case 'j':                  // test  if x = 1 and jump next instruction  
      if(x==1){*buf++;}  
      break;


So we want to turn these simple comparisons into a more familiar IF-THEN construct.

The block of code to conditionally execute will be enclosed within square brackets  [   ]

If the result if the comparison is true - then the code withing the brackets is executed, if false, the interpreter skips the words until it finds the last bracket and then resumes execution there.

Example   If x > 10 then print "x greater than 10 "

11 10 >[_x greater than 10_]

11 assigns 11 to x 
"space" moves x to y
10 assigns 10 to x 
>  performs x >y
[   tests x for true
_x greater than 10_   prints the message
]  marks the end of the conditional execution block


Case Selection

The switch-case statement is a powerful mechanism in C, can it be easily implement in SIMPL?

We could restrict the number of cases to 26, allowing any of the capital letter words to be accessed directly.

Alternatively, we could select a phrase of code from a list of options - based on the value of x. This second methods is more general and is a lot more flexible, as it can incorporate the first method.

We need a pair of balanced characters to instruct the interpreter that we are looking at a list -  so we could use simple parentheses and comma separated elements as follows (, , ,)

We then do a selection of the elements based on the numerical value of x.  The interpreter then jumps into the array, skipping over the entries until the correct one is found.

As an example, the word M is code for _This is a test Message_

5(0p,1p,2p,3p,4p,M,6p)  should select M and print the associated message

A second example adds two integers and prints the message if the result is 3

1 2+(0p,1p,2p,M,4p,5p,6p)

The mechanism to do the skipping can be quite elegant using some simple rules:

First, the value of x is copied into the loop-counter variable k.
If k > 0 the interpreter checks each character in turn incrementing the buffer pointer. If a comma is detected, signifying the end of the first list entry , k is decremented.
If k is zero, the interpreter executes the following table entries until the next comma is detected, this also subtracts one from k forcing it to be less than zero, this condition then forces a break out of the list.  If the final ) is found - this also forces a break out of the selection statement.

This construct is derived from the SIMPL Loop method. We provide C code for two new case statements "(" and ","

// Select the xth member from the list
// Example 5(0p,1p,2p,3p,4p,5p,6p)  should select 5 and print it

 case '(':

      k = x;                                                 // copy x to use as the "phrase counter"                                                              
      while (k)
      {
      ch = *buf++;
      if (ch == ',')                                       // decrement k to see whether to interpret or not
      { k--;}    
      }  
      break;
   
      case ',':
   
      k--;                                          
      while (k<0 nbsp="" y="">

      {
      ch = *buf++;                                    // skip the remaining characters
      if (ch == ')') {break;}
      }
   
      break;

This technique could also be used as a look up table, where a given x is converted into a different value according to a list of numbers.

10(1,2,3,4,5,6,7,8,100,200,300,400)p

This will select element 10 (300) and print it. Note that the first element is zero!




Sunday, January 31, 2016

A Review of Tiny Languages - Part 2

Tiny Languages - for Tiny Boards!
It's a couple of weeks since the first part of this thread reviewing some Tiny Languages where I looked at some minimal BASIC and Forth-like languages.

Inspired by these examples,  I wish to show how Ward Cunningham's Txtzyme interpreted language can be easily modified adding more features and functionality.

The aim is to have a tiny, generic language that can be embedded into the bootloader of any common microcontroller - providing a minimal operating environment from start-up.

What will such a Tiny Language require in terms of features and functionality?

Wish List

Any small language must provide a minimum vocabulary to be useful.  Here are some thoughts on the bare essentials:

Arithmetic and Logical Operations   + - * /   AND, OR , XOR, INV
Memory Operations - including loading, storing, saving to disk, and bootloading the flash or EEprom
Program flow control - decision making - branching  (IF, THEN, ELSE, SWITCH-CASE etc)
Looping  (DO WHILE,   FOR- NEXT etc)
I/O commands  (digital read/write  analogue read, pwm, etc).
Timing, delays, and scheduling operations (mS_delay, uS_delay, millis()  etc)
Peripheral support - eg UART, SRAM,  uSD, keyboard, mouse, graphics etc.

We also need as a minimum of system support for the language kernel:

Keyboard for text entry,
Terminal output  (serial UART routines)
Text Editing  (line editor)
Hex Dump
Screen listing of code in RAM

With these facilities we can at least enter, edit and run code using a serial terminal application and get output text to screen.

At a higher level - for a stand alone computing environment we need permanent storage to disk and some tools to make life easier:

Assembler
Compiler
Disk operations, File Handling (on microSD card)
Graphical output to monitor.


SIMPL

Txtzyme offers a small, understandable, elegant and flexible core with UART communications, analog and digital input and output and delays and timing functions. It is almost the ideal platform on which to base other code.  I have prepared a stripped down version of the Txtzyme interpreter kernel - which compiles to just 658 bytes. It is available here.

At the moment the cut down kernel doesn't do very much apart from allow a decimal number to be printed out using  the "p" command. However, it represents about the minimum needed to support a UART interface, scan a text buffer and execute commands.  Additional commands are added in the switch-case statement within the textEval() function.

This led me to a series of experiments in which the features of Txtzyme were extended - which resulted in SIMPL (Serial Interpreted Minimal Programming Language).

SIMPL has been ported to several microcontrollers - including MSP430, STM32F103, STM32F373, ' 407 and '746 - as well as an FPGA softcore processor called "ZPUino".

SIMPL offers an easy way to interact with hardware, to compose new functions and to schedule functions to be triggered either sequentially or at regular intervals.  It is based on the Txtzyme core functionality - about 1Kbytes which gives a basic communications channel, text entry and display and the means to exercise common microcontroller hardware peripherals.

Adding Maths and Logic Operations

Txtzyme only used a single 16 bit integer variable x, as a control parameter for the coded functions. Whilst this was OK for running loops, reading the ADC channels and toggling I/O it was a little restrictive.

The first extension to Txtzyme was to create the means to have a second variable y.  This immediately allows simple mathematical and logic operations to be performed.

Arithmetical    + - * /  %
Logical            AND OR XOR NOT  
Comparison    < >

In Txtzyme, typing a number at the keyboard, with a serial terminal application causes the interpreter to decode the number's ascii string and place the number into the single parameter variable x.  x can then be used to access I/0, set up loops and delays and other functions.

In SIMPL,  there is a second parameter variable y, and this is used to hold a second operand.

Typing

456 123+p  (note the space between 456 and 123)

This pushes 456 into x and then the space is SIMPLs method of moving x into y, so that the interpreter is free to accept the second number 123 into x. In the above example  123 is added to 456 in x and the result printed with p.

This arrangement is a kind of pseudo-stack of just 2 levels x and y, and note that unlike a true stack, y does not move up to occupy x when x is printed out.  Perhaps it should be thought of a s a machine with 2 registers  x and y, and "space"  is equivalent to mov x,y.

Additional registers could be added but there is  the complication of naming them.

With 2 registers we can now do simple maths, memory addressing and logical and comparison operations.

The addition of these arithmetical and logical operators adds a further 360 bytes to the kernel.  This seems quite a lot for just 9 functions - and so at this point I began wondering whether the extensions to the kernel might be best done in AVR assembly language.  You may recall that an AVR instruction takes up 2 bytes of flash memory - so my C code case statement selection structure is using on average 20 instructions (40 bytes) per command.  (MUL, DIV and MOD will be more).

Whilst Txtzyme was purely a 16bit implementation, if x and y are cast as long integers, then all operations are extended to 32 bit. This however increases the code size by around 625 bytes (as the 32  bit mats operations all take up more code to implement in C).

It would be possible to make a more compact version of SIMPL by coding up the routines in AVR assembly language rather than C. Having studied the TinyForth code structure - the primitive execution structure is coded such that the commands occupy an average of 24 bytes (for 29 commands).  This would result in a 40% reduction in codesize - so is well worth considering.  The topic of coding SIMPL for assembly language plus an analysis of the SIMPL virtual machine will be covered in a later post. It might just be time to fire up Atmel Studio and start writing some AVR assembly code!

Memory Operations

In keeping with Forth parlance  the basic memory operations are Fetch @ and Store !  These effectively are the equivalent of Peek and Poke - and operate on a 16 bit wordsize. With fetch and store there is now the means to take a number off the stack and place it anywhere in RAM, or conversely take a word from RAM and place it on the top of the stack.  The exact location of the storage could be derived from a variable's name, or it could be in a set of easily accessed named registers, eg. R0, R1, R2.....

Text Input and Output

Txtzyme offered a very simple mechanism of loading up a character buffer with the inputted text from the UART serial communications. It would carry on filling the input buffer until a newline character was found, or the end of the buffer was reached.  The input buffer essentially held the whole Txtzyme phrase, and on detecting the newline character would begin to interpret each character in turn, decoding it and calling the various functions associated with each character.

When I wrote the first draft of SIMPL, I realised that I could store the inputted characters into any buffer I wished, by redirecting the input characters to a new named buffer.  I used uppercase ASCII letters for these buffers, named A through to Z.  When I wanted to redirect the input characters to a new named buffer, all I had to do was use a colon : at the start of the line, followed by the naming character  - eg M.

:M   - the start of a new buffer called M

I chose for convenience to make all of these buffers the same fixed length (48 bytes), so that the start address of the buffer could easily be calculated from the ASCII code of the letter.

In this example M is code 77 in ASCII, and A is 65, so it's easy to allocate 48 byte buffers, just by multiplying up the ASCII value by the 48 byte length of the buffer, (plus an offset).

It becomes clear that these named buffers are in their own right small snippets of code - in effect subroutines, and in order to execute the subroutine it's just a case of typing it's naming letter.

Txtzyme subroutines are by their very nature quite short, and it was easy to fit almost everything that might conceivably wish to be done into a few tens of characters - hence it was found that 48 was a good size for the buffer - especially when the Arduino only has 2K of RAM to play in.

Forth readers will recognise this as a very crude means of creating a colon definition, storing the definitions executable code at a fixed address in memory - based on the ASCII name of the routine, and being able to effect a simple jump of the interpreter to that routine.  It's a little like the restart RSTxx instructions on the Z80/8080.  A few restart addresses that the program counter could be set to, in order to quickly call the most commonly used subroutines.  In our case we have 26 to make full use of!

A "line printing" command to print out a string of the stored text from memory is the underscore character _  This is used as a pair surrounding the text message to be output for example

_This is a message_

We could include this with the previously defined "M"  as follows

:M_This is a message_

The text handler would save this in the buffer associate with M, and every time the interpreter encountered the letter M it would print out the message

This is a message

Displaying and Editing Text

In a microcontroller system with only 2Kbytes of RAM, much of this can be taken up with the screen buffer - after all a 25 line x 80 column screen is 2000 bytes!

In a language such as Txtzyme and SIMPL, the source code has been tailored to consist of printable ASCII characters, with some degree of human readability.  The system can easily perform a memory dump to the screen - which is effectively a program listing.

As the program consists of short subroutines threaded together, it would be possible to have a single stepping mode, where a cursor is highlighted as it steps through the current code. With a 115200 baud serial connection, the whole screen of text could be refreshed 5 times per second, more if only the active code is displayed.

Editing text is probably best done on a line by line basis.  A line that requires editing can be brought up using the ? command and then copied into the input buffer, changes made and then pasted back to memory.

Some Forth systems use 1Kbyte blocks for storing and presenting their source code. A similar approach could be employed with SIMPL, with a block command to bring up a numbered block to the screen.

SIMPL is expressed as a series of tokens for compactness in memory and convenience of not having to scan for whole words - however there is no reason why it could be expanded to a more verbose format for screen listings - for example each lower case ASCII character could be expanded to a more easily read format.  The table to do this would be retained in flash ROM - something that there is no real shortage of.  For example:

a    ANALOG
b    BLOCK
c    CALL
d    DIGITAL
e     END
f     FOR
g    GOTO
h    HIGH
i     INPUT
j     JUMP
k    COUNT
l     LOW
m   mS_DELAY
n    NUMBER
o    OUTPUT
p    PRINT
q    QUIT
r     RETURN
s     SAVE
t     TIME
u    uS_DELAY
v    VARIABLE
w   WHILE
x    1st operand
y    2nd operand
z    SLEEP

All of these will fit into 8 characters - so the additional space needed for the verbose form is 26x8 = 208 bytes


In Summary - So Far

So we have a language largely represented by single character instructions which when decoded by the interpreter cause a jump to a subroutine that defines the program's action. These character command words may then be assembled into sequences or phrases and stored into named buffer spaces for execution. New phrases may be compiled and stored at fixed addresses for later interpretation and execution.  There is the means to enter and retrieve text from the RAM either by loading and storing single characters or numbers, or by using the text handler and the string printing command.

In Part 3 we look at the program flow control structures like LOOPS, SWITCH-CASE and constructs made up from conditional jumps.


Sunday, January 17, 2016

A Simple Computing Platform

Is this how modern computers appear to users - even experts? 

It is becoming ever increasingly clear to me - and others, that computing platforms have become just too complex. In an attempt to be all things to all users they are built on a massive agglomerate of software, some which has it's roots in the 1960s, and most people have forgotten why it was there in the first place. Literally they have become a tower of Babel

Reading the Wikipedia entry - the Tower of  Babel was a huge edifice - so big that no-one really knew how big it was. Ironically it was created, so that everyone living in Babel could speak the same language.  According to the myth, the big chap upstairs didn't like this, and confounded the people's speech, so they could no longer understand each other. He then destroyed the tower and sent it's residents scattering to the four corners of the world, and this led to the diversification of language.

Loosely applying this myth - as an analogy of the current state of the computing industry - we are now trying to recreate a Tower of Babel, as a concretion or conglomeration of thousands of different software modules 20+ million lines of code, 1200 developers/contributors, loosely tied together in a Linux wrapper - in the hope that they somehow will fuse to form a unified entity.

Well just as Babel ultimately failed, I believe that our current strategy of building vast megalithic operating systems - then spending all our time worshiping them, is a road to ruin.

Like I might say to a historical resident of Easter Island "Keep on carving the stone heads, Dude,  - just wait and see exactly where that gets you!".

Here's a breakdown of a recent image of the Debian distribution:

=============================================
    Item           Lines             %
=============================================
  ./usr                 845        0.0042
  ./init              5,739        0.0283
  ./samples           8,758        0.0432
  ./ipc               8,926        0.0440
  ./virt             10,701        0.0527
  ./block            37,845        0.1865
  ./security         74,844        0.3688
  ./crypto           90,327        0.4451
  ./scripts          91,474        0.4507
  ./lib             109,466        0.5394
  ./mm              110,035        0.5422
  ./firmware        129,084        0.6361
  ./tools           232,123        1.1438
  ./kernel          246,369        1.2140
  ./Documentation   569,944        2.8085
  ./include         715,349        3.5250
  ./sound           886,892        4.3703
  ./net             899,167        4.4307
  ./fs            1,179,220        5.8107
  ./arch          3,398,176       16.7449
  ./drivers      11,488,536       56.6110
=============================================
A massive 20.3 million lines of code! As you can see, the Linux kernel is just 1.2% of this total.  It is the drivers - for every conceivable peripheral, and every conceivable processor that makes up the bulk of the bloatware.

Don't get me wrong, Linux plays a very important part of the modern digital infrastructure - but this colossal edifice may eventually collapse under it's own weight.

What about small embedded systems - traditionally coded in C and running from Flash? These high end microcontrollers are generally limited to 1Mbyte of Flash and 0.5Mbyte RAM and clock frequencies of <300mhz .="" p="">
So, if you, like me, are fed up dealing with 15 gigabytes of someone else's software in multiple non-compatible languages then this recent article from "The Register" may be of interest.

Project Oberon

This was an ambitious project started in 1985 to create a simple workstation with it's own lightweight language and operating system called Oberon - a successor to Pascal / Modula 2.  The chief designer was Niklaus Wirth - who also was the creator of Pascal, Modula 2 and other languages.  Here's Wirth's presentation of the historical perspectives of the project.

Oberon is not only a language, but an Operating System that includes a compiler. Remarkably the whole Oberon System, when loaded fits into 110kbytes - making it an ideal fit for smaller cpus with limited amounts of RAM.

Below are the line counts for the various Oberon System modules:

                     LOC.                    %

MenuViewers          208                   4.89
Viewers              216 (outer core)      5.08
Modules (loader)     226                   5.32
Edit                 233                   5.48
Kernel               271 (inner core)      6.38
FileDir              352                   8.28
Oberon               411                   9.67
System               420                   9.88
Files                505                  11.88
Texts                532                  12.52
TextFrames           874                  20.57

Total               4248

Adding these up we see that the whole Oberon System consists of 4248 lines of code!  That's consideraby less than the Linux ./init code. and approximately 1/5000th of the Linux distribution. You will also notice that each module is roughly 5% to 20% of the total.

One reason why this is possible is that the Oberon System has been tailored for one particular - and very simple hardware platform and it is so it is not having to cater for every different processor or peripheral device on the planet.

The Oberon Platform

Originally (1988) the Oberon Platform (Ceres) was based on the NS32532 processor.  This was a 25MHz 32bit processor - one of the first 32 bit devices commercially available.  It had a performance roughly equivalent to twice that of an i386 for the same clock frequency.

Fast forwarding to 2013, Project Oberon has been recreated in the form of a low cost "OberonStation" using an inexpensive Xilinx Spartan 6 FPGA - accomplished by Paul Reed and Victor Yurkovsky - a regular FPGA Blogger.

In this Xilinx Journal "Xperiment",   Niklaus Wirth writes about the FPGA implementation.  He also describes a new hardware description language called "Lola 2" which allows FPGA hardware to be designed on a Oberon Workstation and then cross-compiled into Verilog - from where it can be imported into the usual FPGA development toolchain.

The Oberon Station - Spartan 6 FPGA plus 256Kx32bit SRAMS

If you wish to look further at Project Oberon - a pdf of the 2013 Book is available - with html index here.

Thoughts- and Questions on OberonStation

Less is more - this hones down a workstation to the level of complexity where any one can understand the hardware.  It is reminiscent of Chuck Moore/Jeff Fox's Ultratechnology Workstation in a mouse

The Oberon Station boots from the uSD in about a second - which is impressive. My laptop thinks for about 5 seconds before it even responds to it's power switch.

The monochrome video could be greatly extended  - a Spartan 6 should be capable of generating 1024 x 768 resolution VGA in full 24bit colour, or even HDMI. Especially if it uses 32 bit wide SRAM.

The PS/2 keyboard and mouse are good old simple technology - but, in time may be difficult to get hold of.

Adding a FT2232 to act as virtual com port and the means to re-flash the FPGA would also be useful for development purposes.

The Network Port is intended to take a nRF24L01 2.4GHz transceiver.  A couple of jumper links and it could take an ESP8266-01 WiFi module.

Want to democratise this?  Re-lay it out using a Arduino MEGA footprint or add a Raspberry Pi style expansion header - so that it can use popular & standard forms of shields.

There appears to be a footprint for an SMT or FPC expansion header on the left side of the PCB.

With the right RAM this could be clocked at 100MHz++

What about an ARM Implementation?

The RISC5 appears to be a fairly simple cpu architecture,  the Oberon System has been cross-compiled by Astrobe to ARM - so it can run on any ARM equipped device. Currently NXP Cortex M3 and M4 devices are supported with more to come.

This opens up the opportunity for a port to the Cortex M7 - which opens up opportunities for 200MHz + operation, with 400MHz promised for later in 2016.  A port to the $50 STM32F7 Discovery platform would make for a portable, battery powered workstation.

Additionally the RISC5 has been ported to run on the $99 Xilinx Artix 7 "Arty" platform.

Astrobe Systems have recently released a cross compiler and development system to allow Oberon to be developed on a Windows platform.






Friday, January 15, 2016

A Review of Tiny Languages Part 1

Tiny Languages

This week I have been looking at bygone computers and some of the languages they used - tailored to work within the framework of their resource limited hardware.

My recent dealings with the "Forth-like" SIMPL language has led me to look for other examples of minimalist programming languages.  Many of these were devised in the 1970s and 1980s - when home microcomputers were very short of memory resources.

In this post I look at some very small computer languages - often less than 4Kbytes in size.

My recent search has unearthed the following:

VTL     Very Tiny Language   - a BASIC like language for resource limited microcontrollers

VTL-2   An updated VTL with more features -  yet assembles in 768 bytes

Mouse  - developed in the late 1970s for electronic music applications on a PDP8

TinyForth  - A cut down Forth, written in C or assembler

Txtzyme  - an I/O oriented minimal control script with some Forth-like features

SIMPL     - an extended version of Txtzyme to run on several platforms.

TinyBasic  - various offerings available. TinyBasicPlus

Bitlash  - a control oriented, Programmable Command Shell to run on Arduino


VTL

VTL is an interpreter designed in 1977 by Frank McCoy for the 6800 and 8080 machines of that era. The complete 6800 version of his interpreter is ROMable, IN 768 BYTES!

VTL was originally devised for the Altair 680 - an early 6800 microcomputer, with a strong similarity to it's stablemate the MITS Altair 8800 but much smaller in size.  It had 1K of RAM and sockets to accept 1K of ROM.  ROM chips at this time were likely to be only 256 bytes - so 4 sockets required!

There appears to be a following for VTL and its derivatives in Japan - so many of the references are Japanese websites - but easily translates with Google Translate.

Summary of VTL languages over the years - translate from Japanese

"Creating a VTL Language" Some description of VTL for 6800, 8080/Z80 and AVR  - source code in assembler and C - Translate from Japanese. This site and source code provided by T. Nakagawa.

The author, T. Nakagawa, has provided source code (about 370 lines - see this Github Gist) that will run on an Arduino with a bit of fiddling. You will need to add the serial putchr and getchr routines to drive the UAR - and include the UART code from AVR-Lib.

Once these are added, it compiles to about 2.6K under the Arduino IDE.  It should be noted that the AVR uses a 16 bit instruction word - so the byte count for AVR Flash code is generally about twice that of other 8 bit microcontrollers.

If you want to try out VTL - this is a packaged exe that runs on a PC in a command prompt window.

VTL remains of interest because it has some very compact C code for the various building blocks of a simple interpreter - and is relatively easy to understand its operation.

VTL-2

In 2007, some thirty years after his original VTL offering, Frank McCoy revisited his VTL and produced an extended and improved version of VTL - which still fits into 768 bytes (on 6800)   The User Manual and some example programs are here.

Mouse 

Mouse is a very small language that was written in the late 1970s - early 1980s by Peter Grogono.

It was a further development of his early 1970s system/language MUSYS - that was written to aid his work with early computer generated electronic music on resource limited PDP-8 machines.

Mouse took aspects of MUSYS and updated them to suit the late 1970s emerging microprocessor scene.

Here are some links:

The Mouse Programming Language

The Great Mouse Programming Language Revival

Wikipedia has further links that may be of interest.


Tiny Forth

This site and source code is again provided by T. Nakagawa, a Japanese enthusiast of Tiny languages.

He has written TinyForth both in well commented AVR assembly language (1964 bytes) and also in C that closely follows the assembly language. This not only gives a good illustration of how the language has been constructed but also how closely AVR assembly is matched to C.

I have created a Github Gist for this TinyForth - complete with UART getchr and putchr routines. The code compiles to 4854 bytes - I used Arduino 1.04  IDE - as I had some difficulty with later versions with getting the UART code to compile.

It appears to be a subset of Forth - but with sufficient keywords currently available to do simple tasks  - but like any Forth is easily extended.

Input and Output is via a serial UART interface only - it would need further extensions to the dictionary to build up a vocabulary of I/O and timing functions for the Arduino/AVR.

The AVR assembly language version is much more compact - I have added a fully commented version to this Github Gist 

If you want to write a Tiny Forth for an AVR or even an ARM - then this is a good place to study the basic language structure.

In conclusion - TinyForth looks like it could provide a useful kernel for a larger project. It would be worth compiling this source for an ATmega1284 - the extra RAM (16K) and additional I/O port would make a very capable Forth Computer.

As a newcomer to AVR assembly (but having done a lot of Z80 years ago) it is rewarding to see how readily C code can be translated to assembly language.  A lot of the Forth primitive wordss are of immediate use for the Txtzyme/SIMPL interpreter (see below) - and having the C and assembler code together is a useful crib on how one might take the project forwards further.


Txtzyme

Txtzyme was created around 2010-2012 by Ward Cunningham.  Txtzyme has the advantage that it is specifically oriented to I/O control and interaction - yet surprisingly simple.

The Arduino version allows simple control of the Arduino I/O and allows timing functions and loops. LED sequences, musical tone generation and printing serial output of analogue sensors are easily performed.

It is simple in nature - essentially just a single character  interpreter contained within a loop. It uses a single stack variable x to control some parameter of the operation. It is fairly simple to understand and easily extendable to include further "words" such as arithmetical and logical functions.

The Arduino version is just 90 lines of code and compiles to 3518 bytes. The codesize can be much reduced by replacing some of the Arduino C functions with more compact code, possibly even resorting to AVR assembly language in order to make a more compact kernel.

The beauty of Txtzyme is it's simplicity and the fact that it can be easily tailored to suit a particular application.

Reducing the Code Size:

Removal and replacement of the Arduino Serial code and using a custom function to print a long number can bring this down to 1884 bytes.

Removal of the Setup() and loop() functions and replacing with a main() and a while(1) will reduce it to 1782 bytes - but at a loss of the timing delays and millis() functions

Removal and replacement of the Arduino delay and delay_microseconds code will bring it down to
1484 bytes.

Replacing digitalWrite with a simplified function  - reduces it to 1040 bytes

Removal of analogRead and digitalRead  reduces it by a further 92 bytes to 948 bytes.

digitalRead alone is 272 bytes!

If you want to try a cut down version of Txtzyme - I have paired out most of the bloat and put a 658 byte minimum kernel here.  It doesn't do much - you have to add your own functionality in the form of case statements.

Txtzyme appears to indicate that a I/O oriented micro language is possible on the AVR (Arduino) in about 1024 bytes. This makes it  possible to include it with a bootloader plus some extensions in under 2K.

The code-shrunk version of Txtzyme is available on this Github Gist   You may wish to re-instate digitalRead  (line 110) and analogRead (line 150) depending on your requirements.


Next Time

In the next post I look at SIMPL and how it has evolved from Txtzyme.

















Saturday, November 28, 2015

Revelation Time!

Revelation Time!

The STM32F7 Discovery board is remarkable a board for the money providing a rich mix of hardware, communication interfaces and memory. With it's 216MHz STM32F746 ARM Cortex M7 microcontroller and 4.3" capacitive touchscreen display, it makes a very capable platform to develop embedded applications on.  It represents probably the fastest system available that allows true bare metal programming - unhindered by an operating system. For anyone developing embedded systems requiring touchscreen display, ethernet, audio and a fast 32 bit processor, the F7 Discovery is worth considering. All of the principal ICs on the F7 Discovery are available in LQFP or TSSOP packages - which means that the core hardware design could be recreated on a simple double sided pcb - suitable for hobbyist construction.

When I first looked at the STM32F7 Discovery board, and saw the Arduino headers on the underside of the pcb - I thought that such a powerful board, having been design restricted to just 20 feeble I/O lines, was a bit lame - kind of added at the last moment - as an Arduino afterthought.

However, when I took a closer look at what signals had actually been routed out to the Arduino headers - I discovered that it is possible to get all but 1 of the signals for an RGB  2:3:2 display!  It almost looks as the signals were planted on the Arduino headers on purpose - for a backdoor VGA display  - of up to 128 colours.  Now that did get my attention!

A VGA shield could be easily built on a proto shield or even stripboard.

Not only that - but two SPI ports and an additional UART appear on the headers - allowing for a PS2 mouse and keyboard, and an auxiliary serial debug port!

Whoever laid out the F7 Discovery board was either a Genius of a bluffer!

A Pocket Workstation

With the possibility of quite an easy hack to get 7 bit VGA from the Arduino headers, and add a PS2 keyboard and mouse - it occurred to me that the Discovery board had just redeemed itself as a prime contender for the proposed retro-workstation project.   It would certainly work well as a target board - to allow ideas to be tried before committing to further hardware.

A simple shield carrying the VGA resistor networks, a VGA connector and 2 PS2 sockets could be made up very easily - on the new preferred 50x50mm board format.

The Discovery board provides  8Mbyte of SDRAM,  16MByte of Nor Flash and a microSD card. This would be sufficient for much of the experimentation I want to do - after all I am looking for minimal systems with modest resources. In terms of computing power - the Discovery board represents a respectable mid-1990s desktop.

Other useful hardware is the ethernet connectivity, the OTG high speed USB and the audio interface. hardware.

mbed on the STM32F7 Discovery

With mbed available for code development - this seems to be a step up from the humble Arduino - and definitely a very exposed platform for bare metal code development.   The hardware is totally accessible - and not hiding behind Linux, and there is no part of this hardware design that I cannot recreate using LQFP packages on a self designed pcb, adding more SRAM or SDRAM as required.

The hardware is quick too - it looks like it will be about 30 times the speed if the ZPUino - plus more resources - and a more flexible VGA or LCD system.  There is scope for Li Po battery operation - and discover some of the low power modes of the STM32F7 micro.


Discovery F7 VGA Output Hardware Details


Here's the hardware connection details for the proposed "Arduino"  VGA/ PS2 shield.

Colour                      Port                       Arduino Pin

R7                             PG6                       Dig 2
R6                             PA8                       Dig 10

G7                             PI2                        Dig 8
G6                             PI1                        Dig 13
G5                             PI0                        Dig 5

B7                             PB9                       Dig 14
B6                             PB8                       Dig 15

H_SYNC                  PC6                       Dig 1  
V_SYNC                  TBD                      Available on camera FPC

The missing V_sync is probably not too much of an issue.  It could be generated by a Timer - clocked by H_sync

LCD_CLK                PG7                       Dig 4

TIM3 CH1                PB4                       Dig 3
                                 PH6                       Dig 6
TIM2 CH1                PA15                     Dig 9
                                 PB15                     Dig 11
                                 PB14                     Dig 12


For serial communication - we have access to UART7 on PF6 ad PF7 - which appear as AN4 and AN5. This will allow a FTDI cable to be plugged is as an auxiliary/ debug port

So the full line up - rearranged

H_SYNC                  PC6                        Dig 1
R7                             PG6                       Dig 2
TIM3 CH1                PB4                       Dig 3
LCD_CLK                PG7                       Dig 4
G5                             PI0                        Dig 5
TIM12 CH2              PH6                       Dig 6
Spare                        PI3                         Dig 7
G7                             PI2                        Dig 8
TIM2 CH1                PA15                     Dig 9
R6                             PA8                       Dig 10
TIM12 CH2              PB15                     Dig 11
TIM1/8 CH2N          PB14                     Dig 12
G6                             PI1                        Dig 13
B7                             PB9                       Dig 14
B6                             PB8                       Dig 15

                               PA0                       AN0
                               PF10                      AN1
SPI5_MOSI            PF9                        AN2
SPI5_MISO            PF8                        AN3
SPI5_SCK              PF7                        AN4
UART7 TX             PF6                        AN5

Thursday, November 12, 2015

Minimal Text Interpreter - Part 3

The operation and main routines of a minimal text interpreter  - Part 3

This post is merely a description of the first implementation of the text interpreter looking at the principal routines. It's so I can remember what I did in 6 months time.

Function

The minimal text interpreter is the first stage of enabling plain text to be converted into computer machine language.  Charles H. Moore the inventor of Forth, found an efficient means of doing this in the 1960s whilst working with mainframe computers, so I have chosen to adhere reasonably close to his methods.

A word is a group of consecutive characters ending in whitespace. The first task for the interpreter is to step through the line of characters and identify the individual words.  At the same time it can keep track of a word-length counter so that it can reformat the text into a more compact format.

Take the sentence "A word is a group of consecutive characters ending in whitespace"

It is a string of 64 characters, containing 11 words, and a minimum of (11-1) spaces.  We first pick out the individual words and store them into a temporary processing buffer,  we can also count the number of characters in the word and put it alongside

A                    1
word              4
is                   2
a                    1
group             5
of                   2
consecutive    12
characters      10
separated       9
by                  2
whitespace    10

So we have 11 entries in our table,  with their lengths.  If we assume that we are going to restrict the word length to 16 characters - we could express the length as a single hex character

We now crop the words down to the first 3 characters.  For those of less than 3 characters, we fill in with spaces:

A  1
wor4
is 2
a  1
gro5
of 2
conC        (12)
chaA        (10)
sep9
by 2
whiA       (10)

So we have reduced our original 64 input characters  to 11 x 4 - which is about a 30% reduction.  Tests carried out with Forth showed that the first 3 characters and the length was an optimum way of differentiating between and storing words in the dictionary.  For assembler applications where mnemonics tend to be only 3 or 4 characters it is pretty much an optimal first step of decoding the source code, prior to allocating the machine code op-code tokens.

Once the text scanner has  reduced each input word to three characters and a length byte, it then become practical to use this shortened representation to perform a word match.  All of the system keywords and user words can be stored compactly in this format, along with their jump addresses.  If 8 bytes are allocated to the word entry in the look-up table, this allows a 16 bit jump address, a pointer to the table where the original unencoded word is stored and a 1 byte attribute - that can be used to tell the compiler something about the word to help at compilation time.

Consider a system that has a maximum of 256 user words and 256 keywords - each internally coded at 8 bytes per word.  Then this would need 2K in Flash for the keywords - not a problem for most small micros, but the 2K user table would rapidly start to eat up the limited RAM resources.  Fortunately most small user applications are unlikely to have anything like 256 User words, and so halving this, a 1K user dictionary space would be quite acceptable.

Immediate and Compilation Modes

The above text scanning function can be used in two distinct cases:  immediate and compilation modes.

In immediate mode, a word typed into the input buffer will be executed immediately - provided of course that it already exists in the dictionary. If not, it will lead to an error message. Once found in the dictionary the jump address associated with that word is put onto the pc and the processor executes the code it finds at the jump address.

However in compilation mode, the user wants to create a new word definition, and uses a Forth method called the colon definition.  As it name suggests a colon definition begins a new line with a colon : This tells the text interpreter, that the proceeding word is going to be new and the interpreter should enter compilation mode.  A colon definition begins with a colon:  then the name of the new_word, then the definition i.e. the code words associated with that function and finally ends with a semi-colon ;

The Forth word colon definition performs the same operation as a function in C - compiling the function and putting it into memory as a series of threaded calls to the various routines.

: new_word    (put the definition here)  ;

In C

new_word()
{
// put definition here
}

Once a new_word has been defined as above it can be executed immediately - just by typing its name. This is what gives Forth it's almost unique characteristics of being an interactive and extensible language.   The functions are written and compiled and can be tested in isolation of one another - so that a large project may be built interactively in small blocks - testing each block as you go.







Currently only the basics have been implemented - by way of a proof of concept, and running on a 2K RAM Arduino. Later this will be ported to various ARM Cortex parts, the FPGA - softcore ZPUino and ultimately the J1 Forth processor.

There are probably many ways in which this could be implemented - some giving even more codespace and memory efficiency.  As a rookie C programmer, I have stuck to really basic coding methods - that I understand. A more experienced programmer would probably find a neater solution using arrays, pointers and the strings library - but for the moment I have kept it simple.

The interpreter resides in a continuous while(1) loop and consists of the following routines:

txt_read  

Reads the text from the UART into a 128 character buffer using u_getchar.
Checks that the character is printable - i.e. resides between space (32) and tilde ~ (127) in the ascii table and stores it in the buffer.
Keeps accepting text until it hits the buffer limit of 128 characters or breaks out of this if it sees a return or newline  \r or \n character.

colon_check

This checks if the text starts with a colon, and so is going to be a new colon definition.
sets flag colon=1
calls the build_buffer function

word_scan

If the leading character is not a colon, this function determines that the word is either within the body of the definition, or it is for immediate execution.  It calls build_buffer,  but only builds the header to allow a word match. It should not add the word to the dictionary, if it gets a match and is already there.

build_buffer

This checks the first 3 characters of the word and puts them into a new header slot in the headers table.
It also calculates the word length by counting the characters as it stores them into the dictionary table, which it continues until it sees a terminating space character.
It increments the dictionary pointer ready for the next word

word_match

This compares the 4 characters of the header of the newly input word with all the headers in the header table.
If all 4 characters match then it drops out with a match_address (for the jump address look-up table) and sets a match flag  match= 1.


header_list

This is a utility routine which prints out a list of all the headers in the order they are stored in the headers table.

dictionary_list

This is a utility routine which prints out a list of all the words in the dictionary in the order they were stored in the dictionary table.

txt_eval

This is the main character interpretation function which implements the SIMPL language core

is_a_word

Not yet implemented.  Returns true if it finds a word and invokes build_buffer and word_match

is_a_num

Not yet implemented.  Converts the ascii text to a signed integer and stores it in a parameter table.
Might possibly use ascii 0x80 (DEL) to signify to the header builder that the following bytes are a number.  Will need a conversion routine to go between printable and internal storage formats.

UART Routines

These provide getchar and putchar support directly to the ATmega328 UART. Saves a huge amount of codespace compared to Serial.print etc

uart_init

Initialises the ATmega328 UART to the correct baudrate and format.

u_putchar

Waits until the Tx register is empty and then transmits the next character

u_getchar

Waits until a character is present in the UART receive register and returns with it

Printing Routines

Having banished Serial.print - I had to implement some really basic functions

printnum()

Sends a 16 bit integer to the UART for serial output

printlong()

Sends a 32 bit integer to the UART for serial output




A Minimal Text Interpreter - Part 2

A Text Interpreter to run on a Resource Limited Microcontroller  - Part 2

In the previous post, I described the basics of a tiny text interpreter, written in C, intended for use on resource limited microcontrollers. The text interpreter would offer a natural language user interface, allowing programming and command line control of various microcontroller projects.

It will also form the basis of a wider range of self-written computing tools, including assembler and compiler, editor and file handler - all of which could be hosted, if necessary on a resource limited target board.

However, for the moment, and for ease of experimentation, the intention was to get the interpreter to run with only 2K of RAM (as per the Arduino Uno).

I envisioned the text interpreter as being a universal resident utility programme (almost akin to a bootloader) that would be initially flashed onto the microcontroller thus allowing a serial command interface and the means to exercise the hardware or develop small interactive programmes.

At work and at home, there are many instances of when I want some degree of interactive control over a small microcontroller project - even if it is just manipulating some port lines or sending and receiving a few serial responses on a terminal programme.

Some Practical Limitations

In order to keep the demands on the interpreter program reasonable it is necessary to put some limits on its capabilities.  In particular, the number of words it can recognise and create jump addresses for. For convenience I used a look up table to hold the jump addresses.  If the look up table is to remain reasonably compact - then a limit of 256 entries seems reasonable.  Restricting the word capacity will also help keep the dictionary and its headers to a manageable size in RAM. This is important when you only have 2K to play with!

As the 4 byte header is in fact a shortform, or compact coding convenience that represents the dictionary, it could be said that in very RAM limited systems that it is not actually a requirement to keep the dictionary in RAM on chip.  The only role that the dictionary performs is to allow the header entries to be expanded to the full word at times of listing.

As small micros generally have plenty Flash available, then the dictionary for all the standard words could be programmed into flash - as indeed could their headers.  If necessary, a shell hosted by a PC application could be used to host the various dictionaries and source code files needed for particular applications. However, the original aim is that this interpreter vastly increases the user-friendliness of the microcontroller target - even with just a serial terminal as the user interface.

Additionally, I have imposed a word length limit to 16 characters.  Imposing this limit means that the word length can be coded as a single hexadecimal digit - which makes it displayable in ascii and human readable. If you can't name something uniquely in 16 characters then you are probably of German extraction.

Vocabularies

Different tasks need different tools, and as the interpreter will be used for a variety of tasks, then it seems reasonable that it can be augmented or tailored towards a particular task. This can be done very conveniently with the use of vocabularies - with a particular vocab being used for a particular task.  A vocab that contains the mnemonics of a particular processor's instruction set would be one sensible use when using the interpreter within an assembler, compiler or disassembler.  

Forthright

Those of you that are familiar with Forth, will say that I am just creating a portable Forth-like environment, but rather than being coded in the native machine language of the target processor, it has been written in C for convenience and portability.

This is indeed partly true, as the utility I am creating has been inspired by the Forth language - especially in its compactness and low resource requirements.  Even in the 1960s Charles Moore was concerned how the tools provided for computing at that time hampered progress, and so set about redefining the whole man-machine interface. He compressed the previously separate editor, compiler, and interpreter programmes (none of which could be co-resident in memory at the same time) into a single compact, convenient package that did the job of all three.

When Forth was first introduced in the late 1960s, mini computers had sub-MHz clock frequencies, and very little RAM, and so benefited greatly from a moderately fast and compact language like Forth. Nowadays, typical microcontrollers have clock frequencies in the 20MHz to 200MHz range and so are not so hindered by what is essentially a virtual machine implementation of a stack processor written in C.

Virtual and Real Stack Machines

I have embarked on this journey because of my wider interest in soft-core and open core processors implemented on FPGAs. Several of these cores are based on stack machines, partly because they may be readily implemented in surprisingly few lines of VHDL or Verilog. Indeed James Bowman's J1 Forth processor is fully described in fewer than 200 lines of verilog.

Whilst a virtual stack machine might not be the easiest fit for a register based processor without performance penalties, it is a wonderful fit for a real stack machine.  A number of open-core processors including the ZPUino and James Bowman's J1 are true stack machines.  Here the instruction set of the virtual machine have a near one to one direct mapping to the the machine instructions of the stack processor.  In this case the text interpreter can be rewritten in the native assembly language of these cpus, to benefit from the vast increase in speed of running without an additional layer of virtual machine.

In order to do this an Assembler will be required  that is tailored to the instruction set of the Forth Processor, and this is one of the first tasks that the text interpreter will be used for - the assembly of machine code for a custom processor.

One of the reasons why I am concerning myself with such low level primitive tools, is the need to understand them from the ground up so that they can be implemented on a variety of non-conventional processors.

Whilst the ZPUino will execute Arduino code directly (albeit very inefficiently  - because of the C to stack machine programming conflicts), the J1 will need the tools to write it's own language from the ground up - and if you already have the mechanisms of a language in place, plus an easily customisable assembler, then it makes the job a lot easier.

In a later post, I will give an update on the text interpreter and it's application to custom code assemblers.