Programming Techniques ====================== To the programmer, most of HUNTER'S features are likely to seem familiar and quite comparable with many other, less portable, microcomputers. To the operator, HUNTER is likely to be quite different from anything he's encountered before. This fundamental divergence in experience can present a major challenge to the skill of the programmer. Because HUNTER operators tend to be newcomers to computer techniques, and worse, tend to capitalise on HUNTER'S unique physical characteristics by using it far away from the comfort of the computer room, considerable demands are placed on the quality of the programming. These demands are met by making programs as error-free and 'bullet-proof' as possible, together with careful program structures. A HUNTER that interrupts a data entry sequence in the field with "Magnitude Error in Line....." is not likely to be appreciated by the user, or worse, by his customers. Knowing that field operators would have difficulty in recovering from programming failures on the spot, HUNTER'S designers have provided a number of facilities that help overcome these difficulties. But because HUNTER'S programming has to have greater integrity than is ever required at the desk-top, there is no substitute for methodical discipline in programming. The contents of this section explain some techniques that are successfully used to provide reliable and ergonomically friendly user programmes. Data Capture Techniques ----------------------- A typical HUNTER application program consists of 3 segments: #. A 'Data Capture' segment #. An 'Inspection' segment #. A 'Transmission' segment All three segments are contained in a common program although treated as independent modules. All share a common database, the 'captured' information, generally stored in array structures. The operator (as opposed to the programmer) is given a limited range of options within this framework and never has access to the Basic interpreter. On power-up, HUNTER will typically present a menu-style choice of options, often based on the segments or modules themselves. Once a module is selected, HUNTER will lead the operator through a question and answer sequence until his objective is achieved. Consider the following data capture program: :: 10 REM TELEPHONE NUMBERS 20 REM THIS PROGRAM CAPTURES AND STORES NUMBERS 30 REM UP TO 6 DIGITS LONG. THEY CAN THEN BE 40 REM RECALLED OR LISTED ON A PRINTER. 100 REM MODULE 0 WHICH FUNCTION? 110 PRINT "PLEASE CHOOSE A FUNCTION, TYPE '1' TO ENTER DATA; '2' TO INSPECT OR *3' TO TRANSMIT", 120 INPUT A 130 IF A=1 THEN 200 140 IF A=2 THEN 300 150 IF A=3 THEN 400 200 REM MODULE 1 DATA CAPTURE 210 DIM D(10) 220 FOR N=1 TO 10 230 INPUT D(N) 240 NEXT N 250 GOTO 100 300 REM MODULE 2 INSPECT DATA 310 PRINT "WHICH NUMBER DO YOU WANT TO INSPECT?" 320 PRINT "PLEASE ENTER A NUMBER 1-101", 330 INPUT N 340 PRINT D(N) 350 GOTO 100 400 REM TRANSMIT THE DATA 410 FOR N=1 TO 10 420 LPRINT D(N) 430 NEXT N 440 GOTO 100 This very simple program demonstrates the basic features of much more complex data capture routines, but has one dramatic failing: it is not "bullet proof". If the operator does not stick precisely to the sequence laid down, the program will soon encounter a problem and resort to error messages that will not help a non-programmer. Because of this, the great majority of effort in programming HUNTER applications is devoted to preventing occurrences that might cause confusion. HUNTER'S Basic interpreter contains many features designed to prevent the inexplicable happening in the field; but complex programs can sometimes outwit even their own authors! A simple solution to this problem is simply to add three more lines: :: 50 ONERROR 500 500 PRINT 'THAT CANT BE RIGHT - PLEASE TRY AGAIN" 510 GOTO 100 Now, all the error messages from the interpreter are intercepted and re-directed. The program simply tries again. This is fine, but the problem remains: the errors shouldn't be there in the first place! Data Storage Arrays ------------------- Types of Arrays ~~~~~~~~~~~~~~~ Captured data is generally held in array structures created within HUNTER'S very large memory. There are three types of array: - Simple Variables - Double Precision - Strings **Simple Variables** are used for storage of decimal values of up to 6 digit accuracy. **Double Precision** arrays store numbers up to 14 digit accuracy, but use more memory. .. Note:: Both these types store much larger numbers than indicated, but only by truncating the least significant digits. For example, the number 12345678 entered as a simple variable would be stored and reproduced as 12345600. **String Arrays** store every character, whether numeric or otherwise, literally. They can have any number of characters (up to a maximum of 255 characters in each string). Facilities are provided for converting strings to numbers and vice versa. Array Structures ~~~~~~~~~~~~~~~~ Every array is denoted by a name and placed in memory in a sequential table. Multiple arrays are packed in memory by Basic and accessed via a Symbol Table. Individual array elements are identified by the array name and the element number, together with a character to identify the array type. For instance: .. Note:: Arrays start from element 0 ``A(10)`` is the eleventh element of simple variable array A. ``A!(2)`` is the third element of double precision array A! (quite different and independent from array A in the example above). ``A$(0)`` is the first element in string array A$. ``A$(0)`` is identical with ``A$``, which can be used for shorthand, useful if there are multiple references to a single string in the program. In each case, the number in parentheses is the element number, and can be variable: ``A$(A)`` or an expression: ``A$(A*5)`` or another array element: ``A$(A(6))`` Remember the element numbers start from 0! Creating Arrays ~~~~~~~~~~~~~~~ Arrays can only be created once: if a subsequent attempt is made to re-define an existing array, an error occurs. This is to warn the programmer that he may be accidentally duplicating an array name. If the statement ``DIM A$(1,6)`` is repeated at anytime an error message: :: * DIM Error will appear. This can be easily avoided by incorporating the DIM in a program sequence that is only executed once, and subsequently branched around. This is often called an Initialisation Sequence. A typical format is: :: 10 IF Z<>0 THEN 100 20 DIM A$(l,6) 30 Z=55 The variable Z is a flag, indicating that the program has been run before. (All variables are cleared to 0 by CLEAR or any change to program content, but not by power off or removing batteries). A slightly more sophisticated version is: :: 10 IF Z<>0 THEN 100 20 DIM A$(l,6) 100 Z=Z+1 Where Z acts both as a flag and as a counter of the number of times the program has been run, a very useful statistic! Array Sizes ~~~~~~~~~~~ Arrays are limited in size only by HUNTER'S memory space. Remember that arrays compete with program for space, automatically allocated by HUNTER'S operating system. Array size allocation is simplified by self-sizing. For this purpose, the Function :doc:`../basic-functions/fre` can be used as a variable. FRE provides the number of memory bytes remaining as follows: | After NEW : The total memory available | After program entry : The memory available for data | After array definition : The memory remaining The number FRE can be used to automatically calculate the maximum number of array elements possible for any given array type and to sign on informing the operator of this information. :: 10 IF Z<>0 THEN 100 20 N=2 30 Y=INT (((FRE(0)-7-N*7)/5)-1) 40 DIM A(Y) 100 PRINT 'TOTAL NUMBER OF ELEMENTS AVAILABLE :",Y Note that Y is taken as an integer (INT), that the symbol table entry (-7) is subtracted, that the element size is 5 bytes and that arrays start from zero, so the maximum number is one less (-1). N*7 is an allowance for the number of variables used in the subsequent program, assuming 7 bytes per variable. A string array can be sized as follows: :: 10 IF Z<>0 THEN 100 20 N=2 30 Y=INT (((FRE(0)-7-N*7-256)/15)-1) 40 DIM A$(Y,4) 100 PRINT 'TOTAL NUMBER OF STRINGS AVAILABLE :",Y Accessing Array Elements ~~~~~~~~~~~~~~~~~~~~~~~~ Each element in a data array is accessible by its array index, expressed in parentheses, e.g: :: A$(235) is the 236th element in A$. .. Note:: Array indexes must be within the range declared in the corresponding DIM statement. HUNTER Basic warns the programmer of any attempt to access an element outside the declared range with: \*MAG Error. Be especially careful with incrementing indexes like FOR NEXT loops. Array indexes often have a direct relationship to external variables, like stock codes. It is always preferable to directly access an array in this fashion in the interests of speed, rather than working sequentially through every element. If there are discontinuities (gaps) in the existing codes, or if the numbers are too large, a conversion table or algorithm may be needed. Since a literal table (one entry for every code) is likely to be very inefficient, it is generally worth putting considerable effort into deriving an efficient 'tree' structure for direct array access. Array Searches ~~~~~~~~~~~~~~ There is often a need to search an array for an element of known content. In Basic, this procedure can be painfully slow. One solution to this dilemma is to use a specialised machine-code subroutine to search the array and return with the index of the target element. A much more practical method is the Basic function :doc:`../basic-functions/srch`. Data Input Techniques --------------------- We are all familiar with the computer truism: Garbage in - garbage out This was never more true than in data capture applications where out-of-range entries can cause fatal errors that are just embarrassing in the office, but potentially disastrous in the field. To help avoid the most common form of data entry error, HUNTER provide a unique facility :doc:`../basic-functions/input-using`. Input using pre-filters incoming data against a predetermined mask and rejects entries that do not fit at the keyboard, warning the operator to try again. Equally important to the user is optimum use of HUNTER'S screen to provide clear, unambiguous prompt messages and input fields. Using HUNTER's Screen --------------------- HUNTER's large 40 x 8 character, LCD screen can be used to positive effect to help its operator. Because the screen is entirely flexible, these notes are provided as a source of ideas rather than as instructions. This section refers to character-by-character use, more detailed information on direct dot addressing is available in :doc:`hunter-graphics`. The Virtual Screen ~~~~~~~~~~~~~~~~~~ HUNTER'S 40 X 8 character, LCD screen acts as a window to a much larger virtual screen. When characters are written to the screen from a Basic program they are always written to the virtual screen. The commands available in Basic to move the window are :doc:`../basic-functions/cls`, :doc:`../basic-functions/input` and :doc:`../basic-functions/locate`. :doc:`../basic-functions/cls` Clears the virtual screen and sets the window to the top left of the virtual screen. :doc:`../basic-functions/input` The execution of an 'INPUT' command will move the LCD window to the part of the virtual screen containing the 'INPUT' prompt. :doc:`../basic-functions/locate` The Locate command will re-position the cursor in the virtual screen and will move the window so that the cursor remains visible. Cursor Addressing ~~~~~~~~~~~~~~~~~ The cursor position can be commanded from a Basic program, allowing characters to appear anywhere on the screen. Cursor addressing is relative to the virtual screen, therefore characters may not appear on the LCD screen in text mode. The standard Basic format for cursor addressing is: LOCATE X,Y X and Y are the co-ordinate values expressed in decimal. The Standard Header Page ~~~~~~~~~~~~~~~~~~~~~~~~ All HUNTER programmes generated at HUSKY Computers feature a standard header page. The header page supplies vital information about the program and use of this format is strongly advocated to other users. The appearance of a suitable user header page would be:- :: --------------------------------------------- | 20 Oct 198 11:20:32 | | OPTIONS | | 1 = ENTER DATA | | 2 = REVIEW DATA | | 3 = AMEND DATA | | 4 = TRANSMIT DATA | | | | PLEASE ENTER OPTION NUMBER ? | --------------------------------------------- Dynamic Screens ~~~~~~~~~~~~~~~ A vital ergonomic factor in HUNTER program design is reassurance. Many, perhaps most, HUNTER operators have never worked with any kind of computer before and are likely to have some suspicion about this example of 'advanced technology'. The crucial point is that HUNTER MUST COMMUNICATE WITH THE OPERATOR. If it doesn't he'll soon become frustrated at some situation he doesn't understand and resort to 'traditional' solutions - gently encouraging it with a series of sharp blows or worse! Help Statement -------------- The HELP facility provides a means of breaking into normal programs to display text for operator assistance. After the HELP text has been read control is returned to the main program, as if nothing had happened, by pressing the 'HELP' key again. The Help Vector ~~~~~~~~~~~~~~~ The text displayed by HELP can be linked to the operation currently being performed. The start position of the text set can be under program control. This is achieved by the pair of ram locations ``VECTOR``, indicating the memory address of the start of text. This is controlled by the :doc:`../basic-functions/help` function in Basic. ``VECTOR`` can also be set by :doc:`../basic-functions/poke`. Text Storage ~~~~~~~~~~~~ Help text is stored by means of REM statements, which allow storing of ASCII text within programs. The address in the Help vector points to the start of the line number. The Help program will skip forward over the first four bytes, checking the REM token and then displaying the text. .. Note:: The REM token is stored as 143 Decimal, (8FHex). The following diagram shows how the following line of Basic source code is stored: :: 10 REM ABCDEFGHI #----#-------#----#----------------------------#----# | OE | OA 00 | 8F | 41 42 43 44 45 46 47 48 49 | OD | #----#-------#----#----------------------------#----# LINE LINE ASCII TEXT LENGTH NUMBER TOKEN CR LINE TERMINATOR HELP Text Display ~~~~~~~~~~~~~~~~~ The software which controls HELP will scroll forward through the lines of Basic text, or pseudo-Basic text, until the verb found is not a REM. Scrolling backwards is also allowed until a line is found without a REM. In each case, further scrolling is not allowed. Storing the Current Display ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The contents and cursor position of the screen are not lost while in HELP mode. On exit from HELP mode, the screen and cursor are restored to their states prior to HELP mode entry. HUNTER Action during HELP ~~~~~~~~~~~~~~~~~~~~~~~~~ When a program is interrupted for HELP display all normal action is suspended. Serial data reception will continue up to the capacity of the receive buffer. If handshaking is enabled then it will continue in a transparent fashion. Programs will continue after the HELP key is pressed again. HELP will be entered during any scan of the keyboard, whether for status or waiting for an actual key depression. Graphics Mode ~~~~~~~~~~~~~ Because HUNTER'S graphics screen cannot be re-created from RAM memory, HELP text would destroy the contents of the screen if allowed during graphics mode. For this reason, HELP is inhibited in graphics mode and help key depressions are ignored.