0% found this document useful (0 votes)
37 views50 pages

Bitlash Users Guide

Bitlash is an open source interpreted language shell and embedded programming environment for Arduino. It runs entirely on the Arduino and interprets commands typed into a terminal or sent over serial. Functions can be defined and stored in EEPROM for standalone operation. Bitlash also allows integration of custom C code for speed or interfacing hardware.

Uploaded by

blackorgon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
37 views50 pages

Bitlash Users Guide

Bitlash is an open source interpreted language shell and embedded programming environment for Arduino. It runs entirely on the Arduino and interprets commands typed into a terminal or sent over serial. Functions can be defined and stored in EEPROM for standalone operation. Bitlash also allows integration of custom C code for speed or interfacing hardware.

Uploaded by

blackorgon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 50

Bitlash

THE OFFICIAL

User’s
Guide

For Bitlash 2.0


Bitlash User’s Guide

The Bitlash User’s Guide is © 2012 Bill Roy

Bitlash and the Bitlash documentation are © 2008-2012 Bill Roy

Bitlash Code is made available under the MIT Open Source license.

The Bitlash documentation is made available under the Creative Commons Attribution 3.0
Unported License.

Images in this book are © 2012 by Bill Roy http://bitlash.net

BUG v0.51

i
Chapter 1

About Bitlash

What is Bitlash?

How does it work?

Bitlash architecture
Section 1

What is Bitlash?

BITLASH IN A NUTSHELL Bitlash is an open source interpreted language shell and embedded programming
1. Interprets a C-like mini-language extended environment for the popular and useful Arduino.
for digital and analog IO
The Bitlash interpreter runs entirely on the Arduino and interprets commands that you
2. Recognizes most Arduino library functions type in a terminal window or send programmatically to the serial port:
3. Runs entirely on the Arduino with serial IO
bitlash here! v2.0 (c) 2012 Bill Roy -type HELP- 942 bytes free
for control and output
> print "Hello, world!", millis()
4. Saves functions defined from the command Hello, world! 11939
line in EEPROM; small applications are >
possible
It’s easy to extend Bitlash by naming a sequence of commands as a Bitlash
5. Mini-tasker runs functions periodically in
the background for system control
function, which is like a new word in the Bitlash language. A Bitlash application is a
set of such functions, and since they are stored in the EEPROM, Bitlash can start
6. API makes it extending Bitlash with your C
up your application automatically at boot time for standalone operation.
code easy

