GRAPHICS FOR THE HP 28S Written by Brian Maguire Copyright 1988 All Rights Reserved TABLE OF CONTENTS CHAPTER 1 Introduction.................................4 CHAPTER 2 Input and output Utilities...................8 2.1 Introduction 2.2 Interactive Input 2.3 The Graphic String CHAPTER 3 Basic Drawing...............................10 3.1 Introduction 3.2 Drawing 3.3 Manipulating Graphic Strings 3.4 Working with More Than One String 3.5 Giving Graphic Strings Motion CHAPTER ONE INTRODUCTION The beginning few chapters of this text are to familiarize you with using, creating, and manipulating graphic string. After all, the graphic string allows you to extend graphics past a mere 32 by 137 pixel screen and enables you to store, merge, or distort an image any way you desire. Later, you'll learn techniques that allow you to create shapes, fractals, and journey beyond flat two dimensional drawings into a three and four dimensional world. Before getting started, you should familiarize yourself with the set up of this text. Thumb through the chapters paying special attention to the program descriptions. The have been arranged to allow anyone to simply look at a program and start keying it in. The program input and output, as well as required utilities, have been conveniently listed with the basic program description. Below is an explanation of how each program is set up. Some program may not have all the listed headings. PROGRAM NAME ------------ The name of the program will be printed it bold face type. CHECK NUMBER ------------ A check number has been provided with every program. It is the number in parenthesis just below the program name. This check number is generated by the program 'CKNM'. Each program will have it's own unique check number. The use of 'CKNM' is optional, but highly recommended. 'CKNM' program listing is at the end of this chapter. Even though each program is listed in the same format that the 28S uses in edit mode, mistakes are easily made. Even the best programer can delete a character or accidently swap two letters in a name. With the use of 'CKNM', though, these mistakes can be easily found and corrected even before running the program. SUMMARY ------- The opening few paragraphs are intended to summarize program operation. You'll find a brief explanation, a description on how to use the program, possible errors, how the program operates, and other added goodies. INPUT ----- Any input received by the program such as objects on the stack, values of current variables, or input through the keyboard. Each input will be labeled under one of the following headings. LCD : (liquid crystal display) Any input the program gets from the current display. KEYBOARD : What keys are active during program execution. MEMORY : Memory locations that the program uses. LEVEL # : The object that is required to be on a specified level of the stack. OUTPUT ------ All the program output will be listed under this heading. An example of common program output is an object on the stack. Other possibilities are a value stored in a variable, information sent to the printer, or display output. The output headings are as follows. LCD : (liquid crystal display) A brief description of any display output. MEMORY : Any variables in memory that are changed or created by the program. PRINTER : The type of output, if any, sent to the printer. BEEP : Any audible tones and what they signify. LEVEL # : Objects left on the stack by the program. UTILITIES --------- Any statement that isn't a built in 28S command will be listed here. If it areally isn't in your calculator's memory you can flip through the manual, locate the program, and key it in.. PATH ---- The directory path suggested by the author is listed here. Of course the programs can be put into any directory. This heading only serves as a guideline. Below is a diagram of the author's directory paths. It may be helpful to refer to it when keying in programs. The same diagram can be found in appendix B. HOME | SKETCH STACK DISPLAY ------------- Some programs take their values from the stack and return the final calculation back on the stack. A special spot has been given for these programs. It shows the proper arrangement of the stack both before and after program execution. BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:__BEGINNING_OBJECTS_|1:_____ENDING_OBJECTS_| PROGRAM LISTING --------------- This heading contains the actual program and remarks on it's operation. The program is listed the same way the 28S lists it's programs in edit mode. This makes if mush easier to find, and correct any mistakes that are made when keying in a program. Just compare the listing on your calculator with the one in the book. NOTE: Your program listing may not match the one in the book exactly. This is due to the fact that some characters in the 28S's vocabulary are not accessible through most word processors. For example, The 28S uses character 146 and 147 for program delimiters. These characters Do not exist on normal word processors so the combination of two less than signs or two greater than signs have been used in place of the one desired character. Thus an opening program delimiter will be seen as <<. As a result, characters in adjacent rows may not line up. Still, the basic structure has been maintained. EXAMPLE Examples are provided for some programs. An example might be an input sequence with the result being displayed, or a problem with it's solution. An example might even contain another program with it's entire listing. PROGRAM 'CKNM' (339721) SUMMARY This program is designed to generate a unique number for every program. All the programs in this text will have their check number in parenthesis following the program name. To check wether a program has been keyed in properly, simply put the name of the program on level one of the stack and run 'CKNM'. After a few minutes a number will be returned to level one. Note that the check number for this program is 339721. What 'CKNM' does is change the program listing and the program name into a character string. It then adds them together and generates a number which is the sum of each characters ASCII value times it's position in the string. INPUT LEVEL ONE: The name of the program you're checking. OUTPUT LEVEL ONE: An integer ( The resultant check number). UTILITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:_______________NAME_|1:____________INTEGER_| PROGRAM REMARKS -------- ------- << DUP RCL ->STR SWAP :PUT PROGRAM AND NAME INTO STRING. ->STR + 0 OVER SIZE 1 :START CHECK NUMBER AT ZERO. SWAP FOR i OVER i DUP :GET ASCII OF i-th CHARACTER, SUB NUM i * + :MULTIPLY BY i AND ADD. NEXT SWAP DROP >> CHAPTER TWO INPUT_AND_OUTPUT UTILITIES 2.1 INTRODUCTION The HP 28S owner's manual devotes only one small chapter to explaining interactive input and output techniques. In that chapter you'll find only one example which is of little practical use. Rather than being a useful utility, it serves as an example on how one might develop an interactive program. The first part of this chapter starts where the owner's manual leaves off. It presents two very useful programs that can be easily incorporated into almost any program to create an interactive program. The first program, 'KEYW', will suspend a program until a key is pressed. You may notice that it is similar to the program example on page xxx of the owner's manual, but with a few benefits. It will wait for only 5 minutes, after which it will store the program environment and halt execution. This way you can be assured your calculator won't run indefinitely if left unattended. Secondly, it is very flexible. This means it can be easily used by any calling program with no modification. The second program, 'INPT', uses 'KEYW' as a subprogram to allow the user to input more than just one keystroke. It prompts the user on what type of input is needed and then waits for the input to be entered. It also allows simple editing as well. The remaining part of the chapter introduces the reader to the graphic string. It constructs a base from which the following chapters are built upon. Every image created by the HP 28S is stored in the calculator's memory as a graphic string. If we want to create anything beyond simple graphs we really must learn how this string represents a display image and how it can be manipulated. 2.2 INTERACTIVE INPUT If you enjoy using interactive programs you'll probably find this program invaluable. It waits approximately 5 min. for a key to be pressed. If a key isn't pressed that time, the program is halted. Thus if left unattended the calculators auto off function will turn the power off after an additional 10 minutes . This program accesses the systems clock by using the SYSEVAL command. The binary numbers that is returned by #11CAh SYSEVAL is updated by the systems clock 8192 times every second. What this program does is "read" the systems clock and increment the number "read" by 5 minutes. Then, if a key hasn't been pressed, it reads the systems clock again and compares the new reading with the old one. It continues to do this until a key is pressed, and the control is given back to the calling program, or the new reading is larger than the original incremented reading, and execution is halted. I have two words of caution when using this, and similar programs. You'll notice that, if halted, the program stores the calling programs binary word size and display. This way they can be restore to their original value before returning to the calling program. If the program is stopped by pressing the attention key the word size will not be restored but left at 64. This might be a problem if a latter program requires the original wordsize. Secondly, never execute SYSEVAL with a word size less than 20. The SYSEVAL command jumps to the address specified by the first level of the stack. If you have a wordsize smaller than 20, the binary number on level 1 may be smaller than intended. This will cause unpredictable results and, quite possibly, memory loss. PROGRAM 'KEYW' (1540713) SUMMARY This program suspend program execution until a key is pressed, after which, the string value of the key is returned to level one. If a key isn't pressed after 5 minutes the program is halted so that the calculators auto off function can shut the power off after an additional 10 minutes. Simple press [CONT] to continue a program that has been halted by 'KEYW'. INPUT KEYBOARD: Any key. OUTPUT LEVEL ONE: A string representing the key that was pressed. UTILITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:____________________|1:________KEY_STRING_| PROGRAM REMARKS << RCWS 64 STWS # 11CAh SYSEVAL :READS SYSTEM CLOCK. #258000h + :ADDS 5 MIN. DO IF # 11CAh SYSEVAL OVER > :IF NO KEY PRESSED IN 5 MIN THEN DROP LCD-> -> :THEN SAVE WORDSIZE AND DISPLAY ws st :AND HALT. << HALT CLEAR ws st ->LCD :RESTORE DISPLAY AND PUT ws ON >> #11CAh :STACK. SYSEVAL #258000h + :READ NEW TIME, ADD 5 MIN. AND END :START AGAIN UNTIL KEY END SWAP DROP SWAP :KEY PRESSED SO DROP TIME AND STWS :RESTORE WORDSIZE. >> If you're sure you'll never leave you HP unattended you can substitute the above program for the following, much simpler, program. << DO UNTIL KEY END >> EXAMPLE 2.1 Create a program using 'KEYW' that executes one of five subprograms depending on which number the user presses ([1] [2] [3] [4] [5] ). The program should end if any other key is pressed. SOLUTION: << { PRG1 PRG2 PRG3 PRG4 PRG5 } KEYW DUP NUM IF DUP 53 <_ SWAP 49 >_ AND THEN STR-> GET EVAL ELSE DROP2 END >> Almost every command in the calculator's vocabulary, as well as most user defined programs, require specific object to be placed on the stack before execution. The program then uses these objects in it's calculations and normally places the result back on the stack. This may sound simple enough, but if you've had your calculator for more that a day you've probably discovered it is harder than it seems. If more than two parameters are to be passed on to a program its quite easy to forget what needs to be input and in which order it belongs on the stack. In fact Hewlett Packard foresaw this difficulty and built a catalog of commands right into the 28S ROM. The programs may still seem ambiguous, but the catalog can serve as a reminder on program operation. But what can we do for user created programs? One approach would be to display a message on the screen and halt the program. Unfortunately, any message you display is erased once a key is pressed. This might be the only choice in some instances. In most cases though, I think you'll find the following program more desirable. The following program and it's subprograms will display a prompt message on the top line and accept input without halting execution It also allow you to specify a limit on input length. PROGRAM 'INPT' (3100966) SUMMARY This program displays the prompt string on level one of the stack on the first line of the display and waits for input. The length of input is limited by the number on the second level of the stack. Any single character key that is pressed will be added to the current input string. This resultant string is displayed on the second line. The back key (left arrow) can be pressed at any time. This will delete the last character of the input string. INPUT KEYBOARD : Any single character key will be added to the current input string. Enter ends the program. LEVEL ONE: The prompt string to be displayed on line one LEVEL TWO: An integer specifying the maximum length of input through the keyboard. OUTPUT LCD : The prompt string is displayed on line one while the input string is displayed on line two. LEVEL ONE: A string containing the characters that were input through the keyboard. UTILITIES 'BCK'(procedure) BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: n |2: | |1:______PROMPT_STRING_|1:_______INPUT_STRING_| PROGRAM REMARKS << CLLCD 1 DISP s :DISPLAY PROMPT, s=INPUT SIZE << "" :START WITH EMPTY STRING DO KEYW { "BACK" "ENTER" } :CHECKS TO SEE IF PROPER KEY OVER POS :WAS PRESSED. IF DUP THEN SWAP DROP :IF "BACK" WAS PRESSED {BCK 1 } SWAP GET :THEN RUN 'BCK', ELSE PUT 1 ON EVAL :STACK TO END LOOP ELSE DROP IF OVER SIZE :IF SIZE LIMIT REACHED THEN BEEP s >_ OVER SIZE 1 > OR THEN DROP 1440 .1 BEEP ELSE + :ELSE ADD TO STRING AND DISPLAY, END 0 :RUN THROUGH LOOP AGAIN END OVER 2 DISP UNTIL END >> >> PROGRAM 'BCK' (35021) SUMMARY This program is a subprogram used by 'INPT'. It take the string on level one and truncates the last character. It them puts 0 on the stack to continue the DO WHILE loop in the calling program. INPUT LEVEL ONE: The string that represent the current input from the keyboard. OUTPUT LEVEL TWO: The input string minus the last character LEVEL ONE: 0 to continue the DO WHILE loop in 'INPT'. UTILITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: STRING (SIZE=N-1) | |1:____STRING_(SIZE=N)_|1:__________________0_| PROGRAM REMARKS << DUP SIZE 1 SWAP 1 :TRUNCATE LAST CHARACTER - SUB 0 :FROM STRING >> Suppose you wish a program to prompt the user to input two real numbers and set a limit of 10 characters per number. There are several ways to do this. You might want each number input separately, or you might be just as happy accepting both numbers at the same time. Both forms of input are shown below. EXAMPLE 2.2 Program to accept two real numbers separately << 1 2 START i 10 "INPUT REAL NUMBER" INPT STR-> NEXT >> The program will ask for input twice. After running, the first number should be on level 2 while the second should be on level one. EXAMPLE 2.3 Program to accept two real numbers simultaneously << 21 "INPUT TWO REAL NUMBERS" INPT STR-> >> The numbers in example 2.3 can be separated by either a comma or a space. Both will give the same final results as example 2.2. 2.3 THE GRAPHIC STRING The HP 28S is superior over it's predecessor, the 28C in that it can store dozens of graphic strings. A graphic string is a string that the calculator uses to represent the display screen. Each character in a graphic string represents a column 1 pixel wide and 8 pixels high. The calculator takes each character and converts it into its ASCII. It then converts that number into an eight bit binary number. As a binary number, each bit represents a pixel with the most significant bit being the bottom most pixel. The calculator doesn't actually go through each conversion since a charter is already represented as a binary number in the computers memory. Even though the calculator can store quite a number of graphic strings, the 32K of memory will end up filling quickly if too many graphic strings are stored. Then how can a picture be stored and later recalled without tieing up memory space? With the lack of any other input device, we have no choice but to key in each string by hand. It would be ridiculous to enter 548 numbers, convert them to ASCII, and add them all together. The job is greatly reduced, though, with the help of the following two programs. They both take advantage of character repetition. Even with these programs the chore of entering a large graphic string can still be tedious. The first program, '->GST', takes a list and converts it into a string. Every item is evaluated by the following rule. The integer part specifies the character to be printed and the fraction part, times 1000, indicates the repetition. For example, the list { 68.20 96.20) would be converted into a string containing 20 characters whose ASCII number is 68 and 20 characters whose ASCII number is 96. { .137 255.274 .137 }, when converted into a string and displayed, would show two blank lines separated by two filled lines. PROGRAM '->GST' (1600417) SUMMARY This program will convert the graphic list on level one into a graphic string which can then be displayed. The list can be of any size. INPUT LEVEL ONE: A list representing a graphic string. OUTPUT LEVEL ONE: The resultant graphic string. UTILITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:_______GRAPHIC LIST_|1:_____GRAPHIC STRING_| PROGRAM REMARKS << "" SWAP 1 :START WITH EMPTY STRING. DO GETI :GET NEXT ITEM IN STRING LIST. IF DUP FP :CHECK FOR # OF REPETITION. THEN DUP IP CHR :GETS CHAR. FOR STRING. SWAP FP 1000 * DUP 3 :GETS LOG OF 2^(# OF REPS). ROLLD LN 2 LN / CEIL 1 SWAP START DUP + :DOUBLES STRING EVERY TIME IN LOOP. NEXT 1 ROT SUB :GET STRING TO APPROPRIATE LENGTH. ELSE CHR :GETS CHAR. IF NO REPS SPECIFIED. END 3 ROLLD UNTIL 46 FS? END DROP SIZE 1 :FINDS LEN. OF STRING LIST FOR LOOP. SWAP START + :ADDS ALL STRING CREATING MAIN NEXT :STRING. >> EXAMPLE 2.4 Input the following graphic list. { 0 240 248 252.003 248 240.002 248 252.003 248 240 .124 1 3 7 15 31 63.002 31 15 7 3 1 .397 } Now press [->GST]. You should see a heart in the top left corner of the screen. Graphic lists of more figures are in Appendix A. ______________________ | | | | | | |______________________| The next program, 'GST->' does just what you would expect. It converts a graphic string, into a graphic list. This way, you can print and save the list to be key in later or store it, rather that the string version. This will, in many cases, save a lot of memory. To convert the string simply enter it on level 1 and run the program. Working with large lists can be time consuming, so don't worry if the program runs longer than you would expect. The longer the list, the longer the run time. PROGRAM 'GST->' (3960291) SUMMARY 'GST->' takes the string from level one and returns it's graphic list back on level one. The string must be less than or equal to 548 characters. The graphic list will represent 548 characters regardless of the length of the original string. If it is smaller that 548 it will be padded with characters whose ASCII number is zero. INPUT LEVEL ONE: A graphic string. OUTPUT LEVEL TWO: The resultant graphic list. UTILLITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:_____GRAPHIC_STRING_|1:_______GRAPHIC_LIST_| PROGRAM REMARKS << CLLCD DUP >LCD > gstr :DISPLAY STRING AND STORE. << { } 0 3 FOR y 1 137 :LOOP FOR EACH COLUMN. FOR x 3 gstr y :GET NEXT CHARACTER AND CONVERT 137 * x + 548 SUB :TO ASCII. NUM IF OVER TYPE :IF NOT LIST THEN... 5 =/ THEN IF DUP2 :IF NEW & OLD NUMBER SAME THEN... SWAP IP == THEN DROP .001 + :INCREMENT FRACTION PART BY 1 UNIT. ELSE 3 :OTHERWISE MAKE NEW NUMBER OLD AND ROLLD :CHECK OLD NUMBER. IF DUP FP :IF NO FRACTION PART THEN ADD .001 THEN .001 + END + :ADD TO LIST. SWAP END END NEXT IF DUP FP :TAKE CARE OF LAST CHAR. IN LINE. THEN .001 + END + { } :START NEXT LINE WITH EMPTY LIST. NEXT DROP + + + :ADD ALL FOUR LISTS. CLMF :RESTORE SCREEN. >> >> EXAMPLE 2.5 What is the graphic list for the following display? ______________________ | | | WHAT'S MY LIST? | | | |______________________| We first need to create the display and find the graphic string. The following program will do this for you. << CLLCD " WHAT'S MY LIST?" 2 DISP LCD-> CLMF >> Its easy now that we have the graphic string. Simply press [GST->]. The original screen will be displayed and after a few minutes the list shown below should be on the stack. { .137 127 32 24 32 127 0 127 8.003 127 0 126 9.003 126 0 1.002 127 1.002 .003 7 .003 38 73.003 50 .007 127 2 12 2 127 0 3 4 120 4 3 .007 127 64.004 .002 65 127 65 .002 38 73.003 50 0 1.002 127 1.002 0 2 1 81 9 6 .048 .137 .137 } Of course you would never need a graphic list like the one in this example. It is easier to reproduce the display using the DISP command. CHAPTER THREE SIMPLE SKETCHING TECHNIQUES 3.1 INTRODUCTION There are times when we might want to create a display that can't be created by any graphing procedure. We could use such a display to enhance a program or as a header for output sent to the printer. The following chapter presents a basic drawing program. With it you can create and edit any number of pictures. Included, are several tools to help you manipulate and combine graphic strings that you've created. Finally, the chapter ends on a more whimsical note. It gives an added dimension to your drawing by bringing them to life. Both the program 'MOVE' and 'ACTN' let you move one screen against a background. It will probable have little use other than entertainment. 3.2 SKETCHING We've seen how to input a list of numbers to create a picture, scene, or diagram using the program '->GST', but how do we actually create these drawings. One way would be to pain stakingly plot each point on paper and the manually convert that picture into a series of number to be input as a list. That would be absurd when you already own a powerful graphic calculator that can let you create and edit any graphic string. To use the following draw program, store the graphic string you want to edit in a variable named 'SAVE'. If you want to start with a clean slate you can use the program 'CLR' or do it manually by pressing the alpha key (the bottom left key on the left half) so that the alpha indicator turns on. Then enter in CLLCD LCD> 'SAVE' STO [ENTER]. When using 'DRW' you'll have two function keys and four cursor keys. The first function key is the [SHIFT] key. Pressing this key will toggle between edit mode and move mode. In edit mode, any cursor movement is stored on the screen. Thus continually moving the cursor to the left, while also in draw mode, will draw a straight line. In move mode, the arrow keys move the cursor from it's old position to it's new location with out changing the picture. The second function key is the [ENTER] key. When enter is pressed the subprogram 'ENTR' toggles between draw and erase mode. This can be done while either in edit or move mode, but draw and erase mode are only used while editing. In draw mode, the pixel that the cursor is moved to is turned on and left on while in erase mode the pixel is turned off. You'll find quite a few SYSEVAL addresses used by this program. Again let me caution you to have a wordsize of no less than 20. A wordsize smaller than this might cause the program to jump to the wrong address, possibly causing memory loss. The first SYSEVAL address you'll see is Later, in the subprogram 'SHFT' you'll see two new SYSEVAL addresses. The first, #1F8B4h, turns the shift indicator off. The second address, #1F8A7h, as you might have guessed, turns the shift indicator on. This program exploits the use of these two addresses and uses the shift display, not as a shift indicator, but as an edit indicator. PROGRAM 'DRW' SUMMARY 'DRW' allows you to draw a picture or sketch using the four cursor keys. When in move mode (shift indicator off) the cursor keys move the marker without affecting the picture while in edit mode (shift indicator on) the marker will either draw or erase a dot at it's position, depending of the mode (draw or erase). Pressing [SHIFT] will toggle between move and edit mode while [ENTER] will toggle between draw and erase mode. Be sure that a string containing 548 characters is stored in 'SAVE' before running this program. INPUT KEYBOARD : The cursor keys, ( "UP", "DOWN", "LEFT", "RIGHT" ), move the cursor in that direction. [ENTER] toggles the user between edit and move mode while [SHIFT] toggles between draw and erase mode. OUTPUT LCD : Output is immediately displayed on the screen by either turning a pixel on of off, depending on the mode. The shift indicator will be on during edit mode and off during move mode. Likewise, the angle indicator will be on during draw mode, but off during erase mode. UTILITIES 'SAVE'(graphic string), 'KEYW'(procedure), 'ENTR'(procedure), 'SHFT'(procedure) PROGRAM REMARKS << (-1,-32) PMIN :SET PLOT PARAMETERS. (137,1) PMAX 1 CF :START CURSOR IN MOVE, AND DRAW DEG CLLCD SAVE DUP :MODE, DISPLAY CURRENT GRAPHIC STR. ->LCD (69,-16) DUP :START CURSOR IN CENTER. 'LOC' STO PIXEL :DISPLAY CURSOR DO KEYW { "UP" :WAIT FOR PRESSED KEY AND CHECK "DOWN" "LEFT" :IF IT IS A FUNCTION KEY. "RIGHT" "ENTER" "SHIFT" } SWAP POS IF DUP :IF SO THEN GET INCREMENT AMOUNT THEN { (0,1) :AND/OR RUN SUBPROGRAM. (0,-1) (-1,0) (1,0) ENTR SHFT } SWAP GET :ADD INCREMENT EVAL 'LOC' STO+ LOC IF 1 FS? :IF EDIT MODE THEN... THEN IF 60 FS? :IF ERASE MODE THEN DISPLAY STRING, THEN SWAP :TURN ->LCD DUP C->R NEG PXOFF LCD-> SWAP :PUT STING BACK ON STACK AND PIXEL :DISPLAY CURSOR. ELSE PIXEL :OTHERWISE DRAW, DROP OLD STRING, :AND PUT NEW ONE ON STACK. DROP LCD-> END ELSE OVER ->LCD :(MOVE MODE) DISPLAY CURRENT PIXEL :STRING AND CURSOR POSITION. END 0 :0 ON STACK TO CONTINUE LOOP. ELSE 1 :WRONG KEY PRESSED, STOP LOOP. END UNTIL END DROP 'SAVE' :ALL DONE, STORE STRING. STO >> SUBPROGRAM' ENTR' SUMMARY 'ENTR' is a subprogram used by 'DRW'. It toggles between draw and erase mode by toggling the angle indicator, as well as flag 60. It returns a value of (0,0) for the cursor displacement used by 'DRW' INPUT None OUTPUT LEVEL ONE: (0,0) for no displacement. LCD : The angle indicator is toggled MEMORY : The state of flag 60 is toggled. UTILITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:____________________|1:______________(0,0)_| PROGRAM REMARKS << IF 60 FS?C :TOGGLE FLAG 60 AND PUT (0,0) ON THEN DEG :STACK. ELSE RAD END (0,0) >> PROGRAM 'SHFT' SUMMARY 'SHFT' is a subprogram used by 'DRW'. It toggles between edit and move mode by toggling the shift indicator, as well as flag 1. It returns a value of (0,0) for the cursor displacement used by 'DRW' INPUT None OUTPUT LEVEL ONE: (0,0) for no displacement. LCD : The shift indicator is toggled MEMORY : Flag 1 is toggled. UTILITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:____________________|1:______________(0,0)_| PROGRAM REMARKS << IF 1 FS?C :TOGGLE FLAG 1, TOGGLES SHIFT :INDICATOR, AND PUT (0,0) ON THEN # 1F8B4h :STACK. SYSEVAL ELSE 1 SF # 1F8A7h SYSEVAL END (0,0) >> The program listed below will provide a quick way to create the variable 'SAVE' or simply clear the graphic string you're working on. Be aware that running 'CLR' will erase anything that in 'SAVE' so be sure to save your old graphic string first. you can easily do this using the following commands. [SAVE] 'M1' [STO] This will store the old graphic string in 'M1'. PROGRAM 'CLR' SUMMARY This simple program will store a graphic string containing 548 character zeros into 'SAVE'. In effect, it clears 'SAVE'. INPUT None OUTPUT MEMORY : 'SAVE' UTILITIES 'SAVE'(graphic string) PROGRAM REMARKS << CLLCD LCD-> 'SAVE' :STORE BLANK DISPLAY AND BEEP STO 440 .1 BEEP >> EXAMPLE 3.1 Create a boarder around the screen. SOLUTION First, start with a clean slate and create the variable 'SAVE' by running 'CLR'. Next press [DRW]. All indicators, except for the running program indicator, should be off. If not, then press the appropriate key to turn it off. [SHIFT] toggles the shift indicator while [ENTER] toggles the angle mode indicator. You should see a dot in the middle of the screen. Move it to the edge of the screen and press [SHIFT]. The shift indicator should be on to signify that you are in edit mode. Now just move the dot around the perimeter of the screen. Press any key other than [SHIFT] or [ENTER] when you're finished. If you make a mistake press [ENTER] to switch to erase mode. 3.3 MANIPULATING GRAPHIC STRINGS Now that you can create your own custom displays you might want some tools to manipulate your graphic string. The following program, with it's subprogram 'ROTU1' will rotate any graphic string that is 548 characters long by 180 degrees. If you want to rotate a string that is longer than 548 character you'll have to change to limit of the loop in line two from 548 to the size of your string. Their are 137 characters per line on the display screen so to get the proper string size simply multiply the number of display lines by 137. Of course the easiest approach is to use the built in length function SIZE. All you need to do to use this program is to store the string you want to rotate in a variable names 'SAVE'. The program does the rest. Just sit back and watch as the screen displays the transformed string. The resultant string will be stored back into 'SAVE'. PROGRAM 'Rot' SUMMARY This program takes the graphic string stored in 'SAVE', displays it, and rotates the image by 180 degrees. The rotated string is stored back into 'SAVE'. INPUT MEMORY : 'SAVE' OUTPUT MEMORY : 'SAVE' UTILITIES 'SAVE'(graphic string), ROTU1(procedure) PROGRAM REMARKS << RCWS 8 STWS SAVE :SET WORDSIZE TO 8. DUP ->LCD "" 548 1 :START WITH EMPTY STRING. FOR i OVER i i SUB :GET APPROPRIATE CHARACTER. ROTU1 + DUP ->LCD -1 :FIND ROTATED CHARACTER AND ADD. STEP 'SAVE' STO :STORE GRAPHIC STRING AND RESTORE DROP STWS :WORDSIZE. >> PROGRAM 'ROTU1' SUMMARY This subprogram converts the character from level one into a binary number. It then "rotates" it and converts it back into a character, which is return back to level one. INPUT LEVEL ONE: A single character string. OUTPUT LEVEL ONE: The rotated string is return back. UTILITIES None BEFORE AFTER _____________________________________________ |4: |4: | |3: |3: | |2: |2: | |1:__________CHARACTER_|1:__________CHARACTER_| PROGRAM REMARKS << NUM R->B # 0h SWAP :CONVERT ASCII TO BINARY AND START 1 8 :WITH EMPTY BINARY NUMBER. START DUP # 1h AND :IF RIGHT BIT 1 THEN ADD TO NEW ROT + RR SWAP RL :BINARY NUMBER AND SHIFT LEFT,AND NEXT DROP RR B->R :SHIFT OLD NUMBER RIGHT. CHR :CONVERT TO BASE 10 AND GET ASCII. >> Their are times when you might need a mirror image of the graphic string you've created. The following is a simple program that does just that. It takes each line and stores it backwards. The run time of this program is much quicker than 'rot' since takes only 548 loops while 'rot' executes 548*8=4384 loops. Again, like 'rot', 'FLIP' takes the string in 'SAVE', flips it, and stores the transformed string back into 'SAVE'. PROGRAM 'FLIP' SUMMARY This program is similar to 'Rot'. It displays the image stored in 'SAVE', inverts it, and stores it back into 'SAVE'. INPUT MEMORY : 'SAVE' OUTPUT MEMORY : 'SAVE' UTILITIES 'SAVE'(graphic string) PROGRAM REMARKS << SAVE DUP ->LCD "" 0 :DISPLAY ORIGINAL STRING AND START 3 :WITH EMPTY FLIP STRING. FOR j 137 1 :ROW LOOP. FOR i OVER i j :COLUMN LOOP. 137 * + DUP SUB + :GET CHARACTER AND ADD TO NEW STRING DUP ->LCD -1 :DISPLAY CURRENT FLIP STRING. STEP NEXT 'SAVE' STO DROP >> 3.4 WORKING WITH MORE THAN ONE GRAPHIC STRING Lets say you've created more than one graphic strings and now you want to use a combination of several strings. Luckily, the HP 28S allows the AND, OR, NOT, and XOR operators to be used on strings. These commands perform the specified operation on all 4384 pixels of the display screen. You should note, though, that when using AND, OR or XOR both strings must be of the same length. To combine two strings put them both strings on the stack and perform an OR operation. Since we will need to use this procedure quite often, it has been put into a program named 'Comb.'. It takes the string stored in 'BKRD', for background, and combines it with 'SAVE'. The resultant string is stored back into 'BKRD'. Thus by putting different strings into 'SAVE' and repeatedly executing 'Comb.', you can create an entire scene using individual graphic strings. If this name looks familiar its because the 28S has a built in command in it's STAT menu called 'COMB'. Since this is a reserved word, we are not allowed to use it as our own program name. Instead, we can spell part of the word using lower case letters thus distinguishing between the two names. The lower case version will be displayed on the menu label exactly the save way as the upper case version. PROGRAM 'Comb' SUMMARY This program takes the graphic string in 'SAVE' and 'BKRD' and combines them by performing an OR operation. The resultant string is stored back into 'BKRD' while 'SAVE' is left unaffected. INPUT MEMORY : 'SAVE', 'BKRD' OUTPUT MEMORY : 'SAVE', 'BKRD' UTILITIES 'SAVE'(graphic string), 'BKRD'(graphic string) PROGRAM REMARKS << BKRD SAVE OR :PUT BOTH STRINGS ON STACK, 'BKRD' STO :COMBINE, AND PUT BACK IN 'BKRD'. >> 3.5 GIVING GRAPHIC STRINGS MOTION At first glance, you might see little need to move a picture across the screen. But what would you do if two displays you were trying to combine didn't line up properly? With the program below, you can move the display stored in 'SAVE' against a stationary background stored in 'BKRD'. When everything is where you want it, exit the program by pressing [ENTER] and combine the two strings using 'COMB.'. The program will return a error if 'BKRD' doesn't exist or is not 548 characters long. If you just want to relocate the image in 'SAVE' and aren't concerned about the background you can store a blank background by either of two ways. You can do it manually by pressing the alpha key and entering CLLCD LCD-> 'BKRD' STO [ENTER]. A second approach would be to clear 'SAVE' by running 'CLR' and then storing SAVE into 'BKRD' by entering [SAVE] 'BKRD' [STO]. Both do the same thing, but be careful when using the second approach. 'CLR' will clear anything already stored in 'SAVE'. PROGRAM 'MOVE' INPUT KEYBOARD : The cursor keys. OUTPUT LCD : The images on the screen are moved this respect to one another. UTILITIES: 'SAVE'(graphic string), 'BKRD'(graphic string) PROGRAM REMARKS << 3 CF BKRD SAVE OR :DISPLAY THE CURRENT STRINGS IN ->LCD :'SAVE' AND 'BKRD'. DO KEYW { "UP" "DOWN" :WAIT FOR KEY AND CHECK. "LEFT" "RIGHT" "ENTER" } SWAP POS IF DUP :IF RIGHT KEY THEN GET THEN { 138 412 3 :DISPLACEMENT. 545 << 3 SF 0 :IF [ENTER] THE SET FLAG 3. >> } SWAP GET EVAL SAVE DUP ROT :MOVE 'SAVE' AND STORE NEW 548 SUB SWAP + 1 548 :STRING SUB DUP 'SAVE' STO BKRD OR ->LCD ELSE DROP :IF WRONG KEY THEN DROP. END UNTIL 3 FS? :CONTINUE UNTIL FLAG 3 IS END :SET BY PRESSING [ENTER]. >> EXAMPLE 3.2 Using the two programs above, create a display containing 3 hearts. SOLUTION Take the graphic string of a heart we created in example 2.4 and store it in 'SAVE'. Make sure it is 548 characters long. One way to do this is to create a string filled with character zeros and add it the our string. The following commands will do just that. First put the graphic string of the heart on level one of the stack. Now enter the following. { .548 } [->GST] + 1 548 [SUB] 'SAVE' [STO] Now put SAVE on the stack and store it in 'BKRD' as follows. [SAVE] 'BKRD' [STO] With the proper strings stored in 'SAVE' and 'BKRD' we are ready to create. Run 'MOVE' and position the heart stored in 'SAVE' just to the left of the one stored in 'BKRD'. Now exit 'MOVE' by pressing [ENTER]. Now all we need to do to combine these two strings is press [Comb]. The new string is now stored in 'BKRD'. Adding the third heart follow from here. This last program has no practical use, but you may find it very entertaining. It works somewhat like 'MOVE', but doesn't require input from the keyboard. It takes the displacement amount from 'PNTR'. To set 'PNTR' to the desired amount use the program 'DIR'. 'DIR' will ask for the y direction and the x direction. When inputting the x direction, input a value of -1, 0, or 1 to specify left, no x displacement, or right respectively. The y direction must be either -1 for down, 0 for no displacement, or 1 for up. Then you'll be asked a speed. the larger the number, the faster the speed. In the program, the speed is multiplied by the displacement. Thus a speed of 2 will cause the image to jump twice as far as a speed of 1. Try keeping the speed low though, to create smoother motion. PROGRAM 'ACTN' SUMMARY 'ACTN' is almost like 'MOVE' except this time the displacement is input from variable named 'PNTR', rather than the cursor keys. You must first run 'DIR', the program that follows to create and store 'PNTR'. After this is done, 'ACTN' will continue to move 'SAVE' against the background ('BKRD') until any key is pressed. INPUT KEYBOARD : Any key MEMORY : 'SAVE', 'PNTR' OUTPUT LCD : The images on the screen are moved with respect to one another. UTILITIES 'BKRD'(graphic list), 'SAVE'(graphic list), 'PNTR'(integer) PROGRAM REMARKS << DO SAVE PNTR 548 :MOVE IMAGE. SUB SAVE + 548 SUB DUP 'SAVE' STO BKRD :COMBINE WITH 'BKRD. OR ->LCD :DISPLAY. UNTIL KEY :CONTINUE UNTIL A KEY IS PRESSED. END DROP >>