bitlashfunctions - billroy/bitlash GitHub Wiki

Bitlash Functions

Bitlash allows you to store and manage Bitlash Functions in the Arduino's EEPROM. By defining new functions, you extend Bitlash to suit your application.

Think of a function as a stored command line. In Bitlash, that can be multiple statements. And a statement within a function can call a function, so function execution can nest like subroutine calls (up to a dozen levels deep or so). But the simplest use is simply to give a name to a sequence of commands.

Rules For Function Names

Function names must begin with an alpha character ['a'..'z'] and be 12 characters or less in length. (Yes, "filename.txt" is a legal function name.) Function names must be more than one character long (to avoid conflict with the built-in numeric variables named a through z) and must not conflict with any of the pin variables (d0..22 and a0..7), nor with the built-in functions and commands. Function names can contain digits and the underscore '_' and period '.' characters.

Defining a Function

To define a function, use the function name {stmt;stmt;} syntax:

> function toggle13 {d13=!d13;delay(100);}	\\ defines toggle13: flip the bit and wait a while
> function hello {print("Hello, world!);}

Run a function: foreground

To invoke a function, you can type its name at the command line or refer to it in another function (for example in the definition of startup above):

> toggle13			\\ flips bit 13

Run a function: background

To run a function in the background use the run command:

> run toggle13
> ps			\\ is anything running?
0: toggle13		\\ yes, there's our function running
> stop 0		\\ stop it
>				\\ now it's stopped

There is more detail on this topic in the Background Functions section.

List functions in EEPROM

To list all the functions stored in the EEPROM use the ls command:

> ls					\\ list all the functions
function toggle13 {d13=!d13;}
function hello {print("Hello, world!";}

Remove a function from EEPROM

To remove a function use the rm command:

> rm hello				\\ rm removes a function.  rm * does what you think.
> ls
function toggle13 {d13=!d13;}

The Startup Function

If there is a function by the name "startup", it is run automatically at boot time. Make one like this:

> function startup {print 1,2,3;}
> boot
bitlash v2.0 here!...
1 2 3
>

Don't like it?

> function startup {...new definition...}		\\ redefine the startup function
> rm startup					\\ delete the startup function

Tip: If it looks like it's sitting there doing nothing, it's probably running a function. Press ^C to break out of a looping startup command.

The Prompt Function

If there is a function by the name "prompt", it is run automatically whenever the command line prompt is to be printed so that you can customize the prompt. Here is an example of a prompt function that prints the current time in millis:

> function prompt {print millis,;print "$",;}
36244$ 		\\ press enter at this prompt
36484$ 		\\ time advances

Inspecting and Formatting Function Storage in the EEPROM

There may be debris in your EEPROM from another project. Or your Bitlash program can blow chunks, or Bitlash can blow chunks. Anyway, the EEPROM can become "less than fresh". This might first show up as funky results from the ls command, for example.

You can inspect your EEPROM with the peep command, which prints a map of EEPROM:

> peep
E000:  t13\ d13=  !d13 ;del  ay(1 00)\  star tup\  prin t("R  unni ng b  link -13   demo  - p
E040:  ress  ^C"  ); w hile   1:t 13\.  .... ....  .... ....  .... ....  .... ....  .... ....
E080:  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....
E0C0:  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....
E100:  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....
E140:  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....
E180:  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....
E1C0:  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....  .... ....

This is a healthy map. The places marked '.' are empty (==255). The name-value storage for t13 and startup can be seen. As you add functions you will see them fill from low addresses up, always in pairs.

An unhealthy map might have garbage in the supposedly unused part. Or there could be free space available but spread around in fragmented blocks (see Fragmentation below).

You can erase and "reformat" the EEPROM using the "rm *" command; see below.
This will erase any functions you have typed into bitlash, as well as the garbage.
In other words:

Note: RM *" WILL NUKE THE WHOLE EEPROM. There is no way to recover it. Please use caution.

A note on EEPROM usage: Don't bang on the EEPROM

The EEPROM is said to be certified for about 1e5 cycles. Bitlash could drive that many write cycles in under ten minutes, if you told it to. If you do this and your EEPROM breaks you get to keep the pieces. But please write and let us know how it failed. We've never seen it happen. Anyway, use EEPROM for long term storage like function definitions, not loop counters, and factor EEPROM life into your application life cycle model.

EEPROM Free Space Fragmentation

Heavy use of the function store may lead to fragmented free space. You would see this in the peep map as free space dot clusters too small to be of use scattered here and there.

This version of Bitlash does not have a method to compact the free space, but if you are highly motivated to squeeze out the last possible byte, here is a straightforward but unfortunately manual workaround:

  • Use 'ls' to get the contents of all the functions. Copy to safe place!
  • Use 'rm *' to nuke the eeprom. All your functions are gone! Hope you copied them!
  • Paste the output you saved into your bitlash terminal emulator to re-define the functions.

Depending on many factors, (baud rate, clock speed, terminal program, OS, ...) it may be necessary to paste the definitions one at a time.

Reserving EEPROM for Other Applications

A portion of the EEPROM space can be kept from bitlash for use by your application's C code by adjusting the values of STARTDB and ENDDB in bitlash.h. You are advised to save, reformat, and reload any EEPROM contents after changing these values.

Say you want to reserve 32 bytes at the high end of EEPROM (you'll be using EEPROM.read() and EEPROM.write to manipulate it), edit the #define of ENDDB to be

#define ENDDB (E2END - 32)

Bitlash will then use memory from STARTDB to ENDDB - 1. Your 32 bytes run from ENDDB to ENDEEPROM - 1. To read byte 15 of your private EEPROM, use EEPROM.read(ENDDB + 15).

You can use the bitlash "peep" command to dump the EEPROM, which will include your space. Telling bitlash to "rm *" will delete all of your bitlash functions from EEPROM, but will leave your private space unmolested.

It's up to you to manage your private memory, including providing a way to clear it, etc. One reasonable approach is to add a new bitlash C command or two to interact with and manipulate your private EEPROM space.

Note that flashing your firmware from Arduino will NOT erase your reserved EEPROM. (This is a feature, not a bug.)