Built In Functions And Interrupt Routines

Types of Instruction

The BASIC interpreter accepts three types of instruction:

  • Built-in Functions
    • General-purpose Input and Output Functions
    • File System Functions
    • Bluetooth Functions
    • String Functions
  • Interrupt Routines
  • Command-Line Interface
    • Built-in Commands
    • Editing
    • Interactive Use of Built-in Commands

Interrupt routines and functions are built-in and cannot be changed. An interrupt routine is executed only in response to a specific event. Built-in functions are called as an assignment to a BASIC variable. Commands are executed as a normal program line of code.
Capitalization is fundamentally important as the interpreter will not generalize. "A" and "a" are not the same character. Interrupt routines are preceeded by @ and are Capitalized. Functions are NOT capitalized. Commands are written in all CAPS.

Built-in Functions

Built-in functions are implemented in native code and cannot be changed. They fulfill time-critical functions such as Bluetooth functions, external input and output functions, file-system functions, and others.
All built-in functions are called as an assignment to a BASIC variable. They can have one parameter or no parameters. Functions are all lower case. A parameter is defined as any one of the following:

  • a string (S)
  • a variable (V)
  • no parameter (N)

Examples are:
A = atoi "1234"
A = atoi $0
A = atoi $0[5]
The string index parameter is a substring parameter to the function.
Each function has a particular parameter.

List of built-in Functions

General Purpose Input and Output File System Functions Bluetooth Functions String Functions
pioin V open S slave V atoi S
pioout V append S master S a2toi S
pioget V close N inquiry V xtoi S
pioset V read V cancel N x8toi S
pioclr V write V link V hex8 V
pioirq S delete S unlink V hex16 V
psget V size N disconnect V strcmp S
psset V exist S name S strlen S
uartcfg V seek V message S
baud V info V ftp S
uarton N rename S modemctl V
uartoff N erasefs N getaddr N
date S load S getuniq V
reboot N status N
nextsns V success N
sensor S getname S
setdate S maxpower V
zerocnt N bizcard S
readcnt N enable V
uartint N disable V
i2c V shell N
break V dfumode N
lcd S unpair S
auxdac N getconn N
ring N dun N

General-purpose Input and Output Functions

