Sensor and Status Data Format
The messages from the robot can be classified as being of two types, Status and Sensor messages. This data needs to be identified by its format to ensure that it is consistent with the input needs of the higher level system, such as G2. User informational messages do not necessarily provide information interchange between high and low level system. These messages, which are not covered here explicitly are always preceded by a carat symbol on a line to distinguish them from Status and sensor messages. Note that since LLAMA is a flexible language, the following commands may not encompass the current message selection.
All data strings begin with an identifier followed by data elements. Data elements received are separated by whitespace, which is generally the space character. The separation can consist of more than one whitespace character. The data string is always terminated by a newline.
Motion
Get drive motor status
dstat
response:
dstat XX YY
XX is the motion status of the axis, range 0 - 255, zero-leading hexadecimal. This is a bit-mapped result. The following describe the possible status:
XX (hex,decimal) =
00,0 Axis is enabled
80,128 Axis is shutdown
90,144 Axis shutdown due to position error
88,136 Axis shutdown due to power cage failure
84,132 Axis shutdown due to excessive current draw
81,129 Axis shutdown due to high motor temperature
a0,160 Bumper Switch shutdown
YY is the mode status, range 0 - 255, zero-leading hexadecimal. This is a bit-mapped result. The following describe the possible status:
YY (hex) =
80 Axis in Proportional Velocity Mode
40 Axis in Integral Velocity Mode
20 Axis in Trapezoidal Profile Mode
10 Axis in Position Control Mode
08 Axis is executing position move in Velocity Mode
04 Axis is executing a home command
b1 =1, Axis moving CCW, =0, Axis moving CW
b0 =1, Axis is moving, =0, Axis is stopped
Note: decimal values not given, because final value is dependent on b1 and b0.
dstaterr
There is a problem with EXDVR, check if DASC expert module software has been downloaded.
Get encoder errors
eec
response:
eec ST DR
ST is steer motor encoder errors in counts, range +/- 32000, decimal.
DR is drive motor encoder errors in counts, range +/- 32000, decimal.
eecerr
There is a problem with EXDVR, check if DASC expert module software has been downloaded.
Get instantaneous drive speed
ids
response:
ids XX
XX is the current drive motor speed in tenths of feet per second, range +/-40, decimal.
idserr
There is a problem with EXDVR, check if DASC expert module software has been downloaded.
Get instantaneous steer speed
iss
response:
iss XX
XX is the current steer motor speed in tenths of degrees per second, range +/-1000, decimal.
isserr
There is a problem with EXDVR, check if DASC expert module software has been downloaded.
Get current estimated position
pos
response:
pos TH Y X
TH is the current head angle in tenths of degrees, range +/-1800, decimal.
Y is the current y position in tenths of feet, range +/- 32000, decimal.
X is the current x position in tenths of feet, range +/- 32000, decimal.
poserr
The position blackboard has not been initialized from this process. The command “xyton” must be sent first.
posoff
The position blackboard was turned off in this processes earlier, it must be turned on using “xyton.” Note that this message may be received even though the position blackboard is actually on; this is because another process has linked to the blackboard. Note: improper use of “xyton,” “xytoff” and “xytclr” can result in the ultrasonics being turned off without a warning message.
Get steer motor status
sstat
response:
sstat XX YY
XX is the motion status of the axis, range 0 - 255, zero-leading hexadecimal. This is a bit-mapped result. The following describe the possible status:
XX (hex,decimal) =
00,0 Axis is enabled
80,128 Axis is shutdown
90,144 Axis shutdown due to position error
88,136 Axis shutdown due to power cage failure
84,132 Axis shutdown due to excessive current draw
81,129 Axis shutdown due to high motor temperature
a0,160 Bumper Switch shutdown
YY is the mode status, range 0 - 255, zero-leading hexadecimal. This is a bit-mapped result. The following describe the possible status:
YY (hex) =
80 Axis in Proportional Velocity Mode
40 Axis in Integral Velocity Mode
20 Axis in Trapezoidal Profile Mode
10 Axis in Position Control Mode
08 Axis is executing position move in Velocity Mode
04 Axis is executing a home command
b1 =1, Axis moving CCW, =0, Axis moving CW
b0 =1, Axis is moving, =0, Axis is stopped
Note: decimal values not given, because final value is dependent on b1 and b0.
sstaterr
There is a problem with EXDVR, check if DASC expert module software has been downloaded.
Ultrasonics
Receive range data:
ug
response:
ug XX XX XX XX ..... XX XX
XX is the range of the target, range 0 and 3-255, zero-leading hexadecimal. If XX is 0, then that ultrasonic is off else the range is tenths of feet.
uerr
The ultrasonic blackboard has not been initialized from this process. The command “ulon” must be sent first.
uoff
The ultrasonics were turned off in this processes earlier, they must be turned on using “ulon.” Note that this message may be received even though the ultrasonics are actually on; this is because another process has linked to the ultrasonics. Note: improper use of “ulon,” “uloff” and “ulclr” can result in the ultrasonics being turned off without a warning message.
Get current parameter blackboard:
up
response:
up ID FM0 FM1 FM2 MAX
ID is the interfire delay, range 1 - 255, decimal.
FM0 is the fire mask, range 0 - 255, decimal. This is a bit masking command. Bit 7 is ultrasonic 7, Bit 6 is ultrasonic 6, etc. If the bit is 1 then that ultrasonic is on, otherwise it is off.
FM1 is the fire mask, range 0 - 255, decimal. This is a bit masking command. Bit 7 is ultrasonic 15, Bit 6 is ultrasonic 14, etc. If the bit is 1 then that ultrasonic is on, otherwise it is off.
FM2 is the fire mask, range 0 - 255, decimal. This is a bit masking command. Bit 7 is ultrasonic 23, Bit 6 is ultrasonic 22, etc. If the bit is 1 then that ultrasonic is on, otherwise it is off.
MAX is the maximum range required, range 1 - 255, decimal.
uperr
There is a problem with EXDVR, check if ultrasonics expert module software has been downloaded.
Get current sequence blackboard:
us
response:
us ISP ILV FST NUM
ISP is the inter-fire spacing, range 1 - 24, decimal.
ILV is the inter-leave factor, range 1 - 24, decimal, but never more than the current inter-fire spacing.
FST is the number of the first sensor to fire, range 0 - 23, decimal.
NUM is the number of sensors to fire starting at the first sensor to fire, range 1 - 24, decimal.
userr
There is a problem with EXDVR, check if ultrasonics expert module software has been downloaded.
Bumpers
Get numbers of pressed bumpers
bpg
response:
bpg XX XX ... XX
XX ranges from 0 - 6, decimal. If no bumpers have been pressed, then XX is zero, otherwise the identification off all pressed bumpers is listed.
Get numbers of inactive bumpers
bps
response:
bps XX XX ... XX
XX ranges from 0 - 6, decimal. If all bumpers are active, meaning that they will cause an emergency stop if pressed, then XX is zero, otherwise the identification off all inactive bumpers is listed.
Speech
Get speech controller status
tg
response:
spstat YN XX
YN is either “yes” or “no,” lowercase, which states if the speech processor is currently “speaking.”
XX ranges from 0 - 127, decimal, and gives the current bytes in the speech microcontroller’s buffer.
spstaterr
There is a problem with EXDVR, check if speech expert module has been installed or reset.
Beacon
Find one beacon
bdisp
response:
bef COND CODE ALT INT AZI
COND is the signal quality of the beacon, range 0 - 255, decimal. This is a bit-masking command. The mask is given as follows, if the bit is one, that condition is true. (see p. 36 of DMR product manual).
b7 - Fault
b6 - Saturate Condition
b5 - Bad Intensity
b4 - Bad Code
b3 - Noisy transmission
b2 - High Threshold
b1 - Low Gain
b0 - No beacon
Note: COND = 1, is removed by the macro and identified as “bnone.”
CODE is the beacon identifier code, range 0 - 255, decimal.
ALT is the altitude angle in tenths of degrees of the beacon from the detector’s centerline, range +/-200.
INT is the intensity in hundreds of counts, range +/-162.
AZI is the azimuth angle from the detector’s centerline in tenths of degrees, range +/-200.
berr
The beacon blackboard has not been initialized from this process. The command “beon” must be sent first.
boff
The beacon blackboard was turned off in this processes earlier, they must be turned on using “beon.” Note that this message may be received even though the beacon blackboard is actually on; this is because another process has linked to the beacon blackboard. Note: improper use of “beon,” “beoff” and “beclr” can result in the beacon blackboard being turned off without a warning message.
bbad
A bad quality signal from a beacon was detected.
bnone
No beacons in search space.
Find all beacons
bfall
response (typical):
bstart
bef COND CODE ALT INT ANG
.
.
bbad
.
bef COND CODE ALT INT ANG
bstop
COND is the signal quality of the beacon, range 0 - 255, decimal. This is a bit-masking command. The mask is given as follows, if the bit is one, that condition is true. (see p. 36 of DMR product manual).
b7 - Fault
b6 - Saturate Condition
b5 - Bad Intensity
b4 - Bad Code
b3 - Noisy transmission
b2 - High Threshold
b1 - Low Gain
b0 - No beacon
Note: COND = 1, is removed by the macro and not displayed.
CODE is the beacon identifier code, range 0 - 255, decimal.
ALT is the altitude angle in tenths of degrees of the beacon from the detector’s centerline, range +/-200.
INT is the intensity in hundreds of counts, range +/-162.
ANG is the azimuth angle from the detector’s centerline in tenths of degrees added to the current head angle, range +/-2000.
berr
The beacon blackboard was not been initialized properly, check macro definition. The command “beon” must be sent first.
boff
The beacon blackboard was turned off in this processes earlier, they must be turned on using “beon.” Note that this message may be received even though the beacon blackboard is actually on; this is because another process has linked to the beacon blackboard. Note: improper use of “beon,” “beoff” and “beclr” can result in the beacon blackboard being turned off without a warning message, in other words, another process should not use “beclr” unless the system manager is performing this function.
bbad
A bad quality signal from a beacon was detected.
Laser
Find one set of reflectors
ldisp
response:
lf AZI ... AZI
AZI is the azimuth angle from the laser detector’s centerline in tenths of degrees, range +/-450. There will be anywhere from one to eight AZI’s on one line.
lerr
The laser blackboard has not been initialized from this process. The command “laon” must be sent first.
loff
The laser blackboard was turned off in this processes earlier, it must be turned on using “laon.” Note that this message may be received even though the laser blackboard is actually on; this is because another process has linked to the laser blackboard. Note: improper use of “laon,” “laoff” and “laclr” can result in the laser blackboard being turned off without a warning message.
lnone
No laser reflectors in search space.
Find all laser reflectors
lfall
response (typical):
lstart
lf ANG
.
.
.
lf ANG ANG
lstop
ANG is the azimuth angle from the laser detector’s centerline in tenths of degrees added to the current head angle, range +/-2250, decimal.
lerr
The laser blackboard was not been initialized properly, check macro definition. The command “laon” must be sent first.
loff
The laser blackboard was turned off in this processes earlier, it must be turned on using “laon.” Note that this message may be received even though the laser blackboard is actually on; this is because another process has linked to the laser blackboard. Note: improper use of “laon,” “laoff” and “laclr” can result in the laser blackboard being turned off without a warning message, in other words, another process should not use “laclr” unless the system manager is performing this function.
Time
Get current time
gettime
response:
gt WEEK MONTH DAY HR:MIN:SEC YEAR
WEEK is Sun, Mon, Tue, Wed, Thu, Fri, Sat.
MONTH is January, February, March, April, May, June, July, August, September, October, November, December.
DAY is day of month, range 1 - 31, decimal.
HR, is hour, range 0 - 23, decimal.
MIN, is minute, range 0 - 59, decimal.
SEC is seconds, range 0 - 59, decimal.
YEAR is year, range 1900 - 2100, decimal.
Note: date must be reset every time robot is rebooted; use “settime.”
gterr
Some problem with system clock.
“UNTIL” (Line-Arc) Functions
Until Terminated due to Emergency Stop
condition:
emergency stop has occured
response:
clescount XX
If an emergency stop occurs during an “until” command then motion will cease and this message is sent. XX is the number of “until” commands in a sequence that began with an “runtil” command at the point of interruption. This can be useful to determine at what point in a linear “until” performance order motion ceased.
Until Terminated due to STOP command
condition:
a stop has been issued by some process
response:
rucount XX
If a stop occurs during an “until” command then motion will cease and this message is sent. XX is the number of “until” commands in a sequence that began with an “runtil” command at the point of interruption. This can be useful to determine at what point in a linear “until” performance order motion ceased.
Until Terminated Due to Other Until
condition:
An until command has been received during until execution
response:
sucount XX
If an “until” command is received during an “until” command then the new command will supercede the old and the old will send this warning. XX is the number of “until” commands in a sequence that began with an “runtil” command at the point of interruption. This can be useful to determine at what point in a linear “until” performance order motion ceased.
Special Functions
Show Handle
{ <performance order> }
response:
handle XX
Whenever a spawned process is started, LLAMA returns a handle with a unique identifier. XX is a zero-leading decimal number, range 1 - 31, and is the OS-9 process id number for that spawned process.
spawnerr
Returned if the performance order contains a syntax error. The performance order will not be executed.
Show Nohandle
This is an unsolicited message.
response:
nohandle XX (process ended "properly")
nohandle XX (process ended abruptly, note extra space)
Whenever a spawned process terminates, the nohandle message is sent to G2. XX is a zero-leading decimal number, range 1 - 31, and is the OS-9 process id number for that spawned process.
Interpreter Status
command:
numi
response:
numinuse X (active, or non-sleeping, interpreters)
numcount X (total number of interpreters available)
G2 can get basic information regarding interpreter status. X is a decimal number, range 0 - 31, and numinuse £ numcount. Numbers do not include the system interpreter.
Get System Status
command:
stat
response:
intermode
workmode
If the appropriate message is returned based on the mode of operation.
Display error code
This is an unsolicited message
response:
err XX YY ZZ
This is a generic error messaging format for the LLAMA system. XX is the process id number of the process (true for spawned interpreters, but not necessarily true for other processes, in which case XX is zero) sending the error message, it is zero-leading decimal, range 0 - 31. YY is the process type, it is zero-leading decimal, range 0 - 99, and ZZ is the error type (or error number), it is zero-leading decimal, range 0 - 99.
Note: typically the speech process handles the error display. G2 can turn off all error messaging or restrict it to certain processes by appropriately instructing the speech process. If the speech process is not installed, all error messages will be sent to G2.
LLAMA Specifications
Token Interface
Delimiters on Input:
Interactive mode: cr/lf combination, except only first token will be recognized.
Work mode: space, cr/lf, tab, any control character
This means that when the delimiter is detected, the previous token is executed. Buffering is currently limited so don’t send more than about one line (~80 chars) of tokens until last line has executed.
Text Return:
1. All text messages are preceded by a carat (^) and end with a carriage return.
2. ^?<token> means that LLAMA doesn’t recognize the token (command).
Data Return:
1. Data is returned with the mnemonic generating the request preceding the data requested or using given outputs.
2. Unsolicited data (such as compressed messages/errors) have specific codes which are defined at the end of the Appendix.
Limitations
Integer range: +2147483647, -2147483648
Maximum number of characters in input number (when specified as binary): 32
Number stack size: 512 numbers (effective)
Dictionary stack size (maximum number of nested macros): 40
Warning: Significantlly increasing this value may result in the OS-9 process stack overflowing—solve by specifying more space for process stack during compilation.
Index stack size (maximum number of nested do-loops over all nested macros): 50
Maximum number of nested do loops (including top-most) per macro: 2
Maximum number of nested conditionals (including top-most) per macro: 10
Maximum number of characters in macro name: 15
Maximum number of spawned interpreters allowed: 8
Warning: if a spawned interpreter returns a handle of 20 or above and the sensor blackboard is accessed, chaos is bound to ensue. To fix, change MAXPROCESS (in LLAMA.H) to a larger number and recompile. This should not be a problem under normal operating conditions.
Maximum number of characters in display buffer: 255
Maximum number of allophones to encode: 127
Maximum line length: 80 characters, including delimiter
Using Built-In Demo Programs
The LLAMA system has a number of “canned” demo programs that are executed usually using a single command. These can be put together into a performance order in G2.
- Use the “sq” and “sqc” to demonstrate on-board position correction schemes.
- Use “stopit” to show how collision avoidance can be used and also how background tasks operate.
- Employ a number of “canned” speech phases to update a demo’s progress and to enhance the robot’s “people skills.”
- Build macros in G2 and download to the robot, such as a 3 beacon detector.
Software Installation
The LLAMA Files
LLAMA, the on-board robot operating system is composed of four fundamental programs. Three of these operate concurrently. Of these four programs, most are composed of various modules that have been compiled using a cross-compiler from C source code. These modules are found in the PC in room 438 in the C:\LLAMA\SYSMGR directory. Alternatively, an install floppy disk is available to place the needed files on this PC. This floppy contains a compressed file, called ALLFLS.ZIP, for creating robot applications.
The following is a list of the modules used in this system:
DLEX - downloads expert module software from disk to ram. It is only used when the robot is rebooted.
SYSMGR - starts EXDVR, SPKR, INTERPRT, in that order, as joined processes, meaning that SYSMGR sleeps once the other three become active. It ensures that they start in an orderly fashion.
EXDVR - A “funnel” for control data that is sent to the expert modules. It contains a queue and sensor controls. It receives commands from all of the active interpreters and from the speaker computer.
SPKR - an optional module that converts error codes to readable text. It also controls the speech synthesizer.
INTERPRT - The main module that communicates with the terminal and EXDVR and SPKR. It contains a FORTH compiler and interpreter. It is able to spawn (fork) other similar FORTH interpreters for time-activated functions in a concurrent framework. G2 communicates with this process. The top level interpreter should only be used for house-keeping and spawning of other interpreters, so that if a spawned interpreter “hangs” it will be possible to destroy it under full G2 control.
Also:
RADIO - used on bootup, a program that checks if a radio connection is present and if it is, it will reconfigure the TNC parameters properly and then connect to the appropriate base station.
AVOID - used for obstacle avoidance demo. It may be started by itself provided the following commands are issued in this order: exdvr -o&<cr> spkr -o&<cr> avoid (parameters)<cr> (<cr> is carriage return). The first two processes will execute as background tasks and must be available to avoid. These processes must be killed before LLAMA is started. Either initially note the process id numbers and then perform a “kill” or execute a “procs” to determine the process id numbers to kill. Applications:Developing newWhen developing new applications, exdvr and spkr can be executing in the background while a new version of your application is downloaded, thus they do not need to be killed after every use of your application.
Compiling LLAMA Files
The OS-9 cross compiler is used to create executable files from C text files. A basic “make” utility was designed specifically for compiling linking LLAMA sub-modules into executable files through Microware’s cross-compiler and linker. This utility, called “MAKEOS9,” expects a listing of each file that will make up the final executable in a .LBR file. Each sub-module file must be listed as a .r file with complete path list within the .LBR file so the linker can find it. A batch file is used to execute the “MAKEOS9” utility through other batch files. The primary make batch files are “PCBCC” and “PCBM.” For example, to compile “INTERPRT,” the “.LBR” file must contain all sub-modules and be (preferably) located in the current directory and executed as such: PCBCC INTERPRT
Any file that includes floating point operations must use the “PCBM” utility. The appropriate commands are given:
PCBCC INTERPRT
PCBCC DLEX
PCBCC SYSMGR
PCBCC SPKR
PCBCC RADIO
PCBM EXDVR
PCBM AVOID
Ensure that the PC’s path environment variable points to the C:\PCBRIDGE directory, which contains the “PCBCC” and “PCBM” batch files. Also ensure that your current directory in which you execute the preceding command does not include these batch files as they may not be up-to-date (MS-DOS will execute the file in the current directory first). The PC’s clock must be correct for the make utility to function properly. The compiler will generate object files with a .r extension. The executable will have no extension. Note: “MAKEOS9” is not a complete make utility and will not check for changes in “.H” files.
Downloading LLAMA Files
After booting the robot, two files must be present in the OS-9 memory, “kermit” and “lmm.” From the PC, choose the executable file to download and send it through kermit using “lmm filename”. “lmm” is a batch file that first executes “kermlmm,” a short C compiled code that sends the appropriate start sequence to the kermit and lmm on the robot. It then sends the file through kermit on the PC. Kermit must be in the C:\KERMIT directory and also be properly configured (either 9600 or 19200 baud). This process can also be done as a menu item in the “pcb” program on the PC, although problems have been experienced with this Microware program.
The LLAMA disk in OS-9 will tend to have the bare minimum system functions due to limited disk space (400K bytes). Use the CMDS disk to get the full range of functions, i.e. if you want to start a multi-user system with login and passwords on the robot.
Once downloaded, the files can be executed immediately. Do not download when:
- the file doesn’t exist in the current PC directory (lmm will check for this).
- kermit and lmm are not on the robot disk.
- the terminal is not configured (i.e. download port must be configured as a terminal).
- the wrong baud rate has been selected.
- while a program by the same name as the one to download is running concurrently.
Kermit on the PC can be terminated with a control-c.
Creating an Execution Disk
Choose a blank diskette. Note: due to problems with head alignment on the robots, choose and label disks that will be written to on only the selected robot. The following steps outline how a LLAMA disk can be created from a commands (CMDS) disk (assuming LLAMA files have been downloaded into the robot’s memory):
1. Format the diskette using: format /dd
2. Make the following directories using: makdir
bootobjs, expert, llama, cmds
3. chd to bootobjs and save the files:
null, ram, pipe, pipeman
4. chd to llama and save the files:
sysmgr, exdvr, interprt, spkr, avoid
5. chd to expert and save the files:
dmrdasc1, dmrpgmultra, dmrbeac, mrvlaser
6. chd to cmds and save the files:
backup, date, del, dir, dlex, free, kermit, lmm, load, procs, radio, save, setime, shell, xmode, edt, mfree
7. A startup file called “startup” must be created in the root directory of every LLAMA disk. Execute edt startup and enter the following:
setime -s
load /dd/cmds/load
load /dd/cmds/kermit /dd/cmds/lmm
load /dd/bootobjs/*
load /dd/llama/*
dlex <>>>/term
radio -r MARP -b EEB -e <>>>/term
xmode /t2 echo bsp=8 del=18 eor=d eof=4 reprint=12 dup=1 psc=17 abort=3
xmode /t2 quit=5 bse=8 bell=7 xon=11 xoff=13 tabc=9 tabs=4
shell <>>>/t2&
8. chd to expert and create the file called “autoconfig” by executing edt autoconfig and enter the following:
dmrdasc1
dmrpgmultra
dmrbeac
mrvlaser
9. The disk is ready for use. Note that the startup file should have the proper name of the robot under the “radio” command, either HERC or MARP.
LLAMA version 1.1 has been optimized for size. It still uses a good portion of the 400K disk space. The following is a list of files in the “cmds” directory that either must be on the LLAMA disk (underlined) or should be on the disk:
backup, date, del, dir, dlex, edt, format, free, kermit, list, lmm, load, makdir, mfree, procs, radio, save, setime, shell, xmode
To backup the new disk, format another, set the write-protect on the master and execute (with the master in the robot) backup /dd -b=105k or if all LLAMA files have been unlinked out of memory backup /dd -b=150k.
Other OS-9 Commands
The disk directory command is:
dir
The memory directory command is:
mdir
To change to a directory in OS-9 use:
chd /dd/llama (example)
To return to root use:
chd .. (note space)
To save a file use:
save filename
or
save filename -r (if already exists on disk)
To load all files in a directory:
load /dd/llama/*
All executable files must be loaded into memory to be executed. The system does this automatically, however, if a “link” or “load” is not performed, the files will be removed after executing. If some files are to be used a lot, load the files into memory, so that disk access is kept to a minimum.
Speech Microcontroller Data Format
The Speech synthesizer driver can be modified for general use to convert serial to buffered parallel data stream, thus only a new packet specification is needed. The original microcontroller code can be modified fairly easily for this purpose.
Figure M-6. Speech Microcontroller board.
This protocol used on the internal high-speed serial multi-drop (called SDLC by Denning) line uses a simple packet format that has been adopted into this design. The operational scheme may not exactly fit Denning’s standard, however, it has proven to be compatible, i.e. it doesn’t crash or lock up system activity. Refer to Figure M-6 for parts locations. The assembly listings for the microcontroller should be located on the PC in room 438 under C:\MICROPRG\SPEECH4.PRN (for 68705P3S version). The version used on the robots is in C:\PEPSI\MICRO\SPCHSYN2.PRN (for 68HC705C8S).
The operational scheme is as follows:
1) Watch serial input line for any reset activity:
xx-d0-00-00-cksmhi-cksmlo, when found go to (2)
2) Ignore all packets (but follow them) until get own reset, reply only after 2nd (confirm) reset packet & go to (3).
3) Watch for any commands but also watch other packets to maintain synchronization.
4) Execute (own) commands and return to 3.
5) Own packets are limited to 256 bytes although this may overwrite buffer if longer than 128 bytes — if own packet longer - fail w/o reply and wait for reset sequence (2 reset packets, don’t have to be together). The reason for this is to prevent lockup if missed a byte — master will send resets if doesn’t get replies to commands.
6) Other module packets not limited (every byte sent over line is accounted for to maintain packet synchronization).
7) If more data is received than can be stored in ring buffer (FIFO), last items will be written over first data but pointers will not change.
A State Machine approach is used.
Approach of new Expert modules:
1. All new modules will use an access bit that will not be used on the robot, i.e. “intrusion detection,” which is bit b4 or in hex: 10.
2. The second byte in the input stream determines which new expert module is being referenced.
3. I have set an limit of 16 modules, referenced by the first 4 bits in the byte field. The last 4 bits determine the command mode of which some can be assigned. The preassigned types are as follows:
0: Download Reset to XMOD (use as XMOD reset also)
1: Version return from XMOD (optional)
2: Received Packet with error/without error (from XMOD)
3: Execution Addr for ram-based XMOD (to XMOD)
4: Send program in packets (typ. 128 bytes) (to XMOD)
5: No more prg pkts to follow, done (to XMOD)
6: Data to XMOD
7: Status from XMOD
8-15 may be used, can use for data from XMOD, etc.
4. THIS MODULE: 0,6,7 are implemented.
This Modules assignments:
1. Access is 10h as mentioned earlier.
2. Function is 0Xh, meaning it’s the first new xmod.
3. Reset is expected as:
10 00 00 00 00 10
4. Data is expected as:
10 06 00 LN XX XX ... XX CH CL
(length LN no longer than 128 bytes of data)
5. Reply for command-received is:
10 02 00 00 00 12 ®ok
10 02 00 01 XX CH CL ®error
where XX=
bit 7 = 1 if buffer overwritten (typically due to slow removal of data from buffer)
bit 6 = 1 if not able to add to buffer since currently resetting S.P.
bit 5 = 1 if uart detected a receive error
bit 4 = 1 if unrecognized function
bit 0 = 1 if only one byte in cksm in error
bit 1 = 1 if two bytes in cksm in error
6. Status Request is expected as:
10 07 00 00 00 17
7. Reply for status-request is:
10 07 00 01 XY CH CL
bit 7 = 1 of XY if S.P. still talking
bits 0-6 give # of bytes in buffer up to 128
NOTE: (8-11) may not be implemented in 68HC705 version.
8. Core Dump is expected as (this is for debug purposes only):
10 08 00 00 00 18
9. Reply for Core-Dump is:
10 08 00 80 XX ——— XX CH CL
where XX’s (128 bytes) are the 68705’s ram contents in sequential order from addr 00
10. Flush Buffer is expected as:
10 09 00 00 00 18:
11. Reply is:
10 09 00 00 00 18
Error Codes
System errors will appear on screen numerically coded. The addition of a message, either verbal or text or both is a user choice that is handled by the speech computer; refer to the command “tc” in the Macros and Primitives Chapter. Since these errors are organized with a err prefix followed by three numbers:
process_id ( 0 - 31 ) process_type ( 0 - 99 ) error# ( 0 - 99 )
For example, if an expert module failed and severed its communication link with LLAMA, the following message is bound to appear (unless the error message disable feature was selected):
err 06 10 01
Which says that OS-9 process 6, known as EXDVR by its identification of 10 had an error number 1 which means SDLC time-out receiving packet.
Computer Types
The following are the module group numbers for error reports. For example, any message that has an identfier between 20 and 29, inclusive, is a system interpreter error message.
System manager: 0X
Sdlc computer: 1X
System interpreter: 2X
Spawned interpreter: 3X
Obstacle avoider: 4X (may occur only during obstacle avoider execution)
System Manager Errors
err 00 00 00 “can’t fork process”
Expert Driver Errors, General Interface
err 00 10 00 “read from pipe failed”
err 00 10 01 “timed-out reading SDLC packet header”
err 00 10 02 “return packet longer than expected”
err 00 10 03 “error reading from SDLC”
err 00 10 04 “timed-out reading SDLC packet body”
err 00 10 05 “alarm function failed”
Expert Driver Errors, Laser Interface
err 00 19 00 “error unlinking from laser_sem_event”
err 00 19 01 “error unlinking from laser_r1sem_event”
err 00 19 02 “error creating EV_LASER_SEM”
err 00 19 03 “error creating EV_LASER_R1SEM”
err 00 19 04 “error linking to EV_LASER_SEM”
err 00 19 05 “error linking to EV_LASER_R1SEM”
err 00 19 06 “error deleting EV_LASER_SEM”
err 00 19 07 “error deleting EV_LASER_R1SEM”
err 00 19 08 “dp id field invalid”
err 00 19 09 “laser expert module not ready”
err 00 19 10 “error handling semaphore event”
err 00 19 11 “invalid cfg partition size”
err 00 19 12 “dp id field invalid expert”
err 00 19 13 “laser expert module not ready, expert”
err 00 19 14 “error handling semaphore event,expert”
err 00 19 15 “invalid cfg partition size, expert”
err 00 19 16 “error linking to laser_sem event”
err 00 19 17 “error linking to laser_r1sem event”
err 00 19 18 “addr field invalid”
err 00 19 19 “expert module not ready in dpread”
err 00 19 20 “expert module no read partition”
err 00 19 21 “request length overrange”
err 00 19 22 “timeout on sem flag”
err 00 19 23 “timeout on expert module”
err 00 19 24 “timeout on expert module second”
err 00 19 25 “address field invalid in dptrans”
err 00 19 26 “error handling event”
err 00 19 27 “bad frame reveived”
err 00 19 28 “bad checksum received”
err 00 19 29 “abort received”
err 00 19 30 “bad ack data”
err 00 19 31 “returned data does not match”
err 00 19 32 “non-recoverable error”
err 00 19 33 “expert module not ready in dptrans”
err 00 19 34 “request length overrange in dptrans”
err 00 19 35 “timeout in dptrans”
err 00 19 36 “invalid cmd status”
err 00 19 37 “recv’d length too long in dptrans”
err 00 19 38 “checksum does not match in dptrans”
err 00 19 39 “expert module not ready dpsend”
err 00 19 40 “cmd field out of range in dpsend”
err 00 19 41 “request length overrange in dpsend”
err 00 19 42 “laser bad count”
System Interpreter Errors
err 00 20 00 “line length exceeded”
err 00 20 01 “can’t access device descriptor”
err 00 20 02 “error setting alarm”
System and Spawned Interpreter Errors, IO Control
NOTE: For Spawned Interpreters, the identification is 3X, where X is the equivalent System interpreter error message: 2X. Additionally, spawned interpreters will have their process id encoded in the first argument of the error string.
err 00 21 00 “SLDC reply failed”
err 00 21 01 “unknown SDLC reply condition number”
err 00 21 02 “sdlc command refused”
System and Spawned Interpreter Errors, Sensor Receive
err 00 22 00 “ultrasonic blackboard consistent bad data”
err 00 22 01 “beacon blackboard consistent bad data”
err 00 22 02 “laser blackboard consistent bad data”
err 00 22 03 “xyt position blackboard consistent bad data”
err 00 22 04 “ultrasonic sequence blackboard consistent bad data”
err 00 22 05 “ultrasonic parameter blackboard consistent bad data”
err 00 22 06 “ultrasonic sequence setting failed”
err 00 22 07 “ultrasonic parameter setting failed”
err 00 22 08 “ultrasonic sequence setting refused”
err 00 22 09 “ultrasonic parameter setting refused”
System and Spawned Interpreter Errors, Schedule
err 00 23 00 “bad count skipping txabs”
err 00 23 01 “error executing txabs”
err 00 23 02 “bad count, skipping txrel”
err 00 23 03 “error executing txrel”
err 00 23 04 “illegal time specified for txrel, executing now”
err 00 23 05 “error executing sl256”
System and Spawned Interpreter and Obstacle Avoider Errors, Motion
err 00 24 00 “safe steer acceleration limit exceeded, limiting”
err 00 24 01 “safe steer speed limit exceeded, limiting”
err 00 24 02 “steer accel assignment exceeded, limiting”
err 00 24 03 “steer speed assignment exceeded, limiting”
err 00 24 04 “zero home speed not allowed”
err 00 24 05 “home speed exceeded... limiting”
err 00 24 06 “home acceleration out of range... limiting”
err 00 24 07 “turn speed out of range... limiting”
err 00 24 08 “turn distance limit exceeded... limiting”
err 00 24 09 “turn acceleration out of range... limiting”
err 00 24 10 “safe drive acceleration limit exceeded, limiting”
err 00 24 11 “safe drive speed limit exceeded, limiting”
err 00 24 12 “drive accel assignment exceeded, limiting”
err 00 24 13 “drive speed assignment exceeded, limiting”
err 00 24 14 “maximum move distance limit exceeded, limiting”
err 00 24 15 “negative speed not allowed”
err 00 24 16 “safe move speed limit exceeded, limiting”
err 00 24 17 “safe move acceleration limit exceeded, limiting”
err 00 24 18 “error sending emergency stop”
err 00 24 19 “error getting motor status”
err 00 24 20 “cles timeout error, check bumper”
err 00 24 21 “desired max drive speed out of range”
err 00 24 22 “forked process error”
err 00 24 23 “can’t fork process”
System and Spawned Interpreter Errors, Parser
err 00 25 00 “not enough memory for dictionary”
err 00 25 01 “note, token defined previously”
err 00 25 02 “out of memory compiling”
err 00 25 03 “out of memory executing”
err 00 25 04 “can’t execute compile-only primitives”
System and Spawned Interpreter Errors, Compiler
err 00 26 00 “cannot compile/spawn within a spawn definition”
err 00 26 01 “not enough memory for malloc-make command list”
err 00 26 02 “must enter a name”
err 00 26 03 “numbers not allowed for macro name”
err 00 26 04 “token name exceeds maximum length allowed”
err 00 26 05 “out of memory for name”
err 00 26 06 “out of memory for token list”
err 00 26 07 “start conditional without ender”
err 00 26 08 “do with no loop”
err 00 26 09 “var/cons needs a qualifier — quitting”
err 00 26 10 “unterminated string — quitting”
err 00 26 11 “no tokens found to compile — quitting”
err 00 26 12 “too many nested conditionals”
err 00 26 13 “then without if”
err 00 26 14 “endif without if”
err 00 26 15 “else without if”
err 00 26 16 “only one nested do loop allowed”
err 00 26 17 “loop without do”
err 00 26 18 “+loop without do”
err 00 26 19 “until without begin”
err 00 26 20 “repeat without begin”
err 00 26 21 “while without begin”
err 00 26 22 “leave without do”
err 00 26 23 “out of memory for constant”
err 00 26 24 “out of memory for variable”
err 00 26 25 “out of memory for quote”
err 00 26 26 “input quote too long”
err 00 26 27 “compiling var/cons definition not allowed”
System Interpreter Errors, Spawner
err 00 27 00 “kill value out of range”
err 00 27 01 “flush value out of range”
err 00 27 02 “not enough memory for malloc-build interpreter table”
err 00 27 03 “can’t spawn another interpreter — too many running”
err 00 27 04 “can’t spawn interpreter, spawn command failed”
err 00 27 05 “can’t open pipe to spawned interpreter”
err 00 27 06 “not enough memory for malloc-make block”
err 00 27 07 “not enough memory for malloc-make command list”
err 00 27 08 “cannot compile/spawn within a spawn definition”
err 00 27 09 “exit value out of range”
err 00 27 10 “interpreter table violation, reboot suggested”
Spawned Interpreter Errors, General
err 00 30 00 “can’t access device desciptors”
err 00 30 01 “can’t open pipe to exdvr”
err 00 30 02 “can’t create spnint-sdlc event”
err 00 30 03 “can’t link to spin event”
err 00 30 04 “can’t create pipe to system interpreter”
err 00 30 05 “signal event problem”
err 00 30 06 “error linking sysint-spnint event”
err 00 30 07 “out of memory getting node to execute macro”
err 00 30 08 “not enough memory for number stack”
err 00 30 09 “not enough memory for dictionary stack”
err 00 30 10 “not enough memory for index stack”
err 00 30 11 “not enough memory for command packet”
err 00 30 12 “not enough memory for reply packet”
Built-in Messages
The following messages are encoded into LLAMA. They can be accessed by entering the appropriate message string as given:
General
0 0 tm “LLAMA ready”
1 0 tm “LLAMA done, see ya”
2 0 tm “clearing emergency stop, please wait”
3 0 tm “alarm”
4 0 tm “point”
5 0 tm “degrees”
TAGE Controller
0 1 tm “Hello Professor Albrecht”
1 1 tm “I am the terminator”
2 1 tm “I will be back!”
3 1 tm “excecuting line”
4 1 tm “excecuting square”
5 1 tm “excecuting circle”
6 1 tm “excecuting figure 8”
7 1 tm “excecuting triangle”
DEMO Macros
0 2 tm “Hello, my name is Ms. Marple.”
1 2 tm “I am going to give you a demo of my capabilities”
2 2 tm “I can turn in place”
3 2 tm “I can orient myself”
4 2 tm “and move forward one foot”
5 2 tm “I want to move in a square”
6 2 tm “first I have to see if I have enough room”
7 2 tm “I don’t have enough room”
8 2 tm “Let’s go!”
9 2 tm “Move some objects away from my”
10 2 tm “front right side”
11 2 tm “press a bumper switch when done”
12 2 tm “Let’s try something else”
13 2 tm “Notice the accumulated error”
14 2 tm “Let’s find some beacons”
15 2 tm “Let’s find some laser reflectors”
16 2 tm “Push a bumper switch”
17 2 tm “Press switch 4 to stop”
18 2 tm “Let’s go in a circle”
Obstacle Avoider
0 3 tm “starting obstacle avoidance.”
1 3 tm “obstacle avoidance done.”
2 3 tm “I have reached the goal.”
3 3 tm “I see the goal.”
4 3 tm “path blocked”
5 3 tm “I failed to reach the goal, I am sorry.”
6 3 tm “I am stuck, please move obstacle.”
7 3 tm “Go Huskies!”
Numbers
Numbers are encoded as follows, from zero to thirty one:
0 4 tm zero
1 4 tm one
... etc.
Stack Information
0 5 tm “stack empty”
1 5 tm “popping from empty stack, returning zero”
2 5 tm “cannot divide by zero”
3 5 tm “cannot modulus by zero”
4 5 tm “stack size too small, nothing pushed”
Known Bugs
LLAMA is a very complex system and is not impervious to bugs. There are various classes of bugs and they are listed as follows
Operational Bugs
1. If LLAMA is given successive “move” or successive “TURN” commands, the expert module will hang and the robot will have to be rebooted. This seems to be a bug in the expert module software. Use “ststop” and “drstop” functions immediately following these commands as appropriate.
2. If LLAMA is given a “TURN” or “DSV” commands with a speed that is small enough to prevent the motor from turning due to frictional effects, the expert module will hang and the robot will need to be rebooted. The speeds for these commands should be at least 5 degrees per second, but this can vary depending on the surface texture of the ground.
3. The function “wake” does no checking of what processes are available to wake up. If a process id is specified for a nonexistent process or for a process that is not sleeping, unpredictable system behavior will result. This bug was found by spawning two “demo” macros simultaneously, which is not appropriate.
4. When a function is compiled or spawned, a near identical routine is used to form a temporary list of the input stream in the interpreter. When in “interactive” mode each line of tokens delimited by a carriage return is placed into a list that is linked as each successive line arrives. The problem occurs when in “work” mode and compiling: a new list of about 80 bytes is generated for each token, which tends to waste a lot of memory. For very long definitions, it is conceivable that OS-9’s memory space will become full and cause an error. This problem was identified in the spawning mode and fixed but was missed for the compile mode. Solutions: a) don’t do anything, just make sure that when in work mode, keep definitions down to about 100-200 tokens maximum; b) rewrite the “compileit” function in the “COMPILE.C” module to reflect the changes in the “spawnit” function in the “SPAWN.C” module; c) when defining, use the interactive mode.
5. LLAMA supports recursion, but there is no stack checking. An unterminated recursive function will very likely cause a system crash. Solutions: a) put a check on the dictionary stack, this will slow the system by about 50%; b) make sure, through simulation, that recursive functions will end and not go beyond the allocated space for the dictionary stack; c) avoid use of recursion.
6. The “quit” function in LLAMA is the same as the “exit” function in FORTH. Unfortunately, LLAMA has a “exit” function that serves a different purpose and so the following alias is not appropriate:
: exit quit ;
7. LLAMA has some inconsistent uses of global and local variables. This is not a bug, except that the system may not do what you expect. For example, setting the maximum drive speed from both of two spawned processes will set the maximum drive speed of the “until” functions to the most recently received maximum drive speed change. Solution: avoid running two processes that change this variable at the same time.
8. G2 cannot send certain characters to LLAMA due to G2’s internal construction. The “dot-quote” function, “@,” and “!” have been renamed, however it is possible that not every needed primitive or macro was modified.
Logical Bugs
1. If the system interpreter is given an input and then erased using the “backspace” key, and then followed by a carriage return, a “>?” will be returned. The system behavior is not compromised in this situation. This bug is caused by a coding problem in the “getline” function in the “INTERPRT.C” module. Since G2 control of LLAMA will not use a backspace, this bug can be ignored.
2. Any function that pushes numbers onto the stack will allow at most 513 numbers on the stack since these functions call an internal function called “push.” The function “rep,” however, will allow at most 512 numbers on the stack (“rep” does not call the push function). This bug is insignificant if the stack is not used to capacity. Note: the stack size is 513 items.
3. The system command parser (PARSESYS.C) is separate from the general command parser (PARSER.C). The system parser was not updated to the newer definition standards of the general command parser. This has caused some potentially undesirable side effects. The problem arises most noticeably when a curly bracket is accidentally appended to the next token,
{2 3 + . }
where there is no delimiter between the open curly bracket and the “two.” This causes the “two” to be ignored while no errors are flagged. This may cause some confusion since the sequence will work partially.
4. To simplify the input parser, control characters and multiple spaces are converted into single space delimiters. Although a tab, which is a control character, may echo correctly to the screen, sending a backspace immediately following the tab will not move the cursor to the previous tab stop. This not a concern for G2 to LLAMA interfacing.
Macro Bugs
1. The macro “demo,” in particular “demo8,” should be executed only once per LLAMA start. This is because the “stopit” macro dies after it is used once. By starting “demo” more than once, it will try to access a non-existent “stopit.” The way around this is to manually start another “stopit” macro in the system interpreter. Also, the “procid” variable must be initialized appropriately.
Warnings
1. The XXXon and XXXoff sensor blackboard control functions are local to the interpreter in which they are used. The reason for this is that it allows multiple processes to share the blackboard. When they all cease using the resource (link count = 0) then that sensor information is no longer accessed from the expert module, improving system efficiency.
2. When the system is in work mode, the system interpreter will execute each token individually, not after a complete line is given. In theory, this will improve system efficiency.
3. If the system seems to be doing nothing while entering tokens, the probable cause is that the system has been placed into either spawn or compile mode. Remember: These types of definitions can span many lines. G2 doesn’t like spaces between brackets so you must enter two spaces to generate one actual space between words and brackets in G2’s edit boxes.
The Complete Code for DEMO
The follow examples show how the “demo” macro executes in the robot. This also illustrates how complex robot functions can be condensed into a simple executable.
***********************************************************
*
* Define Variables
*
***********************************************************
0 variable ult (a generic variable)
0 variable procid (procedure id variable)
***********************************************************
*
* Initialize background task
*
***********************************************************
[ (define background task as compiled code)
pid (put process id on the stack)
procid ! (save id into global variable)
pause (wait for a signal)
stopit (execute safety function when woken up)
***********************************************************
* DEMO-1
* Illustrate "TURN" and give greeting
*
***********************************************************
: demo1
0 2 tm ("Hello, my name is Ms. Marple.")
4 1 ts (add a pause)
1 sl (sleep one second)
170 30 turn (turn 170 degrees, 30 degs/sec)
1 2 tm ("I am going to give you a demo of my capabilities")
begin (wait until steer motor stops)
plst
until
;
***********************************************************
* DEMO-2
* Turn exactly 90 degrees counter-clockwise
*
***********************************************************
: demo2
2 2 tm ("I can turn in place")
-90 30 turn (turn -90 degrees, 30 degs/sec)
begin (wait until steer motor stops)
plst
until
;
***********************************************************
* DEMO-3
* Home head to body
*
***********************************************************
: demo3
3 2 tm ("I can orient myself")
300 400 HOMEACC (home head)
begin (wait until steer motor stops)
plst
until
;
***********************************************************
* DEMO-4
* Move forward one foot w/o steering
*
***********************************************************
: demo4
4 2 tm ("and move forward one foot")
2 sl (sleep 2 seconds)
10 5 move (move forward 1 foot @ .5 feet/sec)
begin (wait until move complete)
pldr
until
1 sl (sleep 1 second)
;
***********************************************************
* MACRO-1
* read ultrasonics to stack and discard readings 7-24
*
***********************************************************
: t1
us (put 24 sonar readings on stack)
18 0 do (loop 18 times)
drop (discard top stack item)
loop
;
***********************************************************
* MACRO-2
* Get number of readings that are less than 3 feet
*
***********************************************************
: t2
0 ult ! (put 0 into variable "ult")
6 0 do (loop 6 times (6+18=24))
30 < (is reading less than 3 feet?)
if
1 ult +! (yes, increment "ult")
endif
loop
;
***********************************************************
* DEMO-5
* Check if space available to move
*
***********************************************************
: demo5
5 2 tm ("I want to move in a square")
4 sl
6 2 tm ("first I have to see if I have enough room")
3 sl
ub (start ultrasonics)
2 sl
t1 t2 (interpret sonar readings)
ult @ (put "ult" on stack, non-zero if a sonar reading is less than 30, or 3 feet)
if (do "if" if "ult" is non-zero)
7 2 tm ("I don’t have enough room")
2 sl
endif
;
***********************************************************
* DEMO-6
* If space is available, move in a square
*
***********************************************************
: demo6
ulon (start ultrasonics)
1 sl
3 0 do (loop 3 times)
t1 t2 (interpret sonar readings)
ult @ 0= (check if "ult" is equal to zero)
if (yes, then we have room to move)
8 2 tm ("Let’s go!")
2 sl
uloff (turn off ultrasonics)
sqc (perform "square" macro)
0 ult ! (set "ult" to zero)
leave (set loop variables equal to each other so can exit loop)
else
9 2 tm ("Move some objects away from my")
10 2 tm ("front right side")
8 sl (no room otherwise)
endif
loop
ult @ (put "ult" on top of stack)
if (do if not enough room)
12 2 tm ("Let’s try something else")
uloff (turn off ultrasonics)
endif
2 sl
;
***********************************************************
* DEMO-7
* Read bumper switches and say number pressed out loud
*
***********************************************************
: demo7
16 2 tm ("Press a bumper switch")
3 sl
17 2 tm ("Press switch 4 to stop")
0 ult ! (put zero into "ult")
bpr bpme (reset bumpers and disable emergency stop feature - use bumpers in tactile mode)
begin (loop until bumper 4 is pressed)
bpgs (put number of bumpers pressed on stack)
dup (duplicate "quantity" onto stack)
if (do if no zero, or a switch pressed)
0 do (loop number of switches pressed)
dup (check for switch 4 pressed)
4 =
if (if 4 pressed)
1 ult ! (store 1 into variable)
endif
4 tm (say switch number out loud)
loop
64 sl2 (delay for switch bounce)
else
drop (clean up stack)
endif
ult @ (get "ult" value computed)
until (exit if "ult" is one)
bpr (restore emergency stop feature)
3 sl
;
***********************************************************
* DEMO-8
* Do a circle and check for obstacles, stop if find any
*
***********************************************************
: demo8
18 2 tm ("Let’s go in a circle")
3 sl
procid @ wake (start up safety macro as background task, wake it up)
20 st 3 dr (start drive and steer motors at 20 degrees/sec and .3 feet/sec)
20 sl (wait 20 seconds)
s (stop all motors)
2 sl
;
***********************************************************
* DEMO-9
* Find all beacons and show status values
*
***********************************************************
: demo9
14 2 tm ("Let’s find some beacons")
3 sl
bfall (beacon find macro)
;
***********************************************************
* DEMO-10
* Find all reflectors and display angles
*
***********************************************************
: demo10
15 2 tm ("Let’s find some laser reflectors")
3 sl
lreset (laser reset, must be performed once after system is started)
lfall (laser find macro)
;
***********************************************************
* DEMO-11
* Say "good bye"
*
***********************************************************
: demo11
5 sl
10 0 tm ("I’m going to Bimini soon, see ya")
3 sl
6 0 tm ("off")
;
***********************************************************
* DEMO
* Execute all sub-demos in sequence
*
***********************************************************
: demo
demo1 demo2 demo3 demo4 demo5
demo6 demo7 demo8 demo9 demo10 demo11
;