Tutorial
PL/i Programming Language for i.CanDoIt
This set of pages will provide brief tutorials about programming in PL/i. This language is more simple than C, but more structured than Basic. The objective in creating this language was to compile compact code that would run efficiently and safely as a virtual machine, like a very lean Java.
Index of PL/i Tutorials
Tutorial #11

Time Functions

There are several soft timers available to PL/i. These may be triggered, tested for timeout, checked for present time value, and retriggered. The timers count tenths of seconds. Syntax for timer functions is:

<var> = timer ( <timer> );
<var> = timeout ( <timer> );
trigger ( <timer> , <value> );

<timer> must be an integer timer number. The value returned by timer is a tick count of tenths of seconds remaining before timeout. The value returned by timeout is a boolean which is TRUE if the timer has timed out since the last call to timeout with that timer number, or FALSE if not yet timed out or previously timed out. The timeout function may be used in an expression, for example:

if timeout(2) then seti (10, 0); endif;

The above example will "turn off" the output at register 10 when timer 2 times out. If we wanted to make this more readable, we would have first declared constants such as:

#PumpTimer = 2;
#PumpMotor = 10;

and now our example becomes:

if timeout(#PumpTimer) then
seti (#PumpMotor, 0);
endif;

The trigger function will start, or restart (retrigger), the timer specified, resetting its time value to <value> in tenths of seconds. If the timer had not previously timed out, the new value will take effect without the timeout function returning a TRUE in between. However, if triggered with a value of zero, this will force the timer to zero and cause the timeout function to return TRUE upon its next call.

The function ticks will return the value of a continuously incrementing time counter. Each "tick" represents on tenth of a second, and the counter rolls over to zero when full. Syntax for reading the tick counter is:

myVar = ticks();

The function delay will suspend program execution for some number of seconds, or generate a delay. Examples:

delay (50);
delay (2);

The first example will pause program execution for 5 seconds. The second example will pause for two tenths of a second.

Flash and EEPROM Access

The definition of Flash and EEPROM access vary depending on what the target processor is. When the target is the AddMe III I/O processor, you have access to both EEPROM for frequently changing non-volatile memory, and Flash for infrequently changing non-volatile data memory. When running the program in debug mode on the web server, but the final target is the AddMe III I/O coprocessor, both Flash and EEPROM are emulated. When the final target is the web server, EEPROM is not available, and Flash is implemented as a Flash file in the web server's file system (but you still use the same functions for addressing Flash records). Syntax for the calls is:

read_flash ( <sector> , <var> );
write_flash ( <sector> , <var> );
read_eeprom ( <offset> , <var> );
write_eeprom ( <offset> , <var> );

Read will transfer data from non-volatile memory to the variable named. Write will transfer data from the variable named to non-volatile memory. EEPROM offset is given in bytes starting from zero. Flash sectors are numbered from one. Each Flash sector is 64 bytes. Exactly the variable size will be written to EEPROM. The <var> size up to 64 bytes will be written to a single sector of Flash with each write call. Single byte writes to Flash should be avoided since each byte will consume 64 bytes of Flash. Records of up to 64 bytes should be used for efficient Flash memory usage. EEPROM can be written a single byte at a time with no penalty.

Memory capacity allocated to these functions: There are 64 sectors of 64 bytes (4096 bytes total) of Flash memory set aside for PL/i data storage. This data may be initialized by uploading a CSV file from the server's Initial Data web page. If no initial data is uploaded, Flash data is initially all hex FF's or -1. There are 512 bytes of EEPROM set aside for PL/i data storage. EEPROM is also initialized to all FF's or -1.

Miscellaneous Functions

You may deliberately cause the program to stop executing by using the die function. This would be used in the event of detecting a fatal error of some sort. The abort code given in the call will be reported to the system's runtime error reporting mechanism for diagnostics. The syntax for the call is:

die ( <code> );

There are two procedures available for debugging programs. These will only function when running a program via the web interface, and will be treated as "no operation" instructions elsewhere.

read ( <var> , <tag> );
write ( <expression> , <tag> );

The "read" procedure will take input from the input window attempting to parse a single numeric value. The value will be assigned to the variable named. The "write" procedure will print the value of the argument (variable, literal, or expression) to the output window in the web interface. In both cases, the "tag" is a numeric value you choose to help you simply identify where in the program the read/write came from.

You may require knowledge of variable sizes in order to calculate offsets into EEPROM or Flash when using the memory access functions. A "sizeof" function familiar to C programmars is available, and returns the variable size in bytes.

<var2> = sizeof ( <var1> );