Function Description
nextsns This function schedules the reading of all internal sensors within the number of seconds provided as a variable. After taking the reading, the interrupt routine @SENSOR will be called. This happens only once. The next reading must be scheduled. "nextsns 0" turns this function off.
sensor Returns the following five last-read values of the sensors to the string variable used in the assignment: AIO0, AIO1, temperature, RSSI-slave, RSSI-master. The analog values range from 0 to 1800. When the correction factors (@0008 in config.txt) are used, the values can be calibrated to the actual reading. It is usually expressed in millivolts, depending on the hardware. In addition, the temperature reading is placed into the string given as a parameter, and the relative signal strength indicators for the incoming slave connection and the outgoing master connection. Each number takes 5 character positions in the string: E.g. "0112 1850 27 1 -1"
pioin This function configures the port as an input. An expression (a number or a variable) specifies the port number. Port numbers 1 to 12 can be used.
pioout Configures the port as an output. Port numbers from 1 to 12 can be used.
pioget Reads the value of the port and returns it into the variable specified
pioset Sets the port active (high). If the port is configured as an input, it activates a pull-up resistor on that input. In addition "pioset 20" switches the LED on the AIRcable SMD on (pin LED1).
pioclr Sets the port to inactive (low). You can clear the LED from the AIRcable SMD by doing "pioclr 20"
pioirq This function gets a string like "P00010000000". It starts with a 'P' and follows with '0' and '1' for the 11 available digital input pins. This function activates the input PIN to create interrupts when a change occurs. See @PIO_IRQ interrupt routine below.
date This function writes a date string into the string given as a parameter, e.g., "20050531T192100Z"
reboot This function reboots the processor in 2 seconds. All connections will be terminated.
uartcfg Configuration of the UART interface is coded in one integer value ranging from 128 to 255. The 8 bits are coded like this: 1PPSBBBB. For even parity, set 0x40; for odd parity, set 0x20; for two-stop bits, set 0x10. Baud rates are enumerated: 0 is 1200 baud, 1 is 2400 baud, 2 is 4800 baud, 3 is 9600 baud, 4 is 19200 baud, 5 is 38400 baud, 8 is 115200, and 12 is 1382400 baud.
baud A simpler function that changes the baud rate of the UART to the baud rate specified in the variable. Baud-rate values are specified in 100-baud values, such as 96 for 9600 baud and 1152 for 115200 baud. e.g. "A = baud 96"
break The break command creates a break condition on the UART port. The TX line will be held low for a longer period of time.
psget This command allows access to the configuration of the AIRmote devices as stored in the file config.txt. The argument is the key number as described in the config.txt file format. The result is placed in the string given that describes the configuration key in the same format.
psset Enables writing to the configuration. Argument is the length of the string. The string that will be stored in the configuration must have the correct format to be successful.
setdate Function to allow to adjust the clock. The string parameter contains a valid date string such as 20060123T085854Z.
uartoff This function decouples the UART input from the BASIC input handler. If the UART port is connected to a streaming data source the system has to process the input even if no BASIC application receives the input. To improve performance, switch off the UART if not needed.
uarton This function connects the UART input stream with the BASIC input handler system again. Normally these functions are not required, since the UART input stream is usually connected.
uartint This function schedules a one time interrupt if data is received on the UART. The routine @UART is called. It is then the responsibility of the routine to read data and maybe reschedule the interrupt. No parameter.
readcnt The AIRcable has an internal seconds counter you can read when ever you want. Once the counter reaches 32767 it will reset to -32768. The counter will be set to zero when zerocnt is called, on booting you can't determinate the counter state. You need to zero it manually if you want to use it.
zerocnt Restart the internal seconds counter.
i2c: This special functions allows the user to communicate using the i2c port. Check here for more details: Example at: http://code.google.com/p/aircable/wiki/GenericI2Ccode
lcd The AIRmote allows you to take control over some 8 chars 11 segments per char LCD panels. The OS all ready includes fonts, and has some special chars to have more control over what's displayed. The command to control what the LCD is displaying is lcd, this command takes an string as argument, and will replace the current display content with the string content. If the argument is null (A = lcd) then the display will be cleaned. All the characters will be displayed in CAPS.
Control characters:
  • ".": adds the decimal point to the previous character.
  • ",": adds a coma to the previous character.

NULL ( value equal 0): Will skip the char, and not delete the previous value.
Special circuitry is needed to make the LCD work, you can get the schematics at: (COMING SOON)

auxdac The AIRmote has an 8 bit DAC Digital to Analogic Converter integrated in it. It allows you to generate continuous current signals, with values that goes linearly from 0V to VBATT with 255 steps.
ring You can connect a buzzer to the AIRmote and make it make some sounds by calling ring. Ring takes an argument from 0 to 100 allowing you to take control over the volume it makes the buzzer ring.

File System Functions

A BASIC program can have one open file. A file name can be up to eleven characters long. The file system holds four files.

Function Description
open This opens the file and sets the file pointer to the beginning of the file. The parameter is a string that specifies the name of the file.
append This opens the file specified but puts the file pointer to the end of the file. If the file does not exist, it will be created.
close This closes the open file. If the file was overwritten at this time, the file system cleans up unused blocks and recalculates the size.
delete The file specified will be deleted from the file system. The file must be closed before it will be deleted.
erasefs This deletes the whole file system. All data in the files are lost. The files AIRcable.bas and config.txt are not erased. No parameter.
exist Returns non-zero if the file with the name specified already exists in the file system.
info This parameter is an integer from 0 to 3 specifying the index number of a file in the file system. The file's information (name, size, date) is put as a string into $0.
load This function allows you to load a BASIC program from the file system into the BASIC interpreter. The parameter is the name of the file to load. Lines specified in the file will overwrite lines in the existing BASIC program. If @ERASE is in the file, the existing BASIC program will be erased. Otherwise, BASIC programs can be partially loaded using this function. Existing lines should be deleted when not needed, using just the line number and a space in the new file.
read The parameter specifies the number of bytes to be read. The result will be placed into $0. The function returns the number of bytes read. A maximum of 32 bytes can be read. It returns zero when the end of the file has been reached.
rename A file that has been opened can be renamed to the string given. It is only successful if a file with the new file name does not exist.
seek Places the file pointer to the specified byte number in an opened file.
size Returns the number of bytes the opened file contains. The file has to be opened.
write Writes the number of bytes from $0 into the open file. It returns the number of bytes written.

