Der FKG-Roboter

FORPHYS-Mess-Interfaces

Forschendes Lernen im Physik-UR

Quantenphysik für die Schule

Grundfakten der Quantenphysik

Materialien Physik-UR

Impressum

Kommentare und Wünsche

© H. Hübel Würzburg 2005

 

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:

  • As a most simple method to customize variable names, "alias" words can be compiled, but at the cost of additional memory and runtime. The advantage for the user is not to care for the details of the processor memory map. For instance to rename V17 as "COOKIE":
    : COOKIE V6 ;

    ( You can get the SRAM address of a specific variable, e.g. V6 with the command V6 . (dot command) )

  • Much better execution speed you will obtain with the following compilation:
    Z: COOKIE V6 ;
    With Z: the compilation is directed into the internal EEPROM of the AVR controller. Unfortunately, this memory space is narrow.

  • If you need a constant by name instead of a variable, you can do it the same way. But instead of a memory address, you assign the constant value with the name:
    : ROUTE 66 ;

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.

  1. Exclude ready part with \ ### ... \ >>>.
  2. 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.
  3. 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.)
  4. To revise some part of source code: set \ >>> higher again.
  5. 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.