10!  OUTPUT 2 USING "#,K";"<lf>REN<cr>INDENT<cr><lf>RE-STORE ""PLOT""<cr>"
20    !
30 !  EDIT Test_prog
40 !  EDIT Plot_plot
50 !  EDIT Plot_good_csize
60 !  EDIT Plot_set_viewp
70 !  EDIT Plot_do_axes
80 !  EDIT Plot_do_data
90 !  EDIT Plot_grid
100!  EDIT Plot_x_pixel
110!  EDIT Plot_y_pixel
120!  EDIT Plot_background
130!  EDIT Plot_do_mkr
140!  EDIT Plot_move_mkr
150!  EDIT Plot_have_color
160!  EDIT Plot_set_color
170!  EDIT Plot_eng_format
180!  EDIT Plot_bold_label
190!  EDIT Plot_make_x
200!  EDIT Plot_make_y
210!
220   !
230 Plot_doc: ! 19-Jun-86
240 ! ******************************************************************
250 !               PLOT (Plot_) MODULE DESCRIPTION
260 ! Subprograms in the PLOT file are called by DISP subprograms
270 ! to do graphics.  PLOT subprograms interface between the DISP subprograms
280 ! and the graphics commands, and hide some of the hardware dependencies.
290 !
300 !------------------------------------------------------------------
310 !
320 ! ******************************************************************
330 Test_prog:  !---------------------------------------------------------
340  ! LOADSUB ALL FROM "USER"
350  !
360   !  <PLACE TEST CODE HERE>
370   CALL Plot_plot
380   CSIZE FNPlot_good_csize
390   DISP "filling data_buffer"
400   Rl=1024
410   Num_bins=Rl
420   ALLOCATE Data_buffer(1:20,0:Rl-1),Data_header(1:20,1:10)
430   DIM Plot_array(0:4095,1:2)
440   FOR B=1 TO 4
450     Data_header(B,1)=0    !offset
460     Data_header(B,2)=1    !scale factor
470     Data_header(B,3)=1    !overload
480     Data_header(B,4)=2     !log
490     Data_header(B,5)=100   !log of zero
500     Data_header(B,6)=100  !average
510   NEXT B
520   FOR I=0 TO Rl-5
530     Data_buffer(1,I)=.0011+I/Rl
540     FOR B=2 TO 4
550       Data_buffer(B,I)=Data_buffer(1,I)
560     NEXT B
570   NEXT I
580   DISP "PLOTTING"
590   !
600   Plot_title$="title"
610   X_units$="Sec"
620   Y_units$="dBpC"
630   X_min=128
640   X_max=51200
650   Y_min=.001
660   Y_max=1
670   Start_bin=0
680   Do_log_x=0
690   Do_log_y=1
700   FOR Num_plots=1 TO 14 STEP 2
710     GCLEAR
720     CLIP ON
730     FOR Plot_num=1 TO 1
740       DISP "num_plots, plot_num ";Num_plots,Plot_num
750       !
760       CALL Plot_set_viewp(Num_plots,(Plot_num),X_label_length,5,0)
770       CALL Plot_do_axes(Plot_title$,X_units$,Y_units$,X_min,X_max,Y_min,Y_max,X_label_length)
780       CALL Plot_set_viewp(Num_plots,(Plot_num),X_label_length,5,1)
790       Average=Data_header(Plot_num,6)
800       Overload=Data_header(Plot_num,3)
810       REDIM Plot_array(Start_bin:Start_bin+Num_bins-1,1:2)
820       CALL Plot_make_y(Data_buffer(*),Data_header(*),Plot_array(*),Plot_num,Start_bin,Start_bin+Num_bins-1,Do_log_y,Offset,Scale_factor)
830       CALL Plot_make_x(Plot_array(*),Do_log_x,X_min,X_max)
840       CALL Plot_background
850       CALL Plot_grid(X_min,X_max,Y_min,Y_max,Do_log_x,Do_log_y)
860       CALL Plot_do_data(Plot_array(*),Overload,"HI",Y_min,Y_max,Offset,Scale_factor,Do_log_y)
870       IF 1 THEN 
880         REPEAT
890           CALL Plot_do_mkr(Plot_array(*),X_units$,Y_units$,X_min,X_max,Y_min,Y_max,Offset,Scale_factor,Do_log_y)
900           CALL Plot_move_mkr(Plot_array(*),X_units$,X_min,X_max)
910         UNTIL 0
920       END IF
930     NEXT Plot_num
940     PAUSE
950     WAIT .5
960   NEXT Num_plots
970   END
980   ! PAGE -> 
990   !************************************************************************
1000 Plot_plot:SUB Plot_plot
1010  !This subprogram declares and initializes common blocks used by subprograms in the PLOT file.
1020  !Plot_ common variables are used only by other Plot_ subprograms.
1030  !The graphics display is initialized and all pen colors are defined.
1040  !------------------------------------------------------------------------
1050    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
1060    COM /Plot_viewp/ Left,Right,Top,Bottom      !last viewport command
1070    COM /Plot_mkr/ INTEGER Mkr_bin
1080    Mkr_bin=-1
1090    INTEGER A(0:5)
1100    GINIT
1110    ON ERROR GOTO No_color
1120    PLOTTER IS CRT,"INTERNAL";COLOR MAP
1130    Have_color=1
1140    Use_color=1
1150    OFF ERROR 
1160    !set up color map so compliment shows up
1170    GESCAPE CRT,1;A(*)
1180    Num_colors=A(0)
1190    !
1200    !All colors are defined here.  In order for the marker
1210    !cursor to be visible, the compliment of the pen number must
1220    !be a pen number whose color is visible.  White seems to work
1230    !for most.
1240    SET PEN 1 INTENSITY 1,1,1               !labels etc
1250    SET PEN Num_colors-1-1 INTENSITY 0,0,0  !compliment of 1 for marker locator
1260    SET PEN 2 INTENSITY 1,0,0               !red
1270    SET PEN 5 INTENSITY 0,1,1               !cyan for traces
1280    SET PEN Num_colors-5-1 INTENSITY 1,1,1  !compliment of 5
1290    SET PEN 6 INTENSITY 1,.4,.2             !brick red grid
1300    SET PEN Num_colors-6-1 INTENSITY 1,1,1  !compliment of 6
1310    SET PEN 7 INTENSITY .3,.3,.3            ! for background
1320    SET PEN Num_colors-7-1 INTENSITY 1,1,1  !compliment of 7
1330    !
1340    IF POS(SYSTEM$("CRT ID"),"CGB") THEN   !bit mapped
1350      CONTROL CRT,15;1       !white disp
1360      CONTROL CRT,16;5       !cyan softkeys
1370    ELSE
1380      CONTROL CRT,15;136     !white disp
1390      CONTROL CRT,16;140     !cyan softkeys
1400    END IF
1410    GOTO Get_config
1420 No_color:OFF ERROR 
1430    PLOTTER IS CRT,"INTERNAL"
1440    Have_color=0
1450    Use_color=0
1460 Get_config:!
1470    GESCAPE CRT,3;A(*)       !gets CRT pixel size in A(*)
1480    X_pixels=A(2)
1490    Y_pixels=A(3)
1500  SUBEND
1510  !************************************************************************
1520 Plot_good_csize:DEF FNPlot_good_csize
1530  !This function returns minimum CSIZE for no character distortion.
1540    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
1550    RETURN 100*15/Y_pixels   !15 pix/char.cell,  Y pix, 100 gdus
1560  FNEND
1570  ! PAGE -> 
1580  !************************************************************************
1590 Plot_set_viewp:SUB Plot_set_viewp(Num_plots,Plot_num,X_label_length,Y_label_length,Pixels_in)
1600  !This subprogram is called prior to plotting to setup viewport for next
1610  !plot.
1620  !INPUTS:  Num_plots:  1..16   Total number of plots to be done.
1630  !         Plot_num:   1..Num_plots  Current plot number
1640  !         Y_label_length 1..12  Number of characters to leave room for
1650  !                     at the left of the viewport
1660  !         Pixels_in:  The number of pixels to shrink the viewport by.
1670  !                     Used to avoid drawing on the frame.
1680  !OUTPUTS: X_label_length  Number of characters that there is room for
1690  !                     in the title and along the x axis
1700  !------------------------------------------------------------------------
1710    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
1720    COM /Plot_viewp/ Left,Right,Top,Bottom
1730    Num_plots=MAX(1,MIN(16,Num_plots))
1740    Plot_num=MAX(1,MIN(Num_plots,Plot_num))
1750    Y_label_length=MAX(0,MIN(12,Y_label_length))
1760    STATUS CRT,13;Crt_height
1770    Y_offset=100*(6.5/Crt_height)  !start plots above DISP line (line 6)
1780    Y_offset=MIN(Y_offset,24)      !
1790    Y_plots=PROUND(SQR(Num_plots)+.49999,0)
1800    X_plots=INT(Num_plots/Y_plots+.9999)
1810    X=(Plot_num-1) MOD X_plots
1820    Y=(Plot_num-1) DIV X_plots
1830    Y=Y_plots-Y-1      !to plot top first
1840    X_size=100*RATIO/X_plots
1850    Y_size=(100-Y_offset)/Y_plots
1860    Left=X*X_size+Y_label_length*.6*FNPlot_good_csize
1870    IF Plot_num<>Num_plots THEN  !not last plot
1880      Right=(X+1)*X_size
1890    ELSE  !force last plot to use remainder of screen
1900      Right=X_plots*X_size
1910    END IF
1920    Bottom=Y_offset+Y*Y_size+FNPlot_good_csize     !+ 1 char
1930    Top=Y_offset+(Y+1)*Y_size-FNPlot_good_csize
1940    IF Pixels_in<>0 THEN 
1950      Left=Left+Pixels_in*100*RATIO/X_pixels
1960      Right=Right-Pixels_in*100*RATIO/X_pixels
1970      Bottom=Bottom+Pixels_in*100/Y_pixels
1980      Top=Top-Pixels_in*100/Y_pixels
1990    END IF
2000    VIEWPORT Left,Right,Bottom,Top
2010    X_label_length=INT((Right-Left)/(.6*FNPlot_good_csize)+.1)
2020  SUBEND
2030  ! PAGE -> 
2040  !************************************************************************
2050 Plot_do_axes:SUB Plot_do_axes(Plot_title$,X_units$,Y_units$,X_min,X_max,Y_min,Y_max,X_label_length)
2060  !This subprogram labels the axis of one plot.
2070  !INPUTS:  Plot_title$, X_units$, Y_units$:  strings
2080  !         X_min,X_max,Y_min,Y_max:  plot boundaries in real-world units.
2090  !         X_label_length: The number of characters that will fit along
2100  !                     the X axis.
2110  !------------------------------------------------------------------------
2120    DIM Min$[18],Max$[18],Prefix$[1]
2130    Left=1
2140    Right=2
2150    Bottom=3
2160    Top=4
2170    GRAPHICS ON
2180    PEN 1
2190    LINE TYPE 1
2200    WINDOW Left,Right,Bottom,Top
2210    FRAME
2220    CLIP OFF
2230    LDIR 0
2240    GOSUB Plot_title
2250    IF X_units$<>"" THEN GOSUB Plot_x
2260    IF Y_units$<>"" THEN GOSUB Plot_y
2270    SUBEXIT
2280 Plot_title:  !------------------------------------------------------
2290    LORG 1
2300    MOVE Left,Top
2310    IF LEN(Plot_title$)>X_label_length THEN 
2320      LABEL Plot_title$[1,X_label_length]
2330    ELSE
2340      LABEL Plot_title$
2350    END IF
2360    RETURN 
2370 Plot_x:     !--------------------------------------------------------
2380    IF (X_min=0) OR (X_max=0) THEN 
2390      Digits=3
2400    ELSE
2410      Digits=LGT(ABS(X_min/(X_max-X_min)))+1   !min num of sig digits
2420      Digits=MAX(3,MIN(7,Digits))
2430    END IF
2440    CALL Plot_eng_format(X_min,X_max,Min$,Max$,Digits,Prefix$)
2450    Length=X_label_length
2460    IF Min$<>"0" THEN Min$=Min$&Prefix$
2470    IF Max$<>"0" THEN Max$=Max$&Prefix$
2480    !start labeling, keeping track of how much room is left
2490    IF Length>=LEN(Min$) THEN   !if there is room for left label
2500      LORG 3
2510      MOVE Left,Bottom
2520      LABEL Min$
2530      Length=Length-LEN(Min$)
2540    END IF
2550    IF Length>LEN(Max$) THEN 
2560      LORG 9
2570      MOVE Right,Bottom
2580      LABEL Max$
2590      Length=Length-LEN(Max$)
2600    END IF
2610    IF (X_label_length-2*MAX(LEN(Min$),LEN(Max$)))>LEN(X_units$) THEN           !if room in center
2620      LORG 6
2630      MOVE (Left+Right)/2,Bottom
2640      LABEL X_units$
2650    END IF
2660    RETURN 
2670 Plot_y:     !--------------------------------------------------------
2680    CALL Plot_eng_format(Y_min,Y_max,Min$,Max$,3,Prefix$)
2690    IF Min$<>"0" THEN Min$=Min$&Prefix$
2700    IF Max$<>"0" THEN Max$=Max$&Prefix$
2710    LORG 7
2720    MOVE Left,Bottom
2730    IF Min$<>Max$ THEN LABEL Min$
2740    LORG 9
2750    MOVE Left,Top
2760    LABEL Max$
2770    LORG 8
2780    MOVE Left,(Top+Bottom)/2
2790    LABEL Y_units$
2800    RETURN 
2810  SUBEND
2820  ! PAGE -> 
2830  !************************************************************************
2840 Plot_do_data:SUB Plot_do_data(Plot_array(*),Overload,Message$,Y_min,Y_max,Offset,Scale_factor,Do_log_y)
2850  !This subprogram draws the data for one plot.  To save time, the data can
2860  !be "scaled" by Offset and Scale_factor using the WINDOW command.
2870  !INPUTS:  Plot_array(*):  Array of XY pairs ready for a PLOT command.
2880  !                     Plot_array(*,1) = X = bin numbers.  Plot_array(*,2)
2890  !                     = Y = un-scaled Y data.
2900  !         Overload, Message$:  Used to annotate the plot.
2910  !         Y_min,Y_max: Plot boundary values in real world units.
2920  !         Offset, Scale_factor: scaling for Y values.
2930  !         Do_log_y:  Flag, non-zero if y axis is logarithmic.
2940  !-----------------------------------------------------------------------
2950    INTEGER Start_bin,Stop_bin
2960    GRAPHICS ON
2970    LINE TYPE 1
2980    CLIP ON
2990    Start_bin=BASE(Plot_array,1)
3000    Stop_bin=BASE(Plot_array,1)+SIZE(Plot_array,1)-1
3010    IF Scale_factor=0 THEN 
3020      CALL User_error("ERROR: Data_header scale factor is zero. (Plot_do_data)")
3030      Scale_factor=1
3040    END IF
3050    WINDOW 0,1,0,1
3060    LORG 9
3070    MOVE 1,1
3080    PEN 1
3090    IF Message$<>"" THEN LABEL Message$&" "
3100    IF Overload THEN 
3110      IF FNPlot_use_color THEN PEN 3
3120      LABEL "OVLD "
3130    END IF
3140    IF FNPlot_use_color THEN PEN 5
3150    MOVE 0,0   !to avoid error 19 if next window is 1E-7 (BASIC bug?)
3160    !note that the window is used to scale the data
3170    IF Do_log_y THEN 
3180      WINDOW Start_bin,Stop_bin,LGT(Y_min)*Scale_factor+Offset,LGT(Y_max)*Scale_factor+Offset
3190    ELSE
3200      WINDOW Start_bin,Stop_bin,Y_min*Scale_factor+Offset,Y_max*Scale_factor+Offset
3210    END IF
3220    ON ERROR GOTO Plot_error
3230    MOVE Plot_array(Start_bin,1),Plot_array(Start_bin,2)
3240    PLOT Plot_array(*)
3250    MOVE 0,0
3260 Plot_error:OFF ERROR 
3270  SUBEND
3280  ! PAGE -> 
3290  !************************************************************************
3300 Plot_grid:SUB Plot_grid(X_min,X_max,Y_min,Y_max,Do_log_x,Do_log_y)
3310  !This subprogram draws linear or log grids.  If linear, puts up between 4
3320  !and 10 grid lines spaced at 1, 2, or 5 units.  If log, puts up solid
3330  !lines at 1  and 1 dotted line at 5 or 4 dotted lines at 2, 4, 6, 8.
3340    IF FNPlot_use_color THEN PEN 6
3350    CLIP ON
3360    X_pwr=PROUND(LGT(X_max-X_min)-.51,0)
3370    Y_pwr=PROUND(LGT(Y_max-Y_min)-.51,0)
3380    X_tic=10^X_pwr     !gives 1 to 10 tics every 1 or 10 or 100 ...
3390    Y_tic=10^Y_pwr
3400    SELECT (X_max-X_min)/X_tic  !number of tics
3410    CASE 2 TO 3.9
3420      X_tic=X_tic/2  !tic spacing of 5
3430    CASE <2
3440      X_tic=X_tic/5  !tic spacing of 2
3450    END SELECT
3460    SELECT (Y_max-Y_min)/Y_tic  !number of tics
3470    CASE 2 TO 3.9
3480      Y_tic=Y_tic/2  !tic spacing of 5
3490    CASE <2
3500      Y_tic=Y_tic/5  !tic spacing of 2
3510    END SELECT
3520    IF NOT (Do_log_x OR Do_log_y) THEN !linear, linear
3530      WINDOW X_min,X_max,Y_min,Y_max
3540      LINE TYPE 4
3550      GRID X_tic,Y_tic,PROUND(X_min,X_pwr),PROUND(Y_min,Y_pwr)
3560    ELSE   !at least one is log
3570      IF Do_log_x THEN 
3580        WINDOW LGT(X_min),LGT(X_max),0,1
3590        LINE TYPE 1
3600        GRID 1,3,LGT(1),-1         !X grid at 1, no Y
3610        LINE TYPE 4
3620        IF 1/(FNPlot_x_pixel*LGT(X_max/X_min))>40 THEN  !if enought pixels/decade
3630          GRID 1,3,LGT(2),-1
3640          GRID 1,3,LGT(4),-1
3650          GRID 1,3,LGT(6),-1
3660          GRID 1,3,LGT(8),-1
3670        ELSE  !not enough pixels/decade
3680          GRID 1,3,LGT(5),-1
3690        END IF
3700      ELSE
3710        WINDOW X_min,X_max,0,1
3720        LINE TYPE 4
3730        GRID X_tic,3,PROUND(X_min,X_pwr),-1
3740      END IF
3750      IF Do_log_y THEN 
3760        WINDOW 0,1,LGT(Y_min),LGT(Y_max)
3770        LINE TYPE 1
3780        GRID 3,1,-1,LGT(1)         !y grid at 1, no x
3790        LINE TYPE 4
3800        IF 1/(FNPlot_y_pixel*LGT(Y_max/Y_min))>40 THEN  !if enought pixels/decade
3810          GRID 3,1,-1,LGT(2)
3820          GRID 3,1,-1,LGT(4)
3830          GRID 3,1,-1,LGT(6)
3840          GRID 3,1,-1,LGT(8)
3850        ELSE  !not enough pixels/decade
3860          GRID 3,1,-1,LGT(5)
3870        END IF
3880      ELSE
3890        WINDOW 0,1,Y_min,Y_max
3900        LINE TYPE 4
3910        GRID 3,Y_tic,-1,PROUND(Y_min,Y_pwr)
3920      END IF
3930    END IF
3940    LINE TYPE 1
3950  SUBEND
3960  !*****************************************************************
3970 Plot_x_pixel:DEF FNPlot_x_pixel
3980  !This function returns the horizontal size of one pixel as a ratio of the
3990  !current window size.   1/FNPlot_x_pixel is the number of X pixels in
4000  !the current viewport.
4010    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
4020    COM /Plot_viewp/ Left,Right,Top,Bottom !last viewport command
4030    IF Left+Right=0 THEN CALL User_stop("PROGRAM ERROR: Plot_set_veiwp not called before FNPlot_x_pixel")
4040    RETURN 1/(X_pixels*.01*(Right-Left)/RATIO)
4050  FNEND
4060  !*****************************************************************
4070 Plot_y_pixel:DEF FNPlot_y_pixel
4080  !This function returns the vertical size of one pixel as a ratio of the
4090  !current window size.  1/FNPlot_y_pixel is the number of y pixels in
4100  !the current viewport.
4110    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
4120    COM /Plot_viewp/ Left,Right,Top,Bottom !last viewport command
4130    IF Left+Right=0 THEN CALL User_stop("PROGRAM ERROR: Plot_set_veiwp not called before FNPlot_y_pixel")
4140    RETURN 1/(Y_pixels*.01*(Top-Bottom))
4150  FNEND
4160  !*****************************************************************
4170 Plot_background:SUB Plot_background
4180  !This subprogram erases the current viewport by drawing a rectangle using
4190  !background color.
4200    WINDOW 0,1,0,1
4210    MOVE 0,0
4220    IF FNPlot_use_color THEN 
4230      AREA PEN 7   !background color set in Plot_plot
4240    ELSE
4250      AREA PEN -1  !erase
4260    END IF
4270    RECTANGLE 1,1,FILL
4280    AREA PEN 1
4290  SUBEND
4300  ! PAGE -> 
4310  !*****************************************************************
4320 Plot_do_mkr:SUB Plot_do_mkr(Plot_array(*),X_units$,Y_units$,X_min,X_max,Y_min1,Y_max1,Offset,Scale_factor,Do_log_y)
4330  !This subprogram operates the marker on one trace.  Pass parameters are
4340  !similar to Plot_do_data.
4350    COM /Plot_mkr/ INTEGER Mkr_bin  !for memory between calls
4360    INTEGER Start_bin,Stop_bin,Last_marker
4370    DIM D_line$[80]
4380    GRAPHICS INPUT IS KBD,"KBD"   !use keyborad arrows to move marker
4390    LINE TYPE 1
4400    CLIP ON
4410    Start_bin=BASE(Plot_array,1)
4420    Stop_bin=BASE(Plot_array,1)+SIZE(Plot_array,1)-1
4430    Per_bin_x=(X_max-X_min)/(Stop_bin-Start_bin)
4440    IF Mkr_bin=-1 THEN Mkr_bin=(Stop_bin+Start_bin)/2  !un initialized
4450    Mkr_bin=MAX(Start_bin,MIN(Stop_bin,Mkr_bin))
4460    IF Scale_factor=0 THEN 
4470      CALL User_error("ERROR: Data_header scale factor is zero (Plot_do_mkr)")
4480      Scale_factor=1
4490    END IF
4500    IF Do_log_y THEN 
4510      Y_min=LGT(Y_min1)
4520      Y_max=LGT(Y_max1)
4530    ELSE
4540      Y_min=Y_min1
4550      Y_max=Y_max1
4560    END IF
4570    MOVE 0,0   !to avoid error 19 if next window is 1E-7 (BASIC bug)
4580    WINDOW Start_bin,Stop_bin,Y_min,Y_max
4590    CLIP ON
4600    ! Marker_gain is a fudge factor that allows the marker to hit each bin
4610    ! The min locator change is 1 pixel.  Marker_gain maps one pixel into
4620    ! one bin.
4630    Marker_gain=1/(SIZE(Plot_array,1)*FNPlot_x_pixel)
4640    Y=(Plot_array(Mkr_bin,2)-Offset)/Scale_factor
4650    SET LOCATOR Mkr_bin,MAX(Y_min,MIN(Y_max,Y))
4660    SET ECHO Plot_array(Mkr_bin,1),MAX(Y_min,MIN(Y_max,Y))
4670    GOSUB Disp_mkr
4680    REPEAT
4690      DISABLE 
4700      READ LOCATOR Locator_x,Dummy
4710      Mkr_bin=MAX(Start_bin,MIN(Stop_bin,Mkr_bin+(Locator_x-Mkr_bin)*Marker_gain))
4720      Y=(Plot_array(Mkr_bin,2)-Offset)/Scale_factor
4730      SET LOCATOR Mkr_bin,MAX(Y_min,MIN(Y_max,Y))
4740      IF Mkr_bin=Last_marker THEN    !not moving
4750        GOSUB Disp_mkr
4760      ELSE
4770        SET ECHO Plot_array(Mkr_bin,1),MAX(Y_min,MIN(Y_max,Y))
4780      END IF
4790      Last_marker=Mkr_bin
4800      ENABLE 
4810    UNTIL FNUser_key_press
4820    DISP 
4830    IF FNUser_check_key>3 THEN SET ECHO Start_bin-10.0*(Stop_bin-Start_bin),Y_min
4840    !move the marker off of the screen unless the "Move marker" softkey
4850    SUBEXIT
4860 Disp_mkr:  !------------------------------------------------
4870   !Given marker_bin and Y, displays marker value
4880    IF Do_log_y THEN !Plot_data has been logged, need to un-log
4890      CALL Plot_eng_format(10^Y,0,Y$,"",8,Y_prefix$)
4900    ELSE
4910      IF POS(UPC$(Y_units$),"DB") THEN !special case for dB
4920        Y$=""
4930        OUTPUT Y$ USING "#,DDDD.DDD";Y
4940      ELSE
4950        CALL Plot_eng_format(Y,0,Y$,"",8,Y_prefix$)
4960      END IF
4970    END IF
4980    X=X_min+(Mkr_bin-Start_bin)*(Per_bin_x)
4990    CALL Plot_eng_format(X,0,X$,"",8,X_prefix$)
5000    D_line$=X$&X_prefix$&" "&X_units$
5010    D_line$=D_line$&RPT$(" ",20-LEN(D_line$))
5020    D_line$=D_line$&Y$&Y_prefix$&" "&Y_units$
5030    DISP D_line$
5040    RETURN 
5050  SUBEND
5060  ! PAGE -> 
5070  !************************************************************************
5080 Plot_move_mkr:SUB Plot_move_mkr(Plot_array(*),X_units$,X_min,X_max,To$)
5090  ! This subprogram is called from the marker menu when a "Marker to ?"
5100  ! soft key is pressed.
5110  ! It's output is a side effect:  It may modify the current marker
5120  ! bin number stored in common.
5130  !---------------------------------------------------------------------
5140    COM /Plot_mkr/ INTEGER Mkr_bin  !for memory between calls
5150    DIM New_entry$[100]
5160    INTEGER X,Start_bin,Stop_bin
5170    Start_bin=BASE(Plot_array,1)
5180    Stop_bin=BASE(Plot_array,1)+SIZE(Plot_array,1)-1
5190    Per_bin_x=(X_max-X_min)/(Stop_bin-Start_bin)
5200    SELECT To$
5210    CASE "MIN"
5220      GOSUB To_min
5230    CASE "MAX"
5240      GOSUB To_max
5250    CASE ELSE
5260      GOSUB To_x
5270    END SELECT
5280    SUBEXIT
5290 To_x:  !-----------------------------------------------------------
5300    IF X_units$<>"" THEN 
5310      DISP "Move marker: X axis value in ";X_units$;
5320    ELSE
5330      DISP "Move marker: X axis value ";
5340    END IF
5350    LINPUT New_entry$
5360    DISP 
5370    IF LEN(New_entry$)>0 THEN 
5380      ON ERROR GOTO Nevermind
5390      Mkr_bin=MIN(Stop_bin,(VAL(New_entry$)-X_min)/Per_bin_x+Start_bin)
5400 Nevermind:OFF ERROR 
5410    END IF
5420    RETURN 
5430 To_min:        !-------------------------------------------------------
5440    FOR X=Start_bin TO Stop_bin
5450      IF Plot_array(X,2)<Plot_array(Mkr_bin,2) THEN 
5460        Mkr_bin=X
5470      END IF
5480    NEXT X
5490    RETURN 
5500 To_max:        !-------------------------------------------------------
5510    FOR X=Start_bin TO Stop_bin
5520      IF Plot_array(X,2)>Plot_array(Mkr_bin,2) THEN 
5530        Mkr_bin=X
5540      END IF
5550    NEXT X
5560    RETURN 
5570  SUBEND
5580  ! PAGE -> 
5590  !************************************************************************
5600  DEF FNPlot_have_color
5610  !This function returns 1 if color is available
5620    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
5630    RETURN Have_color
5640  FNEND
5650  SUB Plot_set_color(Use_color)
5660  !This subprogram turn on and off color by setting a flag in common.
5670    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color_c
5680    IF (Use_color<>0) AND FNPlot_have_color THEN 
5690      Use_color_c=1
5700    ELSE
5710      Use_color_c=0
5720    END IF
5730  SUBEND
5740  DEF FNPlot_use_color
5750  !This function returns 1 if color is turned on.
5760    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
5770    RETURN Use_color
5780  FNEND
5790  ! PAGE -> 
5800  !************************************************************************
5810 Plot_eng_format:SUB Plot_eng_format(Value1,Value2,V1$,V2$,Digits,Prefix$)
5820  !This subprogram converts 2 values to engineering format.
5830  !To use it with only one value, set the other to zero
5840  !INPUTS:  Value1, Value2:  values in fundamental units (Hz).
5850  !         Digits:  Number of digits to round to.
5860  !OUTPUTS: V1$, V2$: Strings returning the rounded output.
5870  !         Prefix$: Engineering format prefix for units.
5880  !------------------------------------------------------------------------
5890    Max_value=DROUND(MAX(ABS(Value1),ABS(Value2)),Digits)
5900    IF Max_value>10^(-15) THEN  !check for log of zero
5910      SELECT LGT(Max_value)
5920      CASE >=6
5930        Exponent=6
5940        Prefix$="M"
5950      CASE 3 TO 6
5960        Exponent=3
5970        Prefix$="K"
5980      CASE 0 TO 3
5990        Exponent=0
6000        Prefix$=""
6010      CASE -3 TO 0
6020        Exponent=-3
6030        Prefix$="m"
6040      CASE -6 TO -3
6050        Exponent=-6
6060        Prefix$="u"
6070      CASE -9 TO -6
6080        Exponent=-9
6090        Prefix$="n"
6100      CASE <-9
6110        Exponent=-12
6120        Prefix$="p"
6130      END SELECT
6140    ELSE
6150      Exponent=0
6160      Prefix$=""
6170    END IF
6180    V1$=VAL$(DROUND(Value1/10^Exponent,Digits))
6190    V2$=VAL$(DROUND(Value2/10^Exponent,Digits))
6200  SUBEND
6210  ! PAGE -> 
6220  !************************************************************************
6230 Plot_bold_label:SUB Plot_bold_label(Char_size,L$)
6240  !This subprogram plots a bold label with CSIZE Char_size.
6250    INTEGER N,Max_n
6260    WHERE X,Y
6270    CSIZE Char_size
6280    Max_n=(Char_size/FNPlot_good_csize)-1
6290    X_step=FNPlot_x_pixel*.999
6300    Y_step=FNPlot_y_pixel*.999
6310    FOR N=0 TO Max_n
6320      MOVE X+Max_n*X_step,Y+N*Y_step
6330      LABEL L$
6340    NEXT N
6350    FOR N=0 TO Max_n
6360      MOVE X+N*X_step,Y
6370      LABEL L$
6380    NEXT N
6390    FOR N=0 TO Max_n
6400      MOVE X+N*X_step,Y+Max_n*Y_step
6410      LABEL L$
6420    NEXT N
6430    FOR N=Max_n TO 0 STEP -1   !want to do X+0,Y+0 last for pen position
6440      MOVE X,Y+N*Y_step
6450      LABEL L$
6460    NEXT N
6470  SUBEND
6480  ! PAGE -> 
6490  !************************************************************************
6500 Plot_make_x:SUB Plot_make_x(Plot_array(*),Do_log_x,X_min,X_max)
6510   !This subprogram fills the X elements of Plot_array(*) for the PLOT
6520   !command. If the x axis is to be LOGed, it is done here.
6530   !
6540   !INPUTS:  Do_log_x:    Flag 0: linear x axis,  <>0 : log x axis
6550   !         X_min,X_max: X axis bounds in real world units.
6560   !OUTPUTS: Plot_array(*):  2D array of xy points ready for PLOT command.
6570   !                    Plot_array(*,1) = x = bin numbers for linear plots,
6580   !                                  "distorted" bin numbers for log plots.
6590   !                    Plot_array(*,2) = y = y values. not changed.
6600   !
6610   !-----------------------------------------------------------------
6620    INTEGER Bin,Start_bin,Stop_bin
6630    Start_bin=BASE(Plot_array,1)
6640    Stop_bin=SIZE(Plot_array,1)+Start_bin-1
6650    IF Do_log_x THEN          ! x axis is logged
6660      GOSUB Do_log
6670    ELSE
6680      GOSUB Do_lin
6690    END IF
6700    SUBEXIT
6710 Do_lin:    !--------------------------------------------------------
6720    !re- compute only if necessary
6730    IF (Plot_array(Start_bin+1,1)<>Start_bin+1) OR (Plot_array(Stop_bin,1)<>Stop_bin) THEN 
6740      FOR Bin=Start_bin TO Stop_bin
6750        Plot_array(Bin,1)=Bin
6760      NEXT Bin
6770    END IF
6780    RETURN 
6790 Do_log:    !--------------------------------------------------------
6800    !The x-axis log works like this:
6810    !The X elements of Plot_array(*) that are usually bin numbers for
6820    !linear plots are "distorted" into log sequence.  The distortion
6830    !is such that the first and last bins are not changed.  In other
6840    !words Plot_array(Start_bin,1)=Start_bin  and
6850    !Plot_array(Stop_bin,1)=Stop_bin,  but everything between will
6860    !be different.  The formula for the distortion is
6870    !    Plot_array(Bin,1) = A*LGT(Freq) + B
6880    !where A and B are figured below, and Freq is real world X value
6890    !of the Bin.
6900    !
6910    A=(Stop_bin-Start_bin)/LGT(X_max/X_min)
6920    B=Start_bin-A*LGT(X_min)
6930    Per_bin_x=(X_max-X_min)/(Stop_bin-Start_bin)
6940    !
6950    !Comput new values only if old values are incorrect.
6960    IF ABS(Plot_array(Start_bin+1,1)-(A*LGT(X_min+Per_bin_x)+B))>1.E-4 OR (Plot_array(Stop_bin,1)<>Stop_bin) THEN 
6970      FOR Bin=Start_bin TO Stop_bin-1
6980        Plot_array(Bin,1)=A*LGT(X_min+(Bin-Start_bin)*Per_bin_x)+B
6990      NEXT Bin
7000      Plot_array(Stop_bin,1)=Stop_bin
7010    END IF
7020    RETURN 
7030  SUBEND
7040  ! PAGE -> 
7050  !************************************************************************
7060 Plot_make_y:SUB Plot_make_y(Data_buffer(*),Data_header(*),Plot_array(*),Buf_num,Start_bin,Stop_bin_r,Do_log,Offset,Scale_factor)
7070   !This subprogram converts Data_buffer(*) into Plot_array(*) for the PLOT
7080   !command. If the data is to be LOGed, it is done here.
7090   !There is a CSUB version that does the same operation much quicker.
7100   !The CSUB should be above this, so the CSUB will be used.
7110   !
7120   !INPUTS: Data_buffer(*):  2D array of y data blocks.  This sub only
7130   !                    operates on one block, Data_buffer(Buf_num,*).
7140   !        Data_header(*):  2D array of header info for y data blocks.
7150   !        Buf_num:    Which buffer of Data_buffer.
7160   !        Start_bin, Stop_bin:  Data_buffer index range to plot.
7170   !OUTPUTS: Plot_array(*):  2D array of xy points ready for PLOT command.
7180   !                    Plot_array(*,1) = x, not changed.
7190   !                    Plot_array(*,2) = y = y values.
7200   !        Offset:  Offset yet to be subtracted from y values.
7210   !        Scale_factor:  Scale factor yet to be applied to y values.
7220   !
7230   ! For maximum speed, this sub has a separate DO loop for each case.
7240   !-----------------------------------------------------------------
7250    INTEGER X,Stop_bin
7260    Stop_bin=Stop_bin_r
7270    Offset=Data_header(Buf_num,1)
7280    Scale_factor=Data_header(Buf_num,2)
7290    Log_multiplier=Data_header(Buf_num,4)
7300    IF Do_log THEN Log_multiplier=1
7310    IF Log_multiplier=0 THEN         !linear
7320      FOR X=Start_bin TO Stop_bin
7330        Plot_array(X,2)=Data_buffer(Buf_num,X)
7340      NEXT X
7350    ELSE                              !do log
7360      ON ERROR GOTO No_zero
7370      Zero_value=LGT((Data_header(Buf_num,5)-Offset)/Scale_factor)
7380 No_zero:OFF ERROR 
7390      IF Log_multiplier>0 THEN        !positive log multiplier
7400        FOR X=Start_bin TO Stop_bin
7410          IF Data_buffer(Buf_num,X)>0 THEN 
7420            Plot_array(X,2)=LGT((Data_buffer(Buf_num,X)-Offset)/Scale_factor)
7430          ELSE
7440            Plot_array(X,2)=Zero_value
7450          END IF
7460        NEXT X
7470        !zero offset since it has been applied, change scale factor
7480        Offset=0
7490        Scale_factor=1/Log_multiplier
7500      ELSE                            !negative log multiplier
7510        FOR X=Start_bin TO Stop_bin
7520          IF Data_buffer(Buf_num,X)>0 THEN 
7530            Plot_array(X,2)=-LGT((Data_buffer(Buf_num,X)-Offset)/Scale_factor)
7540          ELSE
7550            Plot_array(X,2)=-Zero_value
7560          END IF
7570        NEXT X
7580        Offset=0
7590        Scale_factor=-1/Log_multiplier
7600      END IF                          !log multiplier sign
7610    END IF
7620  SUBEND
7630  ! PAGE -> 
7640  !************************************************************************