Bluetooth Functions

The BASIC program controls the Bluetooth access and the serial-port profile SPP

Function Description
slave This function opens the Bluetooth device for incoming serial connections. The parameter specifies the number of seconds the port stays open. After that, the port closes again and the application has to call "slave" again. Note that the UART and the slave SPP port are not being connected automatically. Use the link command. As soon as another Bluetooth device successfully connects to this device, an interrupt routine @SLAVE will be called. the function "slave" now takes negative numbers. It means that the unit becomes undiscoverable for that amount of time. After slave makes a timeout @IDLE is triggered. You can call slave 0 at anytime to cancel @IDLE triggering, and to removes SPP register.
Since OS version 30 special care is taken when the argument absolute value is 1: +1 or -1, in this cases the device is either registered to become visible (+1) or invisible (-1) but then after a timeout @IDLE is not triggered.
dun This command behaves exactly as slave except instead of registering an SPP profile it registers a DUN (Dial-UP Network) profile. Both SPP and DUN behave exactly the same, but some cell phones and pda's can't connect to networks (like internet) over SPP.
master Creates a connection to an SPP channel of another Bluetooth device. The parameter is the Bluetooth address as a string. When the connection is successful, the interrupt routine @MASTER is called.
inquiry To find other Bluetooth devices in range, call this function. The parameter is the number of seconds the inquiry is active. When a Bluetooth device is found, an interrupt routine @INQUIRY is called.
cancel This function is used in the inquiry-result interrupt routine to stop further inquiry results from being scheduled.
link Use this to link either two of the three available channels together so they route data through. The parameter is a number that determines which channel to link. For example: 1 links the UART and the SLAVE channel, 2 links the UART and the MASTER channel, and 3 links the SLAVE and the MASTER channel for range-extender functions.
unlink This function disconnects the channels. Use the same values to determine which one should be disconnected.
disconnect This command disconnects one of the over-air connections. The parameter disconnects the SLAVE connection; non-zero disconnects the MASTER from the other Bluetooth device(s).
message This function allows an OBEX vNote transfer to another Bluetooth device. The content of the string parameter will be placed in the BODY part of the vNote to be sent. The 12 digit Bluetooth address to where the message is sent is in $0 as a string.
ftp This function allows the transmission of a file in the e2fs file system to another Bluetooth device. The parameter of the call is the file name on the remote device. The address to which the file is being sent is a string in $0. The file that is to be sent has to be opened by the e2fs open call before the ftp function call, the ftp command will automatically call close. This example sends a file called test.txt to another device. The file created there is named "from.txt"
91 S = open "test.txt"
92 $0 = "0013105D4CAC"
94 U = ftp "from.txt"
modemctl To send a modem-control command to an active SPP connection, this function can be called in response to a change of the DTR input line on the AIRcable Industrial Male device. The value 0 as a parameter sets the modem-control, a 1 resets it. This command should not be used when two SPP connections are active.
getaddr To receive our own Bluetooth address as a string in the $0 variable, call this function with no parameter.
enable and disable Disable removes the FTP or OBEX record. It effectively disables the FTP and/or the OBEX server. Parameter is a bitmap. 1 is the FTP service. 2 is the OBEX service. 3 as a parameter means that both FTP and OBEX service are disabled . Enable enables the service records again.
getuniq Gets a string parameter and prints the unique number into the first five characters of this string, with leading zeroes.
shell When a slave connection was successful the user can start the BASIC shell. The BASIC shell is a command line interpreter that controls the BASIC program execution. The built-in function "A = shell" should only be used within the @SLAVE . The BASIC shell will echo all the chars it receives back to SPP, so there's no need to enable echo on your terminal emulator.
unpair This function which removes the pairing information from a single Bluetooth address given or it removes all stored pairings when the parameter is 0. Note: the first paired device is considered the default device and cannot be removed individually.
getconn Returns the address of the recent SPP connection to the BASIC program. The application can then find out who has connected. It can be used to do unpair or disconnect.
status This function returns the state the Bluetooth processor is in. 5 states are defined and encoded into one decimal number. If an inquiry process is busy, 10000 will be added to this number. If a message transfer or an ftp transfer initiated by the AIRcable is in progress, 1000 will be added. If the device receives an FTP or a message, 100 will be added. If a master connection is established, 10 will be added and if a slave connection exists, 1 is added to this status number. This information can be used to determine when an operation is finished.
As an example, this subroutine waits until an FTP transmission completes.
0 REM wait until ftp/msg successful
420 E = status
421 IF E < 1000 THEN 429
422 WAIT 5
423 GOTO 420
success This function returns whether the last operation (ftp or message) was successful or not. If the return value is 1 then the operation was a success. It is -1 if an error occurred. It is set to 0 if a connection could not be established.
name This command temporarily changes the user-friendly name of the Bluetooth device that is displayed during the inquiry process. The parameter is a string. The default is the configured name in the config.txt file, a space, and the unique 5-digit number generated.
getname Returns the name of the confg.txt file device (Bluetooth friendly name) into the given string. Getname does not return the actual name of the device that has been changed using the name function.
maxpower Allows the adjustment of the maximum RF output power for all communications. Normally this is set by the configuration parameter @0004 = 0000 0006.
bizcard This function sends a business card from an open file to another Bluetooth device. The argument given is the BT address. The file to send must be opened before. The contents should follow the OBEX specification of business cards. Some devices will not accept this if the content is not correct. The OBEX PIM item transfer for vCards will be used to send the content.
This is an example for a vCard accepted by PCs, PDAs and cell phones:
BEGIN:VCARD
VERSION:3.0
N:Smith;Bill
ORG:Wireless Cables Inc.
TEL;PREF;WORK;VOICE: 408 850 1884
END:VCARD
dfumode This function will to put the AIRcable into firmware upgrade mode. The function is not available on all AIRcable OS products. Right now only the AIRcable Industrial support firmware upgrade. In addition on the AIRcable Industrial, when the security disable jumper is plugged in during reboot, the device will automatically go into firmware upgrade mode. Also the BASIC program will be erased.

