An Introduction to Integral PC Technical BASIC Graphics GVG / 13 October 1986 + IPC Technical BASIC has a large command set; this command set includes many operations for display graphics that allow a user to create sophisticated imagery with little effort. This note describes most of Tech BASIC's commands for display graphics and provides examples for their use. The Integral PC's built-in electroluminescent display has a display resolution of 255 by 512 dots; when any Tech BASIC graphics command is invoked, Tech BASIC brings up a graphics window that covers the entire display (except for the menu keys, if they are left visible). Tech BASIC regards this screen as a plotter that it draws on with an invisible "pen". Tech BASIC describes points on the display with the following coordinate system: (0,100) (200,100) +---------------------------------------------------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | +---------------------------------------------------------+ (0,0) (200,0) BASIC documentation refers to these coordinates as "graphics units", or GUs for short. BASIC can move the pen from GU to GU without drawing a line with the MOVE command, which has the form: MOVE x_coordinate, y_coordinate Alternatively, BASIC can draw from point to point, using the DRAW command, which has the form: DRAW x_coordinate, y_coordinate 2 The program listed below uses the MOVE and DRAW commands to draw a little triangle in the lower-left-hand corner of the display: example_1: 10 ! This program demonstrates "absolute" moves and draws a tringle in 20 ! "graphics" coordinates. 30 ! 40 PEN 1 @ GCLEAR @ LINE TYPE 1 @ SETGU ! Initializations (ignore for now). 50 ! 60 MOVE 0,0 @ DRAW 10,0 @ DRAW 5,10 @ DRAW 0,0 70 ! 80 END Not much to this, except maybe for line 40, which performs some initializations. Except for the GCLEAR command (which wipes the graphics display clean), pay no heed - they will all be explained quickly enough. + Anyone who tries to generate graphics with this limited amount of knowledge will quickly realize that the coordinate system specified by Tech BASIC is not convenient for many purposes. For example, suppose a user wants to plot a function that varies from -1 to +1; the user will then be forced to do a lot of clumsy rescaling of from the values returned by the function to the actual coordinates of the screen ... ... except that BASIC will do all of that for the user! BASIC provides a SCALE command that allows the user to specify his (or her) own coordinates for the display. (BASIC documentation refers to the user-defined coordinates as "user units", or UUs for short.) The SCALE command has the form: SCALE left, right, bottom, top - where each of the four parameters specifies the user coordinate assigned to the given side of the display - left side, right side, bottom, and top. 3 The following example rescales the display and then draws exactly the same figure as the previous example - but in UUs instead the default GUs. (Once a SCALE statement is invoked, MOVE and DRAW act in UUs until they're told otherwise ... more on that later.) example_2: 10 ! This program demonstrates the "scale" command by rescaling the entire 20 ! screen into "user" units - and then plotting the same figure as 30 ! plotted in example 1. (Try changing the four coordinates for fun.) 40 ! 50 PEN 1 @ GCLEAR @ LINE TYPE 1 @ SETGU ! Initializations - ignore them. 60 ! 70 left=0 80 right=20 90 bottom=0 100 top=20 110 ! 120 SCALE left,right,bottom,top ! Perform the mapping. 130 ! 140 MOVE 1,1 @ DRAW 9,1 @ DRAW 5,9 @ DRAW 1,1 ! Draw a triangle. 150 ! 160 END It's fun to switch coordinate values; switching the bottom and top values creates upside-down images, and switching the left and right values creates mirror images. + BASIC graphics are optimized for plotting line graphs and provide special functions to make such plots easy. The AXES command draws a set of coordinate axes on the display. AXES has the syntax: AXES x_spacing, y_spacing, x_origin, y_origin, x_major, y_major, size All the parameters are optional. Before I describe them, however, let me make a subtle point to make the description easier. As I pointed out earlier, BASIC graphics uses two coordinate systems - either default coordinates (GUs) or user-specified coordinates (UUs). Some commands (or parameters associated with commands) ALWAYS use the default GU coordinates; a SCALE command has no effect on them. Other commands use whatever coordinate system is currently in effect, either GUs or UUs; the MOVE and DRAW commands are good examples. BASIC documentation refers to the coordinate system currently in effect as "current units" - which sounds good enough to me. Ahem! To continue ... 4 If no parameters are specified, AXES draws a set of axes through the display's (0,0) coordinate (as specified in current units), without drawing any tick marks on the axes. The first two parameters specify the spacing of tick marks on the coordinate axes (in current units). If no other parameters are specified, the AXES command draws the axes through the (0,0) coordinate, and draws the tick marks with the specified spacing, with each tick 2 GUs in size. The second two parameters specify the coordinates of the origin (in current units). The tick-spacing parameters must be specified if the origin is, but tick marks can be disabled by setting the spacing parameters to zero. The third two parameters allow the user to specify that every second, third, fourth, (et cetera) tick be twice the size of the others. The previous four coordinates must be specified if these two are. If the "size" coordinate is not specified, the major ticks will be 2 GUs in size, and the minor ticks will be 1 GU in size. The size coordinate allows the user to specify the size of the major tick marks (in GUs); the minor tick marks will then be half the size of the major tick marks. The following example uses the AXES command to place a set of axes on the display: example_3: 10 ! This program demonstrates the "axes" statement. Try playing with the 20 ! parameters for fun. Note that the display is remapped from the 30 ! default "graphics" units to "user" units using the "scale" command. 40 ! (Note that all the parameters do NOT have to be specified.) 50 ! 60 PEN 1 @ GCLEAR @ LINE TYPE 1 @ SETGU @ SCALE -100,100,-50,50 70 ! 80 x_tick=5 ! X-tick-mark every 5 user's units. 90 y_tick=10 ! Y-tick-mark every 10 user's units. 100 x_origin=0 ! Origin at (x,y) = (0,20) in user's units. 110 y_origin=20 120 x_big_tick=4 ! Every fourth x-tick-mark is a big tick. 130 y_big_tick=2 ! Every second y-tick-mark is a big tick. 140 size_of_tick=10 ! Big ticks are four graphics units long. 150 ! 160 AXES x_tick,y_tick,x_origin,y_origin,x_big_tick,y_big_tick,size_of_tick 170 ! 180 END 5 + The GRID command is similar to the AXES command, but it allows the user to create a grid on the screen. Its syntax is similar to that of the AXES command: GRID x_spacing, y_spacing, x_origin, y_origin, x_grid, y_grid, size If GRID is executed without parameters, a grid is drawn over the entire display, using the current units for spacing. The first two parameters specify the spacing of grid lines (in current units). The second two parameters specify the coordinates of the origin (in current units). The third two parameters allow the user to specify tick marks between grid lines, with a grid line every second, third, fourth, or so on, tick mark, as specified by the user. The size coordinate allows the user to specify the size of the tick marks (in GUs); if the "size" coordinate is not specified, the ticks will be 2 GUs in size. The following example uses the GRID command to place a grid on the display: example_4: 10 ! This program demonstrates the GRID command; note that all the 20 ! parameters do NOT have to be specified. Note also that the screen is 30 ! remapped from graphics units to user units. 40 ! 50 PEN 1 @ GCLEAR @ LINE TYPE 1 @ SETGU @ SCALE -100,100,-50,50 60 ! 70 x_tick=5 ! Ticks every five user units. 80 y_tick=5 90 x_origin=-40 ! Grid origin at (-40,20). 100 y_origin=20 110 x_big_tick=2 ! Grid lines every two ticks. 120 y_big_tick=2 130 size_of_tick=4 ! Tick marks are four graphic units long. 140 ! 150 GRID x_tick,y_tick,x_origin,y_origin,x_big_tick,y_big_tick,size_of_tick 160 ! 170 END 6 + As I said in the beginning of this note, BASIC draws on the display with an invisible "pen". The user can specify four different types of "ink" for this pen with the PEN command: PEN ink_value The "ink_value" can have four different values: >= 1: plots white dots 0: doesn't plot anything -1: plots black dots -2: exclusive-ORs dots; the pen always writes dots the opposite color they were originally. The PEN command has some peculiar synergisms with the GCLEAR command. If the Integral PC is turned on and NO windows are inverted from the usual black-characters-on-white-background mode, then, when BASIC is invoked, the BASIC window will be also in the black characters-on-white-background mode. In this state, executing the following command sequences will cause the following changes in the graphics window: PEN 1 @ GCLEAR Turns graphics display black. PEN 0 @ GCLEAR No change in graphics display. PEN -1 @ GCLEAR Turns graphics display light. PEN -2 @ GCLEAR Turns graphics display light. This gets strange when the user turns a window to light-characters-on-black- background mode. Depending on the point in the sequence of window creation, the command sequences specified above will either act as specified - or have the opposite results. (Anybody who wants to investigate all the special cases has my blessing, but I have better things to do. However, as far as printer dumps using the DUMP GRAPHICS command are concerned, the table of commands above will give the proper printout polarities - no matter what the display mode is.) Try this program to play with the PEN command: example_5: 10 ! This program demonstrates the various pen types by specifying a pen, 20 ! clearing the screen, drawing a box, specifying another pen (but NOT 30 ! clearing the screen!), and drawing a diagonal crisscross the screen. 40 ! (There are four pen types: -2,-1,0,1. Try them all.) 50 ! 60 PEN 1 @ GCLEAR @ LINE TYPE 1 @ SCALE 0,100,0,50 70 ! 80 PEN -1 @ GCLEAR ! Change pen, clear the screen. 90 MOVE 10,10 @ DRAW 90,10 @ DRAW 90,40 @ DRAW 10,40 @ DRAW 10,10 100 ! 110 PEN -2 ! Change the pen again. 120 DRAW 90,40 @ DRAW 10,10 ! Draw a diagonal. 130 ! 140 END 7 + The graphics pen can draw in eight different line types, as specified by the LINE TYPE command - which has the syntax: LINE TYPE The eight line types are as follows: LINE TYPE 1: solid line (default) LINE TYPE 2: no line ("null" line) LINE TYPE 3: dots LINE TYPE 4: short dashes LINE TYPE 5: long dashes LINE TYPE 6: dash-and-dot LINE TYPE 7: long-dash / short-dash LINE TYPE 8: long-dash / double short-dash The following example illustrates the 8 line types: example_6: 10 ! This program demonstrates the "line type" command by drawing figures 20 ! using the eight different line types. 30 ! 40 PEN 1 @ GCLEAR @ SCALE 0,200,0,100 50 ! 60 MOVE 10,10 70 LINE TYPE 1 @ DRAW 10,90 80 LINE TYPE 2 @ DRAW 90,90 90 LINE TYPE 3 @ DRAW 90,10 100 LINE TYPE 4 @ DRAW 10,10 110 MOVE 110,10 120 LINE TYPE 5 @ DRAW 110,90 130 LINE TYPE 6 @ DRAW 190,90 140 LINE TYPE 7 @ DRAW 190,10 150 LINE TYPE 8 @ DRAW 110,10 160 ! 170 END 8 + So, far all the graphics examples have been drawn using ABSOLUTE grid coordinates. In some cases, however, it is more convenient to draw using RELATIVE (or "incremental") coordinates - through the IMOVE (Incremental MOVE) and IDRAW (Incremental DRAW) commands. These commands have the syntax: IMOVE x_increment, y_increment - and: IDRAW x_increment, y_increment Suppose (X,Y) is a coordinate, specified in current units. Then: IMOVE x_increment, y_increment - moves the pen to the coordinate: (X + x_increment, Y + y_increment). Incremental plotting is useful for drawing the same object at several places on the display - as shown by the example below, which "bricks up" the display by using IMOVE and IDRAW to draw a "brick" over and over again: example_7 ("Amontillado"): 10 ! This program demonstrates the incrmental move and draw commands by 20 ! filling the screen up with "bricks". 30 ! 40 PEN 1 @ GCLEAR @ LINE TYPE 1 @ SCALE 0,100,0,100 50 ! 60 MOVE 0,0 70 FOR rows=1 TO 10 80 FOR columns=1 TO 10 90 IMOVE 1,1 ! Draw a box. 100 IDRAW 8,0 110 IDRAW 0,8 120 IDRAW -8,0 130 IDRAW 0,-8 140 IMOVE 9,-1 ! Move to the right and ... 150 NEXT columns ! ... draw the next box. 160 IMOVE -100,10 ! Move up and back to the left side and ... 170 NEXT rows ! ... draw the next row of boxes. 180 ! 190 END 9 + An interesting feature of incremental plotting is that it allows the reference axes to be rotated though an angle - by using the PDIR (Plot DIRECTION) command, which has the syntax: PDIR angle What this means is simple enough. Suppose a BASIC program has a command like "IDRAW 9,0". Given a scaling that doesn't do something silly like place positive values to the left of the display, this command will draw a straight line to the right. However, if "PDIR 90" is executed, and BASIC is in DEGREES mode, then "IDRAW 9,0" will draw the line straight up. (Note that PDIR works only for incremental plotting. Absolute plotting ignores it.) The following example uses PDIR to draw a "daisy wheel" on the display: example_8: 10 ! This program demonstrates the "pdir" command (which changes the 20 ! drawing angle for incremental moves and draws) by drawing a "daisy 30 ! wheel". (All the program does is draw a triangle with the starting 40 ! vertex at 0,0, then rotates ten degrees, draws the triangle again ... 50 ! and so on through the full circle. 60 ! 70 PEN 1 @ GCLEAR @ DEG @ SCALE -100,100,-50,50 80 ! 90 FOR angle=0 TO 360 STEP 10 100 PDIR angle ! Rotate ten degrees. 110 MOVE 0,0 ! Draw the triangle. 120 IDRAW 40,0 130 IDRAW 0,3 140 IDRAW -40,-3 150 NEXT angle ! Do it again. 160 ! 170 END (Users who are playing with PDIR should be careful to make sure that BASIC is not in RADians mode when they are expressing PDIR in DEGrees, and vice-versa.) + As I said earlier, BASIC graphics are oriented towards plotting functions - and, of course, plots needs labels. Tech BASIC incorporates a number of commands for making labels. The first command is LABEL, which prints a label at the current pen position. The label can be a string or a number, or any combination thereof; image specifiers can be used as well. (Indeed, the syntax of the LABEL command is almost identical to that of the PRINT or DISP commands.) 10 The next command is CSIZE, which specifies the height of the characters in the label (in GUs). The syntax of CSIZE is: CSIZE size, aspect_ration, slant The "size" parameter must be specified; the "aspect_ratio" (which specifies the width/height ratio) and "slant" parameters are optional. The following program demonstrates the LABEL and CSIZE commands: example_9: 10 ! This program illustrates the CSIZE command by showing the results of 20 ! changing the size, aspect ration, and slant of the letter "M". 30 ! 40 PEN 1 @ GCLEAR @ LORG 5 @ DEG @ SCALE 0,9,0,4 50 ! 60 size=1 ! Change sizes. 70 FOR column=1 TO 8 80 MOVE column,3 @ CSIZE size @ LABEL USING "K" ; "M" 90 size=size+5 100 NEXT column 110 ! 120 aspect_ratio=0.1 ! Change aspect ratios. 130 FOR column=1 TO 8 140 MOVE column,2 @ CSIZE 8,aspect_ratio @ LABEL USING "K" ; "M" 150 aspect_ratio=aspect_ratio+0.5 160 NEXT column 170 ! 180 slant=0 ! Change slants 190 FOR column=1 TO 8 200 MOVE column,1 @ CSIZE 8,0.6,slant @ LABEL USING "K" ; "M" 210 slant=slant+10 220 NEXT column 230 ! 240 END Note the LABEL USING "K" command ... the "K" image parameter needs to be specified when using LABEL with a string parameter; the "K" parameter causes all extraneous blanks to be removed from the string. This is one of the peculiar differences between HP-86/87 BASIC and Tech BASIC. HP-86/87 BASIC seems to work fine without using the "K" parameter, while labels will almost invariably end up in the wrong place if the "K" parameter isn't used. For that reason: ALWAYS USE THE "K" PARAMETER WHEN LABELING WITH A STRING IN TECH BASIC! (I suspect the reason is that the internal data structure of the string is different in the two BASICS - but I digress ... ) 11 + Labels can be written in different angles by using the LDIR (Label DIRection) command. This is similar to the PDIR command, but it works only for labels. Its syntax is: LDIR angle The following example demonstrates LDIR: example_10: 10 ! This little program demonstrates the "label direction" command. 20 ! It prints the word "rotation" in a number of different angles. 30 ! 40 PEN 1 @ GCLEAR @ LORG 1 @ DEG @ CSIZE 6 @ SCALE -100,100,-50,50 50 ! 60 FOR angle=0 TO 360 STEP 30 70 MOVE 0,0 80 LDIR angle 90 LABEL USING "K" ; " rotation" 100 NEXT angle 110 ! 120 END (As with the PDIR commands, users should be careful to remember whether they are in RADians or DEGrees mode when they use this command.) + There's a fine point in plotting labels that I glossed over. I said the LABEL command plots a label at the current pen position ... but that begs the question: where is the label situated on the display, relative to the pen coordinate? Above? Below? To the left? To the right? Centered on it? The LORG (Label ORiGin) allows a user to specify the position of the label relative to the pen. LORG has the syntax: LORG label_origin The "label_origin" parameter has values from 1 to 9. Suppose the rectangle shown below outlines a label; the numbers on the rectangle are located at the label origin given by the number: 3 ---------- 6 ---------- 9 | | 2 5 8 | | 1 ---------- 4 ---------- 7 12 The following example shows how LORG works: example_11: 10 ! This program demonstrates the "lorg" (label origin) command by 20 ! putting up a grid and then labeling the vertices of the grid - 30 ! with the point of attachment of the label determined by the 40 ! "lorg" command. 50 ! 60 PEN 1 @ GCLEAR @ CSIZE 8 @ LINE TYPE 1 @ FRAME 70 SCALE 0.75,3.25,0.75,3.25 @ GRID 1,1 80 ! 90 label_origin=1 100 FOR x_coordinate=1 TO 3 110 FOR y_coordinate=1 TO 3 120 MOVE x_coordinate,y_coordinate 130 LORG label_origin @ LABEL USING "K,DD" ; "LORG",label_origin 140 label_origin=label_origin+1 150 NEXT y_coordinate 160 NEXT x_coordinate 170 ! 180 END + Before I leave the subject of labels ... remember that I said LABEL can use IMAGE statements, just like a PRINT or DISP statement? The following example demonstrates this by printing the same number using five different IMAGE specifiers. example_12: 10 ! This program demonstrates the "label using" statement by tacking up 20 ! a number using different IMAGE formats. 30 ! 40 PEN 1 @ GCLEAR @ CSIZE 11 @ LORG 5 50 LOCATE 0,200,0,100 @ SETGU @ SCALE -100,100,-50,50 60 ! 70 number=1095.88376 80 ! 90 MOVE 50,25 @ LABEL USING "6Z" ; number 100 MOVE -50,25 @ LABEL USING "6D.3D" ; number 110 MOVE -50,-25 @ LABEL USING "6*.4D" ; number 120 MOVE 50,-25 @ LABEL USING "DC3D.6D" ; number 130 MOVE 0,0 @ LABEL USING "S5DE" ; number 140 ! 150 END 13 + Another thing that I glossed over earlier was a fine point about the SCALE command. I stated that the SCALE command was used to convert the display window to user-defined coordinates. This is the truth, but not the whole truth - actually, a small chunk of the display window - call it a "windowpane" - can be defined as the user's plotting area using the LOCATE command. Once this windowpane has been set aside, SCALE no longer scales the entire window - it just scales the windowpane. LOCATE has the syntax: LOCATE x_min, x_max, y_min, y_max - where the four coordinates are in default GUs. The following example sets aside a square in the middle of the display as the user's plotting area, scales the square appropriately, and draws a lissajou pattern in the square. example_13: 10 ! This program demonstrates the "locate" command (and the "frame" 20 ! command) by "locating" a user's plotting surface in a square in 30 ! in the center of the display - and plotting a lissajou pattern in 40 ! the square. (The phase and frequency of the sine function on the 50 ! "y" axis relative to the sine function on the "x" axis can be 60 ! adjusted by changing the "phase" and "rel_freq" variables. 70 ! 80 PEN 1 @ GCLEAR @ LINE TYPE 1 @ RAD 90 ! 100 LOCATE 60,140,10,90 @ SCALE -1.1,1.1,-1.1,1.1 @ FRAME 110 ! 120 number_samples=300 130 angle_increment=2*PI/100 140 ! 150 phase=PI/6 160 rel_freq=3 170 ! 180 angle=0 190 MOVE SIN(angle),SIN(rel_freq*angle+phase) 200 ! 210 FOR sample=1 TO number_samples 220 angle=angle+angle_increment 230 DRAW SIN(angle),SIN(rel_freq*angle+phase) 240 NEXT sample 250 ! 260 END Note the use of the FRAME command; this draws a border around the area defined by the LOCATE command. (Note also that once a LOCATE has been put in effect, SCALE commands refer to the windowpane defined by the LOCATE command. To allow the SCALE command to scale the entire graphics display window again, use the command: LOCATE 0,200,0,100.) 14 By the way ... for those who don't know what a lissajou pattern is - it's a plot created by using the value of one sine function as the x-value of a point and the value of another sine function (at the same angle as the first) as the y-value of the point; the resulting pattern can be be interpreted to discover the relative phase and frequencies of the two sine waves. Lissajou patterns were important in the days before sophisticated dual-trace oscilloscopes; a engineer used the lissajou pattern to compare two signals by plugging a reference signal into the x-axis input of a scope, and plugged the signal to be measured into the y-axis input of a scope. The resulting patterns have a sort of hypnotic fascination; lissajou patterns are often seen on scopes in old science-fiction movies and the like. (You learn these things when you get a vocational-school degree ... ) This example allows the user to tweak the relative phase and frequency of the y-axis signal, and it is fun to do so and examine the results. But, back to the subject at hand ... + The AXES command allows the user to plot a set of axes, and the LABEL statement allows the user to plot labels. Since a user often wants to label axes, BASIC provides a command that both plots axes and labels them: LAXES (Label AXES). LAXES has the syntax: LAXES x_spacing, y_spacing, x_origin, y_origin, x_major, y_major, size The parameters are specified in exactly the same way as AXES; the only important detail is that labels are plotted on each major tick. The following example demonstrates the use of LAXES: example_14: 10 PEN 1 @ GCLEAR @ CSIZE 4 @ LOCATE 20,180,20,80 @ SCALE 0,50,0,25 @ FRAME 20 ! 30 x_tick=5 40 y_tick=5 50 x_origin=0 60 y_origin=0 70 x_big_tick=1 80 y_big_tick=1 90 size_of_tick=10 100 ! 110 LAXES x_tick,y_tick,x_origin,y_origin,x_big_tick,y_big_tick,size_of_tick 120 ! 130 END 15 The next example illustrates the use of LAXES in a practical application: plotting a decaying sine wave: example_15: 10 ! This program demonstrates the LAXES command by displaying a damped 20 ! sine wave. (Note that the amplitude, time-constant, and frequency 30 ! can be modified. Note also that, due to a bug, LAXES only works well 40 ! with integer labels.) 50 ! 60 PEN 1 @ GCLEAR @ CSIZE 4 @ FRAME @ RAD @ LOCATE 20,180,20,80 70 ! 80 length_of_scan=10 @ number_samples=200 90 sample_size=length_of_scan/number_samples 100 ! 110 amp=5 @ tc=2 @ freq=1 120 ! 130 SCALE 0,length_of_scan,-amp,amp @ LAXES 1,1 140 ! 150 ctr=0 160 MOVE ctr,amp*EXP((-ctr)/tc)*SIN(2*PI*freq*ctr) 170 ! 180 FOR sample=1 TO number_samples 190 ctr=ctr+sample_size 200 DRAW ctr,amp*EXP((-ctr)/tc)*SIN(2*PI*freq*ctr) 210 NEXT sample 220 ! 230 END As the program notes, LAXES doesn't work worth a damn with fractional labels. This is a clear bug in BASIC, but even if there wasn't a bug, LAXES doesn't allow any way of specifying the format of the labels; other methods have to be used if a specific format is desired. 16 The following program shows how to print fractional labels: example_16: 10 ! This program draws a damped sine wave, like in the previous example 20 ! except that the axis labels are not integers. The actual labeling is 30 ! done with two program loops. Note that the loop that labels the "Y" 40 ! axis has some special provisions for labeling the "0.0" value; this is 50 ! necessary because Tech BASIC uses binary (not BCD!) numbers and the 60 ! computation that was providing the "Y" axis values was providing a 70 ! value for "0.0" that was slightly less than zero. 80 ! 90 PEN 1 @ GCLEAR @ CSIZE 3 @ RAD @ LOCATE 20,180,20,80 @ FRAME 100 ! 110 length_of_scan=1 @ number_samples=200 120 sample_size=length_of_scan/number_samples 130 ! 140 amp=1 @ tc=0.3 @ freq=10 150 ! 160 SCALE 0,length_of_scan,-amp,amp 170 ! 180 number_of_ticks=10 190 x_tick=length_of_scan/number_of_ticks 200 y_tick=amp/(number_of_ticks/2) 210 AXES x_tick,y_tick 220 ! 230 label_value=0 @ LDIR PI/2 @ LORG 8 ! Label the X-axis. 240 Label_X_Axis: 250 MOVE label_value,-amp 260 LABEL USING "DZ.DD,K" ; label_value," " 270 label_value=label_value+x_tick 280 IF label_value<=length_of_scan THEN GOTO Label_X_Axis 290 ! 300 label_value=-amp @ LDIR 0 @ LORG 8 ! Label the Y-axis. 310 Label_Y_Axis: 320 MOVE 0,label_value 330 IF ABS(label_value)