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
>>