String Functions

Function Description
a2toi This function turns two number characters into an integer value. A string index variable as a parameter provides the start point. No termination is necessary.
atoi This function turns a specified string into an integer. The limit is 16 bits. If the characters are not numbers - or during overflow - the result is zero.
hex16 This function prints a variable given as exactly four hex numbers into $0. For example: if B contains 27, then A = hex16 B will print "001B" (in) the first four positions of $0.
hex8 This function prints a variable given as two hex numbers into $0. For example: if B contains 27, then A = hex8 B will print "1B" into the first two positions of $0.
strcmp This compares the given string with $0. The result is 0 if the strings are the same, -1 when the string is less than $0, and >0 if the string is greater than $0. If one string is shorter than the other, the string is compared against the substring. For example, "AIRmote 1234" is equal to "AIRmote".
strlen This returns the length of the string given as a parameter. This command is useful when writing into the file system.
x8toi This function turns exactly two hex numbers into an integer value.
xtoi This function turns exactly four hex numbers in a string into an integer value. A string index variable can be used as a parameter.

Theories of Operation

On the AIRcable Industrial (and other AIRcable OS based devices) a BASIC program controls the Bluetooth baseband processor. Since all operations (Bluetooth, BASIC, timer, etc.) are running on the same processor the device is implemented as a multi tasking system where several tasks perform operations concurrently. The BASIC program controls the multi-tasking system underneath it.

Routines - Interrupts

The BASIC program is organized in routines. Each routine is a section in the BASIC program that starts with @ROUTINE and ends with RETURN. These routines are like interrupt routines in an operating system. The BASIC interpreter knows twelve of these routines:

  • @INIT
  • @IDLE
  • @SLAVE
  • @ALARM
  • @SENSOR
  • @PIO_IRQ
  • @MASTER
  • @PIN_CODE
  • @CONTROL
  • @FTP
  • @MESSAGE
  • @INQUIRY
  • @UART

