Psion Homepage Logo.

A brief look at the PSION Organiser II CM/XP (Part 2)

OPL (Organiser Programming Language) is a quite powerful compiler language. This means that the source code (what you type in) is first translated into a kind of machine code and can then be used like a built-in application.

Select PROG from the main menu. The program menu comes up:

[EDIT LIST DIR   ]
[NEW RUN ERASE   ]
 COPY
EDIT: edit an existing file
LIST: print a file via CommsLink
DIR: list all program files on a pack
NEW: creates a new file
RUN: execute a program
ERASE: delete a file
COPY: copy a file to another pack

The first program is very simple:

TEST:
PRINT "hello world"
GET

To enter the program, select NEW and type test (the filename) and press [EXE].
The program-editor comes up. You'll notice the filename in the first line. For now, the rest of the line is left blank so press [EXE] to change to the next line.
Now enter the other lines (case is not important). When you're finished, press [MODE].
The compiler menu comes up:

[TRAN SAVE QUIT  ]
[                ]
TRAN: compile and save
SAVE: save source, don't compile
QUIT: abandon all changes
[ON] return to editor

Press [EXE] to TRANslate the prog.
If you have misspelled a command, you'll receive an error message and get the opportunity to go on editing. The cursor will be close to the misspelled command.
If everything is OK, the SAVE dialogue comes up. You have the chance to change the pack, but usually you'll just press [EXE].
Now press [S] to START the program. The last used program is at the prompt, so you'll just have to press [EXE]. What you see now should be

[hello world     ]
[                ]

This is the result of the PRINT command. GET is a function that waits for a key (without using it, the program would have ended immediately and you would not have seen the text).

Press any key to return to the PROG-menu.

 

Now that you know how to enter programs, you might also read the LZ Programming Manual. Although some OPL commands and functions described there will not work on the CM/XP, it is far more detailled.

If you decide to have a breif look, we are going to discuss some programming concepts:

Commands vs. Functions: Commands are instructions that tell the computer to perform a specific task. Most commands must be followed by further information (e.g. print was followed by the text to be printed). Functions instruct the computer to return a value. If further information is needed, it is written in brackets (e.g. len("OTTO") returns 4 because OTTO is a four letter word)

Variables: For more complex programs we need a place to store immediate results. OPL lets you define "named memory boxes" to store data. These boxes are called variables (because the data inside is variable). There are 3 types of data:
- floating point numbers
- integer numbers (range -32768 to +32767, no decimals)
- character strings

To tell OPL the type of variable, identifiers are added to the variable name.
   %...........integer (e.g. number%)
   $............string (e.g. name$)
   nothing...float (e.g. amount)

Floats can also be used for integer data, but they use more memory and behave differently with the logical operators.
If you store a value with decimals in an integer variable, the decimals are cut off (NOT rounded).

f =  2.0/3     => 0.666666666667
i% = 2.0/3     => 0 (!!!)

Also note very well:
Any expression consisting of only integers will result an integer even if stored in a float!

i1% = 2 :i2% = 3
f1 = i1%/i2%         => 0 (!!!)
f2 = 2/3             => 0 (!!!)

To get the expected result, at least one of the values must be a float:

f1 = FLT(i1%)/i2%
f2 = 2.0/3
f1 = i1%/FLT(i2%)
f2 = 2/3.0

Now f1 and f2 will be 0.66... (the flt function converts an integer to a float)

Keep the above in mind as this somehow unusual behaviour is a frequent reason for wrong results!

Before using variables, we have to tell OPL which variables we are going to use. This is done by the LOCAL or GLOBAL statement (must be at the very beginning of the program, the difference between the two is covered later).

The second program is a simple centimetre to inch converter:

cm2inch:
LOCAL inch,cm
PRINT "cm  :",
INPUT cm
inch=cm/2.54
PRINT "inch:",FIX$(inch,2,10);
GET

The INPUT command reads data from the keyboard and stores it in the specified variable after you press [EXE]. If you enter data that cannot be stored in the variable (e.g. a character into a numeric variable), a question mark is printed and you have to re-enter the data.

Have you noticed the commas and semicolons in the PRINT commands? They are used to separate the different items to print. A comma inserts a space between the items, a semicolon does not. Usually the print command moves the cursor to the next line after printing the items, but if there is a comma or semicolon at the end, the cursor stays in the same line.

