2 ! OUTPUT 2 USING "#,K";"<lf>INDENT<cr><lf>RE-STORE ""PSD""<cr>" 4 ! 5 ! Rev 1.1 Fixed #2 in SUBs Appl_update, Appl_get_data, Appl_powerup 7 END 8 ! 10 ! PAGE -> 12 !*********************************************************************** 14 Appl_appl:SUB Appl_appl 16 ! Called when program is first run ("poweron") 18 ! All COM declarations specific to this application are defined here 20 COM /Appl_data/ Data_buffer(1:16,0:4095),Data_header(1:16,1:10) 22 COM /Appl_buf_info/ Disp_choices$(1:2,1:63)[16],Input_labels$(1:63)[16],Num_inputs 24 COM /Psd_block_info/ Icode_info$(0:127)[40],Source$(0:511)[80],INTEGER Compiled(0:1024),Icode_compiled,Icode_id,Source_size 26 COM /Psd_scale_info/ Half_lsb,Corr_fact,Flat_top_fact,Hann_fact,Range(1:63) 27 COM /Psd_bw_info/ Flat_top_bw,Hann_bw 29 COM /Psd_meas_mode/ Real_time 30 Source_size=SIZE(Source$,1) 32 SUBEND 34 ! 36 ! PAGE -> 38 !*********************************************************************** 40 Appl_start:SUB Appl_start 42 ! Called when a measurement is to be started (restarted) 44 ! 46 COM /Appl_buf_info/ Disp_choices$(*),Input_labels$(*),Num_inputs 48 COM /Appl_data/ Data_buffer(*),Data_header(*) 50 COM /Psd_meas_mode/ Real_time 52 COM /Psd_block_info/ Icode_info$(*),Source$(*),INTEGER Compiled(*),Icode_compiled,Icode_id,Source_size 54 ! 56 INTEGER Temp_list(0:2) 58 DIM A$[255] 60 ! 62 !Clear Error queue,Stop Icode,Clear Pending SRQs 64 Hw_cmd("CLR;ABRT;STA?",2) 66 IF FNHw_io_error THEN 68 Hw_dev_clear 70 Hw_cmd("CLR;ABRT;STA?",1) 72 IF FNHw_io_error THEN 74 User_stop("***Unrecoverable timeout error in Appl_start***") 76 END IF 78 END IF 80 ! 82 ! Set real time bit if a realtime meas mode has been selected 84 Real_time=FNMeas_cont_mode 86 ! 88 CALL Psd_syst_params 90 ! 92 DISP "Initializing Input modules to take data" 94 ! First clear errors, and masks of all input modules 96 Inpt_cmd("ALL INPUT","CLR;RQS 0;INTR 0;CLASM 50") 98 ! Now set the active modules' (up to MAX_INPUTS) IRQ/SRQ masks 100 Mask$=VAL$(FNInpt_str_2_stat("BLOCK AVAILABLE")) 102 I_mask$=VAL$(FNInpt_str_2_stat("ERROR|FIFO OVERFLOW")) 104 FOR I=1 TO Num_inputs 106 Module_label$=Input_labels$(I) 108 Inpt_cmd(Module_label$,"CLR;RQS",Mask$) 110 Inpt_cmd(Module_label$,"INTR",I_mask$) 112 Inpt_cmd(Module_label$,"CLASP",VAL$(50)) 114 NEXT I 116 Inpt_cmd("ALL INPUT","TRNM ",FNMeas_cont_blk$) !blk or cont 118 Inpt_cmd("ALL INPUT","SYNC ON") 120 ! 122 DISP "FILLING MODULE LIST" 124 Loop_count=1 126 Temp_list(0)=FNMeas_fftsize*2 !xfer_size=bsize 128 Temp_list(1)=Loop_count 130 Temp_list(2)=Num_inputs !module count 132 Hw_write_blk(FNIcode_ext_id("MOD_LIST",Icode_info$(*)),Temp_list(*),1) 134 IF FNHw_io_error THEN 136 Hw_dev_clear 138 Hw_write_blk(FNIcode_ext_id("MOD_LIST",Icode_info$(*)),Temp_list(*),1) 140 IF FNHw_io_error THEN 142 User_stop("***Unrecoverable timeout error in Appl_start***") 144 END IF 146 END IF 148 ! 150 ! Change buff size based on new measurement 152 REDIM Data_buffer(1:MIN(Num_inputs,16),0:FNMeas_fftsize-1) 154 ! 156 ! SETUP HP-IB MODULE FOR SRQ ON MSG,PRG,OR ERROR 158 Mask$=VAL$(FNHw_str_2_stat("MESSAGE|ERROR|PRG")) 160 Hw_cmd("RQS "&Mask$,1) 162 IF FNHw_io_error THEN 164 Hw_dev_clear 166 Hw_cmd("RQS "&Mask$,1) 168 IF FNHw_io_error THEN 170 User_stop("***Unrecoverable timeout error in Appl_start***") 172 END IF 174 END IF 176 ! 178 DISP "Starting the Icode program" 180 Hw_wait_gbl_rdy 182 Hw_cmd("PROG"&VAL$(Icode_id),1) 184 IF FNHw_io_error THEN 186 Hw_dev_clear 188 Hw_cmd("PROG"&VAL$(Icode_id),1) 190 IF FNHw_io_error THEN 192 User_stop("***Unrecoverable timeout error in Appl_start***") 194 END IF 196 END IF 198 ! 200 SUBEND 202 ! 204 ! PAGE -> 206 !*********************************************************************** 208 Appl_get_data:SUB Appl_get_data(Got_new_data,Stopped,Screen_cleared) 210 ! Called to get new data from the module 212 ! If new data is not available, this module should return 214 ! with Got_new_data false. If there is new data, it should 216 ! update the Data_buffer (and Data_header array if necessary) and 218 ! return with Got_new_data true. 220 ! 222 COM /Appl_data/ Data_buffer(*),Data_header(*) 224 COM /Appl_buf_info/ Disp_choices$(*),Input_labels$(*),Num_inputs 226 COM /Psd_scale_info/ Half_lsb,Corr_fact,Flat_top_fact,Hann_fact,Range(*) 228 COM /Psd_meas_mode/ Real_time 230 COM /Psd_block_info/ Icode_info$(*),Source$(*),INTEGER Compiled(*),Icode_compiled,Icode_id,Source_size 231 COM /Psd_bw_info/ Flat_top_bw,Hann_bw 233 ! 234 Got_new_data=0 236 Screen_cleared=0 238 ! 240 DISP "Ready for data from HP3565S" 242 IF NOT FNHw_srq THEN SUBEXIT 244 ! 246 Got_srq:! 248 Sta=VAL(FNHw_cmd_rsp$("STA?")) 250 IF BINAND(Sta,FNHw_str_2_stat("MESSAGE")) THEN 252 DISP "Processing message from HP3565S HP-IB interface module" 254 Sig_value=VAL(FNHw_cmd_rsp$("SIG?")) 256 SELECT Sig_value 258 CASE <0 !intermediate average 260 DISP "reading data from HP3565S" 262 Average_number=ABS(Sig_value) 264 GOSUB Get_info 266 Stopped=0 268 IF FNMeas_avg_disp$="ALL" THEN CALL Hw_cmd("CONT") 270 DISP "" 272 SUBEXIT 274 CASE 1 !final average with possible restart 276 DISP "reading data from HP3565S" 278 Average_number=FNMeas_num_avg 280 GOSUB Get_info 282 IF (NOT FNMeas_free_run) THEN Stopped=1 284 DISP "" 286 SUBEXIT 288 CASE 2 !problems!!! 290 User_error("Unexpected problems....sorry...will try to recover...ck cables, cycle power,..") 292 GOSUB Ck_for_errors 294 Stopped=1 296 CASE 5 !Free run 298 DISP "reading data from HP3565S" 300 Average_number=0 302 GOSUB Get_info 304 Stopped=0 306 DISP "" 308 SUBEXIT 310 CASE 6 !for synchronization between Icode and Basic 312 Hw_cmd("CONT") 314 CASE 20 !fell out of continuous mode, stopped 316 Average_number=VAL(FNHw_cmd_rsp$("SIG?")) 318 DISP "reading data from HP3565S--WENT FROM CONT MODE TO STOP" 320 Real_time=0 322 GOSUB Get_info 324 Stopped=1 326 DISP "" 328 SUBEXIT 330 CASE 30 !fell out of continuous mode into block mode 332 DISP "Went from continuous to block transfer mode...showing last RT avg" 334 Average_number=VAL(FNHw_cmd_rsp$("SIG?")) 336 Real_time=1 !this plot is real time 338 GOSUB Get_info 340 Real_time=0 !next plots won't be real time 342 CASE 99 !small problems 344 User_error("Unable to continue in real time: choose a smaller span or more averages...") 346 GOSUB Ck_for_errors 348 Stopped=1 350 END SELECT 352 END IF 354 IF BINAND(Sta,FNHw_str_2_stat("ERROR")) THEN 356 GOSUB Ck_for_errors 358 LINPUT "<ret> to try to continue",Dummy$ 360 Stopped=1 362 END IF 364 SUBEXIT 366 Get_info: ! 368 ! 370 !some time could have been saved by getting some of this info in 372 ! appl_update, but it may not have been as clear... 374 ! 376 Got_new_data=1 378 Hw_read_fblk(FNIcode_ext_id("OUTPUT_BUFF",Icode_info$(*)),Data_buffer(*)) 380 SELECT UPC$(FNMeas_wind_type$) 382 CASE "HANN" 384 Scaler=Corr_fact*Hann_fact 386 CASE "FLAT TOP" 388 Scaler=Corr_fact*Flat_top_fact 390 CASE "RECTANGULAR" 392 Scaler=Corr_fact 394 END SELECT 396 ! 398 IF FNMeas_log_y THEN ! we need to convert to density, so.... 400 !....so: mult Vp^2 by 1/(2*bin_width) for V^2/Hz 402 Scaler=Scaler/(2*1.28*FNMeas_span/FNMeas_fftsize) 403 SELECT UPC$(FNMeas_wind_type$) 404 CASE "HANN" 405 Scaler=Scaler/Hann_bw 407 CASE "FLAT TOP" 408 Scaler=Scaler/Flat_top_bw 410 END SELECT 411 END IF 412 ! 413 FOR I=1 TO Num_inputs 414 Range_fact=10^(Range(I)/10) 415 Ovld=BINAND(FNHw_rmst(FNCnfg_get_modnum(Input_labels$(I))),FNInpt_str_2_stat("OVERLOAD")) 416 Data_header(I,1)=0 !don't need the offset feature 417 Data_header(I,2)=1/(Scaler*Range_fact) 418 Data_header(I,3)=Ovld 420 Data_header(I,5)=Half_lsb/Scaler 422 Data_header(I,6)=Average_number 424 Data_header(I,7)=Real_time 426 IF FNMeas_log_y THEN !we want V^2/hz 428 Data_header(I,4)=0 !can't do logs twice 430 ELSE !we want dB 432 Data_header(I,4)=10 !for 10*log(mag^2) 434 END IF 436 NEXT I 438 RETURN 440 Ck_for_errors: ! 442 User_clr_scr 444 Screen_cleared=1 446 Errs=FNDiag_chk_errors 448 IF Errs THEN CALL User_error("*** System errors caused mesurement failure ***") 450 RETURN 452 SUBEND 454 ! 456 ! PAGE -> 458 !*********************************************************************** 460 Appl_update:SUB Appl_update 462 ! This routine is call whenever the display configuration is changed 464 ! The default limits for the Y-axis are set here 466 ! 468 COM /Appl_data/ Data_buffer(*),Data_header(*) 470 COM /Appl_buf_info/ Disp_choices$(*),Input_labels$(*),Num_inputs 472 COM /Psd_scale_info/ Half_lsb,Corr_fact,Flat_top_fact,Hann_fact,Range(*) 473 COM /Psd_bw_info/ Flat_top_bw,Hann_bw 475 ! 476 DIM Mod$[50] 478 ! 480 Num_plots=FNDisp_num_plots 482 ALLOCATE Plot_to_buf(1:Num_plots) 484 ALLOCATE X_units$(1:Num_plots)[10],Y_units$(1:Num_plots)[10] 486 ALLOCATE Start_x(1:Num_plots),Per_bin_x(1:Num_plots) 488 ALLOCATE Start_bin(1:Num_plots),Num_bins(1:Num_plots) 490 ALLOCATE Y_def_max(1:Num_plots),Y_def_min(1:Num_plots) 492 ALLOCATE Do_log_x(1:Num_plots) 494 ALLOCATE Do_log_y(1:Num_plots) 496 ALLOCATE Plot_titles$(1:Num_plots)[45] 498 ! 500 Fftsize=FNMeas_fftsize 502 Span=FNMeas_span 504 Cf=FNMeas_cf 506 Hz_per_bin=1.28*Span/Fftsize 508 ! 510 MAT Start_bin= (0) 512 MAT Num_bins= (1024) 514 ! 516 Log_x_plots=FNMeas_log_x 518 Log_y_plots=FNMeas_log_y 520 FOR Plot_num=1 TO Num_plots 522 Module_label$=Disp_choices$(1,FNDisp_choice(Plot_num,1)) 524 Range(Plot_num)=VAL(FNInpt_rsp$(Module_label$,"RANGE")) 526 SELECT UPC$(Disp_choices$(2,FNDisp_choice(Plot_num,2))) 528 CASE "PS" 530 Plot_to_buf(Plot_num)=FNDisp_choice(Plot_num,1) !may change 532 Start_x(Plot_num)=(Cf-(Fftsize*25/64)*Hz_per_bin) !BIN 0 FREQ VALUE 534 Per_bin_x(Plot_num)=(Hz_per_bin) 536 Num_bins(Plot_num)=(Fftsize/1.28+1) !401 point fft 538 IF FNMeas_log_y THEN 540 Y_units$(Plot_num)="V^2/Hz" 541 SELECT UPC$(FNMeas_wind_type$) !Ymax depends on window,range,span 542 CASE "HANN" 543 Y_d_max=1.5*10^((Range(Plot_num)/10)-LGT(Hz_per_bin))*Hann_bw 545 CASE "FLAT TOP" 546 Y_d_max=1.5*10^((Range(Plot_num)/10)-LGT(Hz_per_bin))*Flat_top_bw 547 CASE ELSE 548 Y_d_max=1.5*10^((Range(Plot_num)/10)-LGT(Hz_per_bin)) 549 END SELECT 550 Y_def_max(Plot_num)=DROUND(Y_d_max,1) 551 Y_def_min(Plot_num)=Y_def_max(Plot_num)*(1.E-8)!8 DECADES = 80 dB 552 IF FNInpt_rsp$(Module_label$,"INPUT MODE")="CHRG" THEN 553 Plot_titles$(Plot_num)=Module_label$&" PSD pC^2/Hz" 554 ELSE 555 Plot_titles$(Plot_num)=Module_label$&" PSD V^2/Hz" 556 END IF 557 ELSE 558 Y_units$(Plot_num)="dB" 560 Y_def_max(Plot_num)=Range(Plot_num) 562 Y_def_min(Plot_num)=Y_def_max(Plot_num)-100 564 IF FNInpt_rsp$(Module_label$,"INPUT MODE")="CHRG" THEN 566 Plot_titles$(Plot_num)=Module_label$&" PS pCp" 568 ELSE 570 Plot_titles$(Plot_num)=Module_label$&" PS Vp" 572 END IF 574 END IF 576 X_units$(Plot_num)=("Hz") 578 Do_log_x(Plot_num)=Log_x_plots 580 Do_log_y(Plot_num)=Log_y_plots 582 CASE "TIME" ! for reference only: time displays are not supported 584 Plot_to_buf(Plot_num)=FNDisp_choice(Plot_num,1) !WILL CHANGE 586 Plot_titles$(Plot_num)=Module_label$&" Time" 588 Y_def_max(Plot_num)=10^(Range(Plot_num)/20) 590 Y_def_min(Plot_num)=-Y_def_max(Plot_num) 592 X_units$(Plot_num)="Secs" 594 Y_units$(Plot_num)="Volt" 596 Start_x(Plot_num)=0 598 Per_bin_x(Plot_num)=.390625/Span 600 Do_log_x(Plot_num)=0 602 Do_log_y(Plot_num)=0 604 END SELECT 606 NEXT Plot_num 608 ! 610 Disp_plot_set(Plot_to_buf(*),X_units$(*),Y_units$(*),Start_x(*),Per_bin_x(*),Start_bin(*),Num_bins(*),Y_def_max(*),Y_def_min(*)) 612 Disp_put_titles(Plot_titles$(*)) !define my own trace titles 614 Disp_log_set(Do_log_x(*),Do_log_y(*)) !pass info about log-log plots 616 SUBEND 618 ! 620 ! PAGE -> 622 !*********************************************************************** 624 Appl_init:SUB Appl_init 626 ! This routine is called by Appl_main whenever the configuration 628 ! has changed (and at power on). 630 ! Icode program is assembled and downloaded, 632 ! FFT coefficients are retrieved/generated, 634 ! Display Spreadsheet parameters are defined, 636 ! Number of channels is limited to 16 here. 638 COM /Appl_data/ Data_buffer(*),Data_header(*) 640 COM /Appl_buf_info/ Disp_choices$(*),Input_labels$(*),Num_inputs 642 COM /Psd_block_info/ Icode_info$(*),Source$(*),INTEGER Compiled(*),Icode_compiled,Icode_id,Source_size 644 ! 646 Hw_dev_clear !abort any HP-IB activity 648 Appl_powerup !pass labels to spreadsheets, init constants 650 Hw_cmd("TRGU;DISA;LSPR 1")! make sure default SP algorthms are loaded 652 ! 654 ! 656 ! Get the available module names from the cnfg module 658 Cnfg_labels("ALL INPUT",Input_labels$(*),Num_inputs) 660 Num_inputs=MIN(16,Num_inputs) !NO MORE THAN 16 INPUT CHANNELS ALLOWED 662 IF Num_inputs=0 THEN SUBEXIT 664 ! 666 CALL Psd_icode_prog !assembles and downloads the icode program 668 !allocates blocks 670 ALLOCATE INTEGER Coef(0:4095) 672 Lib_fft_coefs(Coef(*)) !generate FFT coefficient table 674 Hw_write_blk(FNIcode_ext_id("COEF",Icode_info$(*)),Coef(*)) 676 ! 678 Num_cols=2 680 ALLOCATE Disp_titles$(1:Num_cols,1:2)[20] 682 ALLOCATE Disp_prompt$(1:Num_cols)[80] 684 ALLOCATE Disp_width(1:Num_cols) 686 ! 688 MAT Disp_titles$= ("") 690 Disp_titles$(1,1)="Module" 692 Disp_titles$(1,2)="Label" 694 Disp_titles$(2,1)="Trace" 696 Disp_titles$(2,2)="Type" 698 Disp_prompt$(1)="Enter module label" 700 Disp_prompt$(2)="Enter trace type: PS" 702 Disp_width(1)=16 704 Disp_width(2)=7 706 ! 708 MAT Disp_choices$= ("") 710 FOR Module_index=1 TO Num_inputs 712 Disp_choices$(1,Module_index)=Input_labels$(Module_index) 714 NEXT Module_index 716 ! 718 Disp_choices$(2,1)="PS" 720 ! 722 ! Setup Disp module with titles 724 Disp_spread_set(Disp_titles$(*),Disp_prompt$(*),Disp_width(*),Disp_choices$(*)) 726 ! 728 ! The module list is used by the Icode instruction 'f_thruput' 730 DISP "FILLING MODULE LIST" 732 ALLOCATE INTEGER Module_list(0:Num_inputs+2) 734 Module_list(0)=Num_inputs 736 FOR I=1 TO Num_inputs 738 Module_list(I+2)=FNCnfg_get_modnum(Input_labels$(I)) !Input_mod(1)-->module_list(3), ETC 740 NEXT I 742 Hw_write_blk(FNIcode_ext_id("MOD_LIST",Icode_info$(*)),Module_list(*)) 744 ! 746 ! Let 1st module trigger as a default 748 Inpt_cmd(Input_labels$(1),"TRIGGER MODE","SEND TRIGGER") 750 ! 752 ! Initialize data_buffer to default 512 fftsize 754 REDIM Data_buffer(1:MIN(Num_inputs,16),0:511) 756 DISP "" 758 SUBEND 760 ! 762 ! PAGE -> 764 !*********************************************************************** 766 Psd_syst_params:SUB Psd_syst_params 768 ! Fills a parameter block with info necessary for FFT, 770 ! windows, averaging, display modes, etc., then downloads 772 ! to the Parameter block (in HP-IB module) for use by Icode. 774 ! 776 COM /Psd_block_info/ Icode_info$(*),Source$(*),INTEGER Compiled(*),Icode_compiled,Icode_id,Source_size 778 DISP "Fill parameter block with system information..." 780 ALLOCATE INTEGER Param(0:15) 782 Fftsize=FNMeas_fftsize 784 SELECT UPC$(FNMeas_wind_type$) 786 CASE "RECTANGULAR" 788 Do_window=0 790 CASE "HANN" 792 Do_window=1 794 Wind_type_code=1 796 CASE "FLAT TOP" 798 Do_window=1 800 Wind_type_code=2 802 END SELECT 804 ! 806 ! Want to Display only FINAL, SOME, or ALL averages? 808 SELECT FNMeas_avg_disp$ 810 CASE "FINAL" 812 Avg_disp_mode=0 814 CASE "SOME" 816 Avg_disp_mode=1 818 CASE "ALL" 820 Avg_disp_mode=2 822 END SELECT 824 Param(0)=0 !block scaling exponent MSW 826 Param(1)=0 !block scaling exponent LSW 828 Param(2)=PROUND(LOG(Fftsize)/LOG(2),0) !9,10,11,12 830 Param(3)=0 !overflow flag 832 Param(4)=Do_window !SWAP_FLAG 834 Param(5)=Do_window !WINDOW FLAG 836 Param(6)=2 !OUTPUT IS MAG^2 838 ! 840 ! Following information is system info for use by the ICODE program 842 ! 844 Param(7)=Fftsize 846 Param(8)=FNMeas_num_avg 848 Param(9)=Wind_type_code !1=hanning, 2=flattop 850 Param(10)=Avg_disp_mode !0=final, 1=some, 2=all 852 Param(11)=FNMeas_avg_mode !0=OFF, 1=ON 854 Param(12)=FNMeas_free_run !0=OFF, 1=FREE RUN 856 Param(13)=FNMeas_cont_mode!0=block,1=continuous 858 Param(14)=FNMeas_sw_to_blk !switch to block if probl in cont mode 860 ! 862 GOSUB Send_params 864 IF FNHw_io_error THEN 866 Hw_dev_clear 868 GOSUB Send_params 870 IF FNHw_io_error THEN 872 User_clr_scr 874 User_error("Unable to send param block to HP-IB module--I/O timeout") 876 END IF 878 END IF 880 SUBEXIT 882 Send_params: ! 884 Hw_write_blk(FNIcode_ext_id("PARAM",Icode_info$(*)),Param(*),2) 886 RETURN 888 SUBEND 890 ! 892 ! PAGE -> 894 !*********************************************************************** 896 Psd_icode_prog:SUB Psd_icode_prog 898 ! The icode program is here in the form of DATA statements. 900 ! It is here that the Icode assembler & downloader are called 902 ! Icode_info$(*) is the array required by the assembler, 904 ! Icode_id is the block_id into which the icode program is downloaded 906 ! Source$(*) is the Icode source (in DATA statements below) 908 ! note that Source$ is kept around to make the icode debugger easier 910 ! to use; if memory is very scarce, once the icode program works, it 912 ! could be deleted from the COM. 914 ! Compiled(*) is kept around so that the program does not have to be 916 ! reassembled after (say) a configuration change. 918 ! Icode_compiled is a flag preventing unneccessary compilation 920 ! 922 COM /Psd_block_info/ Icode_info$(*),Source$(*),INTEGER Compiled(*),Icode_compiled,Icode_id,Source_size 924 ! 926 Info_info=2 !let the Icode downloader allocate blocks 928 Do_listing=0 930 ! 932 IF Do_listing THEN 934 ALLOCATE List_array$(0:1024)[95] 936 ELSE 938 ALLOCATE List_array$(0:1)[95] 940 END IF 942 IF NOT Icode_compiled THEN 944 REDIM Source$(0:Source_size-1) !back to max size 946 I=-1 948 REPEAT 950 I=I+1 952 READ Source$(I) 954 UNTIL POS(Source$(I),"EL_COMPLETO") 956 Assy_errors=FNIcode_assemble(Source$(*),Compiled(*),(Info_info),Icode_info$(*),(Do_listing),List_array$(*)) 958 IF Do_listing THEN 960 BEEP 962 DISP "Assembly listing is in 'List_array$(*)' <cont> after listing" 964 PAUSE 966 END IF 968 Icode_compiled=NOT Assy_errors 970 END IF 972 IF Icode_compiled THEN 974 Icode_id=FNIcode_dld(Compiled(*),(Info_info),Icode_info$(*)) 976 END IF 978 ! 980 SUBEXIT 982 ! 984 DATA"!**********************************************************" 986 DATA"! ICODE PROGRAM TO TAKE DATA FOR PSD PROGRAM" 988 DATA"! & DO THE SIGNAL PROCESSING" 990 DATA"!**********************************************************" 992 DATA"" 994 DATA "VAR A 0 !gen purpose temp var" 996 DATA "VAR B 0 !gen purpose temp var" 998 DATA "VAR MINUS1 -1 !will always be -1 but must be a var" 1000 DATA "VAR CONT_MODE 0 !continuous or block mode" 1002 DATA "VAR SWITCH_MODE 0 !switch to block if problems with cont" 1004 DATA "VAR AVG_MODE 0 !0=off 1 = averaging" 1006 DATA "VAR NUM_AVGS 0 !# averages requested" 1008 DATA "VAR AVG_NUM 0 !current average number" 1010 DATA "VAR DISP_MODE 0 !0=show only final average" 1012 DATA " !1=show some averages" 1014 DATA " !2=show all averages" 1016 DATA "VAR FREE_RUN 0 !0=stop after meas" 1018 DATA " !1=restart after meas" 1020 DATA "VAR ZERO 0 !always = 0" 1022 DATA "VAR BSIZ 0 !xfer size from input modules" 1024 DATA "VAR VALID_LOOPS 0 !used by ready ram" 1026 DATA "VAR NUM_MODS 0 !number of input modules" 1028 DATA "VAR CLASS 50 !class of the active inp modules" 1030 DATA "VAR MOD_NUM 0 !current input module" 1032 DATA "VAR FFTSIZE 512 !#complex words" 1034 DATA "VAR FFTSIZEX2 1024 !total # 16 BIT WORDS" 1036 DATA "VAR FFTSIZEX4 2048 !for floating point records" 1038 DATA "VAR FFTSIZEX5 2560 !for fast average array" 1040 DATA "VAR FFT_TOSS 0 !toss first few fft points" 1042 DATA "VAR FFT_KEEP 0 !for 401 line resolution" 1044 DATA "VAR KEEP 0 !200/512 * fftsize for 401 line res." 1046 DATA "VAR KEEP_PL_1 0 !200/512 * fftsize + 1; 401 line res." 1048 DATA "VAR KEEPX4 0 ! 4*keep for fp offset in avg array" 1050 DATA "VAR KEEPX5 0 ! 5*keep offset in avg array" 1052 DATA "VAR FFT_KEEP_O 0 ! 39/32* fftsize offset in m^2 array" 1054 DATA "VAR FREQ_EXP 0 !block scaling exp of mag^2 freq" 1056 DATA "VAR BASE_EXP -24 !fast avg init base exp" 1058 DATA "VAR TEMP 0" 1060 DATA "VAR P_INP 0 !pointer to input buffer" 1062 DATA "VAR P_OUT 0 !pointer to output buffer" 1064 DATA "VAR P_OUT2 0 ! additional offset in output buff" 1066 DATA "VAR FP_WORDSX4 0 !4 16-bit words per float word" 1068 DATA "VAR I 0 !loop counter" 1070 DATA "VAR J 0 !loop counter" 1072 DATA "VAR WIND_TYPE 0 !0 = Rect 1 = Hann 2 = Flat top" 1074 DATA "VAR ARRAY_SIZE 0 !fftsize * # active modules" 1076 DATA "" 1078 DATA "CONST FFT 4032 !start address of fft operation" 1080 DATA "CONST FINAL 0 !show only final average" 1082 DATA "CONST SOME 1 !fast update mode" 1084 DATA "CONST ALL 2 !show each average" 1086 DATA "CONST OFF 0" 1088 DATA "CONST ON 1" 1090 DATA "" 1092 DATA "DEFBLK_SP INPUT_BUFF 32768,2 !time data goes here" 1094 DATA "DEFBLK_MAIN MOD_LIST 128,2" 1096 DATA "DEFBLK_MAIN OUTPUT_BUFF 65536,2 !fp data goes here" 1098 DATA "DEFBLK_SP WIND 8192,2" 1100 DATA "DEFBLK_SP FREQ 8192,2" 1102 DATA "DEFBLK_SP COEF 4096,2" 1104 DATA" DEFBLK_SP PARAM 128,2" 1106 DATA" DEFBLK_MAIN AVG_ARRAY 81920,2" 1108 DATA"" 1110 Psd_icode_start: ! 1112 DATA" C_GOSUB ICODE_INIT !init parameters etc." 1114 DATA"" 1116 DATA" C_GOSUB INIT_W !initialize window" 1118 DATA"" 1120 DATA"! Is averaging on? If so, then branch to averaging routines" 1122 DATA" C_BEQ AVERAGE,AVG_MODE,ON" 1124 DATA"" 1126 DATA"!-----------No average code-----------------------------" 1128 DATA"" 1130 DATA"! Wait for BASIC to catch up, then sync modules" 1132 DATA" NO_AV: F_GLB_COMMAND CLASS,'STRT'" 1134 DATA" F_WAIT_TO_SIG 6" 1136 DATA" F_PAUSE" 1138 DATA" C_GOSUB WAIT_RDY" 1140 DATA" F_SYNC" 1142 DATA"" 1144 DATA"! Begin Free run loop" 1146 DATA" L1: F_THRUPUT 1,1" 1148 DATA" C_BNE FR0,VALID_LOOPS,0" 1150 DATA"" 1152 DATA"! Else, loops weren't valid. If already in blk mode, branch" 1154 DATA" C_BEQ NO_VAL,CONT_MODE,OFF" 1156 DATA"" 1158 DATA"! In cont mode: if stop, just quit" 1160 DATA" C_BEQ SW0,SWITCH_MODE,ON !Switch to continuous?" 1162 DATA" F_WAIT_TO_SIG 20" 1164 DATA" F_WAIT_TO_SIG 0" 1166 DATA" C_END" 1168 DATA"" 1170 DATA"! In cont mode: need to switch to block" 1172 DATA" SW0: F_WAIT_TO_SIG 30" 1174 DATA" F_WAIT_TO_SIG 0 !avg mode is off" 1176 DATA" C_GOSUB RESTART" 1178 DATA" C_GOTO NO_AV" 1180 DATA"" 1182 DATA"! Process module information" 1184 DATA" FR0: V_CEQUATE 0,I !for i=0 to NUM_MODS-1" 1186 DATA" L2: V_MULT I,BSIZ,P_INP !pointer to input data" 1188 DATA"" 1190 DATA"! Reinitialize time exponent (is overwritten by fft/MAGSQ)" 1192 DATA" V_PUT32_INDEXED PARAM,0,ZERO" 1194 DATA" F_SIG_PROC FFT,0,5,PARAM,0,COEF,0" 1196 DATA". WIND,0,INPUT_BUFF,P_INP,FREQ,0" 1198 DATA"" 1200 DATA"! Do some parallel processing while waiting for the FFT" 1202 DATA" V_MULT I,FFTSIZEX4,P_OUT !ptr to output buffer" 1204 DATA" V_ADD 1,I,I" 1206 DATA"" 1208 DATA"! Now wait for the FFT, swap sides, convert to float" 1210 DATA" FFT0: C_SP_BEQ FFT0,2" 1212 DATA"" 1214 DATA" V_GET32_INDEXED PARAM,0,A !get block exp" 1216 DATA" V_PUT32_INDEXED ^FREQ,0,A !save block exp" 1218 DATA" F_INT_TO_FLOAT FREQ,FFT_KEEP_O,AVG_ARRAY,P_OUT,KEEP" 1220 DATA" V_ADD KEEPX4,P_OUT,P_OUT" 1222 DATA" F_INT_TO_FLOAT FREQ,0,AVG_ARRAY,P_OUT,KEEP_PL_1" 1224 DATA"" 1226 DATA"! Any more modules? If so Branch" 1228 DATA" C_BLT L2,I,NUM_MODS" 1230 DATA"" 1232 DATA"! Signal Processing Completed, show results" 1234 DATA" F_MOVE_BLOCK AVG_ARRAY,0,OUTPUT_BUFF,0,FP_WORDSX4" 1236 DATA" F_WAIT_TO_SIG 5 !free run signal" 1238 DATA" C_GOTO L1 !just loop, don't stop!" 1240 DATA"" 1242 DATA"!---------Averaging Code----------------------------------" 1244 DATA"" 1246 DATA" AVERAGE: C_NOP" 1248 DATA"" 1250 DATA"! Initialize averaging array" 1252 DATA" F_FAST_AVG_INIT AVG_ARRAY,0,ARRAY_SIZE,0,BASE_EXP,BASE_EXP" 1254 DATA" V_CEQUATE 1,AVG_NUM" 1256 DATA"" 1258 DATA"! Branch to special routine if 'show only final average'" 1260 DATA" C_BEQ ONLY_LAST,DISP_MODE,FINAL" 1262 DATA"" 1264 DATA"!-----'Show all averages' or 'Fast update' Code----------------" 1266 DATA"" 1268 DATA"! Wait for BASIC to catch up, then start modules" 1270 DATA"INTA: F_GLB_COMMAND CLASS,'STRT'" 1272 DATA" F_WAIT_TO_SIG 6" 1274 DATA" F_PAUSE" 1276 DATA" C_GOSUB WAIT_RDY" 1278 DATA" F_SYNC" 1280 DATA"" 1282 DATA"! Begin averaging loop" 1284 DATA" L_TOP: F_THRUPUT 1,1" 1286 DATA" C_BNE LR0,VALID_LOOPS,0" 1288 DATA"" 1290 DATA"! Else, loops weren't valid. If already in blk mode, branch" 1292 DATA" C_BEQ NO_VAL,CONT_MODE,OFF" 1294 DATA"" 1296 DATA"! In cont mode: if stop, just quit" 1298 DATA" V_SUB AVG_NUM,1,A" 1300 DATA" C_BLE BAD,A,0 !Did it die on the first pass?" 1302 DATA" ! If not, show last real time average" 1304 DATA" F_FAST_AVG_DIV AVG_ARRAY,0,OUTPUT_BUFF,0,ARRAY_SIZE,A" 1306 DATA" C_BEQ SW1,SWITCH_MODE,ON !Switch to continuous?" 1308 DATA" F_WAIT_TO_SIG 20" 1310 DATA" F_WAIT_TO_SIG A !# of avgs completed" 1312 DATA" C_END " 1314 DATA"" 1316 DATA"! In cont mode: need to switch to block" 1318 DATA" SW1: F_WAIT_TO_SIG 30" 1320 DATA" F_WAIT_TO_SIG A !# of avgs completed" 1322 DATA" C_GOSUB RESTART" 1324 DATA" C_GOTO INTA" 1326 DATA"" 1328 DATA"! Do all modules" 1330 DATA" LR0: V_CEQUATE 0,I ! FOR I=0 TO #MODS-1" 1332 DATA" V_CEQUATE 0,P_INP !pointer to inp data" 1334 DATA" TOP: V_PUT32_INDEXED PARAM,0,ZERO" 1336 DATA" F_SIG_PROC FFT,0,5, PARAM,0, COEF,0" 1338 DATA". WIND,0, INPUT_BUFF,P_INP, FREQ,0" 1340 DATA"" 1342 DATA"! Do a bit of parallel processing here" 1344 DATA" V_MULT I,FFTSIZEX5,P_OUT !pointer to output buffer" 1346 DATA" V_ADD 1,I,I !increment loop exponent" 1348 DATA" V_MULT I,BSIZ,P_INP !pointer to next inp data" 1350 DATA"" 1352 DATA" FFT_W: C_SP_BEQ FFT_W,2 !wait till FFT is ready" 1354 DATA" V_GET32_INDEXED PARAM,0,FREQ_EXP" 1356 DATA" F_FAST_AVG_ADD FREQ,FFT_KEEP_O,AVG_ARRAY,P_OUT" 1358 DATA". KEEP,FREQ_EXP" 1360 DATA" V_ADD KEEPX5,P_OUT,P_OUT" 1362 DATA" F_FAST_AVG_ADD FREQ,0,AVG_ARRAY,P_OUT,KEEP_PL_1,FREQ_EXP" 1364 DATA" C_BLT TOP,I,NUM_MODS ! NEXT I" 1366 DATA"" 1368 DATA"! Are all averages completed? If so, show last average" 1370 DATA" C_BEQ LAST1,AVG_NUM,NUM_AVGS" 1372 DATA"" 1374 DATA"! Else, Calc intermediate average" 1376 DATA" F_FAST_AVG_DIV AVG_ARRAY,0,OUTPUT_BUFF,0,ARRAY_SIZE,AVG_NUM" 1378 DATA" V_MULT AVG_NUM,MINUS1,A" 1380 DATA" F_SIGNAL A !signal is -1 * current average" 1382 DATA"" 1384 DATA"! Pause if 'show all' has been selected" 1386 DATA" C_BNE INC,DISP_MODE,ALL ! Branch if Fast update" 1388 DATA" F_PAUSE" 1390 DATA"" 1392 DATA"! Increment average number and loop" 1394 DATA" INC: V_ADD 1,AVG_NUM,AVG_NUM" 1396 DATA" C_GOTO L_TOP" 1398 DATA"" 1400 DATA"! Last average completed" 1402 DATA" LAST1:" 1404 DATA" F_FAST_AVG_DIV AVG_ARRAY,0,OUTPUT_BUFF,0,ARRAY_SIZE" 1406 DATA". NUM_AVGS" 1408 DATA" F_WAIT_TO_SIG 1 !data ready from all" 1410 DATA" C_BEQ QUIT,FREE_RUN,OFF" 1412 DATA"" 1414 DATA"! Else, Free run selected, Initialize averaging array, set" 1416 DATA"! average number to 1, and continue taking data" 1418 DATA"" 1420 DATA" F_FAST_AVG_INIT AVG_ARRAY,0,ARRAY_SIZE,0" 1422 DATA". BASE_EXP,BASE_EXP" 1424 DATA" V_CEQUATE 1,AVG_NUM" 1426 DATA" C_GOTO L_TOP" 1428 DATA"" 1430 DATA"!-----------Show only Last Average Code------------------------" 1432 DATA"" 1434 DATA"! Quick routine to show only last average, blk or cont" 1436 DATA"! Begin averaging loop" 1438 DATA"" 1440 DATA"! Wait for BASIC to catch up, then start modules" 1442 DATA" ONLY_LAST:" 1444 DATA" F_GLB_COMMAND CLASS,'STRT'" 1446 DATA" F_WAIT_TO_SIG 6" 1448 DATA" F_PAUSE" 1450 DATA" C_GOSUB WAIT_RDY" 1452 DATA" F_SYNC" 1454 DATA"" 1456 DATA" F_TOP: F_THRUPUT 1,1" 1458 DATA" C_BNE TO_AV,VALID_LOOPS,0 !branch if we got valid data" 1460 DATA"" 1462 DATA"! Else, loops weren't valid. If already in blk mode, branch" 1464 DATA" C_BEQ NO_VAL,CONT_MODE,OFF" 1466 DATA"" 1468 DATA"! In cont mode: if stop, just divide by avg_num-1, quit" 1470 DATA" V_SUB AVG_NUM,1,A" 1472 DATA" C_BLE BAD,A,0 " !Did it die on the first pass? 1474 DATA" F_FAST_AVG_DIV AVG_ARRAY,0,OUTPUT_BUFF,0,ARRAY_SIZE,A" 1476 DATA" C_BEQ SW,SWITCH_MODE,ON" !Switch to continuous? 1478 DATA" F_WAIT_TO_SIG 20" 1480 DATA" F_WAIT_TO_SIG A ! # real time avgs completed" 1482 DATA" C_END" 1484 DATA"" 1486 DATA"! In cont mode: need to switch to block" 1488 DATA" SW: F_WAIT_TO_SIG 30" 1490 DATA" F_WAIT_TO_SIG A ! # real time avgs completed" 1492 DATA" C_GOSUB RESTART" 1494 DATA" C_GOTO ONLY_LAST" 1496 ! 1498 DATA"! Gets here if loops valid: Process inpt module data" 1500 DATA" TO_AV: V_CEQUATE 0,I !initialize loop counter" 1502 DATA" V_CEQUATE 0,P_INP !initialize ptr to inp buff" 1504 DATA"" 1506 DATA"! Reinitialize the time exponent (gets changed by FFT/mag^2)" 1508 DATA" F_MOD:V_PUT32_INDEXED PARAM,0,ZERO" 1510 DATA" F_SIG_PROC FFT,0,5,PARAM,0,COEF,0" 1512 DATA". WIND,0,INPUT_BUFF,P_INP,FREQ,0" 1514 DATA"" 1516 DATA"! Instead of just waiting for the FFT, do some parallel processing" 1518 DATA" V_MULT I,FFTSIZEX5,P_OUT !offset in output array" 1520 DATA" V_ADD KEEPX5,P_OUT,P_OUT2 !2nd offset in output array" 1522 DATA" V_ADD 1,I,I !increment loop counter" 1524 DATA" V_MULT I,BSIZ,P_INP !pointer to next input data" 1526 DATA"" 1528 DATA"! Now wait for the FFT" 1530 DATA" FFT_1: C_SP_BEQ FFT_1,2" 1532 DATA" V_GET32_INDEXED PARAM,0,FREQ_EXP !get block exp" 1534 DATA"" 1536 DATA"! Swap sides by doing 2 smaller fast averages" 1538 DATA" F_FAST_AVG_ADD FREQ,FFT_KEEP_O,AVG_ARRAY,P_OUT" 1540 DATA". KEEP,FREQ_EXP" 1542 DATA" F_FAST_AVG_ADD FREQ,0,AVG_ARRAY,P_OUT2,KEEP_PL_1,FREQ_EXP" 1544 DATA"" 1546 DATA"! Are data from all modules processed? Branch if no" 1548 DATA" C_BLT F_MOD,I,NUM_MODS" 1550 DATA"" 1552 DATA"! Are all averages completed? If not, do more." 1554 DATA" V_ADD 1,AVG_NUM,AVG_NUM !increment average number" 1556 DATA" C_BLE F_TOP,AVG_NUM,NUM_AVGS" 1558 DATA"" 1560 DATA"!---------Avg Code (cont)------------------------------------" 1562 DATA"" 1564 DATA"! Last average completed" 1566 DATA" LAST_AVG:" 1568 DATA" F_FAST_AVG_DIV AVG_ARRAY,0,OUTPUT_BUFF,0" 1570 DATA". ARRAY_SIZE,NUM_AVGS" 1572 DATA" F_SIGNAL 1 !data ready from all" 1574 DATA" C_BEQ QUIT,FREE_RUN,OFF" 1576 DATA "" 1578 DATA "! Else, Free run selected, Initialize averaging array, set" 1580 DATA "! average number to 1, and continue taking data" 1582 DATA"" 1584 DATA" F_FAST_AVG_INIT AVG_ARRAY,0,ARRAY_SIZE,0" 1586 DATA". BASE_EXP,BASE_EXP" 1588 DATA" V_CEQUATE 1,AVG_NUM" 1590 DATA" C_GOTO F_TOP" 1592 DATA"" 1594 DATA"!------Several endings, some happy, some not--------------------" 1596 DATA"" 1598 DATA" QUIT:" 1600 DATA" F_GLB_COMMAND CLASS,'STOP'" 1602 DATA" C_END" 1604 DATA"" 1606 DATA" BAD: F_SIGNAL 99 !measurement died on the first pass" 1608 DATA" C_END" 1610 DATA"" 1612 DATA" NO_VAL: F_SIGNAL 2" 1614 DATA" C_END" 1616 DATA"" 1618 DATA"" 1620 DATA"!***********************************************************" 1622 DATA"! Subroutine WAIT_RDY waits for global ready" 1624 DATA"!***********************************************************" 1626 DATA" WAIT_RDY:" 1628 DATA" F_GET_GLB_STA A" 1630 DATA" V_NOT A,A" 1632 DATA" C_BITSET WAIT_RDY,A,4 !loop until ready" 1634 DATA" C_RTS" 1636 DATA"" 1638 DATA"!***********************************************************" 1640 DATA"! Subroutine INIT_WIND forms window block in the TMS320 RAM " 1642 DATA"!***********************************************************" 1644 DATA"" 1646 DATA" INIT_W: C_BEQ HANN,WIND_TYPE,1" 1648 DATA" C_BEQ FLAT_TOP,WIND_TYPE,2" 1650 DATA" HANN:" 1652 DATA" F_FLOAT_WINGEN INPUT_BUFF,0,FFTSIZE,2,0.499984,-.499984" 1654 DATA" C_GOTO CONT_WIND" 1656 DATA" FLAT_TOP:" 1658 DATA"" 1660 DATA"! The 'normal' flat top coefficients are" 1662 DATA"! 0.994484/2,-0.955728,0.539289,-.0915810" 1664 DATA"! These are all scaled here to make the peak at 32767" 1666 DATA" F_FLOAT_WINGEN INPUT_BUFF,0,FFTSIZE,4, .954423166665" 1668 DATA". -1.8344567519 , 1.03512960516,-.175783678825" 1670 DATA" CONT_WIND:" 1672 DATA" F_FLOAT_TO_SHORT INPUT_BUFF,0,OUTPUT_BUFF,0,FFTSIZE" 1674 DATA" F_SHORT_INTRLVE OUTPUT_BUFF,0,OUTPUT_BUFF,0,WIND,0,FFTSIZE" 1676 DATA" C_RTS" 1678 DATA"" 1680 DATA"!********************************************************" 1682 DATA"! Subroutine RESTART restarts measurement in block mode" 1684 DATA"!*********************************************************" 1686 DATA" RESTART:" 1688 DATA" F_GLB_COMMAND CLASS,'STOP;CLR'" 1690 DATA" F_GLB_COMMAND CLASS,'TRNM BLK'" 1692 DATA" C_RTS" 1694 DATA"" 1696 DATA"!********************************************************" 1698 DATA"! Subroutine ICODE_INIT gets info from parameter block," 1700 DATA"! Initializes pointers, etc." 1702 DATA"!*********************************************************" 1704 DATA" ICODE_INIT:" 1706 DATA" V_GET16_INDEXED PARAM,7,FFTSIZE !512,1024,2048,4096" 1708 DATA" V_MULT FFTSIZE,2,FFTSIZEX2" 1710 DATA" V_MULT FFTSIZE,4,FFTSIZEX4" 1712 DATA" V_MULT FFTSIZE,5,FFTSIZEX5" 1714 DATA"" 1716 DATA"! The following assignments help to eliminate the" 1718 DATA"! time involved in swapping the FFT sides" 1720 DATA"! Using a 512 complex FFT as an example, we want to Fast" 1722 DATA"! Average the last 200 (32-bit) words in FFT m^2 output into the" 1724 DATA"! first 200 (80-bit) 'words' of the fast average array; we want to" 1726 DATA"! Fast Average the first 201 32-bit words of the FFT M^2 output" 1728 DATA"! into the average array, offset by 200 'words'." 1730 DATA"! Thus we need 5 new variables here:" 1732 DATA"! KEEP=(200/512)*fftsize" 1734 DATA"! KEEP_PL_1=KEEP+1" 1736 DATA"! KEEPX4 = KEEP * 4 (FP offset in fast avg array)" 1738 DATA"! KEEPX5 = KEEP * 5 (offset in fast avg array)" 1740 DATA"! FFT_KEEP_O=FFTSIZE+7/32*FFTSIZE (offset of 1st part of spectrum)" 1742 DATA" V_MULT FFTSIZE, 200, KEEP" 1744 DATA" V_DIV KEEP, 512, KEEP" 1746 DATA" V_ADD KEEP, 1, KEEP_PL_1" 1748 DATA" V_MULT KEEP, 4, KEEPX4" 1750 DATA" V_MULT KEEP, 5, KEEPX5" 1752 DATA" V_MULT FFTSIZE, 39, A" 1754 DATA" V_DIV A, 32, FFT_KEEP_O" 1756 DATA"" 1758 DATA" V_GET16_INDEXED PARAM,8,NUM_AVGS" 1760 DATA" V_GET16_INDEXED PARAM,9,WIND_TYPE !1=HANNING, 2=FLATTOP" 1762 DATA" V_GET16_INDEXED PARAM,10,DISP_MODE !final,some,all=0,1,2" 1764 DATA" V_GET16_INDEXED PARAM,11,AVG_MODE !0=OFF,1=ON" 1766 DATA" V_GET16_INDEXED PARAM,12,FREE_RUN !0=OFF,1=ON" 1768 DATA" V_GET16_INDEXED PARAM,13,CONT_MODE !0=BLOCK,1=CONTINUOUS" 1770 DATA" V_GET16_INDEXED PARAM,14,SWITCH_MODE !0=STOP,1=SW TO BLK" 1772 DATA"" 1774 DATA" V_GET16_INDEXED MOD_LIST,0,BSIZ" 1776 DATA" V_GET16_INDEXED MOD_LIST,2,NUM_MODS !# active inp modules" 1778 DATA" V_MULT FFTSIZE,NUM_MODS,ARRAY_SIZE !#data points" 1780 DATA" V_MULT ARRAY_SIZE,4,FP_WORDSX4 !used in no avg code" 1782 DATA"" 1784 DATA"! Initialize input buffer array" 1786 DATA" F_READY_RAM 1,INPUT_BUFF,0,MOD_LIST,0,VALID_LOOPS" 1788 DATA" F_KEEP_READY_RAM" 1790 DATA" C_RTS" 1792 DATA"!------------------------------------------------------------" 1794 DATA" END: C_END" 1796 DATA"EL_COMPLETO" 1798 SUBEND 1800 ! 1802 ! PAGE -> 1804 !*********************************************************************** 1806 Appl_powerup:SUB Appl_powerup 1808 ! Called by Appl_init, This routine defines the MEASUREMENT, INPUT, 1810 ! and SOURCE spreadsheet choices, as well as some system constants, 1812 ! such as digital filter factor, window correction factors etc. 1814 COM /Psd_scale_info/ Half_lsb,Corr_fact,Flat_top_fact,Hann_fact,Range(*) 1815 COM /Psd_bw_info/ Flat_top_bw,Hann_bw 1817 ! 1818 DISP "Initialize spreadsheet: INPT" 1820 DIM Setup$(1:10)[20] 1822 ! 1824 RESTORE Input_cols 1826 GOSUB Fill_setup 1828 Inpt_init(Setup$(*)) 1830 Input_cols:! 1832 DATA 7 1834 DATA "INPUT MODE","COUPLING","GROUNDING","RANGE","TRIG MODE" 1836 DATA "TRIG LEVEL","TRIG SLOPE" 1838 ! 1840 DISP "Initialize spreadsheet: SRCE" 1842 RESTORE Source_cols 1844 GOSUB Fill_setup 1846 Srce_init(Setup$(*)) 1848 Source_cols:! 1850 DATA 8 1852 DATA "MODE","OFFSET","AMPLITUDE","SINE FREQ","SPAN","CENTER FREQ" 1854 DATA "TRIG","BURST %" 1856 ! 1858 DISP "Initialize spreadsheet: MEAS" 1860 Meas_init 1862 ! 1864 DISP "Initialize system scaling constants" 1866 ! Define system scaling consants to prevent recalculation later 1868 Two_db_over=(10^.1) !+2db overange in input module 1870 Dig_filt_corr=(32768/15094.3657) !filter correction in inp mod 1872 Twin_sided=2 !For twin-sided spectrum 1874 Corr_fact=(Dig_filt_corr*Two_db_over*Twin_sided)^2 !total corr fact 1876 Flat_top_fact=4.1762^2 !flat top window correction 1878 Hann_fact=2^2 !Hanning Correction 1880 Half_lsb=(.5/65536)^2 !assign log(0) to this value 1881 Flat_top_bw=(3.42) !Noise equiv bandwidth factor 1882 Hann_bw=(1.5) !Noise equiv bandwidth factor 1884 DISP "" 1885 ! 1886 SUBEXIT 1888 Fill_setup:! 1890 READ Num_cols 1892 REDIM Setup$(1:Num_cols) 1894 FOR I=1 TO Num_cols 1896 READ Setup$(I) 1898 NEXT I 1900 RETURN 1902 SUBEND 1904 ! 1906 ! PAGE -> 1908 !*********************************************************************** 1910 Appl_help:SUB Appl_help 1912 ! This routine has a series of 'help screens' to give the user some 1914 ! quick information about the system...It is NOT meant to be a 1916 ! substitute for other documentation. 1918 DIM A$[160] 1920 RESTORE Page1 1922 GOSUB Show_page 1924 RESTORE Page2 1926 GOSUB Show_page 1928 RESTORE Page3 1930 GOSUB Show_page 1932 RESTORE Page4 1934 GOSUB Show_page 1936 SUBEXIT 1938 Show_page:! 1940 READ A$ 1942 User_clr_scr 1944 WHILE A$<>"***END***" 1946 OUTPUT CRT;A$ 1948 READ A$ 1950 END WHILE 1952 OUTPUT KBD USING "#,K";"ÿ#Yÿ<" 1954 INPUT "Type 'Y' to continue, anything else to leave...",A$ 1956 IF UPC$(A$[1;1])<>"Y" THEN SUBEXIT 1958 RETURN 1960 Page1: ! 1962 DATA " Help for Power Spectrum Application" 1964 DATA "" 1966 DATA "This is the Power Spectrum Application for the HP35650" 1968 DATA "system. In it you can display the Power Spectrum (dBVp)" 1970 DATA "or Power Spectral Density (V^2/Hz) of up to 16 channels." 1972 DATA "The application tries to 'come up running' once a trigger" 1974 DATA "has been received by the first active input module." 1976 DATA "" 1978 DATA "This application assumes that the Configuration Menu has" 1980 DATA "already been used to assign labels to the modules in your" 1982 DATA "system, and to specify which modules will be active. If you" 1984 DATA "haven't done this, and you want to, use the EXIT key and then" 1986 DATA "the CONFIG key to enter the Configuration Menu. Modules that" 1988 DATA "are inactive are treated as though they are not in the system" 1990 DATA "at all." 1992 DATA "***END***" 1994 Page2: ! 1996 DATA " Help for Power Spectrum Application--Page 2" 1998 DATA "" 2000 DATA "There are four keys that are used to set up a measurement:" 2002 DATA "SOURCE SETUP, INPUT SETUP, DISPLAY SETUP, and MEASURE SETUP." 2004 DATA 2006 DATA "The SOURCE SETUP key is used to set up source modules." 2008 DATA "When the system is first powered up, all source modules are OFF." 2010 DATA "Source modules not selected as being 'OFF' are started upon" 2012 DATA "leaving the SOURCE SETUP. However, if the source is in a" 2014 DATA "trigger mode other than off, it may not start until a trigger" 2016 DATA "is received. Note that the Burst % and Burst Time columns are" 2018 DATA "only meaningful if both source and input modules have the same" 2020 DATA "span and block size." 2022 DATA "***END***" 2024 Page3: ! 2026 DATA " Help for Power Spectrum Application - Page 3" 2028 DATA "" 2030 DATA "The INPUT SETUP key is used to setup input modules." 2032 DATA "When the system powers up, one input module will be in" 2034 DATA "SEND trigger mode, and the others will be in RECEIVE trigger" 2036 DATA "mode. At least one module (input or source) should normally" 2038 DATA "be in SEND trigger mode, so that the system will trigger." 2040 DATA "The inputs start out at range 0 dBVp, and will usually" 2042 DATA "need to have their ranges changed to appropriate levels." 2044 DATA "The Autorange function is useful if the source module is" 2046 DATA "already going, but it takes at least 20 seconds, and will" 2048 DATA "not always work correctly if the source is in a burst or" 2050 DATA "pulse mode." 2052 DATA "" 2054 DATA "The DISPLAY SETUP key is used to change what is displayed" 2056 DATA "on the screen. Each line in the menu corresponds to a trace" 2058 DATA "which could be plotted. The trace will not actually be plotted" 2060 DATA "unless it is made active." 2062 DATA "***END***" 2064 Page4: ! 2066 DATA " Help for Power Spectrum Application - Page 4" 2068 DATA "" 2070 DATA "The MEASURE SETUP key is used to change the nature of the" 2072 DATA "measurement that is being made. Averaging and FFT Window" 2074 DATA "Type, and the frequency span and center frequency can all" 2076 DATA "be set here." 2078 DATA "" 2080 DATA "Any of the four menus can be entered without aborting a" 2082 DATA "measurement that is in progress. However, changing anything" 2084 DATA "in any menu except the DISPLAY SETUP menu will stop the" 2086 DATA "measurement. Any current data is thrown away unless the" 2088 DATA "change was in the SOURCE SETUP menu. While you are in any" 2090 DATA "menu, the measurement is temporarily paused." 2092 DATA "" 2094 DATA "Changes can be made in the DISPLAY SETUP menu without affecting" 2096 DATA "a measurement and without destroying any data. You can do a" 2098 DATA "complete measurement and later decide what data you need to" 2100 DATA "display." 2102 DATA "***END***" 2104 SUBEND 2106 ! 2108 ! PAGE -> 2110 !************************************************************************* 2112 Appl_debug:SUB Appl_debug(INTEGER Debug_mode) 2114 ! This routine enbles the user to call the Icode debugger interactively, 2116 !yet keeps an application's COM blocks separate from the debugger. 2118 !The parameter passed in is defined in the Icode documentation, but 2120 !briefly is as follows: 2122 ! 0: If Icode paused, then debug, else return 2124 ! 1: Wait for pause, then debug 2126 ! 2: Debug 2128 COM /Psd_block_info/ Icode_info$(*),Source$(*),INTEGER Compiled(*),Icode_compiled,Icode_id,Source_size 2130 User_clr_scr ! clear screen 2132 CALL Icode_debug(Debug_mode,Icode_info$(*),Source$(*)) 2134 User_clr_scr ! clear screen 2136 SUBEND 2138 ! 2140 ! PAGE -> 2142 !************************************************************************* 2144 Appl_main:SUB Appl_main(Init) 2146 ! 2148 ! This is the main loop for the application. It sets up the 2150 ! measurement, sets up the softkeys, then (in a loop) processes 2152 ! key presses, updates the measurement, and calls the 2154 ! measurement loop. 2156 ! 2158 COM /Appl_buf_info/ Disp_choices$(*),Input_labels$(*),Num_inputs 2160 ! 2162 GOSUB Appl_main_keys !setup softkeys 2164 ! 2166 Hw_dev_clear !make sure HP-IB path is open 2168 IF Init THEN 2170 Appl_init !Initialize Icode, params etc. 2172 END IF 2174 ! 2176 IF Num_inputs=0 THEN 2178 User_error("*** Sorry, the PSD application requires at least one input ***") 2180 SUBEXIT 2182 END IF 2184 ! 2186 Restart_meas=1 !come up running 2188 Display_changed=1 2190 Meas_stopped=0 !can't be stopped if we are running 2192 Axes_not_done=1 !Axes are not displayed yet 2194 Leave_me=0 !Flag to exit PSD application 2196 REPEAT 2198 ! 2200 IF Meas_stopped THEN 2202 DISP "Waiting for START key. . ." 2204 ON KEY 7 LABEL FNUser_keylabel$("START") CALL User_key7isr 2206 ELSE 2208 ON KEY 7 LABEL FNUser_keylabel$("STOP") CALL User_key7isr 2210 END IF 2212 ! 2214 IF Restart_meas THEN 2216 Appl_start 2218 Restart_meas=0 2220 Meas_stopped=0 2222 Display_changed=1 2224 Data_valid=0 2226 END IF 2228 ! 2230 IF Display_changed THEN 2232 Appl_update 2234 Disp_plot_axis ! a key press causes exit w/o finishing grids 2236 Axes_not_done=FNUser_key_press !are all axes up? 2238 END IF 2240 ! 2242 Appl_meas_loop(Meas_stopped,Display_changed,Data_valid) 2244 ! 2246 WHILE FNUser_key_press 2248 Appl_do_main(Restart_meas,Meas_stopped,Display_changed,Leave_me,Data_valid,Axes_not_done) 2250 END WHILE 2252 ! 2254 UNTIL Leave_me !Exit PSD Application 2256 Hw_dev_clear !make sure ICODE is stopped 2258 Cnfg_cmd("ALL","CLASM 50") !clean up class used in this measurement 2260 SUBEXIT 2262 ! 2264 Appl_dummy: ! 2266 BEEP 2268 RETURN 2270 ! 2272 Appl_main_keys:! 2274 ON KEY 0 LABEL "" GOSUB Appl_dummy 2276 ON KEY 1 LABEL FNUser_keylabel$("INPUT SETUP") CALL User_key1isr 2278 ON KEY 2 LABEL FNUser_keylabel$("SOURCE SETUP") CALL User_key2isr 2280 ON KEY 3 LABEL FNUser_keylabel$("DISPLAY SETUP") CALL User_key3isr 2282 ON KEY 4 LABEL FNUser_keylabel$("MEASURE SETUP") CALL User_key4isr 2284 ON KEY 5 LABEL FNUser_keylabel$("HELP") CALL User_key5isr 2286 ON KEY 6 LABEL FNUser_keylabel$("MARKER") CALL User_key6isr 2288 ON KEY 7 LABEL FNUser_keylabel$("START") CALL User_key7isr 2290 ON KEY 8 LABEL FNUser_keylabel$("EXIT") CALL User_key8isr 2292 ON KEY 9 LABEL "" GOSUB Appl_dummy 2294 RETURN 2296 ! 2298 SUBEND 2300 ! 2302 ! PAGE -> 2304 !*********************************************************************** 2306 Appl_do_main:SUB Appl_do_main(Restart,Stopped,Disp_modified,Leave_me,Data_valid,Axes_not_done) 2308 COM /Appl_data/ Data_buffer(*),Data_header(*) 2310 ! 2312 ! This routine is called when one of the main softkeys is pressed. 2314 ! 2316 Key_num=FNUser_get_key 2318 ! 2320 Change_in_hw=0 2322 ! 2324 SELECT Key_num 2326 CASE 1 2328 ON KEY Key_num LABEL FNUser_keylabel$("MAIN") CALL User_key1isr 2330 CALL Inpt_spread(Change_in_hw) 2332 Disp_modified=1 2334 OFF KEY Key_num 2336 CASE 2 2338 ON KEY Key_num LABEL FNUser_keylabel$("MAIN") CALL User_key2isr 2340 CALL Srce_spread(Change_in_hw) 2342 Disp_modified=1 2344 OFF KEY Key_num 2346 CASE 3 2348 ON KEY Key_num LABEL FNUser_keylabel$("MAIN") CALL User_key3isr 2350 CALL Disp_spread(Disp_modified) 2352 Disp_modified=1 2354 OFF KEY Key_num 2356 CASE 4 2358 ON KEY Key_num LABEL FNUser_keylabel$("MAIN") CALL User_key4isr 2360 CALL Meas_spread(Meas_modified,Default_y) 2362 IF Default_y THEN CALL Disp_reset_y 2364 Disp_modified=1 2366 OFF KEY Key_num 2368 CASE 5 2370 Appl_help 2372 Disp_modified=1 2374 CASE 6 2376 IF Data_valid THEN !there is data to mark 2378 ON KEY Key_num LABEL FNUser_keylabel$("MAIN") CALL User_key6isr 2380 IF Axes_not_done OR Disp_modified THEN ! put 'em up 2382 Disp_plot_axis 2384 Axes_not_done=FNUser_key_press !If Key pressed, axes not done 2386 Disp_modified=0 !because we are fixing it 2388 END IF 2390 CALL Disp_do_mkr(Data_buffer(*),Data_header(*),0) 2392 OFF KEY Key_num 2394 ELSE 2396 Disp_modified=1 2398 User_error("*** There is no valid data for marker now ***") 2400 END IF 2402 CASE 7 2404 IF Stopped THEN 2406 Restart=1 2408 Stopped=0 2410 ELSE 2412 Stopped=1 2414 END IF 2416 CASE 8 2418 Leave_me=1 2420 END SELECT 2422 ! 2424 IF Meas_modified OR Change_in_hw THEN 2426 Stopped=1 2428 Data_valid=0 2430 END IF 2432 ! 2434 IF FNUser_key_press THEN 2436 IF FNUser_check_key=Key_num THEN Key_num=FNUser_get_key 2438 END IF 2440 SUBEND 2442 ! 2444 ! PAGE -> 2446 !*********************************************************************** 2448 Appl_meas_loop:SUB Appl_meas_loop(Stopped,Replot,Data_valid) 2450 COM /Appl_data/ Data_buffer(*),Data_header(*) 2452 ! 2454 ! This routine is called when no keys are being pressed. It 2456 ! should not return until a key has been pressed, or the measurement 2458 ! is done. The plot routine is called here. 2460 ! 2462 Replot=Replot AND Data_valid 2464 REPEAT 2466 IF (NOT Stopped) THEN 2468 Appl_get_data(New_data,Stopped,Screen_cleared) 2470 Data_valid=Data_valid OR New_data 2472 Replot=New_data 2474 END IF 2476 IF Replot AND NOT FNUser_key_press THEN 2478 Disp_plot_data(Data_buffer(*),Data_header(*)) 2480 Replot=0 2482 IF FNUser_key_press AND FNUser_check_key=7 AND Stopped THEN Swallow=FNUser_get_key !see *** below 2484 END IF 2486 Replot=Replot OR Screen_cleared 2488 UNTIL FNUser_key_press OR Stopped 2490 SUBEXIT 2492 !***: note that if the Appl_get_data routine stops the measurement 2494 !(by setting the Stopped flag), the START/STOP key function has changed 2496 !before we can update the label. Thus, the user sees 'STOP' when in 2498 !fact the key is a START key. 'Swallowing' the keypress allows the 2500 !routine to exit in the 'Stopped' state, as the user expects. 2502 SUBEND 2504 ! 2506 ! 2508 ! PAGE -> 2510 !*********************************************************************** 2512 Meas_meas:SUB Meas_meas 2514 ! Contains commons used by the PSD_MEAS subprograms 2516 ! Calls Meas_powerup 2518 COM /Meas_sprd/ Box$(1:2,1:14)[40],Title$(1:2,0:2)[40],Prompt$(1:14)[80] 2520 COM /Meas_sprd_num/ Col_width(1:2),Modify_col,INTEGER Max_row,Max_col 2522 COM /Meas_mod_labels/ Srce_labels$(1:63)[20],Inpt_labels$(1:63)[20] 2524 COM /Meas_mod_counts/ Srce_count,Inpt_count,Current_srce,Current_inpt 2526 COM /Meas_cmnd/ Cmnd$(2:5)[20],Def_value$(2:5)[20] 2528 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 2530 SUBEND 2532 Meas_powerup:SUB Meas_powerup 2534 ! Initializes constants, Sets default measurement parameters. 2536 ! Called by Meas_init. 2538 ! 2540 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 2542 COM /Meas_sprd_num/ Col_width(*),Modify_col,INTEGER Max_row,Max_col 2544 COM /Meas_mod_counts/ Srce_count,Inpt_count,Current_srce,Current_inpt 2546 COM /Meas_cmnd/ Cmnd$(*),Def_value$(*) 2548 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 2550 ! 2552 Cmnd_start=2 2554 Cmnd_stop=5 2556 Info_start=6 2558 X_axis_r=6 2560 Y_axis_r=7 2562 Blk_cont_r=8 2564 Av_r=9 2566 Numav_r=10 2568 Av_disp_r=11 2570 Wind_r=12 2572 Info_stop=12 2574 ! 2576 Max_col=2 2578 Modify_col=2 2580 Max_row=Info_stop 2582 REDIM Box$(1:2,1:Max_row) 2584 MAT Box$= ("") 2586 MAT Title$= ("") 2588 ! 2590 RESTORE Meas_data 2592 FOR Row=Cmnd_start TO Cmnd_stop 2594 READ Cmnd$(Row),Def_value$(Row),Box$(1,Row),Prompt$(Row) 2595 Box$(2,Row)=Def_value$(Row) 2597 NEXT Row 2598 FOR Row=Info_start TO Info_stop 2600 READ Box$(2,Row),Box$(1,Row),Prompt$(Row) 2602 NEXT Row 2604 ! 2606 Current_inpt=1 2608 Title$(1,0)="MEASUREMENT SETUP" 2610 Title$(1,1)="Item" 2612 Title$(2,1)="Value" 2614 Col_width(1)=40 2616 Col_width(2)=20 2618 ! 2620 Row=2 !reset cursor to top row for 1st time thru 2622 SUBEXIT 2624 Meas_data:! 2626 !COMMAND ROWS 2628 DATA "FFT SIZE", "512", "Complex FFT Size ->" 2630 DATA "Enter Complex FFT size (512, 1024, 2048, or 4096); (4096 Block mode only)" 2632 ! 2634 DATA "SPAN", "51200", "Frequency Span (Hz)->" 2636 DATA "Enter Span in Hz (0.39,0.78,...,25,50,100,..,102400)" 2638 ! 2640 DATA "CENTER FREQUENCY", "25600", "Center Frequency (Hz)->" 2642 DATA "Enter Center Frequency in Hz" 2644 ! 2646 DATA "TRIGGER DELAY", "0", "Trigger Delay (Samples)->" 2648 DATA "Enter Trigger Delay in samples (Even number, (-2*(FFTsize-1) to 1048574))" 2650 ! 2652 ! INFO ROWS (No Command) 2654 DATA "LOG Frequency" ,"Frequency axis (LOG/LIN)->" 2656 DATA "Enter Frequency axis mode (LOG Frequency, LIN Frequency)" 2658 DATA "LOG V^2/Hz", "Y axis ->", 2660 DATA "Enter Y axis units: dBVp, LOG V^2/Hz" 2662 DATA "Block", "Data collection mode ->" 2664 DATA "Enter collection mode (Block, Cont --> Stop, Cont-->Switch to blk)" 2666 DATA "ON", "Averaging (ON,OFF)->" 2668 DATA "Enter Averaging mode (ON,OFF)" 2670 DATA "4", "Number of Averages ->" 2672 DATA "Enter Number of averages (1,...,32767)" 2674 DATA "Restart after avgs", "Average Display Mode ->" 2676 DATA "Enter disp mode (after Each avg, Fast update, only Last avg, Restart after avgs)" 2678 DATA "Hann", "Window ->" 2680 DATA "Enter Window Type (Hann, Flat Top, Rectangular)" 2682 SUBEND 2684 ! 2686 ! page -> 2688 !********************************************************************** 2690 Meas_init:SUB Meas_init 2692 ! Gets input labels from the config module, 2694 ! Sets input modules to what is in the measurement spreadsheet 2696 ! 2698 Meas_powerup 2700 Meas_set_mods 2702 SUBEXIT 2704 ! 2706 SUBEND 2708 Meas_spread:SUB Meas_spread(Changed,Reset_y) 2710 ! This is where the user interacts with the Measurement spreadsheet. 2712 ! Valid New entries are put into the spreadsheet, Next/Prev keys 2714 ! are handled. 2716 !Changed is set true if any changes are made, 2718 !Reset_y is set true if changes are made to Y-axis: LIN/LOG 2720 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 2722 COM /Meas_sprd_num/ Col_width(*),Modify_col,INTEGER Max_row,Max_col 2724 COM /Meas_mod_labels/ Srce_labels$(*),Inpt_labels$(*) 2726 COM /Meas_mod_counts/ Srce_count,Inpt_count,Current_srce,Current_inpt 2728 COM /Meas_cmnd/ Cmnd$(*),Def_value$(*) 2730 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 2732 DIM New_entry$[160],Choices$(0:20)[80] 2734 INTEGER Done,Dummy,I,Found_it 2736 Changed=0 2738 Reset_y=0 2740 ! 2742 ! Define softkeys. Keys 1 through 4 are 'firmkeys' 2744 ! 2746 ON KEY 5 LABEL "" CALL User_key5isr 2748 ON KEY 6 LABEL "" CALL User_key6isr 2750 ON KEY 7 LABEL FNUser_keylabel$("Prev") CALL User_key7isr 2752 ON KEY 8 LABEL FNUser_keylabel$("Next") CALL User_key8isr 2754 ! 2756 User_clr_scr 2758 ! 2760 ! Now call spreadsheet. 2762 ! 2764 Col=2 2766 Start_row=1 2768 Done=0 2770 REPEAT 2772 User_spread(Box$(*),Title$(*),Prompt$(*),New_entry$,Col_width(*),Modify_col,Col,Row,Start_row) 2774 SELECT FNUser_check_key 2776 CASE 0 2778 GOSUB Meas_new_entry 2780 CASE 5,6 2782 BEEP 2784 Dummy=FNUser_get_key 2786 CASE 7 ! Prev 2788 Dummy=FNUser_get_key 2790 GOSUB Meas_prev 2792 CASE 8 ! Next 2794 Dummy=FNUser_get_key 2796 GOSUB Meas_next 2798 CASE ELSE ! A softkey, but not one of mine. 2800 Done=1 2802 END SELECT 2804 IF FNMeas_cont_blk$="CONT" AND FNMeas_fftsize=4096 THEN 2806 New_fft_size=2048 2808 GOSUB Update_fft_size 2810 END IF 2812 UNTIL Done 2814 User_clr_scr 2816 SUBEXIT 2818 ! 2820 Meas_new_entry:! 2822 SELECT Row 2824 CASE Cmnd_start ! It's the BLOCK SIZE command 2826 Changed=1 2828 ON ERROR GOTO Meas_bad_size 2830 New_fft_size=VAL(New_entry$) 2832 IF New_fft_size<512 THEN New_fft_size=512 2834 IF New_fft_size>4096 THEN New_fft_size=4096 2836 IF Inpt_count>4 THEN New_fft_size=MIN(2048,VAL(New_entry$)) 2838 IF Inpt_count>8 THEN New_fft_size=MIN(1024,VAL(New_entry$)) 2840 GOSUB Update_fft_size 2842 Meas_bad_size:OFF ERROR 2844 CASE Cmnd_start+1 TO Cmnd_stop-1 2846 Changed=1 2848 ON ERROR GOTO Meas_bad_cmnd 2850 IF Row=Cmnd_start+1 THEN !disallow .195 Hz span 2852 New_entry$=VAL$(MAX(.3,VAL(New_entry$))) 2854 END IF 2856 Inpt_cmd("ALL INPUT",Cmnd$(Row),New_entry$) 2858 Box$(2,Row)=TRIM$(FNInpt_rsp$(Inpt_labels$(1),Cmnd$(Row))) 2860 Meas_bad_cmnd:OFF ERROR 2862 CASE Cmnd_stop !the trigger delay row 2864 ON ERROR GOTO Meas_bad_tdly 2866 Changed=1 2868 New_tdly=2*INT(VAL(New_entry$)/2) 2870 GOSUB Update_tdly 2872 Meas_bad_tdly:OFF ERROR 2874 CASE X_axis_r 2876 ON ERROR GOTO Meas_bad_x_axis 2878 REDIM Choices$(1:2) 2880 Choices$(1)="LOG Frequency" 2882 Choices$(2)="LIN Frequency" 2884 GOSUB Meas_match_it 2886 Meas_bad_x_axis:OFF ERROR 2888 CASE Y_axis_r 2890 ON ERROR GOTO Meas_bad_y_axis 2892 REDIM Choices$(1:2) 2894 Choices$(1)="LOG V^2/Hz" 2896 Choices$(2)="dBVp" 2898 Reset_y=1 !reset Y axis to default if units change 2900 GOSUB Meas_match_it 2902 Meas_bad_y_axis:OFF ERROR 2904 CASE Blk_cont_r 2906 ON ERROR GOTO Meas_bad_blk_r 2908 REDIM Choices$(1:3) 2910 Choices$(1)="Cont --> Stop" 2912 Choices$(2)="Block" 2914 Choices$(3)="Cont-->Switch to blk" 2916 GOSUB Meas_match_it 2918 Meas_bad_blk_r:OFF ERROR 2920 CASE Av_r ! Set average on or off 2922 ON ERROR GOTO Meas_bad_av_r 2924 REDIM Choices$(1:2) 2926 Choices$(1)="ON" 2928 Choices$(2)="OFF" 2930 GOSUB Meas_match_it 2932 Meas_bad_av_r:OFF ERROR 2934 CASE Numav_r ! Set Number of averages 2936 ON ERROR GOTO Meas_no_number 2938 Temp=VAL(New_entry$) 2940 IF Temp<1 THEN Temp=1 2942 IF Temp>32767 THEN Temp=32767 2944 Box$(2,Row)=VAL$(PROUND(Temp,0)) 2946 Changed=1 2948 Meas_no_number:OFF ERROR 2950 CASE Wind_r ! Select window type 2952 ON ERROR GOTO Meas_bad_wind 2954 REDIM Choices$(1:3) 2956 Choices$(1)="Hann" 2958 Choices$(2)="Flat top" 2960 Choices$(3)="Rectangular" 2962 GOSUB Meas_match_it 2964 Meas_bad_wind:OFF ERROR 2966 CASE Av_disp_r 2968 ON ERROR GOTO Meas_bad_av_d 2970 REDIM Choices$(1:4) 2972 Choices$(1)="after Each avg" 2974 Choices$(2)="Restart after avgs" 2976 Choices$(3)="only Last avg" 2978 Choices$(4)="Fast update" 2980 GOSUB Meas_match_it 2982 Meas_bad_av_d:OFF ERROR 2984 END SELECT 2986 RETURN 2988 ! 2990 Meas_match_it:! 2992 Lib_match1(New_entry$,Choices$(*),Found,Choice_num) 2994 IF Found THEN 2996 Changed=1 2998 Box$(2,Row)=Choices$(Choice_num) 3000 END IF 3002 RETURN 3004 ! 3006 Meas_prev:! 3008 SELECT Row 3010 CASE Av_r,X_axis_r,Y_axis_r 3012 GOSUB Meas_toggle 3014 CASE Cmnd_start 3016 Changed=1 3018 Old_fft_size=VAL(Box$(2,Row)) 3020 SELECT Old_fft_size 3022 CASE 1024,2048,4096 3024 New_fft_size=Old_fft_size/2 3026 CASE 512 3028 SELECT Inpt_count 3030 CASE <=4 3032 New_fft_size=4096 3034 CASE <=8 3036 New_fft_size=2048 3038 CASE ELSE 3040 New_fft_size=1024 3042 END SELECT 3044 END SELECT 3046 GOSUB Update_fft_size 3048 CASE Cmnd_start+1 !SPAN ROW 3050 Changed=1 3052 IF VAL(Box$(2,Row))<.4 THEN Box$(2,Row)="200000" !wraparaound 3054 Inpt_cmd("ALL INPUT","SPAN",VAL$(.4*VAL(Box$(2,Row)))) 3056 Box$(2,Row)=TRIM$(FNInpt_rsp$(Inpt_labels$(1),"SPAN")) 3058 CASE Wind_r 3060 Changed=1 3062 SELECT UPC$(Box$(2,Row)) 3064 CASE "HANN" 3066 Box$(2,Row)="Rectangular" 3068 CASE "FLAT TOP" 3070 Box$(2,Row)="Hann" 3072 CASE "RECTANGULAR" 3074 Box$(2,Row)="Flat Top" 3076 END SELECT 3078 CASE Av_disp_r 3080 Changed=1 3082 SELECT UPC$(Box$(2,Row)) 3084 CASE "FAST UPDATE" 3086 Box$(2,Row)="after Each avg" 3088 CASE "AFTER EACH AVG" 3090 Box$(2,Row)="Restart after avgs" 3092 CASE "RESTART AFTER AVGS" 3094 Box$(2,Row)="only Last avg" 3096 CASE "ONLY LAST AVG" 3098 Box$(2,Row)="Fast update" 3100 END SELECT 3102 CASE Blk_cont_r 3104 Changed=1 3106 SELECT UPC$(Box$(2,Row)) 3108 CASE "BLOCK" 3110 Box$(2,Row)="Cont-->Switch to blk" 3112 CASE "CONT --> STOP" 3114 Box$(2,Row)="Block" 3116 CASE "CONT-->SWITCH TO BLK" 3118 Box$(2,Row)="Cont --> Stop" 3120 END SELECT 3122 END SELECT 3124 RETURN 3126 ! 3128 Meas_next:! 3130 SELECT Row 3132 CASE Av_r,X_axis_r,Y_axis_r 3134 GOSUB Meas_toggle ! Toggle average or free run 3136 CASE Cmnd_start 3138 Changed=1 3140 Old_fft_size=VAL(Box$(2,Row)) 3142 SELECT Old_fft_size 3144 CASE 512 3146 New_fft_size=1024 3148 CASE 1024 3150 SELECT Inpt_count 3152 CASE <=8 3154 New_fft_size=2048 3156 CASE ELSE 3158 New_fft_size=512 3160 END SELECT 3162 CASE 2048 3164 SELECT Inpt_count 3166 CASE <=4 3168 New_fft_size=4096 3170 CASE ELSE 3172 New_fft_size=512 3174 END SELECT 3176 CASE 4096 3178 New_fft_size=512 3180 END SELECT 3182 GOSUB Update_fft_size 3184 CASE Cmnd_start+1 !SPAN ROW 3186 Changed=1 3188 IF VAL(Box$(2,Row))>100000 THEN Box$(2,Row)="0.2" !wraparaound 3190 Inpt_cmd("ALL INPUT","SPAN",VAL$(1.5*VAL(Box$(2,Row)))) 3192 Box$(2,Row)=TRIM$(FNInpt_rsp$(Inpt_labels$(1),"SPAN")) 3194 CASE Wind_r 3196 Changed=1 3198 SELECT UPC$(Box$(2,Row)) 3200 CASE "HANN" 3202 Box$(2,Row)="Flat Top" 3204 CASE "FLAT TOP" 3206 Box$(2,Row)="Rectangular" 3208 CASE "RECTANGULAR" 3210 Box$(2,Row)="Hann" 3212 END SELECT 3214 CASE Av_disp_r 3216 Changed=1 3218 SELECT UPC$(Box$(2,Row)) 3220 CASE "ONLY LAST AVG" 3222 Box$(2,Row)="Restart after avgs" 3224 CASE "RESTART AFTER AVGS" 3226 Box$(2,Row)="after Each avg" 3228 CASE "AFTER EACH AVG" 3230 Box$(2,Row)="Fast update" 3232 CASE "FAST UPDATE" 3234 Box$(2,Row)="only Last avg" 3236 END SELECT 3238 CASE Blk_cont_r 3240 Changed=1 3242 SELECT UPC$(Box$(2,Row)) 3244 CASE "CONT --> STOP" 3246 Box$(2,Row)="Cont-->Switch to blk" 3248 CASE "CONT-->SWITCH TO BLK" 3250 Box$(2,Row)="Block" 3252 CASE "BLOCK" 3254 Box$(2,Row)="Cont --> Stop" 3256 END SELECT 3258 END SELECT 3260 RETURN 3262 ! 3264 Meas_toggle:! 3266 SELECT Row 3268 CASE X_axis_r 3270 Changed=1 3272 IF Box$(2,Row)="LOG Frequency" THEN 3274 Box$(2,Row)="LIN Frequency" 3276 ELSE 3278 Box$(2,Row)="LOG Frequency" 3280 END IF 3282 CASE Y_axis_r 3284 Changed=1 3286 Reset_y=1 3288 IF Box$(2,Row)="dBVp" THEN 3290 Box$(2,Row)="LOG V^2/Hz" 3292 ELSE 3294 Box$(2,Row)="dBVp" 3296 END IF 3298 CASE Av_r ! Toggle average mode on or off 3300 Changed=1 3302 IF Box$(2,Row)="ON" THEN 3304 Box$(2,Row)="OFF" 3306 ELSE 3308 Box$(2,Row)="ON" 3310 END IF 3312 END SELECT 3314 RETURN 3316 ! 3318 Update_fft_size:! 3320 Size$=VAL$(2*New_fft_size) 3322 IF FNMeas_cont_blk$="CONT" THEN Size$=VAL$(MIN(VAL(Size$),4096)) 3324 Inpt_cmd("ALL INPUT","BLOCK SIZE",Size$) 3326 Inpt_cmd("ALL INPUT","TRANSFER BLOCK SIZE",Size$) 3328 Box$(2,Cmnd_start)=TRIM$(VAL$(1/2*VAL(FNInpt_rsp$(Inpt_labels$(1),"BLOCK SIZE")))) 3330 IF FNMeas_tdly<-2*FNMeas_fftsize THEN 3332 New_tdly=-2*FNMeas_fftsize+2 3334 GOSUB Update_tdly 3336 END IF 3338 RETURN 3340 Update_tdly:! 3342 IF New_tdly<=-2*FNMeas_fftsize THEN New_tdly=-2*FNMeas_fftsize+2 3344 IF New_tdly>1048574 THEN New_tdly=1048574 3346 Inpt_cmd("ALL INPUT",Cmnd$(Cmnd_stop),VAL$(New_tdly)) 3348 Box$(2,Cmnd_stop)=TRIM$(FNInpt_rsp$(Inpt_labels$(1),Cmnd$(Cmnd_stop))) 3350 RETURN 3352 SUBEND 3354 !************************************************************************ 3356 ! 3358 ! Now some routines for the application to use 3360 ! 3362 !************************************************************************ 3364 Meas_span:DEF FNMeas_span 3366 ! Returns the Inpt span in Hz from the Measurement spreadsheet 3368 ! 3370 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3372 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3374 RETURN VAL(Box$(2,Cmnd_start+1)) 3376 FNEND 3378 ! 3380 Meas_cf:DEF FNMeas_cf 3382 ! Returns the Inpt center freq in Hz from the Measurement spreadsheet 3384 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3386 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3388 RETURN VAL(Box$(2,Cmnd_start+2)) 3390 FNEND 3392 ! 3394 Meas_block_size:DEF FNMeas_block_size 3396 ! Returns the Inpt block size from the Measurement spreadsheet 3398 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3400 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3402 RETURN VAL(Box$(2,Cmnd_start)) 3404 FNEND 3406 ! 3408 Meas_fftsize:DEF FNMeas_fftsize 3410 ! Returns the Complex FFTsize from the Measurement Spreadsheet 3412 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3414 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3416 IF POS(Box$(1,Cmnd_start),"FFT") THEN 3418 RETURN VAL(Box$(2,Cmnd_start)) 3420 ELSE 3422 RETURN 2*VAL(Box$(2,Cmnd_start)) 3424 END IF 3426 FNEND 3428 ! 3430 Meas_wind_type:DEF FNMeas_wind_type$ 3432 ! Returns the window type selected in the Measurement Spreadsheet 3434 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3436 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3438 RETURN Box$(2,Wind_r) 3440 FNEND 3442 ! 3444 Meas_num_avg:DEF FNMeas_num_avg 3446 ! Returns the number of averages selected in the Measurement Spreadsheet 3448 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3450 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3452 IF UPC$(Box$(2,Av_r))="ON" THEN 3454 RETURN VAL(Box$(2,Numav_r)) 3456 ELSE 3458 RETURN 1 3460 END IF 3462 FNEND 3464 ! 3466 Meas_avg_disp:DEF FNMeas_avg_disp$ 3468 ! Returns the display mode selected ('FINAL','ALL','SOME') 3470 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3472 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3474 Av_disp_r=Numav_r+1 !AVG DISPLAY ROW 3476 SELECT UPC$(Box$(2,Av_disp_r)) 3478 CASE "ONLY LAST AVG","RESTART AFTER AVGS" 3480 RETURN "FINAL" 3482 CASE "AFTER EACH AVG" 3484 RETURN "ALL" 3486 CASE "FAST UPDATE" 3488 RETURN "SOME" 3490 CASE ELSE 3492 User_error("unrecognized entry in FNMEAS_AVG_DISP :"&Box$(2,Av_disp_r)) 3494 RETURN "UNKNOWN" 3496 END SELECT 3498 FNEND 3500 ! 3502 Meas_avg_mode:DEF FNMeas_avg_mode 3504 ! Returns 1 if averages are on, 0 if averaging is off 3506 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3508 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3510 IF POS(UPC$(Box$(2,Av_r)),"ON") THEN RETURN 1 3512 RETURN 0 3514 FNEND 3516 ! 3518 Meas_free_run:DEF FNMeas_free_run 3520 ! Returns 1 if free run on, 0 if off 3522 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3524 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3526 IF POS(UPC$(Box$(2,Numav_r+1)),"RESTART") THEN RETURN 1 3528 RETURN 0 3530 FNEND 3532 ! 3534 Meas_num_inputs:DEF FNMeas_num_inputs 3536 !Returns number of inputs 3538 COM /Meas_mod_counts/ Srce_count,Inpt_count,Current_srce,Current_inpt 3540 RETURN Inpt_count 3542 FNEND 3544 ! 3546 Meas_cont_blk:DEF FNMeas_cont_blk$ 3548 ! Returns measurement mode: CONTinous or BLocK 3550 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3552 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3554 IF POS(UPC$(Box$(2,Av_r-1)),"STOP") THEN RETURN "CONT" 3556 IF POS(UPC$(Box$(2,Av_r-1)),"SWIT") THEN RETURN "CONT" 3558 RETURN "BLK" 3560 FNEND 3562 Meas_sw_to_blk:DEF FNMeas_sw_to_blk 3564 ! Returns 1 if switch to block mode has been selected 3566 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3568 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3570 IF POS(UPC$(Box$(2,Av_r-1)),"STOP") THEN RETURN 0 3572 RETURN 1 3574 FNEND 3576 ! 3578 Meas_cont_mode:DEF FNMeas_cont_mode 3580 ! Returns 1 if Continuous mode has been selected 3582 IF FNMeas_cont_blk$="CONT" THEN RETURN 1 3584 RETURN 0 3586 FNEND 3588 ! PAGE -> 3590 !************************************************************************ 3592 Meas_log_x:DEF FNMeas_log_x 3594 ! Returns 1 if x axis is LOG Hz 3596 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3598 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3600 IF POS(UPC$(Box$(2,X_axis_r)),"LOG") THEN RETURN 1 3602 RETURN 0 3604 FNEND 3606 ! PAGE -> 3608 !************************************************************************ 3610 Meas_log_y:DEF FNMeas_log_y 3612 ! Returns 1 if y axis is LOG V^2/Hz 3614 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3616 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3618 IF POS(UPC$(Box$(2,Y_axis_r)),"V^2") THEN RETURN 1 3620 RETURN 0 3622 FNEND 3624 ! 3626 !PAGE -> 3628 !************************************************************************ 3630 Meas_tdly:DEF FNMeas_tdly 3632 ! Returns the trigger delay in samples, from the spreadsheet 3634 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3636 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3638 RETURN VAL(Box$(2,Cmnd_stop)) 3640 FNEND 3642 ! 3644 !PAGE -> 3646 !************************************************************************ 3648 Meas_save:SUB Meas_save(@File,Ok) 3650 !Called by the FILE module to save the state of the 3652 !measurement spreadsheet into file @File. 3654 ! 3656 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3658 File_format_rev=2621 3660 OUTPUT @File;File_format_rev 3662 CALL File_save_s(@File,Box$(*)) 3664 Ok=1 3666 ! 3668 SUBEND 3670 !************************************************************************ 3672 Meas_load:SUB Meas_load(@File,Ok) 3674 !Called by the FILE module to load the state of the meas spreadsheet 3676 !from file @File. Meas_init is called to update the modules 3678 !to update other items. 3680 ! 3682 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3684 ENTER @File;File_format_rev 3686 SELECT File_format_rev 3688 CASE 2621 3690 CALL File_load_s(@File,Box$(*)) 3692 CASE ELSE !unknown rev 3694 CALL User_error("ERROR Incompatible display file format in Meas_load.") 3696 Ok=0 3698 SUBEXIT 3700 END SELECT 3702 CALL Meas_set_mods !Let modules know what was in the boxes 3704 Ok=1 3706 ! 3708 SUBEND 3710 ! PAGE -> 3712 !************************************************************************ 3714 Meas_set_mods:SUB Meas_set_mods 3716 ! This routine is called at powerup and when after retrieving a 3718 ! configuration from a file. It sets the input modules to the 3720 ! states specified in the array Box$(*) 3722 COM /Meas_sprd/ Box$(*),Title$(*),Prompt$(*) 3724 COM /Meas_mod_labels/ Srce_labels$(*),Inpt_labels$(*) 3726 COM /Meas_mod_counts/ Srce_count,Inpt_count,Current_srce,Current_inpt 3728 COM /Meas_cmnd/ Cmnd$(*),Def_value$(*) 3730 COM /Meas_rows/ Cmnd_start,Cmnd_stop,X_axis_r,Y_axis_r,Blk_cont_r,Av_r,Numav_r,Av_disp_r,Wind_r,Row 3732 ! 3734 ! Get Input labels 3736 ! 3738 Cnfg_labels("ALL INPUT",Inpt_labels$(*),Inpt_count) 3740 Inpt_count=MIN(16,Inpt_count) !limited by buffer sizes in HP-IB RAM 3742 IF Inpt_count=0 THEN SUBEXIT 3744 ! 3746 ! Setup Inputs, then read back from current input 3748 ! Since block_size=2*fft_size, hoops must be jumped 3750 ! through here. Also, the FFTsize is limited by the 3752 ! number of modules. 3754 Inpt_cmd("ALL INPUT","ZOOM","ON") 3756 FOR Row=Cmnd_start TO Cmnd_stop 3758 IF Cmnd$(Row)="FFT SIZE" THEN 3760 Tmp$="MEASUREMENT SIZE" 3762 Parm$=VAL$(2*VAL(Box$(2,Row))) 3764 Inpt_cmd("ALL INPUT",Tmp$,Parm$) 3766 Inpt_cmd("ALL INPUT","TRANSFER BLOCK SIZE",Parm$) 3770 ELSE 3772 Inpt_cmd("ALL INPUT",Cmnd$(Row),Box$(2,Row)) 3776 END IF 3778 NEXT Row 3780 Row=2 !Cursor starts at top initially 3782 SUBEND