|
Crashcourse: How to program 'Avise':
W. Schemmert,
Cinetix
mit Ergänzungen von H.H.
(updated 29 Mar 2002)
1. ok-prompt:
Start your favourite terminal program with the following
setup:
19200 baud; 8 databits, no parity, one stopbit (8N1);
no handshake; local terminal echo OFF; 1:1 direct data transfer (no tranfer
protocol or dialup). For transmission from the terminal to 'Avise', the NewLine
signal should be only "Carriage Return" (0xD). For receive operations the
terminal must insert a "Line Feed" character (0xA). |
Restrictions:
Eingabezeile:
-
bei 8535 <= 80 Zeichen pro Zeile,
-
bei 4433 <= 40 Zeichen pro Zeile
Wortlänge:
beim externen EEPROM (maximal 96
Worte:(token codes von 0x20 ab)
-
bei 8 kByte externes EEPROM (24C65 oder 24C64): 64 Bytes
-
bei 32 kBytes externes EEPROM (24C256): 256 Bytes
beim internen EEPROM (token codes 0 to 0x1F)
-
Maximal 32 Worte (entsprechend weniger, wenn jeweils
mehr als 16 Bytes (AVR8535) benötigt werden)
Würde ein Wort mehr Zeichen benötigen, muss es in kleinere Worte
aufgespalten werden. |
As a standard solution, you can use the specialized terminal program
'Atool' which is supplied in the 'Avise' download package. We have made
a new version which is 32 bit Windows compatible.
Connect your 'Avise' hardware to the serial port of the PC, supply the power.
After that, you should see the following (or similar) log-in message on your
terminal display: 'Avise 2.48D ok'.
When you notice this, then press some arbitrary character keys on your keyboard
and finish with <RETURN>. The input should be echoed on your terminal
display. Lower case letters are automatically converted into upper case.
After the <RETURN> keystroke (normally) should appear a repetition
of your string, or at least the first word you entered followed by a question
mark. When this appears, then very very probably everything is working well
and ready for higher tasks.
'Avise' does echo every received valid character immediately. Within a line,
a BACKSPACE input will be served immediately. The system prompt of 'Avise'
is an "ok" string echoed at the end of every correctly processed line. In
case of an operation or command error within a line, a question mark will
be echoed together with an appropriate error message. The last character
before Carriage Return of every line containing an error will be a "tilde"
character (' ~ ' = 0xFE). This may look a little bit strange, but is intended
as support for machine operated programming.
If unexpectedly the init string 'Avise v2.0 ok' appears during program execution,
then probably your program hanged up and execution was terminated by the
microcontroller's watchdog timer. If this is oberved in excess, please check
your power supply or peripherals for overload or current spikes. If the program
hangs up without waking the watchdog, it can always be returned to the inital
state by typing the "tilde" character (' ~ ' = 0xFE) on the terminal keyboard.
This character is catched out of the input stream in the UART interrupt handler.
As a consequence it is forbidden to be used in any user word name.
2. The "words" (commands, functions, subroutines) of
'Avise':
Working with 'Avise' you can type simple commands interactively from the
terminal as well as write and compile complete programs.
For instance type "words <RETURN>". A list of all tokens available
at this time will be displayed on the terminal. Preprogrammed kernel commands
uppermost followed by user defined ones. You find a detailled description
of all kernel words in the glossary file. Due
to its specific parameter transfer by stack, 'Avise' needs not to distinguish
between "commands", "functions", "procedures" or simply "words".
At next type
: test words ; <RETURN>
After the 'ok' prompt appears type
test <RETURN> Especially look at the bottom
of the printout !
Interpretation is performed when a line is completely entered.
-
For AVR processors with 128 bytes of SRAM (like 4433), a console input
line can contain a maximum of 40 characters.
-
Versions with more SRAM (like 8535) can handle a console input line with
max. 80 characters.
This should be selected in the 'ATOOL' startup screen.
Disgression:
Despite certain deviations, 'Avise' essentially follows
the programming rules of the Forth programming language. There is no
general diffence between things like "commands, functions, procedures,
subroutines", which are handled as very separated things in other programming
languages. The basic unit of software is a "word", that means a piece of
code which is called by the user when entering its nameword. On the user
side level, a word is a piece of string separated by spaces, called
a string token. On the operation side, every string token has a byte token
as its counterpart, which describes the address where the respective
program code is stored.
'Avise' has two operating states: one is "interpreting", which
means the mini operating system of 'Avise' transforms the string token into
its correspondig byte token and immediately calls this address for executing
the code. The other state is "compiling" which means: the mini operating
system of 'Avise' evaluates the corresponding byte token from the entered
string token and compiles it into the body of a new user programmed "word",
which subsequently will be labelled by its own string token as well as by
its characteristic byte token. Once finished compilation, this user defined
word can be called in the same way like all kernel words in the interpreting
state (for immediate execution) as well as in the compiling state (to make
it a brick of code in a new, more complex word). User words can be called
or compiled by user words .. and so on up to any level, as long as the AVR
processor return stack does not underflow. This depends on certain factors.
But as a general rule, 5 to 10 levels of subroutines normally should be safe.
Especially every DO-LOOP structure does reserve three entries of the return
stack. So, this kind of command structure may reduce the maximum number of
subroutines considerably.
Complete programs or modules can be started or built into other programs
in the same way as the built-in kernel commands. Complex problem solutions
are best built up "bottom up", and every piece of the final construction
can be tested separately and directly after it has been programmed.
There is only one fundamental difference between the 'Avise' kernel "primary
words" (which are essentially programmed in high speed assembler code in
the program memory of the AVR chip) and the user programmed "secondary words",
which are stored as "threaded token code" in the EEPROM and therefore need
considerably more execution time. "Threaded token code" means a sequence
of references to more basical tokens. These can be user defined tokens, which
are references, too or can be kernel primaries. 'Avise' continues resolving
these references until it ends at a primary, which is then executed at machine
level.
Due to the strict Harvard architecture of the AVR microcontrollers, in principle
it is impossible to program assembler-like user words (though this is possible
with microcontrollers basing on the vonNeumann architecture). User programmed
pieces of machine code can be merged together with the 'Avise' code into
the flash memory and be called with the CALL command. This however, demands
some experience in programming at machine level. With the new ATmega chips,
a counterpart of CALL like LOAD soon will be available.
3. Postfix Notation:
The first very special thing you have to become aquainted with when working
with 'Avise' is the "postfix-" or "reverse polish" notation:
arguments(numbers) and operators (commands) are entered in a order differing
from everyday mathematics.
Type:
A 3 - . <RETURN>
What happend? (a short disgression:)
First: You are just working in the interpreting state of 'Avise'.
Every input line is immediately processed after <RETURN>. The 'Avise'
command interpreter does split it into "tokens" and does process it token
by token. A string token is a piece of string placed between two space
characters. Therefore each two entered arguments MUST be separated by
SPACE CHARACTERS!
The first token is A, the next token is 3, followed by minus and last the
dot. As a first step, the interpreter tries to understand the string token
as a valid hexadecimal number.
'Avise2.0' can be switched to understand HEX numbers (default) with the
command "$" and it can be switched to understand DECIMAL numbers with the
command "%". Note that these are commands and not unitary prefixes and
therefore have to be separated by SPACE from the number string. Selected
once, the number base is valid until the next "$" resp. "%" or until the
next reset.
(Versions without the VAR command only: If the command interpreter fails
to interpret the string token as a number, next it tries to interpret it
as a variable (V0 ... ),i.e. the character 'V' followed by a valid HEX number
in the valid range.)
If this fails, it does run through the list of command words looking for
a name entry which is identical with the scanned string token. Once found,
the correspondig action code is executed. When no correspondence was found,
an error message is sent, the complete rest of the line is omitted, stacks
are cleared. Consequently, user programmed words which can be interpreted
as a hex number or as a variable will be executed as such one.
'Avise' works stack oriented, similar like a HP pocket
calculator. Especially in the interpreting state work is more fluently
than in the conventional notation with equates signs. As a disadvantage complex
operations on the stack may become confusing. In these cases the use of global
variables is recommended.
The data stack is a special type of memory organisation, which strictly follows
the principle "LAST IN - FIRST OUT". The data stored last is always read
out first. New data put into the stack are layed over the preceeding
ones.
Back to the original example:
The first token (hex A, i.e. decimal 10) is recognized as a number and put
on the data stack. The next token causes a 3 to be put on the stack. The
third token fails to be interpreted as a number but is found in the list
of words. At runtime it subtracts uppermost item of the stack from the next
upper item of the stack and puts the result back onto the stack. As a further
result one stack item is "consumed"
The fourth token "." (dot) takes the uppermost item from the stack, converts
it into the ASCII representation of its value and emits it via serial port
to the terminal, where it is displayed. The dot symbol looks a little bit
strange; but in interactive mode it is easier to type than a command like
"PRINT" or so.
In the glossary every command is described with a "stack comment".
Left of the dashes are listed the upper stack entries BEFORE execution, and
right of the dashes are listed the upper stack entries AFTER execution, as
far as they are involved into the execution of this word. The top of the
stack is always in the rightmost position. The stack command of some words
does contain a semicolon followed by a string in pointed brackets. This means
the string token will be consumed during execution of the preceding token.
See, for instance, glossary entries for SEE, FORGET and for : (colon).
4. Handling the stack:
The permanent "consumption" of stack entries is the second feature of
'Avise' you have to be familar with. If a stack entry is needed twice,
it has to be duplicated. This is done with the word DUP. The opposite effect
- remove the uppermost stack entry - is achived with the command DROP.
A convenient debugging tool is .S , which shows the complete stack image
and the actual content of the first 8 user variables (resp. predefined variables
V0 to V7 ('Avise' versions without the VAR command) on the terminal - WITHOUT
CHANGING the stack.
Type: (alway finish the line with <RETURN>)
2 .S
then: 3 DUP .S
ABORT
then: 4 DUP DUP .S
ABORT
then: 5 DUP DROP .S
(The ABORT command is used to clear the stack in between)
Further elementary words for stack manipulation are SWAP (exchange the both
upper stack entries), OVER (copy the second stack entry over the uppermost
one into a new uppermost position, ROT (permutative rotation of the upper
three stack entries), similarly -ROT and ROT4.
Try yourself:
2 3 4 SWAP .S
ABORT
2 3 4 OVER .S
ABORT
2 3 4 ROT .S
ABORT
2 3 4 -ROT .S
Elegantly jugging with these features makes a great part of the art of
programming 'Avise'. When complexity is increasing, conventional global
variables should be taken into account as an alternative storage place.
5. Arithmetics, bit operations and comparisons
In this group of commands the upper two stack entries are taken from the
stack, combined and the result is put back onto the stack. Example:
3 2 +
In case of Subtraction, the TOS ("top of stack") is subtracted from the second
stack entry. Similarly in comparisons the argument which is in normal
mathematics right of the operator, has to be on top of the stack (i.e.
will be placed rightmost in the stack comment, too). In 'Avise', all
comparisons are performed unsigned, except those with a U in the name.
(Spoken in terms of low level programming: in comparisons,
a virtual subtraction - top of the stack (TOS) minus second stack entry -
is performed and the result is checked for the asked condition.)
The
command Ø= makes
an exception as it does replace one argument with the result. Beside its
original function as a compare operator it is oftenly used as an inverter
for boolean values.
If desired, the result of an operation can be used as an argument for the
next operation. In this case, the result will be processed together with
the former third element of the data stack. Example:
5 4 1 + = will result
in 0xFFFF = -1 = TRUE: the stack top elements 1 and 4 are added first and
the result is compared with 5.
6. Reading from and writing to arbitrary memory
cells:
-
to read any microcontroller SRAM cell onto the stack, the command R (means
"READ") is used. For addresses less than 0x60 (CPU internal registers) only
the addressed byte is read. The TOS high byte is set to 0. For addresses
>= 0x60, a word = a pair of bytes is read. The addressed byte is put into
the TOS low byte, the addressed (byte+1) is put into the TOS high byte.
-
to write the top of the stack (=TOS) into a microcontroller SRAM cell, the
command W (means "WRITE") is used. For addresses less than 0x60 (CPU internal
registers) only the TOS low byte is written into the addressed memory cell.
For addresses >= 0x60, a word = a pair of bytes is written. The TOS low
byte is written into the addressed memory cell, the TOS high byte is written
into the addressed memory cell+1. This command can not write into external
EEPROMs !
-
Similarly the commands "ZR" and "ZW" transfer one byte of data (TOS low byte)
data between the microcontroller EEPROM and the stack.
-
The commands "XR" and "XW" are used to transfer one byte of data between
the external EEPROM and the stack.
Note:
For details of these commands reading of the respective descriptions in the
glossary is recommended.
You are referred to the Atmel data sheets to become familar whith the special
meaning and possibilities of the concept of SRAM for the AVR controller
series.
Note:
For the WRITE commands always the data to be written is put first (lower)
on the stack, the address to be written to is put last (upper) on the
stack.
In practice it does look like this:
A5 1000 XW
writes data 0xA5 to the external EEPROM address 0x1000.
Do the countercheck:
1000 XR
.
7. The 'Avise' compiler:
A great advantage of 'Avise' is the possibility for the user to write new
"words" (=commands or functions), which not only refer to the kernel commands
but to elder user-defined words, too and to give them individual names.
The most elementary command for controlling the compiler itself is : (colon)
or Z:
It does start the definition of a new "word". 'Avise' does parse the first
stringtoken following the ':' as the new words name and enter it into the
symbol table (max. 12 characters). Then 'Avise' is switched into its compiling
state; i.e. tokens received by the console will not be executed immediately
but entered into the body of the new word.
A second very important elementary command is ; (semicolon)
It does finish the building of a new word and does link it into the search
path. 'Avise' is switched back into the interpreting state, i.e. will continue
with immediately processing tokens received by the console.
Type:
: y 2 3 + ; <RETURN>
Type:
y . <RETURN>
Type:
WORDS <RETURN> Please observe the last
lines on the terminal screen display.
A special feature of 'Avise' is its ability to compile a limited number of
user words into the processor internal EEPROM. Because the access to these
memory cells is parallel instead of the serial I2C interface, these words
will run much faster (about 15 times) than the user words programmed into
the external EEPROM. This memory should be preferably used for compact
fundamental words, which will oftenly be repeated or need fast execution
for specific reasons. The starter command for such a compilation is Z:
(Zcolon).
For instance, to make a fast-running check function of input
line of I/O port B, line7 and lighting an LED depending on the input state
without loosing the input result, type:
Z: CHECK B7 PBRD DUP IF B3 PBLO ELSE B3 PBHI ENDIF
;
As user token and kernel token are both represented by a single byte,
the possible number of user functions is limited to 128.
For 'Avise' versions without external EEPROM:
The code of each token starts at (token code * 2)(AT90S4433) or at (token
code *4)(other versions with 512 bytes internal EEPROM). If a function is
longer than 2 resp. 4 bytes, some token codes will not be produced. After
compilation, the starting point (and token code) for the next function is
rounded up to the next appropriate value. The symbol table is built into
the upper part of the EEPROM growing downwards.
Versions with external EEPROM are organized as
follows:
-
The internal EEPROM is reserved for the first
32 user functions with token codes 0 to 0x1F.
For the AT90S4433 the code of each token starts at (token code * 8). For
the other versions, it starts at (token code * 16). If a function is longer
than 8 resp. 16 bytes, some token codes will not be produced. After compilation,
the starting point (and token code) for the next function is rounded up to
the next appropriate value.
-
The remaining 96 user function are compiled
into the external EEPROM at predefined addresses. So for each function a
fixed code segment is reserved:
-
-
For an 8 k bytes EEPROM (24C64 or 24C65) the starting point is 0x800,
each segment has 64 bytes. (Adressen 0x800,
0x840, 0x880, ... )
-
-
For a 16 k bytes EEPROM (24C128 or equiv.) the starting point is 0x1000,
each segment has128 bytes.
-
For a 32 k bytes EEPROM (24C256 or equiv.) the starting point is 0x2000,
each segment has 256 bytes. (Adressen 0x2000, 0x2100, 0x2200, ... )
-
The kernel version for a smaller EEPROM can be run in a physically larger
EEPROM, e.g. in applications for data aquisition.
-
The memory below this code space is used for the symbol table (max. about
1.5 kbytes, depending on length of the function names) and for user specific
data like function tables or nonvolatile data storage.
-
Code of any user function is not allowed to be bigger
than one segment. In case, the function must be devided into smaller
subfunctions.
-
VAR variables dont take space in the code area and are not part of the 128
user functions. Their number is limited by the size of the SRAM.
8. Variables and Constants
'Avise' does only know one type of global variable, that is 16 bit integer.
Boolean variables are specially interpreted integers. With the commands BSET,
BLCR, BTST the user can handle his own bitflags, but when there is enough
memory, it is easier to use integers as bitflags. You have to distinguish
between versions of 'Avise', which have the VAR command (i.e. versions for
AT90S8515or AT90S8535 with external EEPROM) and those without.
all AT90S4433 versions:
For these CPU types, 'Avise' does handle 12 predefined global variables with
names 'V0' to 'VB' (numbers in hex!). During program runtime (and only during
runtime !) temporarily the variables 'VC' to 'V17' are available, but will
be overwritten by the command line buffer during interactive operation. Variables
have not to be declared. The addresses for variable parameter fields are
descending from 0xBE (=V0). When a variable is compiled into another user
function, the DOLIT token is compiled, followed by the address of the parameter
field.
AT90S8515 and AT90S8535 versions without external EEPROM:
For these CPU types, 'Avise' does handle 40 predefined global variables
with names 'V0' to 'V27' (numbers in hex!). During program runtime (and only
during runtime !) temporarily the variables 'V28' to 'V4F' are available,
but will be overwritten by the command line buffer during interactive operation.
Variables have not to be declared. The addresses for variable parameter fields
are descending from 0xFE (=V0). When a variable is compiled into another
user function, the DOLIT token is compiled, followed by the address of the
parameter field.
AT90S8515 and AT90S8535 versions with external EEPROM:
There are no predefined variables. Global variables are declared with the
syntax 'VAR '. This puts an appropriate entry into the symbol table
and a parameter field is automatically allocated in the SRAM. Except the
space in the symbol table, VARs do not occupy space in the EEPROM. The token
code of the variable is the address of the SRAM memory cell reserved for
the low byte of this variable. (address +1) is allocated, too, for the high
byte. As the addresses for variable parameter fields are descending from
0xFE, token codes for variables can be easily distinguished from the token
codes of 'normal' user functions. When a variable name is compiled into another
user function, the DOVAR token is compiled, followed by the address (low
byte only) of the parameter field. Runtime behaviour of DOVAR is equivalent
to DOLIT, but needs only one subsequent byte.
Differing from other programming languages, in 'Avise' (as generally in
Forth) variables don't put their value content on the stack when called,
but their absolute SRAM address. Further handling see read function "R"
and write function "W" above.
To perform operations on variables, their value must always be transferred
on the stack (exceptions +W and -W). Direct operations involving two variables
are impossible.
A good programming style would require to name variables by context. Due
to lack of memory, this could not be implemented in some versions of
'Avise'. Some hints to create variables (and constants) with user specific
names:
9. Structuring techniques:
Structuring techniques can only be applied in the compiling state. During
interpreting state, 'Avise' refuses structuring commands. But user words
which contain structuring functions can be called in the interpreting state.
Conditional program execution:
IF ... ELSE ... ENDIF
(the ELSE alternative is optional, similar to other programming languages.)
But there is a significant difference in comparison with other programming
languages: the branch condition is not evaluated right of IF. It must already
be on the stack, when IF is called. During its runtime, IF does check
the top of the data stack. If it is TRUE (i.e. formally
=0xFFFF=-1, practically NOT ZERO), the code between IF and ENDIF (or between
IF and ELSE, respectively) is executed. If the TOS is
FALSE (exactly=ZERO), this piece of code is ignored.
Instead, the code between ELSE and ENDIF is executed.
Type for example:
: TEST IF ." TRUE" ELSE ." FALSE" ENDIF ;
This function does analyze the stack before IF and does consume it this way.
DO ... LOOP (counted loop):
This pair of words is totally different from standard Forth
implementations:
Three stack parameters are consumed by DO at runtime: the first (lowest,
eldest) one is the loop start value, the next younger one is the final loop
parameter, which will be performed last . The actual loop index is not
held on the return stack but in a global variable, whose address is the
latest entered stack parameter consumed by DO. Holding the loop parameter
in a variable makes it much easier to handle it within the loop- especially
when loops are nested. After runtime execution of DO (spoken exactly its
"runtime primitive" DODO, which is compiled by DO), the address of the loop
parameter, the final loop parameter and the LEAVE address are held on the
return stack. Differing from the Forth standard, the loop is run last
with the final loop parameter. For reasons of logical consistence, the
loop is executed once, if the start parameter is equal to the final
parameter.
Program as an example:
: REIHE 0 17 V1 DO V1 R . LOOP ;
Then start REIHE and regard the terminal display.
During execution of REIHE the numbers between 0 and (hex)17 are put on the
data stack and transmitted to the display.
: DOWN 10 0 V1 DO V1 R . LOOP ;
Nach dem Start von DOWN erscheint auf dem Bildschirm die Reihe: 10 F
E D C B A 9 8 7 6 5 4 3 2 1 0 .
Differering from most Forth implementations, the loop
parameter is automatically counted down, when the final loop parameter is
less than the start parameter ('Avise1.2': unsigned compare,
'Avise2.0': signed compare).
BEGIN ... UNTIL loop (uncounted loop with open termination):
Program:
: FOREVER 0 BEGIN 1 + DUP . KEY? UNTIL DROP ;
and start FOREVER. The endless loop is terminated
as soon as any key at the terminal keyboard is pressed. Spoken more
fundamentally: If the top of stack is "FALSE", UNTIL does cause a jump to
the code token just behind BEGIN. ist. If the top of the stack is TRUE, code
execution will continue linear after UNTIL. The final DROP command is necessary
to keep the stack in balance, because KEY? does put on 2 items when a character
was received.
The compiled tokens in structuring code differ significantly from the source
code, as you can verify with the command SEE.
The token contained in the source code are "compile time immediate token".
I.e. these token are not compiled, but immediately executed during compile
time. At this time, they resolve jump addresses and compile them together
with the respective "runtime token", as there are: DODO, DOELSE, DOIF, DOLOOP,
DOUNTIL. These are listed by WORDS and in the glossary for information; but
they cannot be called directly by the user.
10. Debug functions within 'Avise':
-
.S does list the actual items of the data
stack without modifying them. Rightmost printed number = top-of-stack entry.
Furthermore, .S does list the actual content of the 8 first declared variables
(resp. V0 to v7 from left to right.
In single step debug mode, before transmitting the stack information to the
terminal, .S does send the name and the address of the token to be processed
next.
.S can be called everytime interactively or can be compiled into user words
to show state messages at runtime (without halting the program execution).
-
BREAK (not available in AT90S4433 versions)
is built into compiled user words and works as a breakpoint. When debugging
is active (enter 1 DEBUG) and this breakpoint
is reached during program execution, .S is executed and the program flow
is halted until the user types a TAB character into the terminal.
From now on, every token at the same return stack level is executed step
by step and .S is displayed on the terminal. Next step is triggered with
the TAB key. When the '|' character (ASCII code 0x0C) is entered, 'Avise'
returns to normal operation until the next breakpoint.
-
DEBUG (not available in AT90S4433 versions)
can be called interactively - or it can be compiled into functions, if the
debugger shall be activated only under certain runtime conditions. To switch
easily to normal program execution, breakpoints can be globally deactivated
with the command 0 DEBUG and reactivated with
1 DEBUG. When debugging is switched OFF, the
breakpoints are still present, but need very little runtime overhead.
-
SEE shows the internal construction of
user-compiled words. The compiled code is not identical to the sequence of
sourcecode string tokens, especially at loops and at
IF .. ELSE .. ENDIF structures.
The terminal display has following structure, items separated by spaces:
first the offset within the EEPROM memory (real physical address), then a
colon followed by the token compiled there. Some token are followed by additional
parameters, which mean a data value (DOLIT), a jump destination (DOIF, DOELSE,
DOLOOP, DOUNTIL) or a variable parameter address (DOVAR). This way, jump
destinations can be checked without long calculation or offset counting.
The token hex FE does mark the end of a word code and implies an EXIT
token.
SEE must not be compiled into user words.
-
WORDS displays a list of all available
command words and the respective token codes. Kernel functions first followed
by user defined functions. If the output has too many lines, the CPU can
be halted with the TAB key. Next stroke of any key will reactivate the CPU.
11. Warm and cold start, delete words:
During a programming session it does happen usually, that some chaos has
been produced, which one would like to clear up before working on. Differing
from pure compiled languages, this chaos is not (only) in the source code.
By the possibility to compile incrementally, any experiments, inconsequences
and misdecisions of work are contained in the actual runtime system and block
some memory.
-
ABORT causes a WARM start of 'Avise':
All stacks and some essential control parameters are reset to their default
values. Especially the compiling state is finished and the interpreting state
is activated. ABORT can be called interactively or can be compiled into user
words. Else, all SRAM memory locations as variables and I/O register remain
unaltered. When compiled, warm start will be performed at runtime of ABORT.
-
INIT causes a COLD start, i.e. a hardware
reset is forced and all SRAM cells are cleared. Due to the Flash and EPROM
nature of user code memory, all compiled words are preserved.
-
FORGET <name> deletes the named user
word and all user words, which have been defined later. Stacks remain
unchanged. Note that it is possible with 'Avise' to overload user words by
name. Only the newest one is found in the search tree. Elder ones will become
unvisible to the interpreter/compiler; but they will still reside in the
user memory and be called by the words, into which they were compiled. FORGETting
a word, which overloaded the elder one, recovers the elder one for the
interpreter/compiler. This allows easy experimenting with different styles
of implementation, throwing away the experiments and program the final
version.
FORGET must not be compiled into user
words.
12.Using the 'Atool' terminal
program:
Source Loader
Every programming and operation step can be entered manually from the keyboard.
To handle longer programs conveniently, 'Atool' provides a "source
loader".
First you write your user program on a plain ASCII text editor and then you
upload it automatically line by line to 'Avise'. It should be noted that
there is no structural difference between manual and automatic source loading.
No hidden control characters, no special handshake. As the only visual
difference, the source loader does suppress the display of source text echoed
by 'Avise' (though it is physically echoed exactly in the same way as it
is during manual programming. The echo is swallowed by'Atool'.) But 'Avise'
needs some time to compile a line. So, 'Atool' does interpret the "Carriage
Return" character and the "Tilde" character echoed by 'Avise' for flow control.
Furthermore, automatic loading is not restricted to compile programs. It
can be used for interactive control in the same way as this is possible
manually.Which parts of the source are evaluated in interpreting state
and which parts are compiled depends only on the syntactic structure of the
source code. In a practical project, both types probably will be mixed.
'Atool' does supress empty lines, comments and multiple SPACE characters.
The behaviour of the source loader can be controlled by some directives,
which are formally embedded in comments: (jeweils Zwischenraum nach " \ "!)
-
\ ### don't upload the following block of source to 'Avise'
-
\ >>> finishes suppression of upload. From here, continue
again to upload source
-
\ kkk pause the source loader until any terminal key is pressed. This
is intended as a tool to synchronise pre-scripted blocks of interactive commands
with live performances.
A typical programming cycle:
Edit code or first piece of code. Start 'Atool'. Open source pressing F2.
Press F3 for upload (in cases of incomprehensible troubles visual upload
with F4 may be preferred).
Backslash comments normally are suppressed directly by the source loader.
Assume, a certain first part of the program is already stated as error-free
and shall be extended now. Dont quit 'Atool' but put the focus of Windows
on the editor.
-
Exclude ready part with \ ### ... \ >>>.
-
Write source for new functions or commands, save source, but it is not
necessary to quit the editor or to re-open the code file. Upload with
F3.
-
Check, debug. When OK, set \ >>> lower in the source code. When
not OK, delete some part of the compiled code with FORGET. (Alternatively
wrong functions can be overloaded by subsequent compilations.)
-
To revise some part of source code: set \ >>> higher again.
-
and so on.
\ ### and \ >>> can be used several times in sequence
and nested. Always the last directive is valid.
Hotkeys
In general, 'Avise' does only accept "printable characters", no country specific
letters.These are: ASCII codes between 0x20 and 0x7B, furthermore 'Carriage
Return' =0xD as ENTER code and 'Backspace' = 8.
Following ASCII codes have special meaning for 'Avise' - they are filtered
out in the serial interrupt handler at very low system level. (i.e. they
are forbidden in function names):
-
TAB (ASCII code 9) is pressed to proceed in single step mode. Furthermore,
out of the debug mode but in interpreting mode, the CPU can be halted when
TAB is sent. Reactivation with any keystroke.
-
Ctrl-D lets the single step debugger DIVE into the next user word. To achieve
this, 'Avise' is temporarily put into RUN state until the next user word
is called on a DEEPER level of subroutine threading. Attention: if
no call of a deeper levelled user word does follow within this function,
the system may be effectively put into RUN state! It is impossible do dive
into kernel functions, because they are implemented totally different.
-
Ctrl-U lets the single step debugger leave this user word and return in RUN
state UP to the calling user function.
-
Ctrl-R finishes the single step mode and returns to RUN mode until the next
BREAK point. Because some terminal programs have problems to send control
characters the same effect is reached when the vertical line character is
sent.
-
The Vertical Line character '|' (ASCII code 0x7C) is used to put the single
step debugger into RUN mode up to the next breakpoint. The same effect is
reached by 'Ctrl-R'.
-
The swiveled bracket character '}' (ASCII code 0x7D) is ignored. This is
intended for transparent use of 0x7D which is the ID for "private" or
"experimental" MIDI SYSEX messages. This way, after having changed the baudrate
(by autostart function, for instance, any command can given to 'Avise' packed
into such a MIDI SYSEX message. MIDI specific control codes are filtered
automatically.
-
The Tilde character '~' (ASCII code 0x7E) initiates a "warm" start of 'Avise'
from the underground. This is useful to return to console operation from
a never-ending autostart function, e.g. In this case, a hardware reset would
only restart the auto function.
On the other hand, 'Avise' does send the Tilde character ~ to mark any error
message as support of automatic message parsing.
-
The ASCII code 0x7F is ignored.
* Trademarks and product names cited in this text and
corresponding ones are property of their respective owners.
|
|