As the result of the division would have a lot of decimals, the FIX$ function was used to format the number (FIX$ returns a character string representing the passed number). The second parameter specifies the number of decimals, the third one defines the maximum width of the string.

 

Strings: Strings are obviously different from numbers. You'll have noticed that the quotes around the strings we have used (e.g. "cm :") were not printed. They are used to delimit the string. Try the following example:

TEST:                     Screen:
PRINT "<"   ;">"          [<>              ]
PRINT "<   ";">"          [<  >            ]
GET

In the 2nd line, the space characters are outside the quotes and therefor ignored by OPL. As being part of the first string in the 3rd line, they are printed.
The next line of course prints the same:

PRINT "<  >"              [<  >            ] 

String variables: String variables are different to float/ integer variables in many ways. Each character in the string uses one byte of memory. So OPL must know the maximum number of characters that will eventually be stored in the variable. This is accomplished by a parameter in the local or global statement(s) at the very beginning of the program. Remember that string variables must end with the $ sign and no string may be longer than 255 characters!

XOFF:
LOCAL name$(10),memo$(255),k%
PRINT "Name:",
INPUT name$
PRINT "Memo:",
INPUT memo$
CLS
OFF
PRINT "Hello",name$
k%=VIEW(2,memo$)

After reading name and memo into the variables, this program clears the screen (CLS) and turns off the organiser. On wakening, it prints "Hello" and your name. VIEW is a function that displays a string (2nd parameter) at a specified line (1st parameter). If the string does not fit on the screen, the line is scrolled. Cursor keys control scrolling, any other key ends the function and the number of the pressed key is returned.

Starting programs from main menu: The above program could be a nice replacement for the OFF command in the main menu. Just press [MODE] at the appropriated place in the main menu and enter the name of the OPL-program (XOFF). From now on, X will start this program.

Starting programs from within a program, defining functions: Any OPL-program can be called from within another program almost like an OPL command (the only difference is that you have to put a colon right after the name to tell OPL that it is an external procedure). You can also pass parameters to the program and instruct it to return a value (i.e. behave like an OPL-function)

test:
LOCAL a,r%,t
PRINT "net :",
INPUT a
PRINT "rate:",
INPUT r%
t=tax:(a,r%)
PRINT "tax  :",FIX$(t,2,10)
PRINT "gross:",FIX$(a+t,2,10)
GET

This program needs another program to run:

tax:(net,rate%)
RETURN net/100*rate%

The calling program passes 2 parameters (a,r%) to the other program. The subprogram must know where to store the additional information. Therefor two parameter variables are defined in the first line. When calling a subprogram, parameters must match in number and type. The contents of parameter variables cannot be changed.

In the above example it may not be worth defining an extra function, but if the your programs get more complex, you'll soon see the advantages: The function is only defined once, but can be used many times and is available also for other programs - even for the calculator.

[CALC:tax:(123,5)]
[=6.15           ]

Like variables, function-names have to be followed by $ or % if the function returns a string / integer resp.

Global variables vs. local variables: Passing values to subprograms via parameters is one possibility, defining global variables another. As opposed to local variables, globals are also seen in all subsequent sub-routines. The next program globally defines the tax rate, which is later used by the subprogram:

TEST:
GLOBAL rate%
LOCAL a,t
PRINT "net :",
INPUT a
PRINT "rate:",
INPUT rate%
t=tax:(a)
PRINT "tax  :",FIX$(t,2,10)
PRINT "gross:",FIX$(a+t,2,10)
GET
tax:(net)
RETURN net/100*rate%

Note that the second parameter of tax: has disappeared.

Mind that local or parameter variables defined in a subprogram temporarily overrule global variables with the same name.

Psion bar

Now that you know the programming basics, I strongly encourage you to explore the OPL-reference at this site. In my opinion, trial and error is still the most effective way of learning a programming language.

The next chapter will cover array variables, decision making and program loops. Data-files and serial communication will be theme of other chapters.

If you don't find these chapters where you found this document, you're in bad luck as they are not yet written. Maybe a bottle of Champagne would help?

 

These pages should be viewed using Netscape 4.03 or Microsoft Internet Explorer 3.02 at 800x600 pixels.
Left arrow Brief Look, Part 1 ~ Homepage ~ CM? XP? LZ? Right arrow