7. Open Source on Github (http://bitlash.net) In cases where you need native C code to get closer to the hardware, perhaps for
speed or to interface with a custom peripheral, it’s also easy to integrate your C
8. Extensive documentation and sample
applications code with Bitlash as a User Function. Bitlash ships with many examples of user
functions.

3
Section 2

How does Bitlash work?

BITLASH INTERPRETER The Bitlash embedded interpreter that runs in about 14k of memory on an Atmel AVR
processor. It works nicely with Arduino to make a development and prototyping tool for
1. Runs in under 16kB on the AVR ‘328
those situations where you need to bang some bits on the Arduino but writing a sketch in
2. Parses Bitlash code on the fly from RAM, C is premature. It’s very convenient for bringing up and debugging new hardware.
PROGMEM, EEPROM, or SD card
The Bitlash command language is very similar to Arduino C and includes a large reper-
3. Executes commands live from the
command line and runs background tasks toire of the familiar Arduino C functions so you can hack your hardware from the serial
command line or even over the internet via telnet.

You can store commands as functions in EEPROM, compile them into flash memory, or
put them on an SD card. A user-defined bitlash startup function is run automatically at
bootup, making the automation and maintenance of small applications very easy. Here is
the classic Blink13 program as a complete Bitlash application in two functions, toggle13
to toggle the led and startup to initialize and run it:

> function toggle13 {d13=!d13;}


> function startup {pinmode(13,1); run toggle13,1000;}
> boot
(d13 toggles every 1000ms)

4
Section 3

Bitlash architecture

ARCHITECTURE BASICS Here is a diagram of the components of Bitlash and how they interoperate with the
1. Bitlash is an Arduino sketch, written in C Arduino software and the Arduino hardware with Atmel CPU.

2. Bitlash uses the Arduino and avr-gcc


libraries

3. Bitlash can use user C code and libraries

4. These libraries in turn control the Atmel


hardware

5
Chapter 2

Get Bitlash

Download

Install

Hello, world!
Section 1

Get Bitlash

DOWNLOAD AND INSTALL


1. Download Bitlash
1. Visit http://bitlash.net to download or git
clone the latest version If you use git, it’s easiest to clone Bitlash via git; see below.
2. Install the bitlash/ folder into the libraries
For a .zip file download, the latest version of Bitlash can be found at http://bitlash.net
subfolder of your Arduino sketchbook

3. Restart the Arduino IDE so it notices the 2. Install Bitlash


new library

4. Connect with a terminal emulator like the Requirements


Arduino Serial Monitor
You need an Arduino connected to a PC with a working Arduino IDE. These directions are
5. First program: print “hello, world”
for Arduino v0023 through 1.0.1.
6. function hello {print “hello, world”}
Since Bitlash is an Arduino library you upload with a sketch, you need to be comfortable
uploading sketches. Get this working first to save debugging headaches. There is plenty
of help over at the Arduino Forums at http://arduino.cc/forum/

Install Bitlash using Git


You can also grab the latest development version using Git, and clone it right into your li-
braries directory using the recipe below.

NOTE: Back up your existing Bitlash directory first!

$ cd ~/Documents/Arduino/Libraries

7
$ mv bitlash/ bitlash-save/ • Select File / Examples / bitlash / bitlashdemo to open the
$ git clone https://github.com/billroy/bitlash.git demo sketch, then File / Upload to compile and upload it to your
Arduino.
Restart the Arduino IDE and you’re good to go.

When your upload is complete, you are ready to connect to Bitlash. Pro-
Install Bitlash
ceed to the next section on Connecting.
The Arduino Development Environment Guide specifies this procedure
for installing third party libraries: Connect With a Terminal Emulator

"To install these third-party libraries, create a direc- Connect to the serial port at 57600 baud using whatever terminal emu-
tory called libraries within your sketchbook directory. lator works for you. Here are some options:
Then unzip the library there."
• You can use the built-in Arduino Serial Monitor, but see the note
There is also a post on the Arduino weblog with further explanation. below

• On Windows, HyperTerminal seems popular


So, to install Bitlash,
• On OS X I use screen
• Create a directory called librar-
• On Linux screen is available on most distributions
ies within your sketchbook direc-
tory
• Unzip the download and copy or NOTE: USING BITLASH WITH THE ARDUINO SERIAL MONITOR
move the Bitlash distribution
To use the Arduino “Serial Monitor” function with Bitlash, you must se-
folder into the libraries folder
lect “Carriage return” line ending handling option. The Bitlash demos
you just created
use a baud rate of 57600.
• Rename the resulting folder to
simply bitlash, if necessary, to remove the version number. You EXAMPLE: STARTING THE SCREEN COMMAND WITH BITLASH
should end up with a folder setup that looks like this: Here is an example using the screen program in OS X to connect with
• Restart the Arduino IDE; if all goes well, you will find the bitlash Bitlash on a USB-connected Arduino. The /dev/tty.usb… part is the vir-
library listed in the Sketch / Import Library menu. tual serial port name that you can find in the Arduino Tools/Serial Port
menu and the 57600 is the baud rate:

8
$ screen /dev/tty.usbserial-A7003pQ3 57600 d0, d1, d2, and so on. You can read a pin variable’s value and print it
bitlash 2.0 here! (c) 2012 Bill Roy -type HELP- 935 like this:
bytes free
> > print d12
Congratulations, you are up and running: Bitlash is listening for com- 0
mands, as signified by the ‘>’ prompt. …and assign it like this:

> d13=1 * turn on pin 13


Hello, World!
Now that you have a command prompt you can type a command, and …though you must remember to set the pin mode if you want the port
press Enter. to be an output:

Here is the usual Hello World example you might run as your first Bit- > pinmode(13,1)
lash program:
So, returning to blink13, what we want is to toggle the pin periodically.
> print "Hello, world!" Let’s define a function named toggle13 to toggle the pin:
Hello, world!
> > function toggle13 {d13 = !d13;}

While you’re there you might check the arithmetic: A function named toggle13 containing the Bitlash code “d13=!d13;” is
defined and saved in EEPROM. When the function toggle13 runs, this
> print 2+2
program text sets pin d13 to the logical complement of its current
4
value: if it was zero, it becomes one, and vice versa.

First App: Blink13 Now all we need is to arrange for toggle13 to be run at the desired tog-
gle rate, let’s say every 1000 milliseconds; and let’s not forget to set pin
No discussion of “Hello, world!” for embedded systems would be com-
13 as an output. By using the special function name startup we desig-
plete without blinking an LED. This example shows how to build a com-
nate this function to be automagically run at boot time, completing our
plete Bitlash application using Bitlash functions and auto-start.
application:
First it is necessary to introduce the concept of pin variables: Bitlash
function startup {pinmode(13,1); run toggle13,1000;}
gives direct access to the digital IO pins via single-bit variables named

9
List our functions to make sure they’re right using the ls command:

> ls
function toggle13 {d13 = !d13;};
function startup {pinmode(13,1); run toggle13,1000;}
>

You can invoke the startup function from the command line to test:

> startup
(the LED on pin d13 is blinking)

You can also restart to test the power-on startup:

> boot
bitlash here! v2.0...
(the LED on pin d13 is blinking)

Next Steps: Learn Bitlash


Congratulations! If you get this far, you have a free-standing develop-
ment environment on your Arduino.

10
Chapter 3

The Bitlash
Language

Execution Model

Expressions: Constants, Variables, and Operators

Commands

Functions

Defining New Functions in Bitlash

Background Functions
Section 1

Language Overview

THE GRAMMAR How It Works: The Bitlash Execution Model


1. A command line is one or more statements
Think of Bitlash as a dumb command line calculator. You type a line of commands and
separated by semicolons
press Enter; Bitlash interprets the line and returns you to the prompt.
2. A statement is a command, an assignment,
an expression, or a list of statements in {;} Think of a Bitlash function as a saved command line, with a name, stored in EEPROM.
When you invoke to a function by using its name, Bitlash suspends what it’s doing work-
3. Commands and Functions are described in
the next sections ing your main command to execute the function, which is interpreted just as though you
typed the function’s text. Effectively it is a subroutine call.
4. Conditionals (if, while, and switch) also get
their own section Think of background functions as stored command lines scheduled to be run periodically.

5. Expressions support variables a-z, 32-bit When you say run toggle13,1000, it means “whatever else may be happening, please
integer constants, fully recursive function execute the toggle13 function about every 1000 milliseconds.”
calls with arguments, and C-style operators

6. String constants can be passed as


arguments and used in the print command

12
Section 2

Numeric Constants

NUMERIC CONSTANTS Decimal signed numeric constants in the range of a 32-bit signed integer are supported
as you would expect.
1. Signed and unsigned 32-bit decimal
constants: 123, -123
Hex constants of the form 0xHHHHHHHH also work, as do single-quoted ascii character
2. Hex constants: 0x0d constants like ‘q’.

3. Char constants: ‘x’ Binary constants of the form 0b01010101 are also supported.
4. Binary constants: 0b10100101

13
Section 3

String Constants

STRING CONSTANTS String constants can be used as arguments and within the Print statement.

1. Valid as function arguments and in the print print “Hello, world”;


command

2. Supports C-style backslash escape printf(“This is a string: %s”, “some string”);


sequences
A string standing alone is treated as a comment and ignored.

The rules for special characters in string constants are similar to C. The backslash charac-
ter specifies that an escape sequence is to follow. Here are the supported escapes:

Char Value Description

\r 0xd carriage return

\n 0xa line feed

\t 0x9 tab

\\ ‘\’ a backslash

\” “‘ a double quote

\xHH HH 8-bit hex character HH

The hex form is especially useful in crafting escape sequences to print to peripheral de-
vices.

14
Section 4

Numeric Variables

NUMERIC VARIABLES Bitlash provides 26 built-in 32-bit signed integer variables named lowercase ‘a’ through
lowercase ‘z’ (though case is ignored).
1. 26 of them, named a through z

2. 32 bit integer values Variables are initialized to zero at boot time.

3. initialized to zero > i=10; while i-- print i,


9876543210>

15
Section 5

Pin Variables

PIN VARIABLES Pin Variables: Names for the Arduino Pins [a0..a7] and [d0..d22]
1. Special variables named D0 through D22
You can refer to specific analog and digital pins using pin variables. Pin variables are of
and A0 through A7 provide direct access to
read and set IO pin values, e.g., D13=1 the form a0, a1, a2, … a7 and d0, d1, d2, … d22.

2. Shorthand for digitalRead/Write and analog When a pin variable is used in an expression it is a shorthand for digitalRead (for the
Read/Write d0.d22 pin variables) or analogRead (for a0..a7).

> x=d4 ! ! // digitalRead(4) and save it in x


> print x, a6 ! // print digitalRead(4) and analogRead(6)

Assigning to a digital pin variable does as you would expect: it turns the output on or off,
just like digitalWrite.

> d13 = 1 ! // turn on D13

Assigning to the a-pin variables is a little tricky. You might think from the name that it does
some sort of output to an analog pin. But, not so. Assigning to an analog pin variable
does analogWrite, which is PWM output to a DIGITAL PIN!!

> pinmode(5, 1) ! // set D5 to digital output mode


> a5 = 128 ! ! // generate 50% duty cycle PWM on pin 5

16
Section 6

Operators

OPERATORS Here are the operators supported in Bitlash expressions, with meanings as in standard C;
higher precedence binds more tightly.
1. C arithmetic, relational, logical and bitwise
operators are supported with customary
precedence Symbol Name Precedence

2. Neither the compound assignment + add 1


operators nor the member and pointer - subtract 1
operators are supported (sorry, no +=, -=,
* multiply 1
<<=...)
/ divide 1
() parenthesis 1
< less than 2
<= less than or equal to 2
> greater than 2
>= greater than or equal to 2
== equal to 2
!= not equal to 2
<< shift left 3
>> shift right 3
^ exclusive or 4
& logical and 4
| logical or 4
++ pre- or post-increment 5
-- pre- or post-decrement 5

17
Section 7

Commands

TYPING TIPS Here is an alphabetical reference list of Bitlash commands. (See also Bitlash functions.)

1. Control-C stops all running macros and


gives you a fresh command prompt
Expression evaluation

2. Control-U brings up the last line you typed; If you type a “naked expression” it will be evaluated, and any side effects like function
press Enter to re-execute it calls and function executions will happen, but nothing is printed unless you say so using
print. For example:
3. Control-B suspends/resumes background
functions > d13=1; delay(125); d13=0
>
Your code is executed (d13 goes high for 125 ms), but all you see on the console is the
command prompt after it’s done.

boot: restart the arduino


Resets the Arduino. On restart, the startup function will run, if one is present.

function funcname { stmt; …; stmt;}


Defines a new Bitlash Function to be stored in EEPROM.

Bitlash functions have their own section.

> function blip {d13=!d13;}


> ls
function blip {d13=!d13;}

18
> rm blip
> ls peep: print a map of eeprom
>
Peep prints a map of eeprom usage. This can help you see how full
help: display some onboard help text your EEPROM is, and whether you have fragmented free space.

Help displays a short help message that can be helpful if you forget the
name of a command or function. It also displays a list of your functions
via ‘ls’.

if (expr) {stmt; stmt;…} [else {stmt;stmt;...}]


The if command executes the first statement list if the test condition is
true; otherwise, the optional else part is executed, if present.

> if (d4) {print "the light is on";}

ls
List all the functions stored in EEPROM. Note that the “E000” address is actually EEPROM address 0000. Sub-

> function blip {d13=!d13;} tract 0xe000 from the addresses shown.
> ls
function blip {d13=!d13}; print [#pin:] [expr][,](expr][,) – print
In its simplest form: print foo,bar will get you started. But print has a lot
of options, so please see the section on Printing for details.

ps: ‘process status’ – print a list of running back-


ground functions
Ps shows a list of running background functions.

19
> run t13 0: t13
> ps
0: t13 stop tasknum | stop | stop *

return [value]; -- return a value from a function call Stop a background task by number, stop the current task, or stop all
tasks.
The return statement allows you to return a value from anywhere within
a function. > run t13
> ps
A function that does not return via a return statement returns a value of 0: t13
zero. > stop 0
> ps
> function even {if (arg(1)&1) return 0; else return 1;} >
> print even(1), even(0)
0 1 switch (expr) {stmt0; stmt1; …; stmtN;}

rm: delete a function from eeprom The switch command selects one of N statements to execute based on
the value of a numeric expression. This provides a very easy way to
> function blip {d13=!d13;} build state machines, among other things.
> ls
function blip {d13=!d13;} Syntax:
> rm blip
> ls switch (selection-expression) { stmt0; stmt1; ...;
> stmtN;}

Use “rm *” to erase the whole EEPROM. The selection-expression is evaluated to produce an integer result,
which is used to select one of the supplied statements in curly braces.
run: run a function in the background The selected statement, and only the selected statement from
among those in curly braces, is executed, then execution continues af-
See the section on Background functions for details.
ter the switch statement.
> run t13,125
> ps

20
(Note: This construct is similar to but not strictly compatible with (light flickers)
the C switch statement, which has “case x:” tags to specify each Done
>
case.)

If the value of the selection expression is less than zero it is treated as Execution of the while loop is blocking. In other words, during the exe-
zero and therefore the first supplied statement is executed. If the value cution of a while command, no other functions can run, since Bitlash is
is greater than N, the last statement is executed. working as hard as it can to get to the end of that command line. The
combination of while 1 with delay() is particularly deadly, since it uses
Example: This switch statement in the elevator2.btl example calls the whole processor:
wating, goingup, or goingdown, depending on the value of s, the vari-
able that represents the state of the elevator system: > print "this works but NOTE it will hog the whole ardu-
ino"
switch s {waiting; goingup; goingdown;} > while 1 {print millis(); delay(1000);}
(no prompt again until you press ^C)
If the value of s is <= 0, the waiting function will be called.
Bitlash polls the serial port for Control-C during while loops, so you can
If the value of s is == 1, the goingup function will be called. break out.

If the value of s is >= 2, the goingdown function will be called.


Omitting { } for a single statement
Example: Unlike Bitlash 1.0, the case handlers can be any Bitlash state- When using while and if, it is legal syntax to omit the {} if only a single
ment, for example: statement is to be executed, just like in C. (In other words a statement
is recursively defined as a statement or a list of statements in curly
switch (d) {print "foo"; print "bar"; print "baz";
boot;} braces.)

> i=0; while (++i<3) print i; print "done";


while (expr) {stmt1; …; stmtN;} 1
2
The while command repeats execution of the while-statements as long
done
as the test expression is true. When the test expression is false, execu-
>
tion continues after the while’s statement list.

> while (millis() < 100000) {d13=!d13;} print "Done";


21
Nesting
Nested conditionals work as you would expect:

> a=0;while (a++<2) {b=0; while (b++<2) {print a,b;}}


1 1
1 2
2 1
2 2
>

How to simulate a “for” loop


The simplest way is to unroll it as a while. Here is an example that ini-
tializes pins 3 through 8 as outputs and sets them to HIGH:

> i=3; while i<=8 {pinmode(i,1); dw(i,1); i++;}

For extra credit, let’s initialize the even ones on and the odd ones off:

> i=3; while i<=8 {pinmode(i,1); dw(i,(i&1)); i++;}

22
Section 8

Built-in functions

BUILT-IN FUNCTIONS This is an alphabetical reference listing all the built-in functions provided in Bitlash.

1. Many functions call Arduino or avr-glibc Many Bitlash functions are straight pass-throughs from the Arduino functions of the same
functions directly (so the names should be
name. Therefore, the definitive reference for the behavior of the functions is the Arduino
familiar)
extended functions reference at http://arduino.cc/en/Reference/extended.
2. For functions of zero arguments you may
omit the empty parens, so millis and millis() Functions may be used in expressions in the normal way: abs(ar(3)–256) and so forth.
are both valid
Bear in mind that functions return 32-bit integer values (signed long or int32_t in C).
Whether the value is interpreted as signed or unsigned depends on the function.

It is an error to call a function with the wrong number of arguments.

For functions of zero arguments you may omit the empty parens ():

> print free,free(),millis,millis()


335 335 24455 24456

See also Bitlash commands and the Bitlash language.

abs(x): absolute value


Return x < 0 ? -x : x. See Arduino:abs at http://arduino.cc/en/Reference/abs.

ar(apin): analogRead(apin)

23
Return a 10-bit analog-to-digital conversion value from the specified beep(pin, frequencyhz, durationms)
analog input pin. See Arduino:analogread at
http://arduino.cc/en/Reference/analogRead. Toggle the specified pin at the specified frequency for the specified du-
ration. Automatically sets pinMode to OUTPUT.
aw(dpin,value): analogWrite(dpin,value)
Beep is blocking: background execution is paused. Use caution for
Write a PWM value to a ** digital pwm output pin**. The pin must be long durations: there is no way to break out of a long beep (the longest
prepared for output beforehand via pinmode(pin,1). value is several days).

A simpler syntax if the pin is fixed is: a6=128 // make the beeper on pin 11 beep at 440Hz for 200ms
> beep(11,440,200)
See Arduino:analogwrite at http://arduino.cc/en/Reference/analogWrite.
br(val, bitnum): bitread
baud(pin,baud): set baud rate for printed output
Returns the value of the bitnum’th bit [0..31] in val.
By default, Arduino prints at 57600 on pin 0 and 9600 on any other pin.
If you wish to set a different rate use the baud function: See Arduino:bitread at http://arduino.cc/en/Reference/bitRead.

// prepare "print #5:" to produce serial output bs(val, bitnum): bitset


// on pin 5 at 4800 baud (8,n,1)
> baud(5, 4800); Returns val with the bitnum’th bit [0..31] set.

// set the default/hardware serial port to 9600 baud See Arduino:bitset at http://arduino.cc/en/Reference/bitSet.
> baud(0, 9600);
bw(val, bitnum, bitval): bitwrite
See printing.
Returns val with the bitnum’th bit [0..31] set to bitval [0|!0].
bc(val, bitnum): bitclear
See Arduino:bitwrite at http://arduino.cc/en/Reference/bitWrite.
Returns val with the bit indicated by bitnum [0..31] set to 0.
constrain(val,min,max)
See Arduino:bitclear at http://arduino.cc/en/Reference/bitClear.
Returns the closest value to val between min and max.

24
See Arduino:constrain at http://arduino.cc/en/Reference/constrain. er(addr): EEPROM.read(addr)

delay(milliseconds) Return the value stored in EEPROM at the specified address.

Pause execution for the specified number of milliseconds. ew(addr, value): EEPROM.write(addr, value)
Delay is blocking; nothing else happens while a delay() is being proc- Write one-byte value to EEPROM at addr.
essed. For this reason is it better to use background functions to do
things that span non-trivial time. More on Bitlash and EEPROM at Bitlash Functions.

See Arduino:delay at http://arduino.cc/en/Reference/delay. free()


Returns the amount of memory between the top of the heap and the
dr(dpin): digitalRead(dpin)
stack pointer; in other words, the amount of stack space Bitlash and all
The dr() function is shorthand for digitalRead(). It returns the current your other code, including interrupt handlers, have to work with.
logic level on the specified pin.
Numbers less than 50 or so indicate ram starvation and mean that the
If the pin is fixed and known beforehand you can use pin variable nota- odd behavior you are seeing (or will see soon) is attributable to the oc-
tion instead: casional excursion of the stack into the defined ram area, piddling on
the interpreter state. Nothing good will come of this.
> z = 13
> x = dr(z) // return digitalRead(13) Note that malloc() and free() are not used by or included in Bitlash and
the free memory calculation takes no heed of memory broken out of
// same result using pin variable notation
the heap if you should include them for your code.
> x = d13

The free() function will issue an exception if free memory appears to be


See Arduino:digitalread at http://arduino.cc/en/Reference/digitalRead.
less than zero.

dw(dpin,bval)
inb(reg)
digitalWrite: Set the designated pin to the given boolean value.
Return the 8-bit value of the specified AVR processor register.
See Arduino:digitalwrite at http://arduino.cc/en/Reference/digitalWrite.

25
The processor registers and their functions are the function of the ex- millis()
tensive ATmega328P Data Sheet at
http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf. Returns the number of milliseconds since startup.

You will find a convenient cross reference chart of the registers starting
See Arduino:millis at http://arduino.cc/en/Reference/millis.
on page 425.
min(a,b)
You specify a register address (from the first column of the table on pp.
425 ff.) to tell the inb() and outb() which register to address. In the case Returns the lesser of a and b.
where the table has two addresses, use the right-hand one.
See Arduino:min at http://arduino.cc/en/Reference/min.
For example, to read the Timer0 count register TCNT0, find its entry on
page 470 and note its address is 0x46. Then, to read and print it in Bit- outb(reg,value)
lash:
Set the specified AVR processor register to the given value.
> print inb(0x46)
The processor registers and their functions are the function of the ex-
tensive ATmega328P Data Sheet at
map(val, fromlow, fromhigh, tolow, tohigh)
http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf.
Constrains val to [fromlow..fromhigh] and then maps it linearly to You will find a convenient cross reference chart of the registers starting
[tolow..tohigh]. Got it? on page 425.

NOTE: The map() function is deprecated as of Bitlash version 1.1 and You specify a register address (from the first column of the table on pp.
is therefore not included in the build. 425 ff.) to tell the inb() and outb() which register to address. In the case
where the table has two addresses, use the right-hand one.
See Arduino:map at http://arduino.cc/en/Reference/map.
For example, to set the OCR0A register (0x47) to control timer 0 PWM,
max(a,b) you could say:

Returns the greater of a and b. > outb(0x47, 128)

See Arduino:max at http://arduino.cc/en/Reference/max.


pinmode(pin,outie)

26
Set the pin to an output pin if outie is true. > run blink13 // only toggles every 100 ms

See Arduino:pinmode at http://arduino.cc/en/Reference/pinMode.

pulsein(pin, value, timeout)


Times an input pulse. See Arduino:pulsein at
http://arduino.cc/en/Reference/pulseIn.

random(max)
Returns a random number between 0 and max–1.

See Arduino:random at http://arduino.cc/en/Reference/random.

shiftout(dataPin, clkPin, bitOrder, value)


Bitbang the provided value out the data pin, clocking with the clock pin.

See Arduino:shiftout at http://arduino.cc/en/Reference/shiftOut.

sign(value)
Return –1 if value is negative, 0 if 0, or 1 if positive.

snooze(snoozems): defer background task execu-


tion for a while
Suspend further invocations of this background macro for snoozemillis
milliseconds. See the page on Background Functions for details on mul-
titasking with snooze.

> function blink13 {d13=!d13; snooze(100);}

27
Section 9

Defining new functions

WRITING FUNCTIONS IN BITLASH 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.
1. To define a function: function newfunc
{stmt;stmt;}
Think of a function as a stored command line. In Bitlash, that can be multiple statements.
2. Functions are saved in EEPROM; use peep And a statement within a function can call a function, so function execution can nest like
to see a map subroutine calls (up to a dozen levels deep or so). But the simplest use is simply to give a
3. To call a function: newfunc(22, 3, millis()) name to a sequence of commands.

4. To run a function in the background: run Rules For Function Names


newfunc, 1000 (no arguments)
Function names must begin with an alpha character ‘a’..‘z’ and be 12 characters or less in
5. To remove a function: rm newfunc
length. Function names must be more than one character long (to avoid conflict with the
6. If a function named startup exists, it is run built-in numeric variables named a through z) and must not conflict with any of the pin
at boot time variables (d0..22 and a0..7), nor with the built-in functions and commands. Function
7. If a function named prompt exists, it is run names can contain digits and the underscore ‘_’ and period ‘.’ characters.
instead of displaying the ‘>’ prompt
Defining a Function
To define a function, use the function name {stmt;stmt;} syntax:

> function toggle13 {d13=!d13;}! ! // flip bit d13


> function hello {print("Hello, world!”);}

28
Calling a function: foreground Using arguments in the called function
To invoke a function, you can type its name at the command line or re- You can call a function with any number of arguments. A function re-
fer to it in another function (for example in the definition of startup ceives the number of passed-in arguments in arg(0) and the arguments
above): themselves in arg(1)...arg(arg(0)).

> hello > function countargs {print arg(0);}


Hello, world! saved
> toggle13 \\ flips bit 13 > print countargs(10,20);
2
Passing numeric arguments to a function > print countargs
0
A numeric argument can be any valid numeric expression:
> function printargs {i=1;while i<=arg(0) {print
> setcount(32*5+millis(), 42, 0, 0b101, 0x7) arg(i++);}
saved
Passing string constant arguments to a function > printargs(10,20,30)
10
A string constant may be passed as an argument to a function. Space 20
for the string is temporarily allocated in the argument heap. A pointer 30
to the string’s location is passed as the argument value. > printargs
>
You can use string values with the print command (with the :s modifier)
and printf(“%s”) function, and pass them to user functions. > function doubleit { return 2*arg(1); }
saved
> function show { print arg(1), arg(1):s; } > print doubleit(7)
saved 14
> show(“hello”)
505 hello > function bigger { if arg(1)>arg(2) return arg(1); else
return arg(2);}
saved
> print bigger(2,3)
3

29
Running a function: background If there is a function by the name “startup”, it is run automatically at
boot time. Make one like this:
To run a function in the background use the run command:
> function startup {print 1,2,3;}
> run toggle13 > boot
> ps \\ is anything running? bitlash v2.0 here!...
0: toggle13 \\ yes, there's our function running 1 2 3
> stop 0 \\ stop it >
> \\ now it's stopped
Don’t like it?
There is more detail on this topic in the Background Functions section.
\\ redefine the startup function
Listing functions in EEPROM > function startup {...new definition...}

To list all the functions stored in the EEPROM use the ls command: \\ delete the startup function
> rm startup
\\ list all the functions
> ls Tip: If it looks like it’s sitting there doing nothing, it’s probably running a
function toggle13 {d13=!d13;}
function. Press ^C to break out of a looping startup command.
function hello {print("Hello, world!";}

The Prompt Function


Removing a function from EEPROM
If there is a function by the name “prompt”, it is run automatically when-
To remove a function use the rm command:
ever the command line prompt is to be printed so that you can custom-
\\ rm removes a function. rm * does what you think. ize the prompt. Here is an example of a prompt function that prints the
> rm hello current time in millis:
> ls
function toggle13 {d13=!d13;}

The Startup Function

30
> function prompt {print millis,;print "$",;} This is a healthy map. The places marked ‘.’ are empty (==255). The
36244$ \\ press enter at this prompt name-value storage for toggle13 and bcn can be seen. As you add
36484$ \\ time advances
functions you will see them fill from low addresses up, always in pairs.

Inspecting and Formatting Function Storage in the An unhealthy map might have garbage in the supposedly unused part.

EEPROM Or there could be free space available but spread around in frag-
mented blocks (see Fragmentation below).
There may be debris in your EEPROM from another project. Or your
Bitlash program can blow chunks, or Bitlash can blow chunks. Anyway, You can erase and “reformat” the EEPROM using the “rm *” command;
the EEPROM can become “less than fresh”. This might first show up as see below. This will erase any functions you have typed into bitlash, as
funky results from the ls command, for example. well as the garbage. In other words:

You can inspect your EEPROM with the peep command, which prints a Note: RM *" WILL NUKE THE WHOLE EEPROM. There is no way to
map of EEPROM: recover it. Please use caution.

A note on EEPROM usage: Don’t bang on the EE-


PROM
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 cy-
cle 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.

31
This version of Bitlash does not have a method to compact the free You can use the bitlash “peep” command to dump the EEPROM, which
space, but if you are highly motivated to squeeze out the last possible will include your space. Telling bitlash to “rm *” will delete all of your bit-
byte, here is a straightforward but unfortunately manual workaround: lash functions from EEPROM, but will leave your private space unmo-
lested.
• Use ‘ls’ to get the contents of all the functions. Copy to safe
place! 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
• Use ‘rm *’ to nuke the eeprom. All your functions are gone! Hope
command or two to interact with and manipulate your private EEPROM
you copied them!
space.
• Paste the output you saved into your bitlash terminal emulator to
re-define the functions. Note that flashing your firmware from Arduino will NOT erase your re-
served EEPROM. (This is a feature, not a bug.)
Depending on many factors, (baud rate, clock speed, terminal pro-
gram, 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).

32
Section 10

Background Functions

BACKGROUND FUNCTIONS Bitlash can run up to 10 functions in the background while you work in the foreground at
the command prompt.
1. You can start up to 10 tasks to be
periodically run in the background
The Run Command
2. Any function-of-no-arguments can be a
task The run command runs a function in the background:

3. To start a task: run beacon, 250 > run toggle13 // LED on D13 starts flashing
> // and you get the foreground prompt back
4. To list tasks: ps

5. To stop a task: stop 3 Think of the run X command as being a “while 1 X” that runs in the time between your key-
strokes.
6. To stop all tasks: stop * or Control+C

7. To pause all background tasks: Control+B In the above example, toggle13 will be called Very Frequently, perhaps as often as once
each time your loop() procedure calls runBitlash().
8. In a task, to schedule the next task time,
call snooze(time-in-ms) Bitlash stops all background functions when you press ^C. You can also stop a specific
one using ps (to discover its process id) and stop.

> ps // list running background functions


0: toggle13 // toggle13 is number 0
> stop 0 // or stop * or ^C to stop all
>
Run Command: Optional [,snoozems] argument and changes to
snooze()

33
The “run” command has an optional snoozems argument to provide Use the startup function to do a run on your top-level function and your
control over how often each background task is run. This is convenient application can run in the background while you have control of the key-
for tasks that run on a fixed timer: many functions can dispense with board to poke at it:
the snoozing thing entirely if the runtime interval is known when the
> function startup {run myapp}
function is started.
> boot
bitlash here! v2.0...
For example, this will run the function t1 every 27 millis or so:
> ps
run t1,27 0:myapp

If the optional snoozems argument is not specified it is treated as zero: Don’t delay(); use snooze() instead
in other words, you must manage the snooze interval in your function’s
If your objective is to present the illusion of multitasking, you should
code; see below.
avoid using the delay() function in functions, since everything else
This change also has a small impact on semantics of the snooze() func- comes to a screeching halt while delay() is happening.
tion. Previously, snooze() would set the time-at-which-the-task-is-
Foreground keyboard entry may become sluggish if you have many
eligible to run immediately when called.
tasks with delay()s more than a few millis each.
The new behavior is subtly different: the scheduling takes place some-
Bitlash provides the snooze(ms) function to give your background func-
what later, when the function exits the current invocation, not at the
tion tasks a way to delay without hogging the CPU. Bitlash suspends a
time of some call to snooze(). Bitlash maintains a snoozems value for
task which calls snooze() until the specified number of millis has
each background task; by default it is zero, and the task is called as
passed.
fast as the round-robin gets back to it. If you specify a value in the run
command or by calling snooze, this value is saved and applied in the NOTE: Calling snooze() has no apparent immediate effect. Your func-
rescheduling calculation when the task exits. tion continues to execute, if there is further code after the snooze(). But
bitlash will not re-enter your task until the specified time has passed.
Run Your Application Automatically in the Back-
ground Here is an improved toggle13 that uses snooze() instead of delay():

> function snooze13 {d13=!d13; snooze(100);}


> run snooze13

34
>

Since snooze() means “don’t call me again for a while” instead of


“please spin away some time”, you will find that your foreground typing
and responsiveness of other background functions is much improved
compared with “run toggle13”.

Example: Asynchronous Background Tasks


Here is an example of three asynchronous background tasks each do-
ing its thing on its own little timeline, using snooze() to set its calling in-
terval:

> function chirp {print "chirp ",; snooze(2500);}


> function eep {print "eep ",; snooze(800);}
> function ribbit {print "ribbit ",; snooze(3500);}
> function nightfall {run eep;run chirp;run ribbit;ps}
> nightfall
0:eep
1:chirp
2:ribbit
> eep chirp ribbit eep eep eep chirp eep
ribbit eep eep chirp eep eep ribbit eep
chirp eep ^C

35
Section 11

Printing

PRINTING TIPS
Printing Overview
1. For simple printing use the print command:
print “hello, world”, 1, 2, 3; There are two ways to print in Bitlash: the legacy print command, and the printf() func-
2. A C-like printf() function is also built-in: tion. The print command is handy for printing basic values without much formatting con-
printf(“%3d”, 7); trol; it was part of Bitlash 1.0 and is partly retained mainly for backwards compatibility.
The “:x” format specifier language will be deprecated in Bitlash 2.1, leaving only the print-
3. Print to any IO pin at your choice of baud
rate ing of basic values.

4. See the examples/ folder for code to The printf() function is new in Bitlash 2.0. It is more compatible with standard C and
customize the output handler much more capable. It will be the supported printing pathway going forward.

printf(“format string”, value1, value2,… valueN);


The printf() function prints values to the console.

The values are printed under control of a format string, which must contain a specifier for
each value to be printed.

Specifiers are of the format:

Format Specifier := <percent-sign> [<pad-char>] [<width>](<pad-char>]


[<width>) <specifier>
Example: printf("%d", 7) prints "7"
Example: printf("%3d", 7) prints " 7"

36
Example: printf("%03d", 7) ! prints "007" Special Characters
Example: printf("%s","Hello") prints "Hello"
Example: printf("%%") ! prints "%" The percent sign signals a format specifier in the string. To print a per-
cent sign, you must double it:

printf("%%") prints '%'


Table of printf() Format Specifiers
The printf() function does not automatically provide a newline at the
end of printed output. You must indicate line endings using the ‘\n’ char-
Specifier Print Format Pad acter:

blank unless ‘0’ is printf("The time is: %d\n", millis);


d Decimal, signed
specified You can specify arbitrary hex values in a string constant using \xHH no-
tation:
blank unless ‘0’ is
x Hexadecimal
specified printf("\x30"); prints '0'

blank unless ‘0’ is


u Decimal, unsigned Here is a table of the special characters supported by Bitlash in string
specified
constants:
blank unless ‘0’ is
b Binary
specified
Char Value Description
specifier String blank \r 0xd carriage return
c Character the char \n 0xa line feed
# Print-to-pin pin number \t 0x9 tab
% Print ‘%’ \\ ‘\’ a backslash

\” “‘ a double quote

\xHH HH 8-bit hex character HH

37
Specifying the baud rate in this way has the same effect as calling
Padding baud(4,4800): the pin will remain at the indicated baud rate until it is
changed again.
Normally, numeric values and strings are pre-padded with blanks to fill
out the specified field width. You can pre-pad numeric values with ze- ACCESSING SECONDARY UARTS WITH PRINTF
roes instead by adding a zero before the width character: If you are using an Arduino Mega 1280 or Mega 2560 with Bitlash and
you print to pin 18 then Bitlash will automatically use the Serial1 UART
printf("%03d", 7) prints "007"
rather than software serial for I/O. (There is currently no support in Bit-
lash for accessing Serial2 or Serial3 from printf.)
The “*” character used as a width
If the special character ‘*’ is used in place of a width specifier, the next Likewise if you are using a Sanguino with the AVR ATmega 644P proc-
value in the passed-in value list is used as the width: essor, I/O to pin 11 will use the second UART of the Sanguino rather
than software serial.
printf("%*d", 3, 7) prints " 7" - padded to 3 char-
acters with ' '
The Print Comand
Printing to Alternate Serial Pins This section documents the legacy Print command and its options.
You can redirect output to a non-standard serial pin using the ‘#’ speci-
The print command will be retained in Bitlash going forward, but the “:x”
fier, which picks up the pin number to use from the next value in the
sublanguage will be deprecated in a future version. Users are advised
value list:
to migrate to the printf() function with all due haste.
// prints "7" to pin 4 at the default 9600 baud
printf("%#%d", 4, 7) Basic Printing: a list of items
The simplest form of the print command causes bitlash to print out a
It’s a kludge, but the width specifier can be used to override the default
bunch of numeric values separated by spaces, followed by a newline:
9600 baud sending speed:
> print 1, 2+2, 1<<3
// prints "7" to pin 4 at 4800 baud
1 4 8
printf("%4800#%d", 4, 7)
>

38
The print command can print string constants as well as numeric ex-
pressions, as you may recall from the Hello World example: Here is a table mapping the Arduino equivalents for hex, binary, and
raw byte output:
> print "Hello, world!", 123
Hello, world! 123
To suppress the blank and automatic end of line, print a single value to print use :code example prints
followed by the comma, like this:
hex :x print 32:x 20
> print "Time:", // Prints Time: with no trailing
ascii byte :y print 32:y ascii space
blank or newline
binary :b print 32:b 10000
Printing special characters
bars :* print 3:* ***
The rules for special characters are similar to C. See Language for de-
tails on constructing string constants with arbitrary ascii characters.
Printing Bars
Hex, binary, and raw byte output
You can print a bar of N ’*’ characters using the : format specifier, as
You can specify a modifier to produce several different output types by shown in the example above. Any single-byte symbol will work (+-*/
appending “:spec” to any expression in a print statement. Perhaps an <>%:). Here’s a cheap, low-res oscilloscope on pin A3 with adjustable
example is quickest: temporal resolution:

> print 33, 33:x, 33:b, 33:y, 33:* > while 1: print map(a3,0,1024,10,50):*; delay(5)
33 21 100001 ! *********************************
Serial Output to Alternate Pins: print #n:…
Bitlash includes a software serial output capability which supports trans-
mitting on any available output pin at a user-specified baud rate. This
makes it straightforward to integrate additional serial devices with an
Arduino.

39
You send output to an alternate output pin using the “print #n:” con-
struct, where “n” is the Arduino pin number designator for the desired
the output pin:

> print #6:"EMERGENCY DESTRUCT SEQUENCE ALPHA CONFIRMED"

By default bitlash will send output at 9600 baud. If you require a differ-
ent baud rate use the baud function:

> baud(4,4800) // set baud on pin 4 to 4800


> print #4:"ATZ" // send some stuff on pin 4

Note: print #n: is blocking: background tasks will pause while output is
being printed.

EXAMPLE: CLEAR THE SCREEN ON SPARKFUN SERIAL LCD


Here is an example combining the use of printing to an arbitrary pin,
printing special characters, and (importantly!) suppressing the inter-
item and inter-line spacing that bitlash would normally generate. As-
sume the serial LCD is on pin 4 and that all pin setup and baud rate ini-
tialization has been performed. Then this macro will clear the screen:

function cls {print #4:"\xfe\x01\",;}

40
Chapter 4

Extending
Bitlash

User Functions

The Bitlash API


Section 1

User Functions

USER FUNCTIONS While Bitlash functions are a handy and straightforward way to extend Bitlash, there are
cases where you need native C code to get closer to the hardware, perhaps for speed or
1. Copy from an example! See the examples/
folder to interface with a custom peripheral.

2. addBitlashFunction() registers a new Bitlash provides an easy way to call C functions from Bitlash code, just like the Bitlash
function handler with Bitlash built-in functions. In effect, you add your functions to the Bitlash function library, and they
3. Your function must be declared as: numvar become callable from the Bitlash command line.
newfunc(void)
The work happens in a function named addBitlashFunction() that is exposed as part of
4. In your C fuction, the passed-in argument the Bitlash API. You call addBitlashFunction() in your sketch to register your C function
count is getarg(0) and the arguments are
with Bitlash and associate it with a function name. Then Bitlash calls your C function
getarg(1)..getarg(N)
when it is invoked from the command line (or a function…).

Bitlash 2 introduces a new variable-argument scheme, using the getarg() function to fetch
passed arguments from the interpreter core. Users of earlier versions will want to care-
fully review the section on fetching passed arguments below.

If you follow a few rules for setting up your function, you can wrap it in Bitlash without hav-
ing to write a line of parsing code. You get all the parsing, functions, printing, and the rest
of the runtime library for free.

Which is why it is worth reading the next section to learn how to set up your C function so
Bitlash can call it properly.

Declaring the C function

42
Bitlash exposes the C variable type named numvar representing (in You call addBitlashFunction() from your C startup code to register
the Arduino version) the “signed long” integer data types. All internal your function with Bitlash.
calculations are done using fixed-point arithmetic in this precision.
addBitlashFunction() takes two arguments: * a name for the new func-
So the first rule is that your function must return a value of type num- tion * the function handler to call with “(bitlash_function)” cast before it
var.
While you can call addBitlashFunction() any time, one would normally
Here is a simple example to walk through the plumbing. This example call it from setup(), like this, to complete the code for the example:
code is in the examples folder supplied with Bitlash, so you can open it
void setup(void) {
in the Arduino IDE by selecting File -> Examples -> bitlash -> userfunc-
initBitlash(57600); // must be first to initial-
tions if you’d like to follow along.
ize serial port

Suppose for some reason we need to be able to grab the count value
// Register the extension function with Bitlash
from the AVR’s internal Timer1 timer and use it in Bitlash. // "timer1" is the Bitlash name for the func-
tion
In the Arduino sketch, we declare a user function named “timer1”, tak-
// (bitlash_function) timer1 tells Bitlash
ing no arguments, returning a numeric Bitlash value containing the where our handler lives
timer count register value we’re after: //
addBitlashFunction("timer1", (bitlash_function)
numvar timer1(void) { timer1);
return TCNT1; // return the value of Timer 1 }
}
...void setup(void)... void loop(void) {
runBitlash();
This completes the definition of the user function. What remains is to }
call addBitlashFunction() to register this new handler.
The setup() function initializes Bitlash and then calls addBitlashFunc-
Registering a Function With addBit- tion() to install timer1(). The loop() function runs Bitlash as usual.

lashFunction() Now when Bitlash starts up it knows a new word:

bitlash here! ...

43
> print timer1(), timer1(), timer1() The function argument to addBitlashFunction() provides Bitlash with
22 194 67 the name of the C function handler you wrote to handle your user func-
tion. A small syntactic complexity: It is required to cast your function to
The Function Name the type “(bitlash_function)” to pass it to Bitlash, which is why the man-
tatory text “(bitlash_function)” appears before the function name in the
A function name is a string constant of up to IDLEN (11) characters,
example:
like “timer1”. It must start with a letter, and may contain letters, num-
bers, and the underscore ‘_’ and period ‘.’ characters. ...
addBitlashFunction("timer1", (bitlash_function) timer1);
Overriding the built-in function names is not supported; the user func-
...
tions are searched last so if you use a built-in name your function will
never be called. If you omit the cast the compiler will complain about function type mis-
matches.
Fetching Passed Arguments with getarg()
Your bitlash_function is declared (void). How does it get argument val-
NOTE: Maximum Number of User Functions
ues from Bitlash? Bitlash ships with MAX_USER_FUNCTIONS set to 10 and will throw
an exception if you try to install more.
Starting with Bitlash 2.0, a function does not need to accept any particu-
lar number of arguments. The arguments being passed to your macro If you need more functions, adjust the definition of MAX_USER_FUNC-
are available to your code as via the Bitlash function API point getarg(). TIONS in bitlash-functions.c.

The value returned by getarg(0) is the count of arguments passed to


your function. You can fetch the value of those arguments using ge-
Coding User Functions
targ(1), getarg(2),… and so on to getarg(getarg(0)).
Here are some notes on limitations and issues you may need to ad-
See the file examples/tonedemo.pde for an example of how to use ge- dress when coding a user function.
targ(0) to control how your function processes a variable number of in-
put arguments. Sharing the CPU
Calling delay() from a user function is generally to be avoided, since
The Function Handler Argument
delay() blocks everything else from happening.

44
Bitlash background functions don’t (well, can’t) run while your function Printing From User Functions: Console Redirection
is running, since they get time on a poll from loop(). This may affect
your design. Printing from a user function using the Arduino Serial.print() function
works as usual: it goes to the console as you would expect.
Calling Internal Bitlash Functions
You can also print through Bitlash using the Bitlash printing primitives:
Generally it’s fair game to call any internal Bitlash functions you want sp(), spb(), and speol(), about which you will find more in
from your user function; you’re inside the interpreter, after all. But there bitlash-serial.c. If you use the Bitlash printing primitives, you will gain
are things you should be cautious about in addition to the CPU time is- the benefit that any serial output redirection that is in effect when your
sue discussed above. function is called will be applied to your printed output. In other words,
your function can automatically print to whatever pin Bitlash has se-
The interpreter is not re-entrant, and is halfway through parsing and
lected as the output pin.
executing a command line when it encounters your function reference.
Don’t re-enter Bitlash by calling doCommand or runBitlash from your Here’s an example to clarify. Suppose we have these two user func-
user function. tions wired up as sayhi1 and sayhi2:

Avoid recursion and stack-local storage where possible in user func- void sayhi1(void) { Serial.print("Hello"); }
tions. Bear in mind that your function is executing inside the parser and void sayhi2(void) { sp("Hi"); }
is competing with the parser for stack space. Deeply nested recursion Consider this bitlash code:

from a user function can cause a stack overflow, and local variables in
print #3: sayhi1()
your function only make this happen faster. print #3: sayhi2()
print #4: sayhi2()
You can call the get_free_memory() function (which handles the Bitlash
free() function) to see how much stack space is available when your The first line will print “Hello” to the serial console. Serial.print() output
function runs. always goes there.

Unfortunately, it is very difficult to provide hard and fast rules about The second Bitlash command will print “Hi” to the device on pin 3,
how much stack will be required for your application; experimentation is since “redirection to pin 3” is in effect when the function is called.
the best way to be sure. Personally, I get uncomfortable when free()
goes below 200 but I have seen applications that require much more.

45
Likewise, the third command will print “Hi” on pin 4; thus a single user
function can drive multiple output streams without needing special
code.

Examples
See the examples folder in the Bitlash distribution for more. You can
load examples in the Arduino IDE using the File -> Examples -> bitlash
menu.

46
Section 2

The Bitlash API

THE BITLASH API Your Arduino C program can interact with Bitlash using the functions documented here.
Of course, in the tiny and open world of Arduino most everything is visible globally. So
1. In setup(): initBitlash(baudrate);
feel free to dive in and call what you need. The entry points documented here are in-
2. in loop(): runBitlash(); tended to be reasonably well hardened for third party use.
3. It’s C. Call anything you like. See src/
bitlash.h initBitlash(baudrate);
4. A few useful API entry points are You must call this first, normally from setup(), to initialize Bitlash and set the serial port
documented in this section baud rate.

runBitlash();
You must call runBitlash() from your loop() function to make Bitlash go. The more fre-
quently you call runBitlash(), the more smoothly foreground and background activity will
run. If you don’t call runBitlash(), nothing will happen.

Example: Simple Integration

This is the minimum possible integration, and in fact it is the bones of the code that you
will see at the bottom of bitlashdemo.pde:

void setup(void) {
initBitlash(57600);
}
void loop(void) {
runBitlash();

47
// YourOtherCodeHere(); Bitlash will buffer and echo each character until you send a carriage re-
} turn ‘\r’ or linefeed, whereupon it will execute the line, the same way it
works from the console.
doCommand(char *command);
See the examples/bitlashtelnet2.pde telnet server for a sample integra-
A simple way to control Bitlash is to use the doCommand() function to tion using doCharacter().
execute commands from your code. Your code can call doCommand()
to make Bitlash “do stuff” – anything you can type, actually, up to the Console redirection with setOutputHandler()
buffer size limit. Here’s a dumb example that leads up to our next big
You can arrange to capture all the output that Bitlash would normally
case study: this code spends a lot of energy looking for the precise milli-
send to the console serial port, and redirect it to suit your application.
second to beep at the top of the hour:
Use the setOutputHandler() api to direct Bitlash to route its output to
void setup(void) { your character-handling function, which should be defined as taking a
initBitlash(57600); single byte and returning a void, as in:
}
setup() {
void loop(void) { ...
runBitlash(); setOutputHandler(&serialHandler);
// beep at the top of the elapsed hour }
if (millis() % (60*60*1000) == 0) {
! ! doCommand("beep(11,440,1000)"); void serialHandler(byte b) {
! } ...
} }

Lots of ways to do this better (read on for one example), but the takea- There are four examples in the Bitlash distribution that show how this
way point is that your C code can drive Bitlash. works:

doCharacter(char c) See examples/loutbitlash.pde for a silly example that optionally makes


all the output uppercase (therefore loud).
It is also possible to drive Bitlash’s internal command line editor one
character at a time. This is convenient if you have a character input de-
vice.

48
See examples/bitlashtelnet.pde for an example implementing both in- assignVar(char var, long value);
put injection and output capture. examples/bitlashtelnet2.pde is similar
but uses the doCharacter() api instead of doCommand(). Assigns the (signed long 32-bit integer) value to the indicated Bitlash
variable.
And of course the Bitlash web server, BitlashWebServer, uses this con-
assignVar(0,42); ! // a=42
sole redirection capability. See examples/BitlashWebServer.pde

// notation to calculate the var index:


User Functions: addBitlashFunction() and getArg()
assignVar('i'-'a', 33); ! // i=33
You can extend Bitlash at compile time by adding “C User Functions” to
the built-in function library. See the [User Functions|userfunctions) long x = getVar(char var);
page for details.
Returns the value of the given Bitlash variable.

Manipulating Bitlash Variables from C incVar(var);


Bitlash has 26 variables named a through z. These are 32-bit signed
Increments the designated Bitlash variable.
integer values. Your code can read and write these values using a few
simple functions. This allows your C code to control code running in Bit- incVar('i'-'a'); ! // i++
lash, and vice versa.

You refer to a variable using an integer index in the range [0..25] corre-
sponding to ‘a’..‘z’. For example, here is how your code could use the
getVar command to read out the value of the bitlash variable ‘t’ and put
it into the signed long C variable named ‘temperature’:

void loop(void) {
...
long temperature = getVar('t'-'a');
...

Here are the three API functions for Bitlash variable manipulation. Ex-
amples of their use are shown below in the clock application.
49

You might also like