10! OUTPUT 2 USING "#,K";"<lf>REN<cr>INDENT<cr><lf>RE-STORE ""USER""<cr>" 20 ! 30 ! EDIT Test_prog 40 ! EDIT User_user 50 ! EDIT User_spread 60 ! EDIT User_clr_scr 70 ! EDIT User_log_key 80 ! EDIT User_keylabel 90 ! EDIT User_error 100 ! EDIT User_stop 110 ! EDIT User_yes 120 ! 130 User_doc: ! 140 ! ***************************************************************** 150 ! USER INTERFACE (User_) FILE DESCRIPTION 160 ! Subprograms in the USER file are used to 170 ! interface to the user. The two main functions are a spread sheet 180 ! and softkey handling. 190 !------------------------------------------------------------------ 200 ! 210 ! Softkey scheme: 220 ! In the HP3565 Demo programs, softkeys are used to for program 230 ! control but the ON KEY statements do not directly call the appropriate 240 ! subprogram. Rather, each ON KEY statement calls a subprogram 250 ! (like User_key1isr) that logs the key and then exits. The main program 260 ! can then "read" the softkey using FNUser_get_key and call the 270 ! appropriate subprogram. Lower-level subprograms can use FNUser_key_press 280 ! to check if a softkey is pending and exit. This scheme allows the 290 ! softkeys to work like the hardkeys on a traditional instrument, avoids 300 ! priority problems, and allows parameters to be passed to subprograms 310 ! called by sofkteys. 320 !------------------------------------------------------------------ 330 Test_prog: ! 340 ! <PLACE TEST CODE HERE> 350 ! LOADSUB ALL FROM "LIB" 360 CALL User_user 370 !This subprogram demonstrates how the use SUB Spread_sheet 380 ! 390 COM /Spread_demo/ Row,Col,Start_row !keep these in com for memory 400 DIM New_entry$[160] 410 Max_col=4 420 Max_row=10 430 Start_row=0 440 ALLOCATE Box$(1:Max_col,1:Max_row)[20] 450 ALLOCATE Title$(1:Max_col,0:2)[20] 460 ALLOCATE Cmd$(1:Max_col)[10] 470 ALLOCATE Prompt$(1:Max_col)[80] 480 ALLOCATE Col_width(1:Max_col) 490 ! 500 ! These data statements define the setup and titles for each column 510 ! 520 ! col_width title1 title2 Cmd Prompt 530 ! --------- ---------- ---------- --- -------------------- 540 DATA 36, "Channel", "Name", "", "" 550 DATA 4, "Mode", "", "INPM", "Input mode: Volt, ICP, or Chrg" 560 DATA 10, "Range", "(dB)", "RNG", "Full scale Range in dBVp or dBpCp" 570 DATA 10, "Center Freq", "(Hz)", "CF", "Center frequency in Hz"580 ! 590 Modify_col=4 !col 2 an up will be modifiable 600 ! 610 !read the above data into arrays 620 Title$(1,0)="Main title" 630 FOR C=1 TO Max_col 640 READ Col_width(C),Title$(C,1),Title$(C,2),Cmd$(C),Prompt$(C) 650 NEXT C 660 ! 670 !define softkeys. Keys 1 to 4 are reserved for "hardkeys" 680 ON KEY 5 LABEL " Reset" CALL User_key5isr 690 ON KEY 6 LABEL "Autorange" CALL User_key6isr 700 ON KEY 7 LABEL " Etc" CALL User_key7isr 710 ! 720 !fill Box$ array with initial dummy data 730 Box$(1,1)="All inputs" 740 FOR R=2 TO Max_row 750 Box$(1,R)="Ch "&VAL$(R)&" @ 0,"&VAL$(R) 760 Box$(2,R)="Volt" 770 IF R>10 THEN Box$(2,R)="Chg" 780 Box$(3,R)=VAL$(-R*2) 790 Box$(4,R)=VAL$(1024.25*R) 800 NEXT R 810 ! 820 ! 830 CALL User_clr_scr 840 !Now call spread sheet. It returns with New_entry$ and Row and Col 850 Done=0 860 REPEAT 870 CALL User_spread(Box$(*),Title$(*),Prompt$(*),New_entry$,Col_width(*),Modify_col,Col,Row,Start_row) 880 SELECT FNUser_check_key 890 CASE 0 !no key pressed, must be a New_entry$ for Box 900 GOSUB New_entry 910 CASE 5 920 Dummy=FNUser_get_key !to clear the key 930 DISP "Reset-ing" 940 CASE 6 950 Dummy=FNUser_get_key 960 DISP "Autoranging" 970 CASE 7 980 Dummy=FNUser_get_key 990 DISP "Etc ing" 1000 CASE ELSE !a softkey but not one of mine, so exit 1010 Done=1 1020 END SELECT 1030 UNTIL Done 1040 CALL User_clr_scr 1050 ! SUBEXIT 1060 STOP 1070 New_entry: !------------------------------------------------ 1080 !acts on new_entry from spread_sheet 1090 IF TRIM$(New_entry$)<>"" THEN 1100 IF Row=1 THEN 1110 DISP "sending global command ";Cmd$(Col);" ";New_entry$ 1120 FOR R=2 TO Max_row 1130 Box$(Col,R)=New_entry$ 1140 NEXT R 1150 ELSE !not global command 1160 DISP "sending ";Cmd$(Col);" ";New_entry$ 1170 Box$(Col,Row)=New_entry$ 1180 END IF 1190 DISP 1200 END IF 1210 RETURN 1220 ! 1230 ! 1240 END 1250 ! PAGE -> 1260 !************************************************************************ 1270 User_user:SUB User_user 1280 !This subprogram defines and initializes all common blocks used by 1290 !subprograms in the USER file. 1300 COM /User_key/ INTEGER Key_no,None 1310 INTEGER Stat 1320 None=-99 1330 Key_no=None 1340 STATUS KBD,9;Stat !get KBD type 1350 IF BIT(Stat,5) THEN !its a HP46020 1360 CONTROL KBD,14;0 !map f0 to key 0 1370 CONTROL KBD,2;1 !user menu 1 1380 END IF 1390 SUBEND 1400 !************************************************************************ 1410 User_spread:SUB User_spread(Box$(*),Title$(*),Prompt$(*),New_entry$,Col_width(*),Modify_col,Col,Row,Start_row) 1420 ! This subprogram allows the user move a highlighted box around 1430 ! a table of data similar to a spread sheet. It exits 2 different 1440 ! ways: 1) when the user completes a new entry for a box. The new 1450 ! entry is not put in the box, it is returned in New_entry$ 1460 ! 2) When the function FNUser_key_press is becomes true. 1470 ! 1480 ! INPUTS: Box$(1:max_col,1:max_row) : array of boxes 1490 ! Title$(1:max_col,0:2) :array of column titles, two lines each 1500 ! Title$(1,0) is the main title. 1510 ! Title$(*,1..2) are col titles. 1520 ! Prompt$(1:max_col) :array of prompts for each column. 1530 ! If there is only one modifiable column, 1540 ! then prompts are for rows. 1550 ! Col_width(1:max_col) :column sizes in displayed characters. 1560 ! Modify_col :first column that can be modified, 1=all. 1570 ! OUTPUTS:New_entry$ :new entry if keyboard entry. 1580 ! IN&OUT: Col, Row :location of highlighted box. 1590 ! Start_row :top row of display. 1600 ! 1610 !Before calling this the screen should be cleared. 1620 INTEGER Knob_trigger,Knobx_counter,Knoby_counter,C,R,Max_col,Max_row 1630 INTEGER Lines_per_page,Old_row,Pri,Stat,Itf_kbd,Prompt_by_col 1640 DIM My_kbd$[255],Iv$[1],Ul$[1],Iv_ul$[1],De_off$[1],White$[1],Yellow$[1],Cyan$[1],Green$[1] 1650 De_off$=CHR$(128) !display enhancements off 1660 Iv$=CHR$(129) !inverse video 1670 Ul$=CHR$(132) !underline 1680 Iv_ul$=CHR$(133) !both 1690 White$=CHR$(136) 1700 Green$=CHR$(139) 1710 Cyan$=CHR$(140) 1720 Yellow$=CHR$(138) 1730 Pri=VAL(SYSTEM$("SYSTEM PRIORITY"))+1 1740 DISABLE 1750 Lines_per_page=FNLib_crt_height-7-3 !-7 for system, -3 for titles 1760 STATUS KBD,9;Itf_kbd !get KBD type 1770 Itf_kbd=BIT(Itf_kbd,5) 1780 IF Itf_kbd THEN !its a HP46020 1790 Knob_trigger=30 1800 STATUS KBD,2;Stat 1810 IF Stat<>1 THEN CONTROL KBD,2;1 !user menu 1 1820 ELSE !assume knob 1830 Knob_trigger=12 1840 END IF 1850 Max_col=SIZE(Box$,1) 1860 Max_row=SIZE(Box$,2) 1870 Col=MAX(Modify_col,MIN(Max_col,Col)) 1880 Row=MAX(1,MIN(Max_row,Row)) 1890 IF (Modify_col=Max_col) AND SIZE(Prompt$,1)>=Max_row THEN 1900 Prompt_by_col=0 1910 ELSE 1920 Prompt_by_col=1 1930 END IF 1940 ON KNOB .01,Pri GOSUB Knob_isr 1950 ON KBD ALL,Pri GOSUB Kbd_isr 1960 GOSUB Print_page 1970 GOSUB Highlight_box 1980 New_entry$="EMPTY" 1990 ENABLE 2000 REPEAT 2010 IF Prompt_by_col THEN 2020 DISP Prompt$(Col) 2030 ELSE 2040 DISP Prompt$(Row) 2050 END IF 2060 UNTIL New_entry$<>"EMPTY" OR FNUser_key_press 2070 GOSUB Clear_old_box 2080 DISP 2090 SUBEXIT 2100 Print_page: !----------------------------------------------------- 2110 Start_row=MIN(Start_row,Max_row-Lines_per_page+1,Row) 2120 Start_row=MAX(Start_row,Row-Lines_per_page+1,1) 2130 CONTROL CRT,0;1 !character column 1 2140 CONTROL CRT,1;1 !row 1 2150 OUTPUT CRT;Iv_ul$;Green$; 2160 IF BASE(Title$,2)=0 THEN !there is a title 2170 OUTPUT CRT;FNUser_fill$(Title$(1,0),SUM(Col_width)+Max_col) 2180 ELSE 2190 OUTPUT CRT;FNUser_fill$("",SUM(Col_width)+Max_col) 2200 END IF 2210 OUTPUT CRT;Iv$; 2220 FOR C=1 TO Max_col !do first title row 2230 OUTPUT CRT;FNUser_fill$(Title$(C,1),Col_width(C))&"|"; 2240 NEXT C 2250 OUTPUT CRT;Iv_ul$ 2260 FOR C=1 TO Max_col !do second title row 2270 OUTPUT CRT;FNUser_fill$(Title$(C,2),Col_width(C))&"|"; 2280 NEXT C 2290 FOR R=Start_row TO MIN(Max_row,Start_row+Lines_per_page-1) !do each row 2300 OUTPUT CRT;Iv_ul$;Cyan$ 2310 FOR C=1 TO Max_col !do each column of the row 2320 IF C=Modify_col THEN OUTPUT CRT;Ul$;White$; !switch off inverse 2330 OUTPUT CRT;FNUser_fill$(Box$(C,R),Col_width(C))&"|"; 2340 NEXT C 2350 NEXT R 2360 OUTPUT CRT;De_off$;White$; 2370 RETURN 2380 Move_box: !---------------------------------------------------- 2390 Col=MAX(Modify_col,MIN(Max_col,Col)) 2400 Row=MAX(1,MIN(Max_row,Row)) 2410 GOSUB Clear_old_box 2420 IF (Row<Start_row) OR (Row>=Start_row+Lines_per_page) THEN 2430 GOSUB Print_page 2440 END IF 2450 GOSUB Highlight_box 2460 RETURN 2470 Clear_old_box: !-------------------------------------------------- 2480 !re-write old_row without inverse video 2490 CONTROL CRT,0;1 !character column 1 2500 CONTROL CRT,1;Old_row-Start_row+3+1 2510 OUTPUT CRT;Iv_ul$;Cyan$; 2520 FOR C=1 TO Max_col !do each column of the row 2530 IF C=Modify_col THEN OUTPUT CRT;Ul$;White$; !switch off inverse 2540 OUTPUT CRT;FNUser_fill$(Box$(C,Old_row),Col_width(C))&"|"; 2550 NEXT C 2560 OUTPUT CRT;De_off$;White$; 2570 RETURN 2580 Highlight_box: !-------------------------------------------------- 2590 !then write new row with inverse video 2600 CONTROL CRT,0;1 !character column 1 2610 CONTROL CRT,1;Row-Start_row+3+1 2620 OUTPUT CRT;Iv_ul$;Cyan$; 2630 FOR C=1 TO Max_col !do each column of the row 2640 IF C=Modify_col THEN OUTPUT CRT;Ul$;White$; !switch off inverse 2650 IF C=Col THEN 2660 OUTPUT CRT;Iv_ul$;Yellow$; 2670 OUTPUT CRT;FNUser_fill$(Box$(C,Row),Col_width(C))&Ul$&White$&"|"; 2680 ELSE 2690 OUTPUT CRT;FNUser_fill$(Box$(C,Row),Col_width(C))&"|"; 2700 END IF 2710 NEXT C 2720 OUTPUT CRT;De_off$;White$; 2730 Old_row=Row !save to erase 2740 RETURN 2750 Knob_isr:DISABLE !----------------------------------------------- 2760 Knobx_counter=KNOBX+Knobx_counter 2770 IF Itf_kbd THEN !assume the knob is a mouse. 2780 Knoby_counter=Knoby_counter-KNOBY !mice do Y backwards. 2790 ELSE 2800 Knoby_counter=Knoby_counter+KNOBY 2810 END IF 2820 IF ABS(Knobx_counter)>Knob_trigger THEN 2830 IF (Modify_col=Max_col) AND NOT Itf_kbd THEN !1 column, no X 2840 Row=Row+(Knobx_counter DIV Knob_trigger) 2850 ELSE 2860 Col=Col+(Knobx_counter DIV Knob_trigger) 2870 END IF 2880 GOSUB Move_box 2890 Knobx_counter=0 2900 END IF 2910 IF ABS(Knoby_counter)>Knob_trigger THEN 2920 Row=Row+(Knoby_counter DIV Knob_trigger) 2930 GOSUB Move_box 2940 Knoby_counter=0 2950 END IF 2960 ENABLE 2970 RETURN 2980 Kbd_isr:DISABLE !------------------------------------------------- 2990 My_kbd$=KBD$ !read system keyboard buffer 3000 IF LEN(My_kbd$)>0 THEN 3010 IF NUM(My_kbd$[1])=255 THEN ! non-ASCII key pressed 3020 SELECT NUM(My_kbd$[2]) 3030 CASE 94 !up arrow is CHR$(255)&CHR$(94) 3040 Row=Row-1 3050 GOSUB Move_box 3060 CASE 86 !down arrow 3070 Row=Row+1 3080 GOSUB Move_box 3090 CASE 40,60 !left 3100 Col=Col-1 3110 GOSUB Move_box 3120 CASE 41,62 3130 Col=Col+1 !right 3140 GOSUB Move_box 3150 CASE 71 3160 Col=Max_col !shift right 3170 GOSUB Move_box 3180 CASE 72 3190 Col=1 !shift left 3200 GOSUB Move_box 3210 CASE 84 !shift down 3220 Row=Max_row 3230 GOSUB Move_box 3240 CASE 87 !shift up 3250 Row=1 3260 GOSUB Move_box 3270 CASE 92,95 !home 3280 Row=1 3290 Col=1 3300 GOSUB Move_box 3310 CASE 44 !next 3320 Row=Row+Lines_per_page 3330 GOSUB Clear_old_box 3340 Start_row=Start_row+Lines_per_page 3350 Row=MAX(1,MIN(Max_row,Row)) 3360 GOSUB Print_page 3370 GOSUB Highlight_box 3380 CASE 39 !prev 3390 Row=Row-Lines_per_page 3400 GOSUB Clear_old_box 3410 Start_row=Start_row-Lines_per_page 3420 Row=MAX(1,MIN(Max_row,Row)) 3430 GOSUB Print_page 3440 GOSUB Highlight_box 3450 CASE 69,88,38,115,116!ENTER, EXECUTE, SELECT, mouse buttons 3460 !mouse buttons won't work after a GRAPHICS INPUT IS 3470 My_kbd$="" 3480 GOSUB Get_entry 3490 CASE 49 TO 56 !K1 to K8 3500 CALL User_log_key(NUM(My_kbd$[2])-48) 3510 CASE 75 !clr scr 3520 BEEP 651,.03!ignore key 3530 CASE ELSE 3540 OUTPUT KBD USING "#,K";My_kbd$ !pass key to op system 3550 END SELECT 3560 ELSE !first char<>255, ASCII key, must be for box 3570 GOSUB Get_entry 3580 END IF 3590 END IF !LEN >0 3600 ENABLE 3610 RETURN 3620 Get_entry: !--------------------------------------------------- 3630 OUTPUT KBD USING "#,K";My_kbd$ 3640 IF Prompt_by_col THEN 3650 DISP Yellow$;Prompt$(Col);" ";White$; 3660 ELSE 3670 DISP Yellow$;Prompt$(Row);" ";White$; 3680 END IF 3690 LINPUT New_entry$ 3700 DISP 3710 RETURN 3720 SUBEND 3730 !---------------------------------------------------------------------- 3740 User_clr_scr:SUB User_clr_scr 3750 !This subprogram clears the screen. 3760 OUTPUT 2 USING "#,K";CHR$(255)&"K" 3770 !do GCLEAR if not bit mapped. 3780 IF NOT POS(SYSTEM$("CRT ID"),"GB") THEN GCLEAR 3790 SUBEND 3800 !---------------------------------------------------------------------- 3810 User_fill:DEF FNUser_fill$(S$,Length) 3820 !This function returns a string with spaces padded to the requested length. 3830 DIM T$[255] 3840 T$=S$ 3850 IF LEN(T$)>=Length THEN 3860 T$=T$[1,Length] 3870 ELSE 3880 T$=RPT$(" ",INT((Length-LEN(T$))/2))&T$ !pad front 3890 T$=T$&RPT$(" ",Length-LEN(T$)) !pad back 3900 END IF 3910 RETURN T$ 3920 FNEND 3930 !---------------------------------------------------------------------- 3940 User_log_key:SUB User_log_key(New_key_no) 3950 !This subprogram is called by the User_keyXisr subprograms, which are 3960 !called by ON KEY statements. It logs the key by putting the New_key_no 3970 !in common. 3980 COM /User_key/ INTEGER Key_no,None 3990 IF Key_no=None THEN 4000 Key_no=New_key_no 4010 ELSE !a previous key has not been serviced 4020 BEEP 651,.03 4030 END IF 4040 SUBEND 4050 !---------------------------------------------------------------------- 4060 SUB User_key1isr 4070 !These softkey interrupt service routines are called by ON KEY statements. 4080 !They call User_log_key to log the softkey press. 4090 CALL User_log_key(1) 4100 SUBEND 4110 SUB User_key2isr 4120 CALL User_log_key(2) 4130 SUBEND 4140 SUB User_key3isr 4150 CALL User_log_key(3) 4160 SUBEND 4170 SUB User_key4isr 4180 CALL User_log_key(4) 4190 SUBEND 4200 SUB User_key5isr 4210 CALL User_log_key(5) 4220 SUBEND 4230 SUB User_key6isr 4240 CALL User_log_key(6) 4250 SUBEND 4260 SUB User_key7isr 4270 CALL User_log_key(7) 4280 SUBEND 4290 SUB User_key8isr 4300 CALL User_log_key(8) 4310 SUBEND 4320 !---------------------------------------------------------------------- 4330 DEF FNUser_get_key 4340 !This function returns the softkey number and clears the softkey log. 4350 COM /User_key/ INTEGER Key_no,None 4360 Temp=Key_no 4370 Key_no=None 4380 RETURN Temp 4390 FNEND 4400 !---------------------------------------------------------------------- 4410 DEF FNUser_check_key 4420 !This function returns softkey number if a softkey has been pressed, 4430 !0 if not. Does not clear the key log. 4440 COM /User_key/ INTEGER Key_no,None 4450 IF Key_no<>None THEN 4460 RETURN Key_no 4470 ELSE 4480 RETURN 0 4490 END IF 4500 FNEND 4510 !---------------------------------------------------------------------- 4520 DEF FNUser_key_press 4530 !This function returns 1 if a softkey has been pressed, 0 if not. 4540 COM /User_key/ INTEGER Key_no,None 4550 IF Key_no<>None THEN 4560 RETURN 1 4570 ELSE 4580 RETURN 0 4590 END IF 4600 FNEND 4610 !---------------------------------------------------------------------- 4620 User_keylabel:DEF FNUser_keylabel$(Label$) 4630 !This function centers a softkey label. 4640 INTEGER Stat,Columns,Spaces 4650 DIM A$[20],B$[20] 4660 Label$=TRIM$(Label$) 4670 STATUS KBD,9;Stat 4680 IF BIT(Stat,5) THEN ! Keyboard is 46020, two 8-character halves 4690 IF POS(Label$," ") THEN ! there are two words 4700 A$=Label$[POS(Label$," ")+1] ! get second half of string 4710 Columns=8 4720 GOSUB User_kl_center 4730 IF LEN(A$)<=Columns THEN ! didn't run over 4740 B$=A$ ! remember this for return 4750 A$=Label$[1;POS(Label$," ")-1] ! get first half of string 4760 GOSUB User_kl_center 4770 A$=A$&B$ 4780 A$=A$[1;16] 4790 ELSE ! did run over 4800 A$=Label$[1;MIN(LEN(Label$),16)] 4810 END IF 4820 ELSE ! there's only one word 4830 A$=Label$ 4840 Columns=8 4850 GOSUB User_kl_center 4860 A$=A$[1;16] 4870 END IF 4880 ELSE ! one 14-character field 4890 A$=Label$ 4900 Columns=14 4910 GOSUB User_kl_center 4920 A$=A$[1;14] 4930 END IF 4940 RETURN A$ 4950 ! 4960 User_kl_center:! 4970 ! This subroutine centers A$ assuming a column width of Column. 4980 ! Spaces 4990 Spaces=(Columns-LEN(A$)) DIV 2 5000 IF Spaces>0 THEN 5010 A$=RPT$(" ",Spaces)&A$&RPT$(" ",Spaces) 5020 END IF 5030 IF LEN(A$)<Columns THEN A$=A$&" " 5040 RETURN 5050 FNEND 5060 !------------------------------------------------------------------- 5070 User_error:SUB User_error(Aline$) 5080 !This subprogram reports errors to the user using the DISP line, 5090 !beeps, waits 3 sec, and exits. 5100 BEEP 100,.1 5110 DISP Aline$ 5120 WAIT 3 5130 DISP 5140 SUBEND 5150 !------------------------------------------------------------------- 5160 User_stop:SUB User_stop(Aline$) 5170 !This subprogram reports fatal program errors and PAUSEs the program. 5180 !The STEP key can be used to get back to the calling context. 5190 BEEP 100,.5 5200 DISP Aline$ 5210 PAUSE 5220 DISP 5230 SUBEND 5240 !------------------------------------------------------------------- 5250 ! a form feed => 5260 User_yes:DEF FNUser_yes(Prompt$,Default) 5270 ! This subprogram asks a yes/no question, return 1 if yes, 0 if no. 5280 Left_arrow$=CHR$(255)&"H" 5290 REPEAT 5300 IF Default THEN 5310 OUTPUT 2 USING "#,K";"Y"&Left_arrow$ 5320 ELSE 5330 OUTPUT 2 USING "#,K";"N"&Left_arrow$ 5340 END IF 5350 DISP Prompt$&" ?" 5360 ENTER 2;Answer$ 5370 DISP 5380 Answer$=UPC$(TRIM$(Answer$)) 5390 UNTIL Answer$[1,1]="Y" OR Answer$[1,1]="N" 5400 IF Answer$[1,1]="Y" THEN 5410 RETURN 1 5420 ELSE 5430 RETURN 0 5440 END IF 5450 FNEND 5460 !-----------------------------------------------------------------------