The important programming principle is to keep the routines short. Routines should not occupy the processor for very long and then should end quickly. This allows the Bluetooth baseband processor to execute other tasks that are important in the functioning of the entire system. Routines that do not end (even with WAIT) will block the system.
These routines are scheduled for execution either by the system automatically, by other parts of the program, by external hardware, or by Bluetooth events. Some routines interrupt the execution of other routines because they have a higher priority. For example, the @PIN_CODE routine has the highest priority and will interrupt any other routine. Otherwise, routines are scheduled to run after the current routine has finished.
The BASIC interpreter is still running even when the Bluetooth device is connected or even when the BASIC Shell is running.
When data is streaming through the data ports (linked SPP and UART), the BASIC program execution is slowed down. The timing may be affected by the program status.
Routines are preceeded by @ and are Capitalized (for example, @INIT, @IDLE, @SLAVE, etc.). The line number of the start of that routine must follow the declaration.
An interrupt is executed only in response to a specific event. The RETURN at the end of an interrupt routine does NOT execute the next line of written code. Instead, it releases the interrupt routine. Basically, they are subroutines that end with RETURN.

@INIT 30
30 A=pioout 3
31 RETURN

Interrupt List

Interrupt Explanation
@ALARM Alarms can be scheduled from the BASIC program using this routine. After a number of seconds are specified in the function, this interrupt routine is executed.
@CONTROL This routine will be executed when there is a modem request through the SPP interface. If the RTC bit is set in the message, the character '1' is put into the string $0. If it is clear, a '0' will be in the first place of $0.
@FTP Whenever a file is received over FTP, after the file has been received @FTP will be triggered. The name of the file is the name provided by the item sender. If the name is longer than twelve characters, the part before the '.' will be shortened to eight characters.
@IDLE After @INIT finishes, and each time the slave channel close (because the connection was lost, or because there was no connection request), the idle routine is running.
@INIT This is the routine that runs when the AIRmote starts up. This routine initializes the digital input and output lines. It may also trigger an alarm to blink the LEDs.
@INQUIRY Every time another device is discovered during the inquiry process, this routine starts up. The result of the inquiry is in $0. It starts with the Bluetooth address followed by the name of the remote device. The name starts at $0[13].
@MASTER The master routine is running when an outgoing connection request is successful.
@MESSAGE Whenever an OBEX item is received, the item is stored in the file system. The name of the file is the name provided by the item sender. If the name is longer than twelve characters, the part before the '.' will be shortened to eight characters.
@PIN_CODE Whenever another Bluetooth device requests a connection, a PIN code must be supplied. The Bluetooth address of the device that requests the PIN code is $0. This BASIC routine returns the PIN code that the other Bluetooth device must use in $0.
@PIO_IRQ Digital input lines can be configured to create interrupts when the status is changed (See building function: pioirq.). This routine is started with the status of all digital input lines in $0. They are represented as a string, "P00010000000", for example.
@SENSOR When a reading is done, the interrupt routine is called with the result in the string parameter given. The reading consists of the corrected analog input in millivolts, the temperature in degrees Celsius, the relative signal strength of the slave SPP connection, and the RSSI of the master SPP connection, if present.
@SLAVE As soon as an incoming connection is established, the slave routine starts up.
@UART This routine is scheduled once when the uart interrupt is enabled via "A=uartint" and data is received on the UART port.
@ERASE An instruction @ERASE at the beginning of the file will insure that all previous code is removed before the new program is uploaded. If not present, the BASIC lines in the new uploaded code will be overwritten but lines not present will not be erased.
@UNPAIR On upload of the BASIC program this will instruct the device to remove all pairing information stored from previous successful connections.

The following two special commands do not require line numbers. They can be put at the first line of the BASIC program.

Command Explanation
@ERASE An instruction @ERASE at the beginning of the file will insure that all previous code is removed before the new program is uploaded. If not present, the BASIC lines in the new uploaded code will be overwritten but lines not present will not be erased.
@UNPAIR On upload of the BASIC program this will instruct the device to remove all pairing information stored from previous successful connections.

Running the Application using the Scheduler
The AIRcable Industrial knows 5 program-controlled, scheduled routines.

  • @INIT
  • @IDLE, @SLAVE
  • @MASTER
  • @ALARM
  • @SENSOR
  • And 5 hardware or event scheduled routines.
  • @PIN_CODE
  • @PIO_IRQ
  • @CONTROL
  • @MESSAGE
  • @INQUIRY
  • @UART

After the AIRmote has started and run through its @INIT routine, @IDLE will be called.
Normally you would open up the incoming serial connection port with the 'slave' command. The 'slave' command terminates immediately but leaves the port open for a number of seconds. If no connection was established, @IDLE will be called again. @IDLE is also called when a slave connection closes.

  1. Alarms (with the ALARM command) can be scheduled to have the routine @ALARM called within a number of seconds.
  2. The sensor reading scheduler which is started with the 'nextsns' command, can also be used for scheduling application execution. In the @SENSOR routine the next sensor readings can be scheduled.

