When the LZ/LZ64 models were released, the manual for the CM/XP was completely re-written. Below is that renewed version of the CM/XP manual, which was used from 1989 onwards.
© Copyright Psion PLC 1988
All rights reserved. This document and the programs referred to herein are copyrighted works of Psion PLC, London, England. Reproduction in whole or in part including utilisation in machines capable of reproduction or retrieval, without the express permission of Psion PLC, is prohibited. Reverse engineering is also prohibited.
The information in this document is subject to change without notice.
Psion and the Psion logo are registered trademarks of
Psion Organiser II, Datapak and Rampak are trademarks of Psion PLC.
V1 (Jan 89)
Part no. 6100-0024
The Psion Organiser II Where things are
1 Getting started Fitting the battery Switching on The menu system Setting the time 2 Saving records What is a record? Getting used to the keyboard Saving a record 3 Finding and editing records Finding a record Looking at all the records Editing a record Erasing a record Copying a record to a different device 4 Alarms Setting an alarm Switching off an alarm Cancelling an alarm 5 The diary Moving through the pages Making a diary entry Setting an alarm on a diary entry The diary menu 6 The calculator Doing a calculation Calculator memories Editing a calculation Using a result again Built-in OPL functions in calculations OPL procedures in calculations
7 Customising the main menu 8 Storage devices Devices A: B: and C: Datapaks, Rampaks and internal memory The INFO Option The RESET Option 9 Records and files Copying records to different devices Files The COPY Option 10 Replacing the battery
11 Introduction to OPL The Prog menu Creating, saving and running a procedure EDIT, PRINT, DIR, ERASE, COPY 12 Procedures and variables 13 Loops and branches 14 Operators 15 Data file handling 16 Error handling 17 Example programs 18 OPL commands and functions Summary syntax List of commands and functions
A Organiser character set B Technical Data C Technical programming D Error messages E Troubleshooting
The Psion Organiser II is a powerful computer for your pocket.
It has its own internal memory which will retain information, even when the Organiser is switched off. In addition it has two devices which are the key to the open-ended power of the Organiser. These devices are the equivalent of disc drives on a desk-top computer. They can each hold a Datapak - for you to store your own information on, or a program pack - containing a program such as the Pocket Spreadsheet.
The internal memory of the Organiser will hold around 32000 characters of information (Model XP) or 8000 (Model CM) but the addition of one or more Datapaks can boost the storage capacity considerably - by up to 128000 characters per Datapak on Model XP or 64000 characters per Datapak on Model CM.
Datapaks provide a very secure means of storing data. Using them you can create a large and extremely secure personal information base.
The Organiser comes with a powerful set of utilities including:
The Organiser also has its own built-in programming language called OPL, specially designed to handle your database applications and to exploit all the machine's facilities to the full.
So the Organiser supersedes your personal filing system, clock, diary and calculator and puts unparalleled database processing power into the palm of your hand.
Organiser peripherals allow you to print out information stored in your Organiser, connect it to another computer, send information over a telephone line, and much more. The range available includes:
Comms Link - to link to a desk-top computer, modem or another printer
Organiser Developer - to debug OPL programs on a desk-top computer
Bar-code reader and card-swipe reader
Formatter - to clear and reformat Datapaks
Pocket Spreadsheet. (loads 1-2-3 files)
Oxford English Spelling Checker
The range is constantly expanding, so contact PSION at this address for a full list of available products:
London W1H 1DT
As you learn about all the powerful facilities of your Organiser, don't be afraid to try things out - you can't harm the machine by pressing keys, so go ahead and fin out just what the Organiser can do for you.
This is a rear view of the Organiser with the protective case removed. Devices B: and C:, which are protected by sliding covers, can each be fitted with a Datapak, a Rampak or a program pack.
This is a top view of the Organiser showing the Top Port which can be fitted with peripherals such as the Psion printer or the Comms Link:
The manual is divided into three parts:
This chapter shows you how to fit the battery, switch on, choose an option from the main menu, set the time, and switch off again. There is a summary of how to do these things at the end.
The Organiser uses any 9 volt PP3 size battery. However, we recommend alkaline batteries, as they last longer.
To fit the battery:
If the battery only slides in half way, you have tried to put it in the wrong way round. Turn the battery over so that the other metal contact slides into the connector first and try again.
Warning: Never remove the battery from your Organiser or you will lose all your data. Even when the battery runs low, do not remove it until you have read Chapter 10 and you have a new one ready.
To switch the Organiser on:
After the copyright message, the screen will show the main menu which looks like this:
FIND SAVE DIARY CALC PROG ERASE
If you can't see anything on the screen, adjust the contrast using the contrast wheel on the right hand side of the case. You may need to adjust the contrast sometimes - for example when you switch between using the Organiser flat on a desk or holding it in your hand.
You can already see six of the options available on the Organiser main menu. There are six more options available off the screen like this:
FIND SAVE DIARY
CALC PROG ERASE
TIME INFO ALARM COPY RESET OFF
When you select one of these options you access one of the Organiser's built-in utilities:
FIND, SAVE, and ERASE all access the database where
you store information such as addresses.
CALC selects the calculator.
DIARY selects the diary.
PROG takes you to the Organiser programming language (OPL).
TIME selects the clock.
ALARM selects the alarm-setting facility.
INFO gives you a status report on memory and data.
COPY allows you to copy files of the database information.
RESET erases all data in the Organiser and resets it.
Off switches the Organiser off.
The first character of the first word on the screen is covered by a flashing block - this is called the cursor.
To move around the menu:
When the cursor is positioned on the last option visible on the screen, press → once more to see the next line of the menu.
Practice using all four arrow keys, ↑ ↓ ← and → to move between the different menu options.
To select an option from the menu:
If there is more than one option starting with the same letter - as with Calc and Copy - pressing the first letter, C, only moves you between the two options. To choose one or the other, you need to press EXE when the cursor is on the one you want.
To get back to the main menu from any option:
Before you go on, practice moving from the main menu into the options and back again.
To select the Time option:
You have now entered the Time option, and the screen should look like this:
FRI 1 JAN 1988 00:00:00
To set the current time and date:
Note that the day of the week changes automatically whenever the date is changed. The day and date may not align correctly for you if you're not yet in the right month or year.
So, to change the month, year and time:
After setting the correct time and date:
The time is now set. You only need to reset it if you change time zones or the hour changes.
Whenever you want to know the correct time and date you can select TIME from the main menu.
To switch off the Organiser you have to be on the main menu. So, if you are not on the main menu, press ON/CLEAR once or twice to get there.
Just press ON/CLEAR to switch on again.
To conserve battery power, if you leave the Organiser on for five minutes without pressing any keys, it will switch itself off.
When this happens, don't worry. Just press ON/CLEAR once and the Organiser will come on again at the exact place it was when it went off. All your data is intact and you can carry on where you left off.
The Organiser comes equipped with a database where you can store all manner of information. This chapter shows you how to save a record. It also introduces you to the Organiser keyboard.
A record is a any piece of information such as a name and phone number, an account number, a stock number, or any other piece of data you store in the Organiser.
To save a name, address, and phone number:
You could now start to type in a record like this one:
ABRAHAM LINCOLN, PRESIDENT TEL 01-010-0000 THE WHITE HOUSE WASHINGTON, DC
But as you're doing so, look through the keyboard section on the next page and take time to experiment and get the feel of the keys.
As you type the first word the letters will appear to the right of the SAVE A: message on the screen.
When you want to start a new line, press ↓.
Practice using all the keys:
The letter keys normally produce capital (upper case) letters on the screen.
To type lowercase letters hold down SHIFT and press the CAP (↑) key.
To return to capital letters press SHIFT and CAP.
If you hold down SHIFT and press one of the letter keys, you access the number or symbol marked above it.
By holding down SHIFT and pressing NUM the numbers and symbols are locked on, so that you don't have to hold down SHIFT all the time.
Return to letters by holding down SHIFT and pressing NUM again.
When typing letters the cursor is a flashing
When typing numbers the cursor is a line.
To delete mistakes, position the cursor with the arrow keys and use the DEL key.
DEL deletes the character to the left of the cursor.
To delete the character under the cursor hold down SHIFT and then press DEL.
|Scrolling||If you type in a line that is longer than
the screen, the whole line is scrolled to the
left as you type, like this:
←SAVE A:ABRAHAM LI
|New line||To start a new line un a record, press ↓.|
|Join lines||To join up two lines of a record, place the cursor on the first character of the second line and press DEL once.|
(You can't split one line into two separate lines, and you can't insert a new line into the middle of a record.)
When you are satisfied with what you have entered:
It can find be found at any time with the FIND option.
If you wish to abandon a half-finished record, and not save it:
If you have fitted a Datapak to your Organiser, you can save the record there.
When you have finished typing in the record but before you press EXE, press MODE, and the display will show which of the devices you are currently on.
The internal memory of the Organiser is device A:. If you have any Datapaks fitted, they are devices B: and C:
Normally, device A: is current and the screen looks something like this:
SAVE A:ABRAHAM L TEL 01-010-0000
SAVE B:ABRAHAM L TEL 01-010-0000
Or, if you have fitted the Datapak to the lower slot:
SAVE C:ABRAHAM L TEL 01-010-0000
If you have no packs fitted, pressing MODE has no effect.
EXE is short for execute. It is like the Enter key on some computers.
ON/CLEAR is used to clear the line where you are typing or to return to the main menu.
MODE is used to change the mode of operation - for example to be on another pack.
This chapter shows you how to find a record which you have saved, edit it and erase it. It also shows you how to copy a record to pack.
The screen looks like this:
(If you saved your record on a Datapak, press MODE to select the device you want to search.)
To find a record you just need to type in a search-clue. This is just a few of the characters in the record. For example, if you have saved Lincoln's address and phone number:
The screen then shows the record:
AHAM LINCOLN, PR TEL 01-010-0000
In the ABRAHAM LINCOLN example, the first line would be scrolling round and round as there is not enough room for it on the screen.
If the record that was found is not the one you are looking for, press EXE to see the next record the Organiser found containing the search-clue you entered.
If there are no more records which contain your search clue, this message is shown:
**************** **END OF PACK***
Press EXE again and the first matching record will be displayed once more. To return to the main menu, press ON/CLEAR once.
If you wish to browse through all the stored records, select FIND from the main menu, and press EXE without typing in a clue. The first record in the main file is displayed, and at each subsequent press of EXE, the next record is displayed.
After the last record has been displayed, the END OF PACK message is shown. Press EXE once more and you will return to the first record.
Again, to return to the main menu, just press ON/CLEAR once.
Records may at some time need to be altered - for example, when someone's telephone number changes. To edit a record:
SAVE A:ABRAHAM L TEL 01-010-0000
You can now edit the record as you wish. Use the arrow keys to move the cursor to different points in the record, to insert or delete characters.
(See the Keyboard section in Chapter 2 if you are not used to the keys.)
Any of the lines can be altered, and you can add new lines onto the end of the record, although you cannot insert new lines between the original ones.
If you make a mess of your changes, you can delete the version of the record you were editing - before you press EXE - by just pressing ON/CLEAR. The record will disappear and the screen will show:
Press ON/CLEAR to return to the main menu. The original record is still in memory, and you can find it again by selecting FIND once more.
Warning: If you press ON/CLEAR and then EXE when the screen shows the SAVE A: prompt, the original record will be erased from the Organiser memory too.
If you want to erase a record:
You now have a chance to change your mind.
Either way, the screen will show the next matching record or the END OF PACK message.
If you don't type in a search clue, but just press EXE when the screen shows ERASE A: you can go through all your records deciding to erase them or not.
If you wish to copy a record from, for example, the internal memory (A:) to Datapak B:
The record will be copied to the Datapak and the original will still be in the internal memory.
If you want to copy all the records to a different device, you use the COPY option on the main menu. See Chapter 9 for instructions.
This chapter shows you how to set an ordinary alarm and a repeating alarm. These alarms will sound even when the Organiser is switched off.
To set an alarm:
The screen looks like this:
1) FREE press EXE to set
You can have up to 8 alarms set at any one time. They are numbered from 1 to 8; number 1 is shown initially.
The screen will then show the alarm number and the current day of the week and time, like this:
1) TUE 10.26
You can set an alarm for any of the seven days starting with the current one. So, you can make individual settings for up to a week ahead.
If you are using your Organiser when it is time for an alarm to go off, it will interrupt what you are doing, the alarm will sound, and a message like this will be displayed:
When the Organiser is off it is still keeping track of the time, so when your alarm is due to go off the Organiser switches itself on, the alarm sounds, and the message is displayed.
If you are not around to press any keys the Organiser will switch itself off automatically alter a few minutes.
You can make an alarm repeat weekly, daily (like an alarm clock) or hourly.
An "R" for repeat appears under the part of the time where the cursor is positioned.
Under the day - repeats weekly at that time of day.
Under the hour - repeats daily at that hour (like an alarm clock).
Under the minutes - repeats hourly at that number of minutes past the hour.
(To remove the "R" press MODE again before you press EXE to set.)
First select the alarm to cancel, by pressing A on the main menu and pressing ↓, if necessary, until you reach the alarm you want to cancel.
The screen shows:
1) FREE press EXE to set
The alarm is cancelled and you can set the alarm again or return to the main menu with ON/CLEAR.
The Organiser diary allows you to keep track of all your appointments. This chapter shows you how to make an entry and set an alarm for it and then how to use the diary more efficiently by using the options on the diary menu.
To get into the diary:
You enter the diary at the diary page for the current day and time. (There is a diary page for every thirty minutes.)
To go to the diary page where you want to make an entry:
From the last day of the month you step to the first day of the next month. (To flick back through the days of the month use ←.)
On stepping forward from 31st December 1989, you will move to 1st January 1990 and vice versa.
The diary can be thought of as a large sheet of paper divided into boxes, rather like a year planner. The display screen acts like a window which can be moved across and up or down, viewing the contents of one box at a time:
|JAN:01:SUN:08.00 (A)don't smoke||JAN:02:MON:08.00||JAN:03:TUE:08.00|
|JAN:01:SUN:09.30||JAN:02:MON:09.30 MEET BARRY NORMA||JAN:03:TUE:09.30|
As you step through the diary pages, there will be nothing displayed on the bottom line of the screen if you haven't made any entries yet.
To make an entry when you're at the diary page you
The cursor appears on the bottom line of the display with an EDIT: prompt and you can type your text as you would write in a normal diary:
If you type more than sixteen characters, the text will scroll to the left, as usual with long lines. So it is best to keep your diary entries short. The maximum length is 64 characters.
If you are not used to the Organiser keys, look at the Keyboard section in Chapter 2.
When you have typed in your entry, press EXE. You are asked whether you want to set an alarm to sound when that entry becomes due:
JAN:02:MON:09.00 ALARM Y/N
If you choose Y you are given the chance to decide how many minutes before the event you want the alarm to sound:
You can set the number of minutes to any figure between 0 and 59, so you can be prewarned of any of your diary appointments or reminders by up to one hour.
The Organiser suggests 15 minutes as the advance warning time. To change this:
(If you make an entry in a diary page for a date which has passed, you will not be asked if you want an alarm!)
If you are using your Organiser when it is time for an alarm to go off, it will interrupt what you are doing, the alarm will sound, and your diary entry will be displayed.
If the Organiser is off when an alarm becomes due, it switches itself on. Then the alarm process is just the same as above.
(After an alarm has gone off, the diary entry remains unless you delete it, but the alarm indicator at the beginning of the entry disappears.)
To remove an alarm from an entry, move to the relevant date and time and press EXE twice. This leaves you at the ALARM Y/N message. This time, press N and the alarm is cancelled.
The diary has its own sub-menu of options.
If you are not in the diary, select it from the main menu.
The screen shows the first six options, just like the main menu, and the other three are out of sight:
PAGE LIST FIND GOTO SAVE TIDY RESTORE DIR ERASE
There are two kinds of diary options: those which change your position in the diary and those which affect the diary as a whole.
This is the mode you are in when you first enter the diary. It allows you to make your entries and set an alarm which will sound when the entry becomes due.
You go back to the diary page you just left.
This is the mode for viewing only. You can list all your diary entries in order - but you cannot change them in this mode. Use it to scan through your diary, entry by entry.
You see the next diary entry.
You can control the scrolling of long entries with ← and →.
When you have seen the last entry, this message is shown:
END OF DIARY
If you press EXE again you return to the first entry in the diary.
This option is just like the FIND option in the main menu - you can find any entry quickly using a search clue. You can then also change or delete it if you want to.
(If you are shown the END OF DIARY message and you know that you made an entry containing the letters in your search clue, you may have missed it! Press EXE again to search right from the start of the diary.)
When you have found the entry, you can do either of the following:
This option allows you to go straight to any date so that you can make an entry or change the one which is already there.
The screen shows the current date:
1989 SEP 07
You return to PAGE mode, the way the diary is when you first enter it, and you can press EXE to edit to edit the entry or DEL to delete it.
This saves all the entries in your diary in a file on a Datapak or in the internal memory of the Organiser. It is most useful for storing an out-of date diary on a pack and thus freeing Organiser memory space.
To save all your entries:
(A filename may be up to eight characters long. It must begin with a letter.)
All your diary entries are saved to the device you chose under the file name you typed in.
The diary can then be loaded back into memory with the RESTORE option below - but be careful because it will then overwrite the current diary.
Lets you tidy up the diary by deleting out-of-date entries. It makes sense to delete them every so often, as they take up memory space.
The screen shows:
SEP:07:WED:l7.30 DELETE UPTO Y/N
If you decide not to delete all of these entries, press N.
If a diary has been saved to a pack or to the internal memory under a file name, you can restore it with this option. However, be careful because if you restore a diary it will overwrite your current one.
The screen will show:
The diary will be restored and will overwrite any current diary entries. You will be returned to the diary menu.
This allows you to see a directory of the names of all the saved diaries on a device.
The screen will show:
When the required device is selected, press EXE and the name of the first diary saved on that device will be displayed.
When the name of the last diary on the current device has been displayed, the usual end of pack message is given.
This is used to erase a whole diary. (You can't erase the current diary - only one which has previously been saved.)
The screen shows:
The diary is erased from the device and you are returned to the diary menu.
This chapter shows you how to do a simple calculation and then how to use the 10 memories, edit a calculation, and use a result again.
It then goes on to explain how to use the calculator in conjunction with OPL functions and procedures.
The screen shows:
In the calculator you don't need to use SHIFT to get numbers and symbols - they are on automatically. Therefore, you have to use SHIFT to type in letters. (If you are not used to the keys, look at the keyboard section in Chapter 2.]
The basic arithmetic operators, +, -, / (divide), * (multiply) and ** (raise to a power) are used in the same way as they would be in a written calculation. Any number of levels of brackets may be used.
To try out the calculator:
The screen shows:
Clear the calculator by pressing ON/CLEAR.
Notice that the result 3.11111111111 was displayed with 11 decimal places. This is the normal setting. To change this to 3, type FIX=3 after the CALC: prompt and press EXE. (Remember that you have to press SHIFT to type letters.)
Do the calculation 4*7/9 again. The result is now 3.111. You can have from 0 to 11 decimal places. To return to the normal setting (11) type only FIX=
Built into the Organiser are ten memories which can be used either in the calculator or in OPL.
You can store numbers in them for use in calculations. They can then be added to, subtracted from and cleared.
In the calculator and OPL they are referred to by the same names, M0 to M9. (Lower or upper case "m"s may be used.)
To store the result of a calculation to a memory:
M: press 0-9
You now have four choices:
|+||Adds the current result to the total in the memory selected.|
|-||subtracts the current result from the total in the memory selected.|
|EXE||Stores the current result to the memory overwriting the current contents.|
|DELETE||Sets the contents of the memory to 0.|
The four choices above all return you to the calculator. You can also just press ON/CLEAR to return to the calculator with no change to the memories.
To find out the contents of a particular memory:
A useful feature of this calculator is the ability to edit your original calculation. Do another calculation to try this out. When the result is displayed:
The result is erased and you can now edit the calculation on the top line.
You might decide to use the result from one calculation as part of another one. When the result is displayed:
The old result is shown on the top line with the number or symbol at the end.
The percent key (%) does not operate in the same way as the percent key on ordinary calculators. So, you have to calculate percentages in longhand form. For example, to calculate 37% of 250 type in: 37/100*250 or .37*250
You can use E as the exponent. For example, 3.6E4 represents 36000.
In your calculations, you can use any of the numeric functions of the Organiser Programming Language - even if you never use OPL otherwise. The numeric functions are listed at the beginning of Chapter 18. You can use them to do far more operations than are available on an ordinary calculator. For example:
Here the SIN, CO5 and PI functions are used.
Another example might be to find the sine of 30°. This is typed in like this:
The RAD function converts from degrees to the radians which the SIN function requires.
When you press EXE, if there is an error in your calculation, you get an error message and should, as the message says, press the space key and correct it. The cursor flashes on the unrecognised character.
For instance, if you included a character which was not a function name or an arithmetic operator, like this, the cursor would be flashing on the P:
In Chapter 17 there are example OPL procedures, including one to calculate ASIN and one to calculate ACOS.
If you have typed any OPL procedures into the Organiser, you can include the procedure names in your calculations (all procedure names end in a colon]. Put the value you want to operate on in brackets after the procedure name. In this example the value is 0.1:
The value you want the procedure to operate on is called a parameter. You can use a memory name as a parameter:
Procedure names can be included in quite complex calculations. For example, if you had a procedure called FACT: which worked out the factorial of a number passed to it, then you could include this in your calculation like this:
The value 3 is being passed to the procedure. The returned value is then added to 4 and the rest of the calculation performed on the result.
From the calculator, parameters are passed as floating point numbers. To pass an integer to a procedure, you must use the INT function like this:
Part 3 of this manual shows you how to write your own OPL procedures, and there are examples in Chapter 17.
These are the twelve standard options on the Organiser main menu:
|FIND||For retrieving and/or editing records you have previously saved.|
|SAVE||For saving records either in the Organisers internal memory or a removable pack.|
|FROG||OPL (the Organiser Programming Language)|
|ERASE||For erasing records from the Organisers memory or a pack.|
|INFO||Information on how much memory is occupied.|
|COPY||For copying files of records from device to device.|
|RESET||Resets the Organiser, erasing all information in the internal memory.|
|OFF||Switches the Organiser off.|
When you first switch on your Organiser, the menu options are in this order:
FIND SAVE DIARY CALC PROG ERASE TIME INFO ALARM COPY RESET OFF
This is the default menu. However, you may change the order of the options and even delete the ones you never use.
The only menu item that cannot be deleted is OFF. Also you cannot put any other menu item after it; it's always the last.
You can replace a deleted item at a later date, but you don't have to put it back in the same place. So, you can arrange your menu in the order which suits you best.
For instance, if your chief use of the Organiser is as a diary, then it may make sense to put DIARY first on the menu, so you can just press EXE after switching your Organiser on.
To delete an entry from the main menu:
For example, if you want to delete RESET from the menu, you place the cursor on it, press DEL and the screen shows:
RESET DELETE Y/N
You now have the chance to change your mind. Press N or ON/CLEAR and you return to the main menu without making any deletion. Press Y and the menu reappears without the RESET option displayed.
To replace a deleted menu item, either at the same place as before or in another position, position the cursor at the place on the menu where you want the item to be displayed.
The inserted item will then appear at that position in the menu, pushing the following items one position to the right. The item can now be selected as before.
Note: You can insert an OPL procedure into the main menu but not with the same name as one of the original default options. (OPL is covered in Part Three.)
When saving data, the internal memory of the Organiser is known as Device A:, the upper external device is known as device B: and the lower as device C:.
Devices B: and C: are two external devices in the back of your Organiser. When you first purchase your Organiser, these two devices are fitted with covers to protect the electrical connections. You should always keep a pack or one of the covers on each device.
Devices B: and C: can hold a Datapak, a Rampak or a program pack, such as the Pocket Spreadsheet.
The Organiser checks which devices have Datapaks or Rampaks fitted, so when you go to SAVE or FIND a record and press MODE to change the device, you can choose only the relevant devices.
So, if you do not have any packs fitted, pressing the MODE key when trying to SAVE or FIND information will have no effect - you will remain with device A:.
Once you have made a device current, you continue using the same one unless you change to another.
The internal memory of the Organiser and Rampaks are RAM:
Datapaks are EPROM:
The advantages of Datapaks are that they are more secure and are not affected when the battery runs low. They are thus excellent places to store data.
The advantages of Rampaks are that they use very little power and that data is really deleted, so you can edit things as many times as you like without using up any space. They are thus the best medium for writing programs. You should always back-up your valuable data to a Datapak or a desk-top computer to keep it more secure.
Avoid pressing any key while fitting or removing a Datapak. This is easily avoided by placing the machine face down one flat surface, as the keyboard is slightly recessed.
Use the white label on your Datapak to mark it for identification later.
Datapaks are available with capacities of approximately 8000, 16000, 32000, 64000 and 128000 characters, to suit whatever application you have in mind.
For instance, all the names, addresses and telephone numbers most people could ever need can comfortably be held in one Datapak (over 2000 entries of up to 30 characters each in a 64K Datapak).
Read the important information leaflet provided with your Rampak before you fit or remove a Rampak.
The first time you try to perform any operation on a new Datapak, a message may be displayed to let you know that the Organiser is checking its size.
For example, after entering a record with the screen showing SAVE A: you can fit a new Datapak to device B: in order to save the record to that pack. The screen shows:
SAVE A:ABRAHAM L 01-010-0000
The screen shows:
SIZING PACK B: PLEASE WAIT
There is a short pause, and then the screen shows:
SAVE B:ABRAHAM L 01-010-0000
Any Datapak will only be sized once, so if you fit one which has already been sized you can go right ahead and use it.
No matter how careful you are with a Datapak, at some point it will be filled. The next time you try to SAVE any information on that Datapak, the Organiser will display a PACK FULL message.
Although Datapaks store your information permanently, it is possible to clear an entire Datapak using a process called formatting. This is achieved by controlled exposure to ultra-violet light in a machine called the Psion Formatter.
The reformatted Datapak will be completely blank, and when reinserted into the Organiser, will be re-sized as if it were brand new.
If a Datapak is full because unwanted "erased" data is still occupying space, but the pack also contains some data you want to keep, copy all of it to another pack. The erased records and files are ignored, so only real data is copied across. The old pack can then be reformatted in the Psion Formatter.
Note that the white label on the underside of each Datapak is to protect it from excessive exposure to light. It must be removed before formatting can occur.
The INFO option on the main menu tells you how much storage space is left in the internal memory of the Organiser and any packs that are currently in the devices.
The top line of the screen shows the number of free bytes (one byte stores one character) in the internal memory of the Organiser.
The Organiser model XP has 32000 bytes of internal memory, or RAM. However, 8000 bytes are reserved for other programs and peripherals, such as the Spreadsheet. So, memory size on an XP is about 24000 bytes. (On model CM 8192 bytes are available.)
The bottom line shows a scrolling display of the amounts of storage space used, in terms of percentages of the total available. Press ← to stop the line scrolling around and → to start it again.
If you had a number of diary entries and some other data stored on device A:, and some data stored on a Datapak in device B:, the bottom line would show something like this:
DIARY 4% PACK A: 15% PACK B: 36% FREE 81%
The amounts of storage space occupied here are:
|Device A:||Internal memory: 4% by the diary and 15% by other data stored on device A:|
|Device B:||36% by various data|
This leaves a total of 81% of the internal RAM free. A Datapak is not RAM so the percentage occupied on Device B: does not affect this figure.
Note: The current diary resides in the internal memory of the Organiser - unlike diaries stored on a Datapak with the diary SAVE option - so if you have a large current diary the amount of memory free for other activities is diminished.
This option enables you to erase all the data in the internal memory of the Organiser. All diary entries are lost, along with any files or procedures saved on device A:. Data saved on packs is quite safe, of course, and is not affected by this option.
Select RESET from the main menu and the screen shows:
ALL DATA WILL BE LOST - PRESS DEL
If you do not want to reset the machine, press ON/CLEAR and you will be returned to the main menu and all data will be intact. Otherwise press DEL and the screen will show:
ARE YOU SURE PRESS Y/N
If you press N or ON/CLEAR you will be returned to the main menu and all data will still be intact. If you are sure you want to erase all data in the machine, press Y. You will then return to the main menu.
When you are entering information with the SAVE facility, think about making it easy to find again:
Each record may be up to 16 lines long and each whole record may contain up to 254 characters. Each line may contain any number of characters - subject of course to this overall limit.
To copy a record from one device to another:
To copy all the records from one device to another, you use the COPY option on the main menu to copy all the data files. The next section explains this.
A data file is a collection of records. When you save a record using the SAVE option from the main menu, the record goes into a file called MAIN. This is also where the FIND option looks for records.
The MAIN file will always exist on device A: and on any Datapak fitted to your Organiser. The file will be empty unless you have saved records to it.
In addition to the MAIN data file, extra data files can be created using the OPL programming language.
The COPY option on the main menu is for copying data files from one device to another. You can copy files from the Organisers internal memory to one of the packs, and back again, or from one pack to another.
After the FROM prompt you can type in a device name - A:, B: or C: (don't forget the colon), or a device name and a file name - for example A:MAlN. This is the source device and file.
FROM A:MAIN TO B:
Copies the file called MAIN on A: to the pack on device B:
FROM A:MAIN TO B:OLDMAIN
Copies the file called MAIN on A: to the pack on device B: - but gives the copy the name OLDMAIN.
FROM A: TO B:
Copies all the tiles on A: to the pack on device B:
So, if you already have some records in the file B:MAIN and in the file A:MAlN, and you choose to copy all of the files from A: to B:, then the records in A:MAIN will be added to those already in B:MAlN.
Information stored in the internal memory of the Organiser relies on the presence of the battery to keep it safe. This includes the diary, all the records you have saved on device A:, and any OPL procedures there. Data stored on Datapaks is quite secure however.
When the battery runs low, a BATTERY TOO LOW message is displayed on the Organiser's screen. This is displayed for four seconds and then the machine switches itself off.
You must replace the battery before you use the machine again.
Do not remove the old battery until you have a new one ready.
When the old battery is removed, you have a limited time to replace it with a new one, after which you lose the contents of the Organisers memory.
If you are saving information to a Datapak when the battery runs low, the record which is currently being saved is erase on the destination device then the low battery message appears and the machine switches off.
You can use the Psion Mains Adaptor to power your machine while you change batteries. This means that the power supply to the Organiser is uninterrupted and there is no hurry to fit the new battery.
OPL is the Organiser Programming Language. It has an extensive set of commands and functions suitable for all kinds of applications - including the manipulation of the files of data saved in the Organiser as records.
To enter OPL you simply select PROG from the main menu. You are immediately presented with a sub-menu, and you can start new programs or continue with old ones.
Once you have written programs in OPL you can run them from within PROG, or directly from the main menu, or even whilst you are working on the calculator or the Pocket Spreadsheet.
An OPL program consists of one or more procedures, each of which is typed in separately. A simple program may consist of a single procedure. More complex programs are normally made up of several, one of which is the main procedure.
The most efficient way to use OPL is to write short procedures which can be tested individually. Each one should ideally perform just one specific task. That way, programs which have similar requirements can share one common procedure to do the same job.
This chapter shows you how to write, save and run a simple procedure and covers all the options on the PROG menu.
When you select PROG from the main Organiser menu, the screen looks like this:
EDIT LIST DIR NEW RUN ERASE COPY
These options can be selected in the same way as the items on the main menu. Here is a summary of their uses:
|EDIT||Lets you alter and then re-save an existing procedure - allowing improvements. corrections and modifications to be made.|
|LIST||Lists an existing procedure to an attached printer or computer.|
|DIR||Displays a list of all procedures stored on the specified device A:, B: or C:.|
|NEW||Lets you type in and save a new procedure.|
|RUN||Executes an existing procedure.|
|ERASE||Erases a procedure.|
|COPY||Copies a procedure, or all procedures, to another device.|
This section shows how to create, save and run the simple procedure which follows. The section introduces you to the PROG menu and to the process of creating, saving and reusing a procedure.
CLOCK: CLS PRINT "IT IS NOW",HOUR;":";MINUTE GET
The procedure's name is CLOCK: It clears the screen, displays the current time, and waits for you to press a key.
The current device is shown after the word NEW; in this case it is device A: (the internal memory). If you want to work on a pack, press MODE to change device.
The first thing to type is the name for the procedure. This can be up to eight characters long and must start with a letter.
Press EXE, and the procedure name is shown on the top line of the screen, with a colon at the end of the name. The cursor is flashing at the end of it.
If you are not used to the Organiser keys look at the Keyboard section in Chapter 2.
Note: in OPL you can use either upper case or lower case letters in any combination.
Press EXE to get a new line. The display scrolls leaving the cursor ready on a blank line.
PRINT "IT IS NOW",HOUR;":";MINUTE
Check that the line appears on the screen exactly as it does here. All computer languages are precise and even the spaces are important.
Here is an analysis of the line:
The first part, PRINT, is a command. PRINT makes what follows it print on the display screen.
This is followed by a space, and then a piece of text which has been enclosed in quotation marks - the text that will be printed out - "IT IS NOW". In computer terminology, any list of characters between quotation marks like this is called a string.
The next character, a comma, indicates to OPL that anything else which is to be displayed on the screen will follow on the same line as the preceding text, separated from it by a space.
The next word, HOUR, is a function. This function finds out the current hour from the Organiser clock. Here it returns to the print command, which prints it out on the screen.
The next character, a semi-colon, means that the next thing to be printed is placed immediately after the previous thing, with no space.
The next item is another string. This time the string is just one character, a colon, but it must still be enclosed in quotation marks.
The final part of the line is the MINUTE function which returns the current minutes past the hour.
The last line, the GET function. waits for a key to be pressed on the keyboard before executing the rest of the program. This means that when the procedure is run. the message which is printed to the screen will remain there until you press a key - then there are no further instructions, so the program ends.
At any time in the typing in of a procedure you can go back and make an alteration to a line by using the cursor keys.
Press ← and → to move along a line and ↑ and ↓ to move between lines.
If you need to insert a new line in between two existing lines, position the cursor on the start of the line where you want to insert a new one, then press EXE.
When a procedure has been typed into the Organiser, there are three options:
Press MODE to get to a menu of these options:
TRAN SAVE QUIT
This is a sub-menu just like the PROG menu. The following diagram shows the difference between the three options.
Select QUIT and you are prompted with the message ARE YOU SURE Y/N. Press N, and you are returned to the procedure editor. (If you pressed Y, the whole text of the procedure typed in so far would be discarded.)
Warning: Once a procedure has been abandoned with QUIT, there is no way to retrieve it again.
Select TRAN and the procedure is translated internally into a form that OPL can execute.
When the procedure has been translated, the screen displays this prompt:
You may now save the translated procedure to any available device. Press MODE to change devices then EXE to save.
When the translated version is saved, the original text is also saved. This means that there is now a version of the program which can be executed and a version which can be edited. These are both stored under the same procedure name.
If you make a typing error in the procedure. OPL spots it when it is translated. If, for example, you typed the word PRONT instead of PRINT, or left out one of the sets of quotation marks around a string, then this message is displayed:
SYNTAX ERR press space key
Now edit the line in the usual way until it reads correctly then press the MODE key to return to the TRAN/SAVE/QUIT menu and select TRAN again.
If you had typed in part of a procedure and intended to return to it later to complete it or make alterations. you could use the SAVE option from the TRAN/SAVE/QUIT menu so as not to waste memory by producing an unnecessary translated version.
When a procedure is saved rather than translated, no form of error checking is carried out. The text is saved exactly as it was typed in.
The best place to save programs is the internal memory of the Organiser (device A:) or a Rampak. Then, if a procedure takes a couple of versions before it runs exactly as you require, each edit will not be using up space.
When a final version of a procedure has been produced on device A: it is a good idea to make another copy on a Datapak. Copying procedures is described at the end of this chapter.
Once a procedure has been successfully translated you can then RUN it. In other words, you can tell OPL that you want it to execute all the instructions in it. From the PROG menu, select RUN. The screen shows:
Press EXE to run the procedure. If you want to run this procedure another time, when you have not just saved it, the name will not automatically appear after the RUN prompt - you then have to type it in. If there is another procedure name there, clear the entry line first by pressing ON/CLEAR.
When CLOCK: is run, the screen will first clear and then show something like this, depending on the current time:
IT IS NOW 16:35
The last line of the procedure was GET. This instruction simply waits until any key is pressed on the keyboard before continuing. So, when you press a key, the procedure finishes and you are returned to the PROG menu.
That was a simple example for your first procedure. There are more complex examples of OPL procedures in Chapter 17. The next section deals with the remaining options on the PROG menu.
The EDIT option from the PROG menu allows you to return to an old procedure to change it or add to it. When selected from the menu. the screen shows:
Press MODE if you need to change device then type in the name of the procedure and press EXE.
When the procedure is complete. you should use the TRAN option from the TRAN/SAVE/QUIT menu to translate it, as described earlier. If you make a mess of the editing, select QUIT and this version of the procedure will be deleted and you can edit the original version again.
The LIST option is used to print out a listing of a procedure to a printer or another computer.
If you have not got a Psion Printer II, you will need the Psion RS232 Comms Link. This allows any serial printer to be connected to the Organiser or may be used to communicate with another computer.
Select LIST from the PROG menu. If no printer or computer is connected to the Organiser, a DEVICE MISSING error message is displayed. Press SPACE to return to the menu. If one is connected and you get this message, press ON/CLEAR on the main menu to load the device software.
See the Comms link manual for further details.
The DIR option in the PROG menu shows you the directory of procedures stored on the various devices.
Select DIR from the PROG menu. The screen shows:
If necessary, change the device with MODE, then press EXE. If there are any procedures stored on the current device, the first will be displayed. Each time you press EXE the next is displayed - until you get to the END OF PACK message.
Press ON/CLEAR to return to the PROG menu or EXE to repeat the directory list.
The ERASE option from the PROG menu allows you to erase procedures from any of the devices. Select ERASE and the screen shows:
If necessary change device with MODE. You can new type in the name of a procedure to be erased from the current device, eg CLOCK. Press EXE and the screen shows:
ERASE A:CLOCK ERASE Y/N
Press Y to confirm that you wish to erase that procedure, or N to cancel. Once the procedure is erased, it cannot be retrieved.
The COPY option in the PROG menu is used to make copies of procedures from one device to another.
Select COPY from the PROG menu and the screen will show:
COPY OBJECT ONLY Y/N
Press Y if you want to copy just the translated copy of a procedure, the object file, to another device.
Press N to copy both the object and text files - the translated version and the original editable version you typed.
If you are planning to erase the procedure from the internal memory after copying it to a pack, it is unwise to copy the object file only, unless you are certain you will never need to edit it.
However, the advantage of copying just the object file is that the procedure will then occupy only about half of the memory space occupied by the original.
The COPY option operates in a similar way to the COPY option in the main menu.
If a procedure with the same name already exists on the destination device, it will be deleted - with no warning. There can only be one procedure with the same name on any one device.
To halt the execution of a procedure, first press ON/CLEAR. This will pause it indefinitely. You can then press any key to continue or Q to quit. The screen shows:
ESCAPE IN A:procname
Now press the SPACE key to return to wherever the procedure was called from.
The previous chapter dealt with the mechanics of using the PROG menu. The next four chapters cover the basic concepts of OPL programming. If you are familiar with programming languages just skim through these chapters, or refer instead to the reference sections which follow.
Procedures generally consist of the four steps shown in this simplified example:
|2||Declaration of variables||LOCAL x|
|3||Operations upon variables||x=SIN(50)|
|4||Communication of variables||PRINT x|
This chapter deals with these four steps.
e.g. print:, shares89:, TAXCALC:
If you were adding together two numbers, in algebra you could write: 'x + y = z'.
In OPL you would write z=x+y, but first you would have to declare x, y and z as variables, in order to reserve memory space for them. You would do this:
A variable is therefore a named region of memory which at the very beginning of your procedure you declare. This means that you tell the Organiser you are going to use the variable so that it will have space to store the number or text you later assign to it. So in the SINE50 example, the line 'LOCAL x' reserves a memory space named x in which the value given to x in the next line can be stored.
There are three kinds of variables identified when you declare them by the format of the variable name. The three kinds are:
|Floating point variables||e.g. x|
|Integer variables||e.g. x%|
|String variables||e.g. x$|
All variable names may be up to 8 characters long. The first character must be a letter. The other characters may be letters or numbers but not symbols - except for the identifiers % and $ at the end.
A floating point number is one which has a decimal point and then any number of digits after that point, e.g. 13.567 or 8. or 0.05319 or 6.0
You should declare a floating point variable when you know that the sort of value you are likely assign to it will be a floating point number.
A floating point variable name does not have any symbol at the end.
e.g. a, AGE, PROFIT89.
Floating point variables are stored to an accuracy of 12 digits and must be in the range ±9.99999999999E99 to ±9.99999999999E-99 and 0.
An integer is a whole number, eg. 6 or 13 or -3 or 11058
You should use integer variables wherever floating numbers are not necessary and speed or space are important. Integer arithmetic is faster than floating point and it occupies two bytes of memory instead of eight.
An integer variable name ends with a % sign. (The % sign is included in the 8 characters length.)
e.g. a%, AGE%, PROFI89%.
Integer variables must be in the range -32768 to +32767.
A string is a sequence of characters, alphabetic, numeric or symbolic, which is treated literally rather than being evaluated. Examples of strings are: "x + y =" and "01-345-2908" and "profit".
A string variable name ends with a $ sign. (The $ sign is included in the 8 characters length.)
e.g. a$, NAME$, MAN6$.
When declaring a string variable, you must state the maximum length of the string you expect to assign to it. So if you want to enter names up to 15 characters long as the value of NAME$, you have to declare NAME$(15). The number goes in brackets.
The maximum length of a string is 255 characters.
You must declare your variables immediately after the procedure name. You may list together all 3 types, in any order; they must be separated by commas with no spaces between - like this:
To declare variables you use either the LOCAL or the GLOBAL command like this:
LOCAL and GLOBAL define the range the variables are to be active in. The basic difference is that:
For example, in the diagram below, the procedure PROCA: calls three other procedures X: Y: and Z:. At each stage a% has a new value passed on for the next procedure. In the end, the value 9 would be printed.
If you had declared a% not as a global but as a local variable, an error would have been reported when you tried to use it in procedure X:, since X: would not have recognised a%.
However, the danger with global variables is that you may get mistakes occurring if you accidentally use the same variable name twice. So, you should use the LOCAL command unless the GLOBAL one is required.
If OPL comes across a variable which isn't declared in that procedure, it assumes it has been declared in a previous procedure. OPL will then report a MISSING EXTERNAL error if it can't find the variable declared as a global variable in a calling procedure.
There are ten floating point variables which are always available. These are the calculator memories m0, m1, m2...m9. You need not declare these as variables, as they are always in existence (if you do declare them, an error will be reported).
Values may be assigned to these at any time in any procedure. They also retain the values assigned to them when you leave OPL. They may then be accessed from the calculator by the same names, and will have the values last assigned to them in OPL.
You may want to declare a large number of similar variables at the beginning of a program. It is helpful to declare whole groups at once. For this reason, OPL has another type of variable, called array variables.
The idea is simply that, instead of having to declare separately variables a, b, c, d and e, you can declare variables a1 to a5 in one go. In the case of numeric variables, that would look like this:
LOCAL a%(5) (integer variable array)
GLOBAL a(5) (floating point variable array)
Numeric array variables may be thought of as a list of numbers, each with the same name, but with a unique number (an index) to differentiate it from its neighbours. So you might have an array of integers with the variable name NUM%, with five values, numbered 1 to 5.
When the array is declared, the number in brackets is the number of elements in it. Here is a simple example assigning values to the elements of an integer array:
procname: GLOBAL NUM%(5) NUM%(1)=1 NUM%(2)=3 NUM%(3)=5 NUM%(4)=7 NUM%(5)=11 PRINT NUM%(1)+NUM%(2)+NUM%(3)+NUM%(4)+NUM%(5)
This example just finds out the sum of the five elements in the array.
Floating point arrays are used in exactly the same way except that the % sign is omitted from the variable name.
String variables as well as numeric variables may be grouped into arrays. The difference is that with strings, you must declare the number of elements in the array and what the maximum length of the strings is to be - just as you do when you declare the length of an ordinary string variable.
For example GLOBAL ARRAY$(5, 10) allocates memory space for five strings, each up to ten characters in length, under the names ARRAY$(1), ARRAY$(2)...ARRAY$(5). As yet, each of the variables is empty (is a null string), but enough memory still has to be set aside to contain all of the five strings when full.
Once you have declared your variables you can perform any number of operations on them. This might be a combination of arithmetic operations, or you might pass the variables to other procedures for them to operate upon them, or use one of the OPL functions. These are all covered in detail in further sections of this manual. Whatever you do, however, you need to understand how your variables will react according to what type they are and how you combine them.
For example, you cannot divide a string variable by an integer variable. And if you mix integers and floating point variables in the same sum one may convert the other into its own type of variable. The following sections give details of what problems may arise and how to avoid them.
In the procedure below there is a potential mistake in the third line after the name, where the integer variable y% is assigned a floating point value:
procname: GLOBAL x%, y% x%=7 y%=3.7+x% PRINT y% GET
OPL deals with this in the following way: instead of reporting an error, OPL carries out an automatic type conversion internally on the value assigned to the mismatched variable.
The right hand side of y%=3.7+x% is evaluated to 10.7. However, the fractional part of the number is dropped before the result is assigned to the left hand side, y%. The PRINT statement will therefore display the value 10.
Since OPL does not report this as an error, the onus is on you to ensure that it does not happen - unless you want it to! You must always take care when mixing variable types that the answer produced is the one which you expect.
In the procedure below where only floating point variables are used. you can see that another type conversion is made, but does not cause the value to change:
procname: GLOBAL a,b,c a=1.2 b=2.7 c=3 PRINT a+b+c
In this procedure, the floating point variable c is given the integer value 3. An automatic type conversion is carried out in such cases. Here the result is converted to 3.0, so the real value of the variable remains the same.
If you assign a floating point number to an integer variable, then the automatic type conversion will generate an integer rounded down. So if you say a%=2.3 then the value of a% will be 2; but a%=2.9 would also give a% the value 2. And if you assign a negative floating point number to an integer variable, then the number is still rounded down - rather than toward zero. So if you say a%=2.3 then a% will take the value -3. This may not be desirable.
If you expect an expression to return a floating point number, you must ensure that the correct types of number are used within that expression.
It is possible to control how floating point numbers are rounded when convened. For example, if you wanted to round floating point numbers to the nearest half (so 2.4 would round to 2.5 and 2.2 to 2) then you might try the following statement:
where n is the number to be rounded.
This would produce the wrong result, though, To see why, substitute a trial value, say 3.4, instead of n:
INT(2*3.4+0.5) i.e. INT(7.3).
This returns the integer 7. But 7/2, when rounded down gives the integer 3, not 3.5.
To obtain 3.5 you must force the division to give a floating point result. In this case the simplest way to do this is to divide by the floating point value of 2.0, instead of the integer 2. So the expression:
will give the required result.
There is more about integers and floating point variables in the chapter on Operators.
If you try to allocate a number to a suing variable, an error will be reported. There is no automatic type conversion between string and numeric variables. However, OPL does have facilities for forcing conversion of numbers to strings and vice versa. These are the SCI$, FIX$, GEN$ and NUM$ functions - dealt with in Chapter 18.
Adding two numeric variables is very simple. You just use a plus sign and assign the result to another variable, e.g. a=b+c. Adding strings together (concatenating strings) is just as simple.
Alternatively, you could give c$ the same value with the statement c$="DOWN"+"WIND".
When concatenating strings, don't forget that the result mustn't be longer than the maximum you declared the string could be.
Having combined two or more strings, you may later want to split them up again, or you may want to just take, say, the first five characters of a string. This process is known as string slicing.
There are three functions which allow you to do this. They are LEFT$, RIGHT$ and MID$. These allow you to access the left, right or middle portions of a string respectively. For example:
The MID$ function is a little different in that you must say at what character in the first string you want the new stung to start from, and how long the new string is to be. MID$ has the syntax:
MID$(<name of string to be cut from>,<position at which to start cut>,<length of string to be cut>)
So if a$="01-234-5782", the instruction b$=MID$(a$,4,3) would return the value 234 to b$. This is because you have taken the 3 characters starting at the character at position 4 of a$.
String slicing operations leave the original string unchanged - i.e. a$ would still have the value 01-234-5782 after b$ had gained the value 234. The exception would be when the left hand side of the equation is the same string as appears in the right hand side. Eg a$=LEFT$(a$,4) would return a string containing the leftmost four characters of a$ and assign it to a$, thus overwriting the original value.
Note: If you need to define a string which includes the quotation mark character (ASCII character 34) then this character must be included twice in the string. So, if you say a$="x""y""z", then the resulting value of as will be x"y"z.
In the first example procedure at the beginning of this chapter, the statement PRINT x simply takes the value found in the memory space of variable x and prints it on the screen.
Values can also be passed between procedures. In the example on page 12-5, the procedure PROCA called the three other procedures X:, Y: and Z: which returned the adjusted value of a% back to PROCA:. The variable a% was declared global to allow this.
The rest of this chapter deals with two other ways of communicating values: entering values from the keyboard using the INPUT command, and passing values between procedures using parameters.
Values can be entered from the keyboard using the INPUT command, as in the example below.
This simple procedure just asks you to enter a number. The number you enter is assigned to the variable x and is then printed out to the screen with a message:
INPUT: LOCAL x CLS PRINT "ENTER NUMBER" INPUT x CLS PRINT "YOU ENTERED",x GET
For full details of the INPUT command, see Chapter 18.
Values can be passed between procedures using parameters. In the VAT example below, the second procedure VAT1: is followed by a parameter name (p).
The last line of the first procedure PROC1: calls VAT1 with the value of x. The value of x is copied to the parameter p. VAT1: then prints out this value plus VAT at 15%.
PROC1: LOCAL x CLS PRINT "ENTER PRICE" INPUT x VAT1:(x)
VAT1:(p) CLS PRINT "PRICE INCLUDING VAT = ",p*1.15 GET
In this similar VAT example the second procedure VAT2: has two parameters.
The value of the price variable, x, is passed to the parameter pl and the rate of VAT is also a variable, r, which is passed to the parameter p2. VAT2 then prints out the price plus VAT at the rate specified.
PROC2: LOCAL x,r CLS PRINT "ENTER PRICE" INPUT x CLS PRINT "ENTER VAT RATE" INPUT r VAT2:(x,r)
VAT2:(p1,p2) CLS PRINT p1+p2/100*p1 GET
Procedure call - PROC:("a string",9,3,7)
Procedure name - PROC:(p$,p%,p)
This VAT example differs from the previous two in that control does not end with the second procedure but returns instead to the first.
The RETURN command is used to return the value of x plus VAT at r percent - to be printed out in PROC3:. This makes the procedure VAT3: more flexible because it is now just doing the calculation and not printing. This means it can be called by other procedures which need this calculation but do not necessarily need to print to the screen.
PROC3: LOCAL x,r CLS PRINT "ENTER PRICE" INPUT x CLS PRINT "ENTER VAT RATE" INPUT r CLS PRINT "PRICE INCLUDING VAT =",VAT3:(x,r) GET
VAT3:(p1,p2) RETURN p1+p2/100*p1
You can run procedures from the main menu or the PROG menu and you can also display a menu from within a procedure.
Chapter 7 describes how to insert a procedure name in the main menu. It is not possible to pass values to (or return them from) a procedure if it is run from a menu.
By using the MENU function in a procedure, you can make the procedure display a menu, from which selections can be made in the usual way. This is a useful tool for showing the choices available for differing courses of action.
So far we have only considered programs which run in a straight line from start to finish. They consist of a number of instructions which are executed in the order they appear in the program; if you want to carry out an instruction more than once you must repeat it.
That is clearly very inefficient. A far more efficient method is for the program to be able to loop around a particular part as many times as you require, or until a certain condition is met.
There are a number of ways of doing this in OPL.
The first two are the DO/UNTIL and the WHILE/ENDWH loops. These are known as structures. They operate in a similar way to each other, with one difference.
You can have up to eight loops nested within each other.
The following example is a small part of a procedure to illustrate how a DO/UNTIL loop works:
a%=10 DO PRINT "A=";a% a%=a%-1 UNTIL a%=0
The first line assigns the value 10 to the integer variable a%. The loop itself starts on the next line, with the instruction DO. This is the instruction which says to OPL:
"Execute all the following lines of program until an UNTIL instruction is reached. If the condition following that instruction is not met, then repeat the same set of instructions until it is."
The next line tells OPL to print a short text string to the display, followed by the value of the variable a%. The first time through the loop, the value of a% will be 10.
Next, the value of a% has i subtracted from it. That now gives a% the value 9. Now comes the UNTIL instruction, followed by a condition. The condition is that a% is equal to zero.
As this is the first time through the loop, the value of a% is non-zero, so the program control returns to the DO instruction and the loop is repeated. This time the value of a% decrements to 8, and again the condition fails. This process continues until a% does equal zero.
When a equals zero the loop is finished and the program continues with the instructions that follow UNTIL.
The WHILE /ENDWH structure operates in a very similar way. Here is an example:
a=4.1 b=2.7 WHILE a>b PRINT "a is greater" PRINT "than b" b=b+1.04 ENDWH
In this structure, the test condition is at the beginning of the loop.
The BREAK command can be used in conjunction with an IF statement to break out of a DO/UNTIL or WHILE/ENDWH loop. The program is sent to the instruction after the end of the loop.
Another command which can direct the program out of a straight sequence is GOTO. This makes the program jump to a different point. This point is a label.
In this example the program, on reaching the line containing the GOTO instruction. would jump to the line beginning with the label exit::.
GOTO exit:: PRINT "MISS THIS LINE" PRINT "AND THIS ONE" exit::
All labels must end with a double colon.
The label used must be in the same procedure as the GOTO command, and the jump is not conditional (it will always be executed).
The GOTO is one of the ways of branching within a procedure, but it is a fairly crude tool and if used indiscriminately, can lead to procedures which are difficult to read and debug.
A better way is the IF/ELSEIF/ELSE/ENDIF structure.
This structure is used to perform one or more instructions IF a condition is met. If that condition is not met then the ELSEIF instruction may follow, to test another possible condition. There may be any number of ELSEIF instructions within an IF/ENDIF structure.
After all likely eventualities are catered for by the ELSEIF instructions, any other possibilities can be catered for by an ELSE statement, followed at the end by the ENDIF statement. Here is an example to illustrate how this might be used:
whatkey: GLOBAL g% g%=GET PRINT "THAT KEY IS" IF g%>64 AND g%<91 PRINT "UPPER CASE" ELSEIF g%>96 AND g%<123 PRINT "lower case" ELSE PRINT "NOT A LETTER" ENDIF GET
The program just waits for a key to be pressed at the keyboard, and then prints that it is either a lower or upper case letter. (If you don't realise the significance of the numbers 64 and 91 - see Appendix A.) If it is not a letter, then that is printed, as allowed for by the ELSE statement. The ELSE statement needs no condition as it allows for all possibilities other than those outlined in the conditions of the ELSEIF statements.
The ELSEIF and ELSE statements are optional, but for every IF there must be a corresponding ENDIF.
It is also valid for the statement following the ELSE part of the structure to be on the same line as ELSE. So the line ELSE PRINT "NOT A LETTER" would have been quite valid.
ESCAPE OFF, GET, KEY and INPUT must be used with caution in loops for the following reasons:
To halt the execution of a procedure, you normally press ON/CLEAR then Q.
To break out of a procedure which contains an ESCAPE OFF command - which stops the ON/CLEAR key pausing or halting procedures - you have to remove the battery from your Organiser in order to escape, and lose all the data in the internal memory.
To break out of a loop which use any function such as GET or KEY to read a keypress, you have to press ON/CLEAR quickly followed by Q and repeat this very quickly a few times. This may be very difficult to do.
These are the operators available in OPL. divided into three classes:
|**||raise to a power|
|-||unary minus (make negative)|
|>=||greater than or equal to|
|<=||less than or equal to|
|<>||not equal to|
The various operators have differing precedence when they are encountered by OPL. The operators are shown here in order of precedence, with operators of equal precedence on the same line.
|Highest:||-(Unary minus) NOT|
|= > < <> >= <=|
(The logical operators AND. NOT and OR are covered in greater depth later in this chapter.)
An expression such as a+b+c presents no problems because whichever addition is done first, the result will be the same. However, you may want to enforce a different order of precedence upon an operation. For example.
would be evaluated in the order: b multiplied by c, then divided by d, then added to a. To change this order use brackets.
So, to perform the addition and the division before the multiplication, you would write the equation like this:
b% will first be raised to the power of c% and the resulting value will be used as the power of a%.
When in doubt, simply use brackets; they also make the order in which the sum is worked out visible at a glance.
You are free to mix floating point and integer values in an expression, but be aware how OPL handles the mixture:
For example, your procedure might include the expression:
This mixture of variable types would be evaluated like this: b% is converted to floating point and added to c. The resulting floating point value is then automatically converted to an integer in order to be assigned to the integer variable a%.
So any fractional part of the result of the right hand side of the expression will be lost in the conversion to an integer. This may produce results you do not want, so be careful.
The comparison operators and logical operators are based on the idea that a certain situation can be evaluated as either true or false. For example, if a%=6 and b%=8, a%>b% would be false. They are useful for setting up alternative paths in your procedures. For example you could say:
IF salary<expenses PRINT "bad" ELSEIF salary>expenses PRINT "good" ENDIF
If necessary, you can also make use of the fact that the result of these logical expressions is represented by an integer:
These integers can be returned to a variable or printed out to the screen to tell you whether a particular condition is true or false, or used in an IF or ELSEIF statement.
For example, in a procedure you might arrive at two sub-totals, a and b. You want to find out which is the greater. So include the statement
If zero is displayed, a and b are equal or b is the larger number but if -1 is displayed, 'a>b' is true - a is the larger number.
The following table gives examples of using each of the comparison operators:
|<||a%<b||True if a% less than b||-1|
|False if a% greater than or equal to b||0|
|>||a%>b%||True if a% greater than b%||-1|
|False if a% less than or equal to b%||0|
|<=||a<=b||True if a less than or equal to b||-1|
|False if a greater than b||0|
|>=||a>=b%||True if a greater than or equal to b%||-1|
|False if a less than b||0|
|<>||a$<>b$||True if a$ not equal to b$||-1|
|False if a$ equal to b$||0|
|=||a=b||True if a equal to b||-1|
|False if a not equal to b||0|
You can use these operators with a mixture of floating point or integer values but not with a mixture of string and numeric values. So a$<b would be invalid.
The logical operators AND, OR and NOT have different effects depending on whether they are used with floating point numbers or integers:
1 When used with floating point numbers only, the logical operators have the following effects:
|a AND b||True if both a and b are non-zero||-1|
|False if either a or b are zero||0|
|a OR b||True if either a or b is non-zero||-1|
|False if both a and b are zero||0|
|NOT a||True if a is zero||-1|
|False if a is non-zero||0|
2 When used with integer values only, AND, OR and NOT are bitwise logical operators.
The way the Organiser represents integer numbers is in a 16-bit binary code, like this:
This is the number 7 (in base 10).
The Organisers numerical range is +32767 to -32768. 32767 is the largest number that can be represented with 15 binary bits. The 16th bit is used to say whether the number is negative or positive.
As the operators are bitwise they perform the operation on first the first bit, then the second, up to the sixteenth bit of the binary numbers.
For example, the statement PRINT 12 AND 10 will print the value 8. To understand this it is necessary to write down the two integers in binary notation.
These are the sixteen bits of the binary representations of 10 and 12.
12 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0
The AND operator acts on each pair of corresponding binary digits in the two numbers, each pair producing one digit of the four-digit answer. Thus. working from left to right - discounting the first 12 bits:
|1 AND 1||→||1|
|1 AND 0||→||0|
|0 AND 1||→||0|
|0 AND 0||→||0|
The result is therefore the binary number 1000, or 8 in decimal notation.
What result would the statement PRINT 12 OR 10 give? Again, write down the numbers in binary notation and apply the operator to each corresponding pair of digits:
|1 AND 1||→||1|
|1 AND 0||→||1|
|0 AND 1||→||1|
|0 AND 0||→||0|
The result is the binary number 1110, or 14 in decimal.
The NOT operator is different in that it works on only one number. It returns the one's complement of the number, i.e. it replaces the zeroes in the binary number with ones, and the ones with zeroes.
So if 7 looks like this:
NOT 7 will look like this:
This is the binary representation of the decimal integer -8.
Hint. A quick way of calculating the result of NOT for integers is to add 1 to the original number and reverse its sign. Thus, NOT 23 is -24, NOT 0 is -1 and NOT -1 is 0. Note that the last two results are the same as when using NOT on floating point numbers.
When you use the SAVE option from the main menu your records are saved in a file called MAIN. You can access this file and the records in it from OPL. You can also create other files and then manipulate them. This chapter explains how to do this.
There is also an example at the end of Chapter 17 of a data file handling program made up of 5 procedures. It may be a good idea to refer to that program while you read this chapter.
The data file MAIN and any extra ones you create contain records which are divided into fields. When you save a record from the main menu with the SAVE option, you start a new field every time you start a new line by pressing ↓.
In a name and address file, in each record, there might be a name field, a telephone number field, and separate fields for each line of the address.
Before you can start to enter data into a new data file. you must create that file on one of the devices using the CREATE command.
The CREATE command must be supplied with a number of parameters, in the following format:
"<dev>fname", is the device (A:. B: or C:) which the file is to be on, and then the file name. This all goes in quotes as a string, e.g. "a:clients". You can also assign this device and file name string to a string variable (e.g. cl$="a:clients") and then use the variable name (cl$) as the parameter. The file name may be up to 8 characters long.
logname is the logical file name. This may be A, B, C or D. You use this logical file name to refer to the file from within the program.
fldnm1, fldnm2 are the field names. There may be up to 16 fields in any record, and these may be given a qualifier, either % or $, to signify integer data or string data respectively. Fields containing floating point data need no qualifier. Field names may be up to 8 characters long including any qualifier used.
An example of a CREATE command might be:
When a file has been created, it is automatically open. This means records can be saved to it immediately. It also becomes the current file which means that when you use one of the commands for manipulating records, they operate on this file.
You add records to a data file field by field. First you assign some values to the current field names, then you use the APPEND command to add them to the file.
The field names act in a similar way to variables, and can be assigned values and used in INPUT statements. The field name must be used with the logical file name like this:
where B is the logical file name and name$ is the name of the field. These are separated by a full stop.
When you have assigned values to the fields, you add them to the open file with the APPEND command. They are always added as the last record in the data file. If the file is a new one, this will be the first record.
The APPEND command has no parameters - the field values are automatically added to the file in the correct order and format.
If you try to assign a text string to a numeric field name, an error will be reported.
See the second procedure (insert:) in the data file handling program at the end of Chapter 17 for an example of adding records to a data file.
At any time while a data file is open, the field names currently in use can be used like any other variable - for example, in a PRINT statement, or a string or numeric expression. However, in order to operate on a particular field, you must make the record containing it the current one.
Before you can erase a record or operate on the fields in it you must make it current. You can change the current record by using any of the six commands and functions below.
FIRST moves to the first record in a file.
NEXT moves to the following record in a file. If the end of the file is passed, NEXT does not report an error. The current record will then be null. This condition can be tested for with the EOF function.
BACK moves to the previous record in the file. If the current record is the first record in the file then the current record does not change.
LAST moves to the last record in the file.
POSITION moves to a particular record. For example, the instruction POSITION 3 makes record 3 (the first record is record 1) the current record. You can find the current record number by using the POS function which returns the number of the current record.
FIND moves to the record which contains a search string you specify.
The FIND function acts like the FIND facility in the main menu. The difference is that whereas the main menu FIND prints the record found on the screen, this function makes the record the current one so that you can operate on it: editing it, erasing it, or just displaying it.
For example, the line
would make the first record containing the string "ABRAHAM" the current record and return the number of that record to the variable r%. If the number returned is zero, it means that the string was not found.
The procedure called search: at the end of Chapter 17 is an example of how to find and edit records.
To erase a record, make that record current by use of one of the commands FIRST, NEXT, BACK, LAST, POSITION or FIND and then use the ERASE command. This removes the current record from the file and renumbers the ones that follow.
The final procedure (erase:) in the group of data file procedures at the end of Chapter 17 is an example of how to find and erase records.
This chapter covers commonly made errors, then error trapping. There is a list of the OPL error messages in Appendix D.
All programming languages are very particular about the way commands and functions are used. especially in the way program statements are laid out.
Below are a number of errors which are easy to make in OPL. The incorrect statements are boxed and the correct versions are on the right.
Omitting the colon between statements on a multi-statement line:
|a$="text" PRINT a$||a$="text" :PRINT a$|
Omitting the colon after a called procedure name:
|GLOBAL a,b,c||GLOBAL a,b,c|
Omitting one or more of the colons after a label:
|GOTO below:||GOTO below::|
Omitting the space before the colon between statements on a multi-statement line:
|a$=b$:PRINT a$||a$=b$ :PRINT a$|
Passing a floating point value to a procedure which requires an integer - here the procedure proc2:(x%). This may occur when calling a procedure from the calculator or from another procedure.
Passing an integer to a procedure which requires a floating point value - here the procedure proc3:(x)
Passing the wrong number of parameters to a procedure - here, the procedure proc4:(x,y)
OPL only allows numbers between minus 32768 and plus 32767 to be assigned to integer variables, so any expression which exceeds these limits will cause an error:
|LOCAL a%||LOCAL a|
The structures allowed within OPL are DO/UNTIL, WHILE/ENDWH and IF/ELSEIF/ELSE/ENDIF. These may all be nested within one another to up to eight structures deep. Attempting to nest to a greater depth than this will cause an error. Mixing up the three structures eg, by matching up DO with WHILE, will also cause an error:
|WHILE a>2||UNTIL a<=2|
If an error occurs when you run a program, the program stops and an error message is displayed. For example, here a call has been made to a procedure called subproc: which does not exist:
MISSING PROC SUBPROC
Press ON/CLEAR or SPACE and you are asked whether you want to EDIT the procedure. If you say yes and the source code is available, you are returned to the OPL editor to correct the offending line.
When you have done this, press MODE to return to the TRAN/SAVE/QUIT menu, and either translate, save or quit the procedure. If you quit at this stage, the edits you have made are abandoned and the old version of the procedure remains on the current device.
In the case of the run time errors described above, the program stops to display the error message. There are ways of avoiding this by trapping errors and dealing with them yourself within the program - but they put you in full control and must be used carefully. The tools used to control errors are ONERR, TRAP, ERR, ERR$ and RAISE:
ONERR, is used to redirect program control to a label if an error occurs. This is useful if you want to provide your own error handling routine, such as printing out a message for an error you anticipate.
ONERR is followed by the label name which must end in two colons. The label itself must occur somewhere in the same program - but not necessarily the same procedure.
In the example below, LPRINT is being used to print to an attached printer. Normally, when LPRINT is used and no printer is connected, the message DEVICE MISSING is displayed. This procedure supplies a more precise message, CONNECT PRINTER, to make sure the person running it understands.
ONERR noprint:: LPRINT "Memo" LPRINT "Dear Sir" RETURN noprint:: ONERR OFF PRINT "CONNECT PRINTER" GET
The first line causes the program to jump to the label noprint:: if an error occurs. If there is no printer connected, the first LPRINT command causes such a jump and the message "CONNECT PRINTER" is displayed. If there is one connected. "Memo" and "Dear Sir" are printed out and the lines after the label are never executed, because of the RETURN before it.
ONERR should be cancelled with ONERR OFF.
Notice that the first instruction after the label noprint:: is ONERR OFF. This is very important because if you don't do this after the ONERR label:: command is used. all subsequent program errors - even in other procedures called - result in the program being directed to the same label. This diagram illustrates how two completely different errors cause a jump to the same label, and cause the same explanatory message to be printed out:
As all errors go back to the same label unless you switch ONERR OFF, it is very easy to create an endless loop by mistake. If this happens. you cannot press ON/CLEAR and Q to break out, as this just makes control go to the label as any other error would - so. you have to take the battery out of the Organiser, and lose everything in the internal memory. To avoid this:
TRAP traps errors on a specified command only, so it doesn't need to be cancelled like ONERR does. It can be used with any of the commands listed below:
The trap command immediately precedes any of these commands, separated from it by a space - e.g:
TRAP INPUT a%
When INPUT is used without TRAP and a text string is entered when a number is required, the display just scrolls up and a question mark is shown, prompting for another - valid - entry. When you put TRAP in front of INPUT, the command is executed in the usual way, but if an error occurs the next line of the program is executed as if there had been no error. The next line in the example below is a helpful message.
proc: LOCAL a% start:: PRINT "ENTER AGE", TRAP INPUT a% IF ERR=252 PRINT "NUMBER NOT WORD" GOTO start:: ENDIF
The sample above also uses the ERR function.
When errors occur in a program, the number of the error is accessible by using the ERR function. This means that you can be absolutely sure which error you are dealing with.
The anticipated error in the lines below is 246 (NO PACK). If 246 occurs when trying to open the MAIN file on pack B: a helpful error message is printed out. However, just in case a different error occurs, the next lines (ELSE :PRINT ERR$(ERR) make sure that the standard error message for that error is printed.
TRAP OPEN "B:MAIN",A,a$ IF ERR=246 PRINT "NO PACK IN B:" ELSE PRINT ERR$(ERR) ENDIF
The OPL error messages are listed in Appendix D.
If you are using commands to trap errors and handle them yourself, then at some during the development stage of your program you need to test your error handling routines. An easy way to do this is with the RAISE command. You can generate an error that you think might occur when the program is in use, and see if the error handling routine takes care of it in the way you anticipate. For example, this statement causes the NO PACK error to be generated:
RAISE also comes into its own when your program is built up from a number of procedures which call one another in sequence. If the procedure currently being executed was called by another procedure, which was called by another and so on, then you may wish to return to the top level quickly, to carry out a particular operation. The usual method would be to use the RETURN command to exit from all of the procedures in turn.
A faster method would be to use an ONERR statement in the top level procedure, then when you RAISE an error at the lowest level, the program control will return to the label specified in the ONERR statement. even though it is several jumps back in the sequence of procedures.
This chapter contains example programs written in OPL. The programs are not intended to demonstrate all the features of OPL, but they should give you a few hints. To find out more about a particular command or function, refer to chapter 18.
Each of the procedures must be entered separately, you can't enter two procedures in one block. Chapter 11 explains how to type in, translate, save and run a procedure.
In the listings here, variables are shown in lowercase and commands and functions in uppercase. However, it doesn't matter which you use when you enter procedures into the Organiser:
Be careful to type in the necessary spaces:
CLS :PRINT "hello" :GET
Lines beginning with the command REM are remarks: they are there to explain things. They do not affect the way a procedure runs and you don't have to type them in if you don't want to.
This procedure turns the Organiser into a dice. When the program is run, a message is displayed saying that the dice is rolling. You then press S to stop it. A random number from one to six is displayed and you choose whether to roll again or not.
dice: LOCAL dice%,key% KSTAT 1 top:: CLS :PRINT "**DICE ROLLING**" PRINT "PRESS S TO STOP" DO dice% = (INT(RND*6+1)) UNTIL KEY$="S" CLS PRINT "***** ";dice%'" ******" BEEP 50,100 PRINT "ROLL AGAIN Y/N" label:: key%=GET IF key%=%Y GOTO top:: ELSEIF key%=%N RETURN ELSE GOTO label:: ENDIF
dice% is a random number from 1 to 6.
key% is the ASCII value of the keypress read by the GET function.
This is how dice: displays 1, 2, 3, 4, 5 or 6 randomly. The RND function returns a random floating point number, between 0 and 1 (not including 1). It is then multiplied by 6 and 1 is added (so that you get numbers from 1 to 6 instead of from 0 to 5). It is rounded down to a whole number by using the INT function. This number is then assigned to dice%.
Identifying keypresses of Y and N
The ASCII value of the character on the key you press is returned by the GET function and assigned to key%. In OPL you get the ASCII value of any character by putting % in front of it, so %Y is the ASCII value of Y and %N is the ASCII value of N. In case you had the keyboard set to lowercase, KSTAT 1 is used at the start of the procedure to set it to uppercase,. so that you are not pressing y and n.
This procedure acts rather like the INFO option on the main menu. However, it also shows which model of the Organiser is in use, the total amount of memory in the machine and the free space (in bytes) on each of the three devices - if fitted. When you run it, press any key to see the next line of information.
status: LOCAL a$(8),dev%,b$(5),c$(6),dev$(2),num% a$="Memory:" :b$="MAIN" :c$="FREE" PRINT "Model:", num%=PEEKB($FFE8) REM SFFE8 is a memory address IF num%=0 PRINT "CM" PRINT a$,"8K" ELSE PRINT "XP" PRINT a$, IF num%=1 PRINT "16K" ELSEIF num%=2 PRINT "32K" ENDIF ENDIF :GET :dev%=%A REM %A is the ASCII value of A DO dev$=CHR$(dev%)+":" IF EXIST(dev$+b$) OPEN dev$+b$,A,f$ PRINT c$,dev$:SPACE CLOSE :GET ENDIF dev%=dev%+1 UNTIL dev%=%D
a$, b$ and c$ are "Memory", "MAIN" and "FREE".
dev% is the ASCII value of A, then B, then C.
dev$ is the letter A, then B, then C plus a ":".
num% is the number, found in a memory address, which shows which Organiser you have.
How it finds out the type of Organiser
The PEEKB command is used to look in a specific memory address ($FFE8). The number returned shows which type of Organiser you have.
How it finds out the free space on each device
The SPACE command is used to see how much space is free on each device. A file has to be open in order to use the SPACE function, so the MAIN file is OPENed first on each device.
To go through each device, dev% is first assigned the value %A, the ASCII value for A. This is then stepped up by the line dev%=dev%+1, to the values %B, then %C. The loop stops at the value %D.
The ASCII values are converted to the letters A, B, and C by the CHR$ function and together with a ":" are assigned to dev$. So dev$ is A: then B: then C:.
This program calculates monthly mortgage payments. When you run it, you have to enter me amount of the loan, the interest rate and the term in years. Then you specify the source of the loan by selecting from a menu. The program does not allow for tax relief.
The program is made up to two procedures - mortgage: and q: - a general input routine. You must type each one in separately. The input routine could be called by any procedure which needs to prompt the user to enter a floating point number.
mortgage: LOCAL num%,loan,x,term,rate,pay,ques$(2) CLS PRINT "EVALUATE MONTHLY" PRINT "MORTGAGE PAYMENT" PAUSE 30 ques$=CHR$(63)+" " REM CHR$(63) is a "?" - See Appendix A loan=q:("ENTER LOAN"+ques$) DO rate=q:("INTEREST RATE % "+ques$) UNTIL rate>0 AND rate<99 DO term=q:("ENTER TERM (YRS)"+ques$ UNTIL term>.5 AND term<100 num%=MENU("BUILDING-SOCIETY,BANK,OTHER") IF num%=0 :RETURN :ENDIF rate=rate/100 :x=1+11*(num%/2) pay=loan*rate/12/(1-((1+rate/x)**(-x*term))) CLS :PRINT "MONTHLY PAYMENT",FIX$(pay,2,-8) GET RETURN
q:(a$) LOCAL z CLS :PRINT a$,CHR$(16); INPUT Z CLS RETURN(z)
loan, term, rate and pay are the amounts of the loan, the term in years, the interest rate and the monthly payments.
ques$ is "? ".
num% is the number of the menu item you choose.
x is a variable used in the calculation at the end
z is the variable used for the values you input when q is running.
The main procedure mortgage: calls q: three times. passing it a string to be printed out as a prompt. The text string is passed to q: as a parameter. The values returned are assigned to the variables loan, rate, and term.
How "?" is printed
The CHR$ function converts the ASCII value 63 to the question mark character.
How the input routine beeps
The CHR$ function converts the value 16 to the beep control character. This is then "printed" out.
This procedure provides a seconds and minutes stopwatch. Press any key to start the program then, when the stopwatch is running, press S to stop and L to record a lap. If you press S to stop, you then have three options: R restarts counting, Z resets the watch to zero and E ends.
The procedure cancels the Organiser's normal automatic switch-off. So don't leave it running.
watch: LOCAL k$(1),s%,secs%,mins% POKEB $007C,0 REM this poke cancels automatic switch-off CLS :PRINT "S=STOP, L=LAP" PRINT "PRESS ANY KEY... GET :CLS zero:: mins%=0 :secs%=0 :s%=SECOND loop:: k$=KEY$ IF UPPER$(k$)="S" GOTO pause:: ENDIF IF UPPER$(k$)="L" AT 1,2 :PRINT "LAP: ";mins%;":"; IF secs%<10 :PRINT "0"; :ENDIF PRINT secs%:" "; ENDIF IF SECOND<>s% s%=SECOND :secs%=secs%+1 IF secs%=60 :secs%=0 :mins%=mins%+1 :ENDIF PRINT CHR$(14)+"MINS",mins%,"SECS", IF secs%<10 :PRINT "0"; :ENDIF PRINT secs%; ENDIF GOTO loop:: pause:: PRINT CHR$(15)+"RESTART/ZERO/END"; k$=UPPER$(GET$) PRINT CHR$(15); IF k$="R" GOTO loop:: ELSEIF k$="Z" CLS :GOTO zero:: ELSEIF k$<>"E" GOTO pause:: ENDIF POKEB $007C,5
k$ is used for the keypresses read by KEY$ and GET$.
s% is the actual number of seconds past the minute at the start of the procedure.
secs% is the seconds shown counting up.
mins% is the minutes shown counting up.
How the stopwatch counts up
The actual number of seconds past the minute is read from the system clock by the SECOND function and assigned to s% at the start. Then the SECOND function is used again, and if it is no longer equal to s% - i.e. when a second has elapsed, 1 is added to sec% and s% is assigned the actual number of seconds again. Whenever secs% is 60, it is reset to 0 and 1 is added to mins%.
Reading lowercase as well as uppercase keypresses
If you have the keyboard set to lowercase and so press s, for example, instead of S, this is converted to S by the UPPER$ function. This is used throughout the procedure whenever a keypress is read.
Cancelling automatic switch off
This is done by poking the value 0 at address $007C.
The procedure below may be used to mute all audible alarms and beeps from the Organiser. Use the same procedure again to switch the sound on again.
mute: PRINT "Sound now <"; IF PEEKB($A4)=0 POKEB $A4,l PRINT "OFF>" ELSE PRINT "ON>" POKEB $A4,0 ENDIF PRINT "Press any key"; GET
How the sound is muted
$A4 is the memory address of the Organiser buzzer. If you poke any non zero value into this address, you switch the sound off. When you poke zero into it you switch the sound on again. This procedure peeks into the memory address first to see if it contains zero or not and then pokes 1 or 0 as appropriate. There are a few useful memory addresses in Appendix C.
Note: You shouldn't use POKEB and POKEW unless you know exactly what you are doing.
This procedure can be used to provide a degree of security to information in your Organisers internal memory. When you type the procedure in, substitute your own password in quotes, e.g. "SESAME". for the string "YOURPASSWORD".
When you run it, the machine switches off. When you press ON/CLEAR, switching the machine back on, the procedure is still running and the password is requested. If you don't enter the correct one, the machine switches off again.
Warning: If you run this procedure then forget the password, or if you make a mistake when typing it in, you may lose all data in the internal memory.
password: LOCAL pass$(20) ONERR start:: start:: DO OFF CLS :PRINT "Enter password" INPUT pass$ UNTIL UPPER$ (pass$) ="YOURPASSWORD"
pass$ is the string you specify as your password.
The ONERR command
This procedure shows the usefulness and the risks of the ONERR command. Normally. if an error occurs when a procedure is running (such as BATTERY TOO LOW, if the battery is running out or ESCAPE, if ON/CLEAR is pressed), the procedure is interrupted and an error message displayed. This is not desirable here, as it would mean that the program stopped, the Organiser came on again and anyone could access your data. So ONERR off is used. However, if you forget the password, you won't be able to press ON/CLEAR to break out and the program will loop round forever. You would have to remove the battery to stop it, and thus lose all data in the internal memory. Normally it is good practice to use ONERR OFF when you have dealt with an error at a label.
The next three procedures make up a game which demonstrates the use of user defined graphics (UDG's). Each procedure must be typed in separately.
The object of the game is to avoid being caught by the pursuer. Your movable man can jump between the two lines of the display: press the X key to jump down and the S key to jump up. At the end of the game your score will be displayed on the screen.
To pause the game, press ON/CLEAR and to restart press it again. To quit out of the game press ON/CLEAR then Q, then ON/CLEAR again when you see the ESCAPE message.
game: LOCAL a$(1),b$(1),c$(1),d$(1),e$(2),f$(1) LOCAL g$(32),h$(1) LOCAL a%,b%,c%,x%,y%,z%,sc%,b1%,f% igame: CURSOR OFF a$=CHR$(0) :b$=CHR$(1) c$=CHR$(2) :d$=CHR$(3) e$=CHR$(4)+CHRS(6) :f$=CHR$(5) g$=REPT$(CHRS(165),32) :h$=CHR$(7) b%=20 :c%=12 :x%=16 :y%=1 DO CLS :PRINT g$ :AT x%,y% :PRINT h$ a%=1 :c%=1+RND*2 DO AT a%,c% :PRINT a$ :BEEP b%,10*b% AT a%,c% :PRINT b$ :BEEP b%,10*b% AT a%,c% :PRINT c$ :BEEP b%,10*b% AT a%,c% :PRINT d$ :BEEP b%,10*b% AT a%,c% :PRINT e$ :BEEP b%,10*b% AT a%,c% :PRINT f$ :BEEP b%,10*b% AT a%,c% :PRINT "" :z%=KEY IF z% IF z%=%S AND y%=2 AT x%,y% :PRINT CHR$(165) y%=l :AT x%,1 :PRINT h$ ENDIF IF z%=%X AND y%=1 AT x%,y% :PRINT CHR$(165) y%=2 :AT x%,2 :PRINT h$ ENDIF ENDIF a%=a%+1 IF a%=x% AND c%=y% f%=0 DO AT x%,y% :PRINT CHR$(170+f%) BEEP 10,100+f% f%=f%+1 :BEEP 10,100-f% UNTIL f%=30 b%=b%+5 :a%=16 :x%=x%-2 IF x%<1 :CLS :PRINT "GAME OVER" PRINT "SCORE:",sc% :PAUSE 40 WHILE KEY :GET :ENDWH GET :RETURN ENDIF ENDIF UNTIL a%=16 sc%=sc%+1 IF b%>12 :b%=b%-2 ELSEIF b%<6 IF b1% AND b% :b%=b%-1 :b1%=0 ELSE b1%=1 :ENDIF ELSE b%=b%-1 :ENDIF UNTIL c%=3
igame: udg:(0,0,0,28,30,30,30,28,0) udg:(1,0,0,14,31,30,31,14,0) udg:(2,0,0,7,14,12,14,7,0) udg:(3,0,0,3,7,6,7,3,0) udg:(4,0,0,1,3,3,1,0,0) udg:(5,0,0,0,1,1,1,0,0) udg:(6,0,0,24,16,4,16,24,0) udg:(7,30,14,4,14,30,14,11,25)
udg:(x%,a%,b%,c%,d%,e%,f%,g%,h%) POKEB $180,64+x%*8 POKEB $181,a% POKEB $181,b% POKEB $181,c% POKEB $181,d% POKEB $181,e% POKEB $181,f% POKEB $181,g% POKEB $181,h%
The main procedure, game:, calls igame: which then calls udg: 8 times in order to set up the graphics characters used in the game. The last call to udg: in igame: is the one which sets up the little man. User defined characters are explained in Appendix A.
Here are two programs to calculate ACOS and ASIN. Once entered and translated they can be called from within the calculator - e.g. ASIN:(0.1)
acos:(n1) IF n1=1 RETURN 0 ELSEIF n1=-1 RETURN PI ELSEIF ABS(n1)>1 CLS PRINT "OUT OF RANGE ";CHR$(16) PAUSE 12 RETURN ELSE RETURN (PI/2)-ATAN(n1/SQR(1-n1*n1)) ENDIF
asin:(n1) IF ABS(n1)=1 RETURN nl*PI/2 ELSEIF ABS(nl)>1 CLS PRINT "OUT OF RANGE ":CHR$(16) PAUSE 12 RETURN ELSE RETURN ATAN(n1/SQR(1-n1*n1)) ENDIF
This procedure searches for a string, like the FIND option on the main menu does. But it automatically searches on device A: then B: then C: - looking in the file called MAIN on each device. When you run the procedure, you enter a search-clue and then press EXE to see the first matching record. You can then press any key (except the arrow keys) to see the next matching record. If you press ON/CLEAR, you return to the PROG menu.
packfind: LOCAL search$(254),recnum%,key%,dev% dev%=65 ESCAPE OFF AT 1,1 PRINT "Find:"; TRAP INPUT search$ IF ERR=206 RETURN ENDIF DO TRAP OPEN CHR$(dev%)+":MAIN",A,a$ IF ERR=246 CLS :AT 1,1 PRINT "*** NO PACK ***" AT 1,2 PRINT "** IN SLOT ";CHR$(dev%);": **" PAUSE 20 GOTO nextpak:: ENDIF CLS AT 1,1 PRINT "Searching Pak ";CHR$(dev%);"=" PAUSE 15 WHILE NOT EOF recnum%=FIND(search$) IF recnum%<>0 key%=DISP(-1,"") IF key%=1 REM 1 is the code for ON/CLEAR RETURN ENDIF ENDIF NEXT ENDWH CLOSE nextpak:: dev%=dev%+1 UNTIL dev%=68 CLS PRINT REPT$("*",18);"END OF PACK***" PAUSE 25 RETURN
search$ is the search clue you enter.
recnum% is the record number returned by FIND.
key% is the code number, returned by DISP, of the key you press when a record is displayed.
dev% is the device - A, B, then C.
Searching the MAIN files
The OPEN command opens the MAIN file - allowing access to the records in it.
The device variable, dev%, is used with a ":" as the device name in the OPEN command, dev% is first assigned the value 65 - this is the ASCII code for A. The function CHR$ converts this to the letter A. To search on devices B and C, the value of dev% goes up to 66, then 67. Then the searching stops.
The FIND function finds the record containing the search clue and makes it the current record. The DISP function displays the current record and returns the number of any key you press. If that number is 1 (ON/CLEAR) then the program ends and you RETURN to the PROG menu.
Normally ON/CLEAR pauses the execution of a procedure so that Q can be pressed to quit. At the start of this procedure ESCAPE OFF is used. This means that ON/CLEAR does not pause the program, and can thus be read by the DISP function and cause a RETURN to the PROG menu.
Because ESCAPE OFF is used, the INPUT command is TRAPped and followed by the instruction that if you press ON/CLEAR to escape (Error number 206), you RETURN to the PROG menu.
The OPEN command is also TRAPped. Here, if a NO PACK error (246) occurs, a message is printed explaining this.
The main procedure below creates a data file called addr on device A:, to contain names. addresses, post codes and telephone numbers. It is followed by 4 other procedures which allow you to insert, search for, alter and erase records in the file. When you run files:, a menu giving you a choice of these options is displayed.
Each of these 5 procedures must be typed in separately.
files: LOCAL m% IF NOT EXIST("A:ADDR") CREATE "A:ADDR",A,n$,ad1$,ad2$,ad3$,pc$,tel$ ELSE OPEN "A:ADDR",A,n$,ad1$,ad2$,ad3$,pc$,tel$ ENDIF top:: m%=MENU("INSERT,SEARCH,ALTER,ERASE,QUIT") IF m%=0 :STOP ELSEIF m%=1 :insert: ELSEIF m%=2 :search: ELSEIF m%=3 :alter: ELSEIF m%=4 :erase: ELSEIF m%=5 :STOP ENDIF GOTO top::
insert: PRINT "ENTER NAME" :INPUT A.n$ CLS :PRINT "ENTER STREET" :INPUT A.ad1$ CLS :PRINT "ENTER TOWN" :INPUT A.ad2$ CLS :PRINT "ENTER COUNTY" :INPUT A.ad3$ CLS :PRINT "ENTER PCODE" :INPUT A.pc$ CLS :PRINT "ENTER TELNUM" :INPUT A.tel$ APPEND RETURN
search: LOCAL recnum%,search$(30) top:: FIRST :CLS :PRINT "FIND:"; TRAP INPUT search$ IF ERR=206 RETURN ENDIF recnum%=FIND(search$) IF recnum%=0 CLS :PRINT "NOT FOUND" :PAUSE 20 GOTO top:: ENDIF DO DISP(-1,'"W :NEXT :recnum%=FIND(search$) IF recnum%=0 :CLS PRINT REPT$("*",18);"END OF PACK***" PAUSE 20 :RETURN ENDIF UNTIL EOF RETURN
alter: LOCAL recnum%,search$(30),key% top:: FIRST :PRINT "ALTER:"; :TRAP INPUT search$ IF ERR=206 :STOP :ENDIF recnum%=FIND(search$) IF recnum%=0 CLS :PRINT "NOT FOUND" PAUSE 20 :GOTO top:: ENDIF DO ask:: KSTAT 1 :AT 1,2 :PRINT "EDIT Y/N" key%=VIEW(1,A.n$) IF key%<>%Y AND key%<>%N GOTO ask:: ELSEIF key%=%Y :CLS EDIT A.n$ :EDIT A.ad1$ EDIT A.ad2$ :EDIT A.ad3$ EDIT A.pc$ :EDIT A.tel$ :UPDATE :NEXT ELSE :NEXT :recnum%=FIND(search$) IF recnum%=0 CLS :PRINT "NOT FOUND" :PAUSE 20 :RETURN ENDIF ENDIF UNTIL EOF
erase: LOCAL recnum%,search$(30),key% FIRST :CLS :PRINT "ERASE:"; TRAP INPUT search$ IF ERR=206 :STOP :ENDIF recnum%=FIND(search$) IF recnum%=0 CLS :PRINT "NOT FOUND" :PAUSE 20 ENDIF DO IF recnum%=0 CLS :PRINT "NOT FOUND" :PAUSE 20 :RETURN ENDIF ask:: KSTAT 1 :AT 1,2 :PRINT "ERASE Y/N" key%=VIEW(1,A.n$) IF key%<>%Y AND key%<>%N GOTO ask:: ELSEIF key%=%Y ERASE ELSEIF key%=%N NEXT :recnum%=FIND(search$) ENDIF UNTIL EOF
m% is the number of the menu item you select
recnum% is the record number returned by FIND.
search$ is the search clue you enter.
key% is the ASCII value of the key you press whilst the found record is displayed. (%Y is the ASCII value of Y, %N is the ASCII value of N.)
Creating the data file
The first procedure, files:, creates or opens a file called addr on device A: with 6 fields for each record. The six field names are n$ for the name, ad1$, ad2$. and ad3$ for each line of the address, pc$ for the post code and tel$ for the phone number. The file is given the logical name A.
Notice how in insert: the 6 fields of the record are input one by one. The field names are used like variables and preceded by the logical file name (A) and a full stop. Then the APPEND command is used: this is necessary to actually add the record to the end of the file.
Displaying the current record
When a record containing a particular string has been found by FIND it becomes the current record. DISP with -1 as the first parameter, displays it.
In the procedure alter:, VIEW is used to display just the first field of the record, while you decide whether to edit it. If you choose to, each field is then displayed by the EDIT function, which allows you to alter what is on the screen.
Here is a summary of the OPL commands and functions to give you an idea of what is available. This is followed by an alphabetic list which deals with each command and function in detail.
DO/UNTIL Loops until a condition is met
GOTO label:: Branches to a label
IF/ELSEIF/ELSE/ENDIF Acts conditionally
WHILE/ENDWH Loops while a condition is met
BREAK Exits from loop
CONTINUE Goes to the test condition of loop
AT Positions the cursor
BEEP Sounds the buzzer
CLS Clears the display
CURSOR ON/OFF Sets the cursor
EDIT Allows a string to be edited on the screen
ESCAPE ON/OFF Allows user to break out of program
GLOBAL Declares variables for all procedures called
INPUT Allows data to be input
KSTAT Sets the keyboard status
LOCAL Declares variables for current procedure only
OFF Turns the organiser off
PAUSE Pauses the program
PRINT Prints to the screen
LPRINT Prints to an attached printer or computer
RANDOMIZE Sets a new sequence of random numbers
REM Precedes a programmer's remark
RETURN Returns to the calling procedure
STOP Exits from OPL
ONERR label:: Goes to label on error
ONERR OFF Cancels ONERR label::
RAISE Generates an error
TRAP Traps errors on a specified command
APPEND Appends current field values to current file
CLOSE Closes a file
COPY Copies a file
CREATE Creates a file
DELETE Deletes a file
ERASE Erases a record
FIRST/LAST/NEXT/BACK Select first/last/next/ previous record
OPEN Opens a file
POSITION Selects a record by number
RENAME Renames a file
UPDATE Updates a record
USE Changes current file
POKEB Writes a byte to an address
POKEW Writes an integer to two successive addresses
CHR$ Returns a character with a specified ASCII code
FIX$ Returns a number as a fixed point decimal
FREE Returns the amount of free internal memory
GEN$ Returns a number as a string
GET Waits for a keypress. Returns the ASCII value of the key
GET$ Waits for a keypress. Returns the key as a string
KEY Returns the ASCII value of the key pressed
KEY$ Returns the key pressed as a string
NUM$ Returns a number as an integer
MENU Displays a menu
SPACE Returns free memory space on a device
VIEW Displays a scrolling string on the screen
ERR Returns error number
ERR$ Returns error message
COUNT Returns the number of records in a file
DIR$ Returns file name
DISP Displays a record
EOF Tests for end of file
EXIST Checks to see if a file name exists
FIND Finds a record containing a string
POS Returns the current record number
RECSIZE Returns bytes occupied by the current record
ABS Returns the absolute (unsigned) value of a floating point number
ATAN Returns the arctangent of a number
COS Returns the cosine of a number
DEG Converts from radians to degrees
EXP Returns e raised to the power you specify
FLT Converts an integer into a floating point number
IABS Returns the absolute (unsigned) value of an integer
INT Returns a rounded down integer number
INTF As above, but returns a floating point number
LN Returns the natural log of a number
LOG Returns the base 10 log of a number
PI Returns Pi (3.14159265135...)
RAD Converts from degrees to radians
RND Returns a random floating point number
SIN Returns the sine of a number
SQR Returns the square root of a number
TAN Returns the tangent of a number
HEX$ Converts an integer into a hexadecimal string
DATIM$ Returns the date and time as a string
SECOND/MINUTE/HOUR/DAY/MONTH/YEAR Return information from the clock as numbers
ASC Returns the ASCII value of the first character of a string
LEFT$/MID$/RIGHT$ Select characters from strings according to their position
LEN Returns the length of a string
LOC Returns the location of a string within a string
LOWERS/UPPER$ Convert a string to lower/upper case
REPTS Returns repetitions of a specified string
VAL Converts a numeric string into its floating point value
ADDR Returns the address of a variable
PEEKB Returns the value stored at an address
PEEKW Returns the value stored at two consecutive addresses
USR Passes values to the microprocessor and returns an integer
USR$ Passes values to the microprocessor and returns a string
Most OPL commands require one or more arguments after them. The arguments may be either literal values or variables.
The following method of specifying the syntax of a command is used:
<exp> Numeric expression, variable or literal
<exp%> Integer expression in the range -32768 to +32767, integer variable or literal
<exp$> String expression or variable
<dev> Device (A:, B: or C:)
<var> Variable (integer, floating point or string)
<log> Logical file name (A, B, C or D).
<statement list> One or more OPL statements on one or more lines of the procedure.
Functions are used to produce values which can then be assigned to a variable or combined with commands such as PRINT. For example:
The instruction y%=YEAR will assign the integer value 1990 (or whatever the current year is) to the variable y%
The instruction PRINT YEAR will display the number 1990 on the screen
The method of specifying the syntax is the same as for commands.
You can tell what the return type of the function is by the type of the receiving variable shown in the syntax:
Numeric functions which return a floating point value look like this: f=FUNCTION.
Numeric functions which return an integer look like this f%=FUNCTION.
String functions look like this: f$=FUNCTION$.
|Returns the absolute value. i.e. without any sign, of
a floating point number. E.g. ABS(-10) is 10.
See also IABS.
|Returns the address at which the variable inside the brackets is stored in memory. You can use an array as the variable, e.g. a%=ADDR(array()), but you can't specify individual elements of an array.|
|Appends the current field values to the end of the
current file as a new record.
See also UPDATE.
|Returns the ASCII value of the first character of a
If you just need the ASCII code for one particular character you can use the % sign. For example, a%=%G returns the ASCII code for the letter G to the variable a%.
|Positions the cursor at the screen position you specify. <exp1%> is the number of characters across the screen in the range 1 to 16, and <exp2%> (1 or 2) indicates the top or bottom line.|
|Returns the arctangent of the expression inside the brackets. The expression represents an angle expressed in radians.|
|Makes the previous record in the current data file the current record. If the current record is the first record in the file then the current record does not change.|
|Sounds the internal buzzer of the Organiser. The sound duration is <exp1%> milliseconds. The frequency of the sound is determined by the equation (Frequency = 921600/(78+2*<exp2%>)Hz). Alternatively, the control character 16 can be used in conjunction with the PRINT command and the CHR$ function to sound the buzzer, i.e: PRINT CHR$(16)|
|Allows program control to break out of a DO/UNTIL or a WHILE/ENDWH loop, and to continue the execution of the program at the instruction following the terminator of the loop (UNTIL or ENDWH).|
|Returns the ASCII character with the value of the expression inside the brackets. You can use it to print characters unavailable from the keyboard - for example, the instruction PRINT CHR$(63) prints the question mark character. See Appendix A for more information.|
|Closes the current file.
See also OPEN, CREATE, DELETE, USE.
|Clears the screen. and returns the cursor to the first character space on the top line.|
|Returns program control to the test expression of
either a DO/UNTIL or a WHILE/ENDWH loop. E.g:
DO <statement list> IF <exp> CONTINUE ENDIF <statement list> UNTIL <exp>
In the example, the CONTINUE command will be executed if the expression following the IF statement is true. If this happens, program control will then be transferred to the test expression following the UNTIL instruction.
Copies data files from one device to another. There
are three variations:
1 In the first example, a file on one device is copied to a file on another device with a different filename. An example might be:
If there is already a file on the destination device with the name <fname2>, then the records in the file being copied over are appended to it. Otherwise a new file is created with that name and the records written to it.
2 In the second example, the file name on the destination device is taken to be the same as that on the source device.
3 In the third example, all files on the source device are copied onto the destination device, and are given the same names on the destination device as they had on the source device.
|Returns the cosine of the expression inside the brackets. The expression represents an angle expressed in radians.|
|Returns the number of records in the current file.
See also POS, POSITION.
|Creates a data file on device <dev>, with the name
fname, the logical file name <log>, and up to 16
fields as specified by fld1, fld2 etc. The logical file
name may be A, B, C or D and is used to refer to the
file within the program. Each newly created file is
automatically OPEN, and up to four files may be
open at any one time.
An example of the command might be:
In this example a data file is created on device A:
with the name clients and the logical name B. Each
record in the data file can have up to three fields.
|Syntax:||CURSOR ON or CURSOR OFF|
|Switches the cursor on or off. The default setting is CURSOR OFF.|
|Returns the current date and time from the system
clock in string format: e.g:
"MON 17 FEB 1986 16:25:30"
See also SECOND, MINUFE, HOUR, DAY, MONTH, YEAR.
|Returns the current day of the month (1 to 31).
See also SECOND, MINUTE, HOUR, MONTH, YEAR, DATIM$.
|Converts from radians to degrees. Returns the value
of the expression in the brackets, representing an
angle measured in radians, as a number of degrees.
See also RAD.
|Deletes a data file with the name fname from device
<dev>. The file must be closed before this command
See also CREATE, OPEN, CLOSE, USE.
|Returns the name of a data file:
1 DIR$(<dev>) returns the name of the first data file on the device specified in the brackets. The device name (A, B or C) must be enclosed in double quotation marks and brackets. E.g: d$=DIR$("A")
2 Subsequent uses of this function with a null string in the brackets will return the names of the following files on the device, until there are no files left on that device, when the function will return a null string.
|Displays a string or a record according to the value
of <exp%>. The value of <exp%> may be -1, 0 or 1.
If <exp%> is -1 then <exp$> is ignored and the current record is displayed with one field on each line of the display. The cursor keys may be used to scroll around the record.
If <exp%> is 1 then <exp$> is displayed as above. If <exp$> contains tab characters (ASCII character 9), these divide the string into a number of fields so the string is displayed on a number of lines.
If <exp%> is 0 then the last DISPlayed string or record is continued and <exp$> is ignored. If any key other than the cursor keys is pressed, then the number of that key is returned.
No other commands or functions should be used between using DISP with <exp%> equal to 1 or -1 and DISP with <exp%> equal to 0. For example:
a%=DISP(1,a$) WHILE a%<>13 a%=DISP(0,"") ENDWH
This waits for EXE to be pressed and continues
displaying a$ until this happens. Clearly there can
be no reason to use any other command or function
which accesses the screen in between the two uses
of DISP. Doing so may have unpredictable results.
(13 is the code for the EXE key - see Appendix A for
|The DO command is used to indicate the start of a list of one or more statements which terminate with the UNTIL command. The list of statements will be repeated until the expression after the UNTIL command returns logical true.|
|Displays a string which you can edit on the screen
using the cursor keys and DEL. <var$> can be a
string variable name or a field name.
When you have finished editing, press EXE to return
the edited string. If you press EXE before you have
made any changes, then the same string will be
returned as was included inside the brackets. If you
press ON/CLEAR during editing, the string will be
cleared and new text may be typed. However, if the
TRAP command is used with this command and
ON/CLEAR is pressed twice, the string will be
cleared and then control will pass on to the next line
of the procedure with the ESCAPE error condition
|ELSE See IF.|
|ENDIF See IF.|
|ENDWH See WHILE.|
|Tests for the End Of File. Any program instruction
which tries to read past the last record in a data file
will result in the end of file (EOF) being reached. This
can be tested for like this:
DO <statement list> UNTIL EOF
The EOF function returns -1 (True) if the end of file condition has been reached, or 0 (False).
|Erases the current record in the current file.
Following this command, the current record will be the record after the one just deleted. If the erased record was the last record in a file, then following this command, the current record will be null and EOF will return true.
|Returns the number of the last error which occurred.
Appendix D has a list of all the error messages in
numeric order. The number returned will be in the
range 0 to 255. If 0 is returned, there is no error.
See also ERR$, RAISE, ONERR.
|Returns an error message as a string.
<exp%> can either be a number - e.g. e$=ERR$(240),
to return the message for error number 240, or ERR
- i.e. e$=ERR$(ERR), to return the message for the
last error which occurred. If the number is outside
the range 195 to 255. the string returned is
"*** ERROR ***". The error messages are listed in
See also ERR, ONERR, RAISE.
|ESCAPE OFF/ ESCAPE ON|
|Syntax:||ESCAPE OFF or ESCAPE ON|
|Disenables and enables the ON/CLEAR key.
You can normally press ON/CLEAR to pause a
running program, and then Q to quit. ESCAPE OFF
cancels the use of the ON/CLEAR key to pause.
ESCAPE ON lets the ON/CLEAR key pause the program again. This is the default state.
Warning: If your program enters a loop which has no logical exit, and ESCAPE OFF has been used, you won't be able to quit the program unless you remove the battery from the Organiser. All data in the RAM of the machine will then be lost.
|Tests for the existence of a file called fname on
device <dev>. Returns logical true if the file exists
and logical false otherwise - so EXIST can be used
on an IF statement, for example:
IF EXIST("a:clients") <statement list> ENDIF
See also DIR$.
|Returns the value of the arithmetic constant e (2.71828...) raised to the power of <exp>.|
|Searches the current data file for the string inside
the brackets. If found, it returns the record number
where the string occurs, and makes the record the
current record. If the string is not found, zero is
See also NEXT.
|Makes the first record in a data file the current
See also ERASE, NEXT, POSITION, LAST, BACK, POS.
|Returns a string representation of <exp>, with
<exp1%> decimal places in a field which is <exp2%>
characters wide. If <exp2%> is negative then the
string is right justified. So:
FIX$(123456.127,2,9)="123456.13" FIX$(1,2,-5)=" 1.00"
If the number will not fit in the field width specified
then the returned string will contain asterisks.
|Converts the integer expression inside the brackets into a floating point number.|
|Returns the number of free bytes in the internal
memory of the Organiser.
See also SPACE.
|Returns a string representation of <exp> in a field of
width <exp%> characters. GEN$ tries to represent
the number as integer, decimal or scientific, in that
order. If the value of <exp%> is negative then the
result will be right justified. If the number will not fit
in the field width specified then the returned string
will contain asterisks.
See also FIX$, NUM$, SCI$.
|Waits for a key to be pressed and returns the ASCII
value or special code for that key. For example, if the
A key is pressed in lower case mode, the integer
returned is 97. If the EXE key is pressed, the integer
returned is 13. See Appendix A for tables of ASCII
values and special key codes.
See also GET$, KEY, KEY$, PAUSE.
|Waits for a key to be pressed and returns that key as
a string. For example, if the A key is pressed in lower
case mode. the string returned is "a".
See also GET, KEY, KEY$.
|Used to declare variables which will be available in
the current procedure and any procedures below it
in the program.
Variable names ending with no sign are floating point variables; those ending with a percent sign (%) are integers; those ending with a dollar sign ($) are string variables. String variable names must be followed by the maximum length of the string in brackets.
The last variable in the example above is a floating point array. The number following it in brackets is the number of elements in the array. Array variables may be of any of the three types.
Variable names may be up to 8 alphanumeric
characters long, the first of which must be a letter.
The length includes the % or $. More than one
GLOBAL or LOCAL statement may be used but they
must be the first instructions in the procedure. See
the chapter on variables for more information.
|Sends program control to the line containing the label name label:: The label must be in the current procedure, and must end with a double colon. Labels may be up to 8 characters long excluding the colons.|
|Returns the hexadecimal (base 16) version of the integer expression inside the brackets. For example: HEX$(255) will return "FF",|
|Returns the number of the current hour from the
system clock (0 to 23).
See also SECOND, MINUTE, DAY, MONTH, YEAR, DATIM$.
|Returns the absolute value, ie. without any sign, of an integer. E.g. IABS(-10) is 10.|
IF statements are immediately followed by an
expression. If the result of that expression returns
logical true, (non-zero) then the statements following
are executed. If the expression returns logical false
(zero) then those statements are ignored. The
statement list must be followed by an ENDIF.
The ELSEIF statement is optional. but if it is included, and the following expression returns logcal true - while none of the previous ones have, then the next list of statements are executed. There may be more than one ELSEIF, each with its own list of statements.
The ELSE statement is optional. If none of the preceding expressions have returned logical true. then the list of statements after the ELSE statement and before the ENDIF statement are executed.
Allows data to be input from the keyboard during
program execution. There are four variations.
The variable supplied must have been declared previously with a GLOBAL or LOCAL command, or be a field variable of the current file. If inputting to a string variable, only as many characters as have been set aside for that variable with the GLOBAL or LOCAL command may be entered.
If inappropriate input is entered - for example a string when the input command specifies an integer variable - a "?" is displayed and the user is given another chance to make an entry. However, if the TRAP command is used with this command, control will pass on to the next line of the procedure with the ESCAPE error condition (no. 206) being set.
|Returns the integer (ie the whole number part) of the
expression inside the brackets. Negative numbers
are rounded down, so INT(-5.3) will return the result
-6 . Used when the returned value will be within the
Organisers integer range.
See also INTF.
|Used in the same way as the INT function, but the value returned is a floating point number. You may need this when an integer calculation may exceed the Organiser's integer range, for example: PRINT INTF(32000)*100|
|Returns the ASCII value of any key pressed. If no key
has been pressed, zero is returned. This command
does not wait for a key to be pressed.
See also PAUSE, GET, GET$, KEY$.
|Returns a string containing the key pressed. If no
key has been pressed, a null string is returned. This
command does not wait for a key to be pressed.
See also KEY, GET, GET$.
|Sets the state of the keyboard to SHIFT mode. CAPS
mode etc. <exp%> is a number from 1 to 4
according to the following table:
1 Alpha - upper case
|Returns the leftmost <exp%> characters from the
string specified by <exp$>.
See also RIGHT$, MID$, LOWER$, UPPER$, REPT$, LEN, LOC.
|Returns the length of the string expression inside the brackets.|
|Returns the natural (base e) logarithm of the
expression inside the brackets.
See also LOG.
|Returns the position in <exp1$> where <exp2$>
occurs. If the second string expression does not
occur in the first string expression, then the value
zero is returned.
E.g. LOC("STANDING","AND") would return the value 3 because the substring "AND" starts at the third character of the main string.
See also LEFT$, RIGHT$, MID$, LEN, LOWER$, UFPER$, REPT$.
|Used to declare variables which will only be available in the current procedure. Other procedures may use the same variable names for other uses. See GLOBAL for more details on declaring variables.|
|Returns the base 10 logarithm of the expression
inside the brackets.
See also LN.
|Converts any upper case characters in the string
expression inside the brackets to lower case and
returns the completely lower case string.
See also UPPER$.
|Prints numbers or text to a printer. If there is no
printer attached, a DEVICE MISSING error is
If items to be printed are separated by commas, there is a space between them when printed. If they are separated by semi-colons, there are no spaces. A final semi-colon makes the next items printed with an LPRINT command start immediately after these. A final comma has the same effect but inserts a space. Otherwise the next line in used.
The PRINT command operates like LPRINT, but displays on the screen rather than listing to a printer.
|Displays a menu of items. The string inside the brackets takes the form "item1,item2,item3...", and is displayed in the manner of the main menu. Allows a selection to be made from the menu in the usual way with cursor keys and EXE or the initial letter of the selected item, and returns the number of the item selected (1 to...). If ON/CLEAR is pressed, 0 is returned.|
|Returns a string comprising <exp2%> characters of
<exp$>, starting at the character at position
See also LEFT$, RIGHT$, LOWER$, UPPER$, REPT$, LEN, LOC.
|Returns the current minute number from the system
clock (0 to 59).
See also SECOND, HOUR, DAY, MONTH, YEAR, DATIM$.
|Returns the current month from the system clock (1
See also SECOND, MINUTE, HOUR, DAY, YEAR, DATIM$.
|Makes the next record the current record in the
current file. If use of NEXT is continued beyond the
end of a file, no error is reported but the current
record is a null and the EOF function returns true.
See also FIRST, LAST, BACK, POSITION, POS.
|Returns a string representation of the floating point
number <exp> as an integer in a field <exp%>
characters wide. If <exp%> is negative then the
string is right justified. If the number will not fit in
the field width specified then the returned string will
See also FIX$, GEN$, SCI$.
|Switches off the Organiser. If the ON/CLEAR key is pressed, program execution will start again at the program line following the OFF command.|
|Opens an existing data file on device <dev>, with the
logical file name <log>, with the field names as
specified by fld1, fld2 etc. That file may then be
referred to by the logical file name (A, B, C or D) for all
file handling operations. Up to 4 files can be open at
once. For more details see the section on opening a
file in the data file handling chapter.
See also CREATE, CLOSE, DELETE, USE.
|Syntax:||ONERR label:: and ONERR OFF|
|If an error occurs during program execution, the
ONERR label:: instruction transfers program control
to the line containing the label.
The ONERR OFF instruction cancels the ONERR label:: statement, so that any errors occurring below the ONERR OFF statement are no longer referred to the label:: It is advisable to put the command ONERR OFF immediately after the label.
|Pauses the program according to the value of
<exp%>. If <exp%> is:
0 Waits for a key to be pressed.
So PAUSE 100 would cause the program to pause for five seconds.
In the first two cases. the key pressed is stored in a buffer. It is wise to remove this with the KEY function like this:
<statement list> PAUSE 0 KEY <statement list>
The procedure stored in the buffer from the PAUSE 0 command is taken as the input for KEY.
|Returns the value stored at the address specified by the expression inside the brackets. The value returned will be in the range 0 to 255.|
|Returns the value of the two byte integer stored at addresses <exp%> and <exp%>+1.|
|Returns the value of Pi (3.14... ).|
|Writes the number <exp2%>, which must be in the range 0 to 255, into the memory address <exp1%>, which must be an integer. Addresses above 32767 are addressed by negative values or hexadecimal numbers. E.g. $FFFF = -1, which corresponds to address 65535. Warning: Casual use of this command can result in the loss of all data in the Organiser.|
|Writes the integer <exp2%> into two successive
memory addresses, starting with the address
<exp1%>, with the most significant byte in the lower
Warning: casual use of this command can result in the loss of all data in the Organiser.
|Returns the record number of the current record in
the current data file.
See also POSITION, NEXT, ERASE, APPEND, UPDATE.
|Makes record number <exp%> the current record in
the current data file. If <exp%> is greater than the
number of records in the file then the EOF function
will return true.
See also FIRST, NEXT, LAST, BACK, POS.
|Prints numbers or text to the screen.
If items in the PRINT statement are separated by commas then a space is inserted between the items as they appear on the screen. If items in the list are separated by semi-colons then there are no spaces.
A final semi-colon indicates that anything to be printed by the next PRINT statement will start immediately after what is printed by this PRINT statement. A final comma indicates that anything to be printed by the next PRINT statement will follow on the same line with a space inserted between the items. Otherwise the next line is used.
The LPRINT command operates in the same way as the PRINT command except all output is sent to a printer. If there is no printer connected. a DEVICE MISSING error will be reported.
|Converts <exp> from degrees to radians.
See also DEG.
|Artificially generates an error, even though no such
error has occurred. If no ONERR statement has been
issued previously then the appropriate message for
that error number is displayed. The range of possible
internal errors to use as <exp%> is 192 to 255. Refer
to the chapter on error handling for more
explanation. A full list of error numbers and
messages is in Appendix D.
See also ONERR, ERR, ERR$.
|Gives a new seed value to the random number
generator, so that a new sequence of random
numbers will be initiated. So use RANDOMIZE if you
wish to use the same sequence of random numbers
more than once.
See also RND.
|Returns the number of bytes occupied by the current record. No record may contain more than 254 characters. so this function may be used to check that a record may have date added to it without over-stepping this limit.|
|The REM statement precedes a remark you include to explain how a program works. The Organiser ignores all text after the REM statement up to the end of that line.|
|Renames a file on device <dev> called fname1 as the file fname2.|
|Returns a string comprising <exp%> repetitions of
See also LEFT$, RIGHT$, MID$, UPPER$, LOWER$, LEN, LOC.
|Syntax:||RETURN or RETURN <exp>|
|Used on its own, the RETURN command terminates
the execution of a procedure and returns control to
the point where that procedure was called. Use of
this command at the end of a procedure is optional.
The RETURN command may also be used to pass a value back to the level from which the procedure was called. The value must be supplied alter the RETURN command like this: RETURN <exp%> or RETURN <exp> or RETURN <exp$>
You can make sure a procedure is only able to return a particular type of value by using an identifier as the last character of the procedure name. For example, proc$: can only return a string.
|Returns the rightmost <exp%> characters of <exp$>.
See also LEFT$, MID$, REPT$, LEN, LOC.
|Returns a random floating point number in the
range 0 (inclusive) to 1 (exclusive).
See also RANDOMIZE.
|Returns a string representation of <exp> in scientific
format, to <exp1%> decimal places in a field of width
of <exp2%> characters. For example:
SCI$(123456,2,8) = "1.23E+05"
If the number will not fit in the field width specified
then the returned string will contain asterisks.
|Returns the current number of seconds from the
system clock (0 to 59).
See also MINUTE, HOUR, DAY, MONTH, YEAR.
|Returns the sine of the expression inside the brackets. The expression represents an angle expressed in radians.|
|Returns the number of free bytes on the current
device. There must be a file open on the device first.
See also FREE.
|Returns the square root of the expression inside the brackets.|
|Halts execution of the language and returns the Organiser to the point where that program was started. e.g. the main menu or the calculator.|
|Returns the tangent of the expression inside the brackets. The expression represents an angle expressed in radians.|
|TRAP may precede any of these commands: (APPEND/BACK/CLOSE/COPY/CREATE/ DELETE/ERASE/EDIT/FIRST/INPUT/LAST/ NEXT/OPEN/POSITION/RENAME/UPDATE/USE) For example, TRAP FIRST. Any error resulting from the execution of the command will be trapped - the next program line will be executed regardless of whether the error would normally have caused an error message to be displayed.|
|UNTIL See DO.|
|The current record in the current file is deleted and
the current field values are appended as a new
record at the end of the file.
See also APPEND.
|Converts any lower case characters in the string
expression inside the brackets to upper case.
Returns the completely upper case string.
See also LOWER$.
|Selects for use the data file with the logical file name
<log> (A, B, C or D), which must previously have
been opened with the OPEN or CREATE command.
See also OPEN, CLOSE, CREATE, DELETE.
|The value of <exp2%> is passed to the D register and
the value of <exp1%> is passed to the PC register of
the HD6303X microprocessor. The microprocessor
then executes the machine language program
starting at the address <exp1%>. At the end of the
routine, the value in the X register is passed back to
the language as an integer.
Warning: Casual use of this function can result in
the loss of all data in the Organiser.
See also USR$, ADDR.
|The value of <exp2%> is passed to the D register and
the value of <exp1%> is passed to the PC register of
the HD6303X microprocessor. The microprocessor
then executes the machine language program
starting at the address <exp1%>. At the end of the
routine, the value in the X register must point to a
length-byte preceded string. This string is then
returned to the assigned variable.
Warning: Casual use of this command can result
in the loss of all data in the Organiser.
See also USR, ADDR.
|Returns a floating point number which is the value of the string expression inside the brackets. E.g. VAL("470.0") would return the value 470.0. The string cannot contain any non-numeric characters. Scientific notation is allowed, so VAL("1.3E10") would return the value 1.3E10.|
|Displays <exp$> on line number <exp%> (1 or 2) on
the screen. <exp$> can be a string, a string variable,
or a field name.
If the text is longer than 16 characters, the display
auto-scrolls to the left, and pressing the left or right
cursor keys allows you to change the direction of the
scroll. Pressing any other key halts the scrolling or
the text and returns the ASCII value of the key
pressed. If VIEW is used again with <exp$> being a
null string then viewing is continued at the point it
was interrupted by a key press.
This structure is started by the WHILE command
which precedes a numeric expression.
The subsequent list of statements, which must end
with the ENDWH statement, is executed while the
expression returns logical true (non-zero).
|Returns the current year from the system date (1900
See also SECOND, MINUTE, HOUR, DAY, MONTH, DATIM$.
The full character set of the Organiser is shown in the table overleaf. The more common characters can obviously just be typed from the keyboard. However, there are others which do not appear on the keys. These are accessed via the OPL CHR$ function.
By supplying the CHR$ function with the appropriate number from the table overleaf, you can print out to the screen or the printer, or assign to string variables, any of the characters shown. For example, to print out a question mark the instruction is: PRINT CHR$(63)
You can find out the ASCII value of any of the characters on the keyboard at any time without looking at the table. You do this by typing the % sign followed by the character in the calculator. For example if you type %P in the calculator, the number 80 is returned.
The table shows the characters which have the ASCII
codes 32 to 255.
When writing to the screen:
The codes 0 to 7 are for user-defined characters.
The codes 8-16 are for control characters.
It is often useful to access the ASCII value of a character - for example if you want to know whether a user has typed in Y or N and you can't remember the ASCII codes for Y and N.
To do this you can use the % sign and the character, e.g. %Y. The example below is part of a procedure in which you are asked whether or not you want to erase something. If you type N the program stops. If you type Y another procedure called erase: is called. If you type a key other than Y or N the procedure goes to a label in order to give you another chance.
PRINT "ERASE Y/N" label:: g%=GET IF g%=%N :STOP ELSEIF g%=%Y :erase: ELSE GOTO label:: ENDIF
When the GET and KEY functions are used, the ASCII code for the character on the key is normally returned. The keys not in the ASCII set return these numbers:
|7||SHIFT and DEL|
For the screen. the numbers 0 to 7 are reserved for user-defined characters. That means that you can define the pattern of dots which appear on the screen when you print those characters with the CHR$ function.
The pound sign below can easily be defined using the program opposite.
Each character is defined line-by-line by a series of eight bytes, which must be poked into memory address $181, starting with the top line of the character. From each of the eight bytes which make up the characters, the least significant five bits 16 to 1 are used (because the characters are only five dots across.)
The program below called define: makes it easy to define these characters. When it is run, it will insert the character you give it into memory where it will remain until you use the program again to change it.
To define the pound character as character number 1, you would enter the number 1 in response to the first prompt then the numbers 6, 9, 9, 12, 8, 24, 31 and 0 in response to the prompts to enter the byte numbers.
define: LOCAL numb%,count%,byte%(9) start:: PRINT "CHAR NUMBER"+CHR$(63); INPUT numb% count%=1 DO PRINT "ENTER BYTE NO. ";Count% INPUT byte%(count%) count%=count%+1 UNTIL count%=9 PRINT "SAVING CHAR..." POKEB $180,64+(numb% AND 7)*8 count%=1 DO POKEB $181,byte%(count%) count%=count%+1 UNTIL count%=9
Then when you want to print the pound character use the instruction:
Note. On the Organiser, the bottom line of any character is best left blank to allow room for the underscore cursor to be clearly distinguished from the character itself.
For the screen, the numbers 8 to 16 have special uses. These do not produce a visible character, but may be used to affect parts of the screen in the ways listed:
|CHR$(8)||Moves the cursor 1 character to the left.|
|CHR$(9)||Moves the cursor to the next tab position. (The tabs are at position 9 and position 17 on the Organiser screen.)|
|CHR$(10)||Moves the cursor to the next line.|
|CHR$(11)||Moves the cursor to the top left "home" position of the display.|
|CHR$(12)||Clears the display (equivalent to CLS).|
|CHR$(13)||Moves the cursor to the left of the current line.|
|CHR$(14)||Clears the top line of the display and moves the cursor to the top left.|
|CHR$(15)||Clears the bottom line of the display and moves the cursor to the bottom left.|
|CHR$(16)||Sounds the Organiser's buzzer.|
Length - 142.0 mm Width - 78.0 mm Depth- 29.3 mm
Two line by sixteen character alphanumeric dot-matrix liquid crystal display.
A total of thirty six keys including editing, cursor, alphabetic, numeric, MODE and ON/CLEAR.
HD6303X Frequency 3.6864 MHz.
|Model XP||ROM 32K||RAM 32K|
|Model CM||ROM 24K||RAM 8K|
|Extra EPROM 8/16/32/64/128K - from Datapaks.|
|Extra RAM 32K - from Rampak.|
Real time clock with 32768 Hz crystal frequency source.
EPROM (Erasable, Programmable, Read Only Memory)
'Mean time to failure' 50 years at temperatures up to 100°C
30 minutes in Psion Formatter - prepares Datapak for re-use.
Can be re-formatted up to 100 times
|8K Datapak||8192 bytes|
|16K Datapak||16384 bytes|
|32K Datapak||32768 bytes|
|64K Datapak||65536 bytes|
|128K Datapak||131072 bytes (Model XP only)|
Storage medium - battery backed-up RAM.
Capacity - 32768 bytes.
Standard alkaline 9 volt long-life battery. Mains adaptor available.
Psion has a policy of continuous product development. Small modifications arising from this are not necessarily reflected in this manual.
The following list of addresses are used by the Organiser to store certain system variables. These can be accessed by using the PEEKB, PEEKW, POKEB and POKEW commands:
|$0069,$006A||($04)||Horizontal scroll delay counter|
|$006B,$006C||($0A)||Vertical scroll delay counter|
|$0077||($0E)||Delay before keyboard auto-repeat|
|$0078||($00)||Keyboard auto-repeat counter|
|$007C||non-zero||Auto-switch off flag - zero deactivates auto-switch off|
|$20CB,$20CC||Frame counter - increments every 50ms|
|$20CD,$20CE||($012C)||Default number of seconds to auto-switch off|
|$00A4||($00)||Buzzer mute - non-zero value mutes buzzer|
The Organiser memory maps are shown overleaf.
To get a hexadecimal number in OPL, prefix it with a $ identifier - for example $FF.
The Organiser's CPU (Central Processor Unit) is the HD6303X microprocessor. This advanced processor can be programmed directly, in its own language called machine language or machine code.
Machine language programs run far faster than OPL programs and take up less memory, but they are much more difficult to write and debug. Also, a simple mistake in a machine language program can easily wipe out all of the information stored in the internal memory of the Organiser, as these programs take over full control of the chip at the heart of the machine.
To avoid this, it is wise to save all important data to a pack before testing machine language programs, so that all will not be lost if the machine loses all its data, or 'crashes'.
The error messages are listed first in alphabetic order and then in numeric order. Error trapping is covered in Chapter 16.
1 Place the cursor at the position in the menu where you want the item to be.
2 Press MODE and the screen shows:
3 Type in the name of the missing item and press EXE.
The name will reappear, pushing the items that follow to the right.
If you are get this message, it means that you must free some internal memory. Do this by tidying the diary, or erasing unwanted records or procedures.
To tidy the diary:
1 Press MODE from within the diary to get the diary menu.
2 Press T and check that the date on the top line is the current one, so that you will delete only out-of-date entries. Then press Y to confirm.
If you still get the OUT OF MEMORY message try erasing unwanted records or procedures - you can copy them onto a Datapak first if you want to keep them.
When you get this message it means that your battery is about to run out. The Organiser switches itself off when this happens, and you should not switch it on again. Do not remove the battery until you are ready to put a new one in.
The battery goes in with the + connector first.
When you have the new battery ready you can replace it as follows with the machine switched off:
1 Remove the old battery.
2 Fit the new one within 90 seconds or all the data in the internal memory will be deleted.
If you use the Psion Mains Adaptor you can power the Organiser from the mains whilst you change the battery. There is then no time limit.
If you are typing and keypresses start being ignored and cause a beep. you are trying to enter too many characters. The limit is 64 characters in a diary entry and 254 characters on a maximum of 16 lines in a database record.
If a "?" appears on the screen, an OPL program is using the INPUT command and you have entered inappropriate data - for example text when a number was expected. Try again with the right kind of data.
You can usually break out of a running OPL program by pressing ON/CLEAR followed by Q. However, if an OPL program has a loop in it which reads keys with a command such as GET, KEY or INPUT, it may be very hard to break out in this way. Try pressing ON / CLEAR followed by Q repeatedly and very rapidly.
(OPL programs should be designed to avoid this situation.)
If you believe that you have a faulty Datapak or Organiser contact the Psion service department:
London NW10 6EU
Tel: 01 965 8626
$ sign for hexadecimal numbers C-3 for string variables 12-4 on procedure name 12-16 % sign for integer variables 12-3 on procedure name 12-16 used to access ASCII values A-3 ? character printing A-1 ? sign appears on screen what to do E-1 £ sign printing A-4
aborting running procedures 11-13 ABS function (OPL) syntax an summary 18-8 ADDR function (OPL) syntax and summary 18-8 addresses, in memory C-1 alarms 4-1 to 4-4 cancelling 4-3 example program to mute 17-10 on diary entries 5-3 repeating 4-3 switching off 4-2 AND, logical operator explained 14-6 APPEND command (OPL) explained 15-4 syntax and summary 18-8 ARG COUNT ERR D-1 arithmetic operators 14-1 array variables 12-6 example integer array 12-6 ASC function(OPL) syntax and summary 18-8 ASCII codes accessing with % A-3 table of A-2 ASCII values, accessing A-3 AT command (OPL) syntax and summary 18-9
ATAN function (OPL) syntax and summary 18-9 auto scrolling 3-2 auto switch off 1-6
BACK command (OPL) explained 15-5 syntax and summary 18-9 BAD ARRAY SIZE D-1 BAD ASSIGNMENT D-1 BAD CHARACTER D-1 BAD DECLARATION D-1 BAD DEVICE CALL D-2 BAD DEVICE NAME D-2 BAD FIELD LIST D-2 BAD FILE NAME D-2 BAD FN ARGS D-2 BAD IDENTIFIER D-2 BAD LOGICAL NAME D-2 BAD NUMBER D-2 BAD PROC NAME D-3 BAD RECORD TYPE D-3 battery fitting 1-1 replacing 10-1 time limit on replacing 10-1 voltage 1-1 BATFERY TOO LOW D-3 BEEP command (OPL) syntax and summary 18-9 beeping keyboard what to do E-2 branches 13-4 BREAK command (OPL) explained 13-3 syntax and summary 18-9 breaking out of OPL program E-1
calculator 6-1 to 6-7 decimal places 6-2 memories 6-2 operators in 6-1 OPL functions in 6-5 OPL procedures in 6-6 percentages in 6-4 calculator memories as OPL variables 12-6 CAP key 2-2
characters accessing ASCII code A-3 control A-6 printing non-key ones A-1 program for defining A-5 user defined A-4 user-defined, example 17-12 CHRS function (OPL) explained A-1 syntax and summary 18-10 clock setting 1-5 technical details B-1 See TIME CLOSE command (OPL) explained 15-8 syntax and summary 18-10 CLS command (OPL) explained 11-4 syntax and summary 18-10 commas, in OPL syntax 11-4 concatenating strings 12-11 CONTINUE command (OPL) syntax and summary 18-10 control characters A-6 COPY main menu option 9-3 PROG menu option 11-12 COPY command (OPL) syntax and summary 18-11 copying files 9-3 procedures 11-12 records 3-5 COS function (OPL) syntax and summary 18-11 COUNT function (OPL) syntax and summary 18-12 CREATE command (OPL) explained 15-3 syntax and summary 18-12 CURSOR command (OPL) syntax and summary 18-12
data files 15-1 to 15-8 creating in OPL 15-3 example program for handling 17-19 Datapaks changing 8-2 explained 8-2 formatting 8-4 new 8-3 saving records on 2-4 sizing 8-3 technical details B-2 date setting 1-5 DATIM$ function (OPL) syntax and summary 18-12 DAY function (OPL) syntax and summary 18-13 decimal places setting in calculator 6-2 declaring variables explained 12-2 LOCAL and GLOBAL 12-4 DEG function (OPL) syntax and summary 18-13 DEL key 2-3 DELETE command (OPL) syntax and summary 18-13 deleting all data 8-6 DEVICE LOAD ERR D-3 DEVICE MISSING D-3 DEVICE READ FAIL D-3 DEVICE WRITE FAIL D-3 devices 8-1 diary 5-1 to 5-12 alarms 5-3 editing entries 5-7 erasing out-dated entries 5-9 making an entry 5-2 menu 5-5 moving thro the pages 5-1 saving to a Datapak 5-9 diary menu DIR 5-10 ERASE 5-11 FIND 5-7 getting to 5-5 GOTO 5-8 LIST 5-6 PAGE 5-6 RESTORE 5-10 SAVE 5-9 TIDY 5-9 dimensions of Organiser B-1 DIR diary menu 5-10 PROG menu option 11-11 DIR$ function (OPL) syntax and summary 18-13 directory of diaries 5-10 of procedures 11-11 DIRECTORY FULL D-4 display technical details B-1 DIVIDE BY ZERO D-4 DO/UNTIL command (OPL) syntax and summary 18-15 DO/UNTIL commands (OPL) explained 13-1 syntax and summary 18-10 DUPLICATE NAME D-4
EDIT PROG menu option 11-10 EDIT command (OPL) syntax and summary 18-15 editing diary entries 5-7 procedures 11-10 records 3-3 ELSE statement (OPL) syntax and summary 18-22 END OF FILE D-4 EOF function (OPL) syntax and summary 18-16 ERASE diary menu 5-11 main menu 3-4 PROG menu 11-11 ERASE command (OPL) explained 15-6 syntax and summary 18-16 erasing all data 8-6 procedures 11-11 records 3-4 ERR function (OPL) explained 16-8 syntax and summary 18-16 ERR$ function (OPL) syntax and summary 18-17 error messages 16-8 errors common OPL errors 16-1 generating and debugging 16-8 messages 16-8 run-time 16-4 ESCAPE D-4 ESCAPE ON/OFF command (OPL) risks of 13-5 syntax and summary 18-17 escaping from procedures 11-13, 13-5, E-1 EXE key 1-4 EXIST function (OPL) syntax and summary 18-18 EXP function (OPL) syntax and summary 18-18 EXPONENT RANGE D-4
FIELD MISMATCH D-4 fields field names 15-3 field qualifiers 15-3 handling in OPL 15-2 input to 15-4 FILE EXISTS D-4 FILE IN USE D-5 FILE NOT FOUND D-5 FILE NOT OPEN D-5 files changing current in OPL 15-8 closing in OPL 15-8 copying from main menu 9-2 copying to/from Datapak 9-3 creating in OPL 15-3 example program for handling 17-19 handling in OPL 15-1 to 15-8 opening in OPL 15-7 FIND diary menu 5-7 main menu 3-1 FIND function (OPL) explained 15-6 syntax and summary 18-18 finding diary entry 5-7 records 3-1 FIRST command (OPL) explained 15-5 syntax and summary 18-18 FIX$ function (OPL) syntax and summary 18-19 FIX= in calculator 6-2 floating point variables explained 12-5 precedence in OPL 14-3 range 12-3 rounded down 12-10 type conversion 12-8 FLT function (OPL) syntax and summary 18-19 FN ARGUMENT ERR D-5 formatting Datapaks 8-4 FREE function (OPL) syntax and summary 18-19
GEN$ function (OPL) syntax and summary 18-19 GET function (OPL) accessing ASCII codes A-3 explained 11-5 numbers returned by A-3 syntax and summary 18-20 GET$ function (OPL) syntax and summary 18-20 GLOBAL command (OPL) explained 12-4 syntax and summary 18-20 GOTO command (OPL) explained 13-3 syntax and summary 18-21 GOTO, diary menu 5-8
HEXS function (OPL) syntax and summary 18-21 hexadecimal numbers C-3 HOUR function (OPL) explained 11-4 syntax and summary 18-21
IABS function syntax and summary 18-21 IF/ELSEIF/ELSE command (OPL) explained 13-4 IF/ELSEIF/ELSE/ENDIF command (OPL) syntax and summary 18-22 INFO, main menu option 8-5 INPUT command (OPL) explained 12-13 in example input routine 17-7 syntax and summary 18-23 INT function (OPL) syntax and summary 18-23 INTEGER OVERFLOW D-5 integer variables explained 12-3 range 12-3 type conversion 12-8 INTF function (OPL) syntax and summary 18-24
joining lines 2-3 jumps in procedures 13-3
KEY function (OPL) numbers returned by A-3 syntax and summary 18-24 KEYS function (OPL) syntax and summary 18-24
keyboard beeping, what to do E-2 getting used to 2-2 KSTAT command (OPL) syntax and summary 18-24
labels with ONERR command 16-5 labels with GOTO command 13-3 LAST command (OPL) explained 15-5 LEFT$ function (OPL) explained 12-11 syntax and summary 18-25 LEN function (OPL) syntax and summary 18-25 LIST diary menu 5-6 PROG menu option 11-10 listing procedures 11-10 LN function (OPL) syntax and summary 18-25 LOC function (OPL) syntax and summary 18-25 LOCAL command (OPL) explained 12-4 syntax an summary 18-26 LOG function (OPL) syntax and summary 18-26 logical expressions in OPL 14-4 logical file names 15-3 logical operators 14-7 to 14-8 with floating point values 14-6 with integer values 14-6 loops 13-1 to 13-5 breaking out of 13-5 endless, how to avoid 13-5 maximum nested 13-1 low battery 10-1 LOWER$ function (OPL) syntax and summary 18-26 lowercase letters typing in 2-2 LPRINT command (OPL) syntax and summary 18-26
machine language C-3 main file copying to Datapak 9-2 main menu 1-4 customising 7-1 deleting options from 7-2 missing item E-1 replacing options 7-3 selecting options from 1-4 summary of options 7-1 memories calculator as OPL variables 12-6 in calculator 6-2 memory what to do when out of 12-1 memory maps C-1 MENU function (OPL) syntax and summary 18-27 MENU TOO BIG D-5 messages error 16-8 microprocessor, technical details B-1 MID$ function (OPL) explained 12-11 syntax and summary 18-27 MINUTE function (OPL) syntax and summary 18-27 MISMATCHED " D-5 MISMATCHED ()'s D-5 MISSING COMMA D-6 MISSING EXTERNAL D-6 MISSING LABEL D-6 MISSING PROC D-6 MONTH function (OPL) syntax and summary 18-27
NAME TOO LONG D-6 names of procedures 12-1 of variables 12-2 NEW option 11-3 NEXT command (OPL) explained 15-5 syntax and summary 18-28 NO ALLOC CELLS D-6 NO PACK D-6 NO PROC NAME D-7 NOT, logical operator explained 14-6 NUM key 2-2 NUM TO STR ERR D-7 NUM$ function (OPL) syntax and summary 18-28 numbers typing in 2-2
object files copying 11-12 OFF command (OPL) syntax and summary 18-28 OFF main menu option 1-6 ONERR command (OPL) explained 16-5 syntax and summary 18-29 OPEN command (OPL) explained 15-7 syntax and summary 18-29 operators available in OPL 14-1 in the calculator 6-1 precedence in OPL 14-2 OPL commands APPEND 18-8 AT 18-9 BACK 18-9 BEEP 18-9 BREAK 18-9 CLOSE 18-10 CLS 18-10 COPY 18-11 CREATE 18-12 CURSOR 18-12 DELETE 18-13 DO/UNTIL. 18-15 EDIT 18-15 ERASE 18-16 ESCAPE ON/OFF 18-17 FIRST 18-18 GLOBAL 18-20 GOTO 18-21 IF/ELSEIF/ELSE/ENDIF 18-22 INPUT 18-23 KSTAT 18-24 LOCAL 18-26 LPRINT 18-26 NEXT 18-28 OFF 18-28 ONERR 18-29 OPEN 18-29 PAUSE 18-30 POKEB 18-31 POKEW 18-32 POSITION 18-32 PRINT 18-32 RAISE 18-33 RANDOMIZE 18-33 REM 18-34 RENAME 18-34 RETURN 18-34 STOP 18-37 TRAP 18-37 UPDATE 18-38 USE 18-38 WHILE/ENDWH 18-40 OPL functions ABS 18-8 ADDR 18-8 ASC 18-8 ATAN 18-9 CHR$ 18-10, A-1 COS 18-11 COUNT 18-12 DATIM$ 18-12 DAY 18-13 DEG 18-13 DIR$ 18-13 EOF 18-16 ERR 18-16 ERR$ 18-17 EXIST 18-18 EXP 18-13 FIND 18-13 FIX$ 18-19 FLT 18-19 FREE 18-19 GEN$ 18-19 GET 18-20 GET$ 18-20 HEX$ 18-21 HOUR 18-21 IABS 18-21 INT 18-23 INTF 18-24 KEY 18-24 KEY$ 18-24 LEFT$ 18-25 LEN 18-25 LN 18-25 LOC 18-25 LOG 18-26 LOWER$ 18-26 MENU 18-27 MID$ 18-27 MINUTE 18-27 MONTH 18-27 NUM$ 18-23 PEEKB 18-31 PEEKW 18-31 PI 18-31 POS 18-32 RAD 18-33 RECSIZE 18-34 REPT$ 18-34 RIGHT$ 18-35 RND 18-35 SCI$ 18-36 SECOND 18-36 SIN 18-36 SPACE 18-36 SGN 18-37 TAN 18-37 UPPER$ 18-33 USR 18-38 USR$ 18-39 VAL 18-39 YEAR 18-40 OPL functions in calculator 6-5 OR, logical operator explained 14-6 OUT OF MEMORY D-7 what to do E-1
PACK CHANGED D-7 PACK FULL D-7 PACK NOT BIANK D-7 PAGE, diary menu 5-6 PAK NOT COPYABLE D-7 parameters explained 12-14 multiple 12-15 returning 12-16 passwords example program to set 17-10 PAUSE command (OPL) syntax and summary 18-30 PEEKB function (OPL) syntax and summary 18-31 PEEKW function (OPL) syntax and summary 18-31 percentages in calculator 64 PI function (OPL) syntax and summary 18-31 POKEB command (OPL) syntax and summary 18-31 POKEW command (OPL) syntax and summary 18-32 POS function (OPL) explained 15-5 syntax and summary 18-32 POSITION command (OPL) explained 15-5 syntax and summary 18-32 pound sign printing A-4 PRINT command (OPL) explained 11-4 syntax and summary 18-32 printing procedures 11-10 procedure names length and format 12-1 procedures copying 11-12 creating 11-2 editing new 11-5 editing old 11-10 erasing 11-11 escaping from 11-13, 13-5 examples 17-1 to 17-22 in calculator 6-6 introduction to 11-1 listing/printing 11-10 names 11-3 names format 12-1 quitting out of 11-13, 13-5 running 11-9 running from menus 12-17 saving 11-7 to 11-8 translating 11-5, 11-7 PROG TRAN/SAVE/QUIT menu 11-6 PROG menu summary of 11-2 program labels 13-3 programs See procedures programs, examples 17-1 to 17-22
question mark printing A-1 QUIT, PROG option 11-6 quitting running procedures 11-13, 13-5 quotation marks in strings 12-12
RAD function (OPL) syntax and summary 18-33 RAISE command (OPL) explained 16-8 syntax and summary 18-33 Rampaks explained 8-2 RANDOMIZE command (OPL) syntax and summary 18-33 READ ONLY PACK D-7 READ PACK ERROR D-8 RECORD TOO BIG D-8 records abandoning 2-3 adding to file in OPL 15-4 changing current in OPL 15-5 copying to/from Datapak 3-5, 9-2 editing 3-3 erasing 3-4 erasing in OPL 15-6 finding 3-1 finding in OPL 15-6 hints about 9-1 maximum size 9-1 saving 2-1
RECSIZE function (OPL) syntax and summary 18-34 REM command (OPL) syntax and summary 18-34 RENAME command (OPL) syntax and summary 18-34 repeating alarms 4-3 REPT$ function (OPL) syntax and summary 18-34 RESET, main menu option 8-6 RESTORE, diary menu 5-10 RETURN command (OPL) explained 12-16 syntax and summary 18-34 RIGHT$ function (OPL) explained 12-11 syntax and summary 18-35 RND function (OPL) syntax and summary 18-35 RUN PROG menu option 11-9 running procedures 11-9
SAVE diary menu 5-9 main menu 2-1 PROG menu 11-8 saving diaries 5-9 procedures 11-7 to 11-8 records 2-1 records on a Datapak 2-4 SCI$ function (OPL) syntax and summary 18-36 search-clue 3-1 SECOND function (OPL) syntax and summary 18-36 semi-colons, in OPL syntax 11-4 SHIFT key 2-2 SIN function (OPL) syntax and summary 18-36 sizing Datapaks 8-3 slicing strings 12-11 SPACE function (OPL) syntax an summary 18-36 SQR function (OPL) syntax and summary 18-37 STACK OVERFLOW D-8 STACK UNDERFLOW D-8 STOP command (OPL) syntax and summary 18-37 STR TO NUM ERR D-8 STRING TOO LONG D-8 string variables explained 12-4 strings concatenating 12-11 explained 11-4 maximum len 12-4 quotation marks in 12-12 slicing 12-11 STRUCTURE ERR D-8 SUBSCRIPT ERR D-8 switching off automatically 1-6 manually 1-6 switching on 1-2 SYNTAX ERR D-9 system variables C-1
TAN function (OPL) syntax and summary 18-37 TIDY, diary menu 5-9 TIME, setting 1-5 TOO COMPLEX D-9 TRAN, PROG option 11-7 translating procedures 11-7 TRAP command (OPL) explained 16-7 syntax and summary 18-37 trapping errors in OPL 16-4 type conversion, automatic 12~8 type conversion, string/numeric 12-10 TYPE MISMATCH D-9
UDGs example program using 17-12 program for defining A-5 UNKNOWN PACK D-9 UPDATE command (OPL) syntax and summary 18-38 UPPER$ function (OPL) syntax and summary 18-38 USE command (OPL) explained 15-8 syntax and summary 18-38 user defined characters explained A-4 program for defining A-5 user defined graphics example program using 17-12 USR function (OPL) syntax and summary 18-38 USR$ function (OPL) syntax and summary 18-39
VAL function (OPL) syntax and summary 18-39 variables 12-2 array 12-6 explained 12-2 floating point 12-3 GLOBAL v LOCAL 12-5 Int./floating pt. conversion 12-8 Integer 12-3 names 12-2 operations upon 12-8 string 12-4 VIEW function (OPL) syntax and summary 18-40
weight of Organiser B-1 WHILE/ENDWH command (OPL) explained 13-1 syntax and summary 18-40 WRITE PACK ERR D-9
YEAR function (OPL) syntax and summary 18-40