See examples below for application execution scheduling practice.
The following interrupt routines interrupt the BASIC program execution: pair request, inquiry result , message and alarm. All other routines are scheduled for execution after all other scheduled tasks are completed.

The Interactive BASIC Shell

The AIRcable OS devices have a BASIC command-line interface on the slave SPP port. The BASIC shell allows the interactive start of BASIC routines and call-building functions. It can also be used to change, add, or delete BASIC program lines, it is also very usefull for debugging as you can check the code inside a routine with out the respective interrupt.
To log on, open a Bluetooth connection to the SPP port of the AIRcable device. When the connection is established, the @SLAVE routine starts up. In this example, there is a wait of 3 seconds for a '+' and an ENTER to start the interactive shell (otherwise it would link the SPP channel to the UART channel).
When the shell is activated, the system responds with a command prompt: "TAG$."

@SLAVE 300
0 REM 3 seconds timeout for the next INPUT
300 PRINTS "type + for shell: "
301 TIMEOUTS 3
302 INPUTS $0
303 IF $0[0] = 43 THEN 306
304 PRINTS "connected"
305 C=link 1
306 A = shell
307 RETURN

When the shell is active, it processes the input characters according to these rules:

  • command is terminated with a CR
  • command is < 32 characters
  • BACKSPACE deletes the last character
  • characters are echoed back
  • ctrl-C can be used to stop a running BASIC program started with RUN

SHELL Commands

The command-line interface has a few BASIC commands:

  • RUN 40: Starts a BASIC program at that line.
  • LIST: Prints the BASIC program to the console.
  • PRINT $1: Prints a single line of BASIC program, line number 1 in this case.
  • PRINT A: Prints the content of variable A
  • DATE: Prints the current time and date from the real-time clock
  • VERSION: Prints the version number of the AIRmote device.
  • FILES: Lists the files in the file system with name, size and date.

Editing using the Shell

A command starts with a line number, followed by a space and the BASIC command line that should be stored at this line number. Any string up to 32 characters long can be typed in. This is used for string variable initialization and BASIC program code. A line number with a single space following it deletes the line.

Interactive Use of Built-in Commands

Built-in commands can be called by typing the function name in lowercase letters. No variable assignment is possible like the use of build-in function in the BASIC code. Functions have three different types of parameters, as listed be fore: no parameter, one variable, or one string. The interface here is more limited than the BASIC execution engine.
For example, the string parameter can be "$4" with one space after the command. No expression evaluation is performed. It can be an immediate string starting after one space without any '"'.
The variable is a BASIC variable. Only one letter in caps is allowed after the space.

Limitations Summary

Variable Description
BASIC interpreter, 10 lines per second by default, maximum of about 250 lps
Bluetooth maximum of 4 connections at the same time (SPP slave, SPP master, FTP, and OBEX)
Expressions -32768 to 32767, 16-bit
File system maximum of 4 files (in addition to BASIC and config file), maximum of 48-Kbyte file-system space (configuration dependent)
FOR nesting 6 (variables A-F)
GOSUB 8 levels
Line length 32 characters
Line numbers 1-511 1-1024 depending on device
Parser expression parser recursive, maximum of 5 levels
Variables 20, 'A' - 'Z'

Troubleshooting

Due to system size little error checking is performed. In case of a system crash that leaves the device inoperable, use the security overwrite feature in hardware that stops the BASIC engine and keeps only the FTP and OBEX server ports unsecurely open.
Expression complexity is limited. The recursive parser can overrun stack space, which causes the system to reboot.
If a BASIC program stack overflow occurs (for example, too many interrupts scheduled), the AIRcable OS will delete the BASIC program from memory and will go into an unprogrammed state. The PIN code specified in the "config.txt" file is now the active security information.
The special BASIC variable Z can be used for debugging the BASIC code. If Z = 1 the lines the BASIC interpreter executes are printed on the UART. If Z = 2, it prints to the slave port, if Z = 3 it prints to the master SPP port.

This is very helpful to understand what's going on in a system where external events trigger the execution of the BASIC code.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License