; Simple program to allow one to take control of the Fluke Scopemeter 97. ; This source and all associated files are Copyright 1995 of John L. Groezinger. ; Comments may be sent to jlgroezinger@mmm.com ; V1.0, 5/24/95, jlg, original version ; V1.1, 6/22/95, jlg ; added much more information in flukecom.hlp file ; added default of *.* to dir command ; fixed null write file problem when sending strings to a disk file with ; the fputs command to write binary data to disk. Used the fwrite command. ; fixed a missing error message in makecsv to indicated if the .dat file ; did not have enough data in it. Added the init command. Moved the ; version string to the header file. ; V1.2, 6/30/95, jlg ; fixed type in help file ; changed version string ; removed extraneous code from getmeter in flukeint.asp ; speeded up the autobaud procedure significantly ; added optional parameter to timestamp command to timestamp to a file ; added additional documentation to makecsv ; changed error returns in makecsv to 1 for error, 0 for ok ; put some minor tweaks in getmeter to (hopefully) inmprove speed (sub'd ; key2ascii for strfmt) ; added the get/put command to get/save current configuration ; added the profile.mac feature ; V1.3, 8/30/95, jlg ; found bug in the get_array routine, would not operate correctly if data ; was null. ; Notes for future improvements: ; ; 1) Could do further attempts at serial connections including additional ; baud rates, attempts with nonzero ack connection, parity enabled, and ; 7 data bits, xon/xoff. ; ; 2) Add features to store currently used values which have been modified ; as part of the initialization sequence. Guess again, if we have space ; this requires the use of storing the variables and using this to send ; the commands, you cannot just use the variables as part of the setup ; sequence, if (init_aspdebug) ; set aspdebug on ; else ; set aspdebug off ; endif ; Create a read and write file function which would allow you to save and ; restore the current settings of pcplus to a file and then use a case ; switch statement to parse out the resulting savings to restore the ; current configuration. ; ; 3) Should increase error checking on number of parameters, for instance ; additional parameters on copy command are simply ignored, should be parsed ; and complained about. But then again, this is handy for comments.... ; ; 4) Add setup and restore setup functions to meter much more gracefully ; than the current numeric. ; ; 5) A filename which is entered which is too long is simply truncated ; with no error indication ; ; 6) The check_range routine can easily be fooled by putting in any ; nonnumeric value, it will return zero. This is also true about the ifgoto ; command which will use a non-numeric or non-present value as zero ; ; 7) Break script up into several subscripts which use up less at a time ; ; 9) one could envision several extensions to this which would include ; a more sophisticated loop capability (additional loops or labels) and ; shell variables. We'll see..... ; ; 10) if a disk write error occurs and disk logging is occuring, then ; the user will get two write errors, once for the command and a second for ; the disk log. ; ; 11) Look into ways to reduce the time to read from meter to PC ; ; 12) Put common routines in a header file. However, when I tried this, ; I got runtime errors. ; globals string bigresp1 ; all the waveform response strings string bigresp2,bigresp3,bigresp4,bigresp5,bigresp6,bigresp7 integer bigpointer ; pointer into string integer bigstring ; which string integer macroflag ; indicates if in macro mode or not long macropos ; current location in macro file for loop integer logflag ; is logging on? ; values from meter structure string id,yunit,xunit ; channel name, x and y units float yzero,xzero,ydelta,xdelta ; scale information integer ylevel,xsample ; number points and resolution ; user string is left here in parsed out form string cmd1,cmd2,cmd3,cmd4 include "flukecom.h" proc main integer reterror string retstr string tmpstr integer tmplen ; temp variable integer hourwait, minwait ; for clock function float readvalue ; value from last read operation float mingoto, maxgoto ; current tests for ifgoto command long looppos ; location to loop back to for loop long loopcount ; current count in loop long tmplong ; used for whatever integer retack, terminator ; used for "put" command looppos = 0 ; always start loop at zero readvalue = 0.0 ; read is at zero macroflag = 0 logflag = 0 ; no logging loopcount = 1 ; set loop counter at zero ; look for profile.asp fopen macroindex "profile.mac" "rb" if success macroflag = 1 endif while forever call get_cmd switch cmd1 ; commands with 1 second pause case "default" tmpstr = "ds" goto jump1here case "autosetup" tmpstr = "as" call send2meter with tmpstr,&reterror,longtimeout goto jump2here case "reset" tmpstr = "ri" jump1here: call send2meter with tmpstr,&reterror,normal jump2here: if reterror call write_user with "ERROR: reset not done" loopwhile endif pause 1 endcase ; file logging commands case "logon" fopen logindex cmd2 "wb" if failure strfmt tmpstr "ERROR: cannot write %s" cmd2 call write_user with tmpstr loopwhile endif logflag = 1 endcase case "logoff" fclose logindex logflag = 0 endcase ; generic single line commands case "local" tmpstr = "gl" goto jumphere case "remote" tmpstr = "gr" goto jumphere case "lockout" tmpstr = "ll" goto jumphere case "trigger" tmpstr = "ta" goto jumphere case "arm" tmpstr = "at" goto jumphere case "recall" strfmt tmpstr "rs %s" cmd2 goto jumphere case "save" strfmt tmpstr "ss %s" cmd2 jumphere: call send2meter with tmpstr,&reterror,normal if reterror call write_user with "ERROR: meter not ready" endif endcase case "loop" looppos = macropos endcase case ":" endcase case "put" ; open up the file fopen readindex cmd2 "rb" if failure strfmt tmpstr "ERROR: cannot open %s" cmd2 call write_user with tmpstr loopwhile endif ; the following is a modified version of send2meter rflush ; clean up anything that has been ; received transmit "ps" ; send the data string fgets readindex tmpstr eof readindex tmplen while !tmplen transmit tmpstr fgets readindex tmpstr eof readindex tmplen endwhile ; close up the file fclose readindex ; send the terminator computc cret ; get the acknowledge comgetcd retack if retack == -1 ; timeout! call write_user with "ERROR: meter not ready" loopwhile endif comgetcd terminator ; pitch the terminator if terminator != cret ; sync up problem or timeout call write_user with "ERROR: meter not ready" loopwhile endif if retack != '0' ; check the ack code call write_user with "ERROR: meter not ready" loopwhile endif endcase case "get" call send2meter with "qs",&reterror,normal if reterror call write_user with "ERROR: meter not ready" loopwhile endif ; open up the file fopen readindex cmd2 "wb" if failure strfmt tmpstr "ERROR: cannot open %s" cmd2 call write_user with tmpstr loopwhile endif ; get the first string and see if additional ones call getmeter with &retstr,&reterror,normal fputs readindex retstr ; look for the extended strings while (reterror == 1) call getmeter with &retstr,&reterror,normal fputs readindex retstr endwhile ; close up the file fputs readindex "`r`n" fclose readindex endcase case "read" strfmt tmpstr "qm %s,v" cmd2 call send2meter with tmpstr,&reterror,normal if reterror call write_user with "ERROR: meter not ready" loopwhile endif call getmeter with &retstr,&reterror,normal if (reterror) call write_user with "ERROR: can't get measurement" loopwhile endif call write_user with retstr ; store the readvalue in a nonvolatile place atof retstr readvalue ; if optional filename is present strlen cmd3 tmplen if (tmplen) fopen readindex cmd3 "ab" if failure strfmt tmpstr "ERROR: cannot open %s" cmd3 call write_user with tmpstr loopwhile endif strfmt tmpstr "%s,%s,%e`r`n" $date $time1 readvalue fputs readindex tmpstr if (failure) call write_user with "ERROR: cannot write disk" endif fclose readindex endif endcase ; macro related commands case "beep" sound 1000 50 endcase case "dir" strlen cmd2 tmplen if (!tmplen) cmd2 = "*.*" endif dir cmd2 endcase case "shell" shell endcase case "del" delete cmd2 if failure strfmt tmpstr "ERROR: can't delete %s" cmd2 call write_user with tmpstr endif endcase case "ren" rename cmd2 cmd3 if failure strfmt tmpstr "ERROR: can't rename %s to %s" cmd2 cmd3 call write_user with tmpstr endif endcase case "cd" getfattr cmd2 tmpstr if failure strfmt tmpstr "ERROR: no directory %s" cmd2 call write_user with tmpstr loopwhile endif find tmpstr "D" if not found strfmt tmpstr "ERROR: no directory %s" cmd2 call write_user with tmpstr loopwhile endif chdir cmd2 endcase case "type" type cmd2 endcase case "edit" strfmt tmpstr "edit %s" cmd2 run tmpstr endcase case "rmdir" rmdir cmd2 if failure call write_user with "ERROR: can't remove directory" endif endcase case "mkdir" mkdir cmd2 if failure call write_user with "ERROR: can't create directory" endif endcase case "pwd" getdir 0 tmpstr call write_user with tmpstr endcase case "?" type "flukecom.hlp" endcase case "play" loopcount = 1 looppos = 0 strlen cmd2 tmplen if (tmplen == 0) call write_user with "ERROR: no macro file" loopwhile endif fopen macroindex cmd2 "rb" if failure strfmt tmpstr "ERROR: no macro file %s" cmd2 call write_user with tmpstr loopwhile endif macroflag = 1 endcase case "zero" loopcount = 1 endcase case "ifgoto" atof cmd2 mingoto atof cmd3 maxgoto atol cmd4 tmplong ; check to see if inside limits if (readvalue >= mingoto) && (readvalue <= maxgoto) && (macroflag) && ((loopcount < tmplong) || (tmplong <= 0)) if (tmplong >= 0) loopcount++ endif fseek macroindex looppos 0 endif endcase case "ifnotgoto" atof cmd2 mingoto atof cmd3 maxgoto atol cmd4 tmplong ; check to see if inside limits if ((readvalue < mingoto) || (readvalue > maxgoto)) && (macroflag) && ((loopcount < tmplong) || (tmplong <= 0)) if (tmplong >= 0) loopcount++ endif fseek macroindex looppos 0 endif endcase case "timestamp" strfmt tmpstr "%s %s" $date $time1 call write_user with tmpstr ; if optional filename is present strlen cmd2 tmplen if (tmplen) fopen readindex cmd2 "ab" if failure strfmt tmpstr "ERROR: cannot open %s" cmd3 call write_user with tmpstr loopwhile endif strfmt tmpstr "%s,%s`r`n" $date $time1 readvalue fputs readindex tmpstr if (failure) call write_user with "ERROR: cannot write disk" endif fclose readindex endif endcase case "pause" strlen cmd2 tmplen if (tmplen == 0) call write_user with "ERROR: no delay" loopwhile endif atoi cmd2 tmplen if (tmplen == 0) call write_user with "ERROR: illegal delay" loopwhile endif pause tmplen if failure call write_user with "WARNING: aborted" endif endcase case "clock+" atoi cmd2 tmplen ; get the user hour time tmpstr 1 ; get the current time atoi tmpstr hourwait ; find the hour hourwait = hourwait + tmplen atoi cmd3 tmplen ; get the user minute substr retstr tmpstr 3 2 atoi retstr minwait minwait = minwait + tmplen ; check for clock rollover if (minwait >= 60) minwait = 0 hourwait++ endif if (hourwait >= 24) hourwait = 0 endif suspend until hourwait minwait if failure call write_user with "WARNING: aborted" endif endcase case "clock" call check_range with cmd2, 0, 23, &hourwait, &reterror if reterror call write_user with "ERROR: illegal delay" loopwhile endif call check_range with cmd3, 0, 59, &minwait, &reterror if reterror call write_user with "ERROR: illegal delay" loopwhile endif suspend until hourwait minwait if failure call write_user with "WARNING: aborted" endif endcase case "init" if (logflag) fclose logindex logflag = 0 endif execute "flukeint" endcase case "quit" exitwhile endcase case "version" call write_user with versionstr call send2meter with "id",&reterror,normal if reterror call write_user with "ERROR: meter not ready" loopwhile endif call getmeter with &retstr,&reterror,normal if (reterror) call write_user with "ERROR: can't get id from meter" loopwhile endif call write_user with retstr endcase case "copy" call copy_cmd endcase case "" endcase default strfmt tmpstr "ERROR: command %s" cmd1 call write_user with tmpstr endcase endswitch endwhile execute "flukexit" endproc ; for copy command from above, all parameters are handled with globals ; yeah, I know, live with it... proc copy_cmd integer wavenum, dwavenum integer reterror ; for file naming string basename, dbasename string tmpstr ; look at the command string and figure out what to do call wave_number with cmd2,&wavenum call wave_number with cmd3,&dwavenum ; check for existence of command strings strlen cmd2 reterror if (!reterror) call write_user with "ERROR: no source" return endif ; assume that this is a basename basename = cmd2 strlen cmd3 reterror if (!reterror) call write_user with "ERROR: no destination" return endif ; check for special case of datestamp strcmp cmd3 "datestamp" if success call make_date with &dbasename else dbasename = cmd3 endif ; please note that the basename and dbasename variables ; are always set to the cmd2 and cmd3 respectively, regardless ; of the actual operation. For example, even if a keyword is ; found as a source or destination, the cmd2 or cmd3 will ; be used to set the value of basename/dbasename. The only ; exception to this is in the case of datestamp. The wavenum ; and dwavenum vars should be used to key the operation. This ; is a bit of a hack but most of this is. ; copy from meter to specified file if (wavenum) && (!dwavenum) call get_waveform with wavenum,&reterror if (reterror) call write_user with "ERROR: can't get meter data" return endif call write_waveform with dbasename,&reterror if (reterror) call write_user with "ERROR: can't write to disk" return endif endif ; copy from specified file to meter if (!wavenum) && (dwavenum) call read_waveform with basename,&reterror if (reterror) strfmt tmpstr "ERROR: can't read disk file %s" basename call write_user with tmpstr return endif call send_waveform with dwavenum,&reterror if (reterror) call write_user with "ERROR: can't write to meter" return endif endif ; copy from meter to meter if (wavenum) && (dwavenum) call get_waveform with wavenum,&reterror if (reterror) call write_user with "ERROR: can't get meter data" return endif call send_waveform with dwavenum,&reterror if (reterror) call write_user with "ERROR: can't write to meter" return endif endif ; copy from file to file if (!wavenum) && (!dwavenum) call read_waveform with basename,&reterror if (reterror) strfmt tmpstr "ERROR: can't read disk file %s" basename call write_user with tmpstr return endif call write_waveform with dbasename,&reterror if (reterror) call write_user with "ERROR: can't write to disk" return endif endif endproc ; reads data from disk and pulls it into bigresp ; returns zero if ok, 2 if error proc read_waveform strparm basename ; source basename intparm restatus string tmpstr integer reterror ; std error return tmpstr = basename strcat tmpstr ".dat" ; get the binary data fopen srcindex tmpstr "rb" if failure restatus = 2 return endif fread srcindex bigresp1 maxstrlen reterror fread srcindex bigresp2 maxstrlen reterror fread srcindex bigresp3 maxstrlen reterror fread srcindex bigresp4 maxstrlen reterror fread srcindex bigresp5 maxstrlen reterror fread srcindex bigresp6 maxstrlen reterror fread srcindex bigresp7 shortstrlen reterror if (reterror != shortstrlen) restatus = 2 return endif ; get the header data tmpstr = basename strcat tmpstr ".hdr" ; get the binary data fopen srcindex tmpstr "rb" if failure restatus = 2 return endif fgets srcindex id fgets srcindex xunit fgets srcindex yunit fgets srcindex tmpstr atof tmpstr xzero fgets srcindex tmpstr atof tmpstr yzero fgets srcindex tmpstr atof tmpstr xdelta fgets srcindex tmpstr atof tmpstr ydelta fgets srcindex tmpstr atoi tmpstr xsample fgets srcindex tmpstr atoi tmpstr ylevel fclose srcindex restatus = 0 endproc ; takes data from bigresp variables and writes disk files ; returns zero if ok, 2 if error proc write_waveform strparm dbasename ; destination basename intparm restatus ; return status string tmpstr comment ; this stuff is commented out because the csv file is created by an ; external c file integer counter ; pointer into arrays integer reterror ; return status from routines ; for calculations float realx,realy endcomment ; make up the binary file tmpstr = dbasename strcat tmpstr ".dat" fopen destindex tmpstr "wb" if failure restatus = 2 return endif ; write all this binary stuff out fwrite destindex bigresp1 maxstrlen fwrite destindex bigresp2 maxstrlen fwrite destindex bigresp3 maxstrlen fwrite destindex bigresp4 maxstrlen fwrite destindex bigresp5 maxstrlen fwrite destindex bigresp6 maxstrlen fwrite destindex bigresp7 shortstrlen if failure call write_user with "ERROR: cannot write disk" endif fclose destindex ; make up the hdr file tmpstr = dbasename strcat tmpstr ".hdr" fopen destindex tmpstr "wb" if failure restatus = 2 return endif fstrfmt destindex "%s`r`n" id fstrfmt destindex "%s`r`n" xunit fstrfmt destindex "%s`r`n" yunit fstrfmt destindex "%e Xzero`r`n" xzero fstrfmt destindex "%e Yzero`r`n" yzero fstrfmt destindex "%e Xdelta`r`n" xdelta fstrfmt destindex "%e Ydelta`r`n" ydelta fstrfmt destindex "%d Xsample`r`n" xsample fstrfmt destindex "%d Ylevel`r`n" ylevel if failure call write_user with "ERROR: cannot write to disk" endif fclose destindex comment ; all of this stuff is commented out since this runs way to slow ; make up the csv file tmpstr = dbasename strcat tmpstr ".csv" fopen destindex tmpstr "wb" if failure restatus = 2 return endif ; create the csv strings fstrfmt destindex "%s`r`n" dbasename fstrfmt destindex "%s,%s`r`n" xunit yunit ; initialize the array fetching call zero_array counter = 0 call get_array with &reterror while (reterror != -1) realx = (counter * xdelta) + xzero realy = ((reterror - 128) * ydelta) - yzero fstrfmt destindex "%e,%e`r`n" realx realy counter++ call get_array with &reterror endwhile fclose destindex endcomment strfmt tmpstr "makecsv %s" dbasename run tmpstr NOCLEAR restatus = 0 endproc ; get data from bigresp variables and sends to meter ; returns zero if ok, 2 if error proc send_waveform intparm dwavenum intparm restatus string tmpstr integer reterror strfmt tmpstr "pw%d" dwavenum call send2meter with tmpstr,&reterror,extended if (reterror) restatus = 2 return endif restatus = 0 endproc ; gets data from meter and puts into the bigresp variables ; returns zero if ok, 2 if error proc get_waveform intparm wavenum ; keycode for waveform intparm restatus ; return code from operation integer counter ; for parsing string tmpstr string retstr ; return string from get operation integer reterror ; return from send2meter strfmt tmpstr "qw%d" wavenum call send2meter with tmpstr,&reterror,normal if (reterror) restatus = 2 return endif call getmeter with &retstr,&reterror,extended if (reterror) restatus = 2 return endif ; get the values from the response string counter = 0 call parse_str with retstr,&id,&counter,commachar call parse_str with retstr,&yunit,&counter,commachar call parse_str with retstr,&xunit,&counter,commachar call parse_str with retstr,&tmpstr,&counter,commachar atof tmpstr yzero call parse_str with retstr,&tmpstr,&counter,commachar atof tmpstr xzero call parse_str with retstr,&tmpstr,&counter,commachar atof tmpstr ydelta call parse_str with retstr,&tmpstr,&counter,commachar atof tmpstr xdelta call parse_str with retstr,&tmpstr,&counter,commachar atoi tmpstr ylevel call parse_str with retstr,&tmpstr,&counter,commachar atoi tmpstr xsample restatus = 0 endproc ; zero pointers into array proc zero_array bigpointer = 0 bigstring = 1 endproc ; gets value from array proc get_array intparm reterror integer biglength ; length of current string switch bigstring case 1 strpeek bigresp1 bigpointer reterror biglength = maxstrlen endcase case 2 strpeek bigresp2 bigpointer reterror biglength = maxstrlen endcase case 3 strpeek bigresp3 bigpointer reterror biglength = maxstrlen endcase case 4 strpeek bigresp4 bigpointer reterror biglength = maxstrlen endcase case 5 strpeek bigresp5 bigpointer reterror biglength = maxstrlen endcase case 6 strpeek bigresp6 bigpointer reterror biglength = maxstrlen endcase case 7 strpeek bigresp7 bigpointer reterror biglength = shortstrlen endcase default reterror = -1 return endcase endswitch ; point to next item in array bigpointer++ ; clean up if necessary if (bigpointer >= biglength) bigpointer = 0 bigstring++ endif endproc ; checks correct range of numeric value ; minval is lowest ok value ; maxval is highest ok value ; returns value in integer, ; 0 error return indicates, ok, 2 indicates error proc check_range strparm instr intparm minval, maxval intparm value intparm reterror integer strlength ; check for zero length string strlen instr strlength if (!strlength) reterror = 2 return endif ; convert the string atoi instr value if (value >= minval) && (value <= maxval) reterror = 0 return endif reterror = 2 endproc ; create a string with date code proc make_date strparm outstr string tmpstr string datestr string timestr outstr = "" date datestr ; get appropo strings time timestr 1 substr tmpstr datestr 3 2 ; get the day strcat outstr tmpstr substr tmpstr timestr 0 2 ; get the hour strcat outstr tmpstr substr tmpstr timestr 3 2 ; get the minute strcat outstr tmpstr substr tmpstr timestr 6 2 ; get the second strcat outstr tmpstr endproc proc write_user strparm outstr string tmpstr strfmt tmpstr "%s`r`n" outstr message tmpstr if (logflag) fputs logindex tmpstr if failure message "ERROR: cannot write to disk`r`n" endif endif endproc proc nocr_write_user strparm outstr message outstr if (logflag) fputs logindex outstr if failure message "ERROR: cannot write to disk`r`n" endif endif endproc ; this routine is a general token parser which is intended to ; look for the parsechar and return the current token from the ; current location in the string up but not including the separator ; It will return the token found into the string which is passed, ; a null string is returned if no token is found or if end of the string ; The variable pointer is used to offset from the beginning of the string ; where to start the search and it is left at pointer at the first character ; beyound the end of the string (string length) ; or the first whitespace following the current token ; Strings are based at 0 start ; parsechar is used to determine the character to parse on proc parse_str strparm instr strparm outstr intparm pointer intparm parsechar integer lastchar integer currchar string currcharstr outstr = "" ; get the length of the string strlen instr lastchar if (!lastchar) return endif ; check if pointer is beyond end of string if (pointer >= lastchar) return endif strpeek instr pointer currchar ; strip off leading whitespace while (currchar == parsechar) pointer++ if (pointer == lastchar) return endif strpeek instr pointer currchar endwhile ; find the next whitespace, this is token while (currchar != parsechar) key2ascii currchar currcharstr strcat outstr currcharstr pointer++ if (pointer == lastchar) return endif strpeek instr pointer currchar endwhile endproc ; return error code ; of 1 indicates an ack error existed on the receive ; this is a warning that the ack code is incorrect ; of 2 indicates a sync problem existed on the receive (or timeout) ; this is a fatal ; Response string must be handled separately. proc send2meter strparm instr intparm reterror intparm opcode string tmpstr integer retack ; acknowledge byte integer terminator integer checksum integer counter ; for long timeout tries rflush ; clean up anything that has been ; received strfmt tmpstr "%s`r" instr ; format up the data to send transmit tmpstr counter = 0 comgetcd retack if (opcode == longtimeout) && (counter < longtimetries) && (retack == -1) comgetcd retack counter++ endif if retack == -1 ; timeout! reterror = 2 return endif comgetcd terminator ; pitch the terminator if terminator != cret ; sync up problem or timeout reterror = 2 return endif if retack != '0' ; check the ack code reterror = 1 return endif ; is this an extended waveform operation if (opcode == extended) checksum = 0 call zero_array call get_array with &retack while (retack != -1) checksum = checksum + retack computc retack call get_array with &retack endwhile checksum = checksum & 255 computc checksum ; wait for the acknowledge byte comgetcd retack if retack == -1 ; timeout! reterror = 2 return endif comgetcd terminator ; pitch the terminator if terminator != cret ; sync up problem or timeout reterror = 2 return endif if retack != '0' ; check the ack code reterror = 2 return endif endif reterror = 0 endproc ; this routine checks the input string and reduces it to the correct ; waveform number ; It requires the string to be sent with the ascii descripter and it ; returns a value for the waveform number, 0 if not recognized. proc wave_number strparm instr intparm reterror switch instr case "a" reterror = 101 endcase case "b" reterror = 102 endcase case "ab" reterror = 103 endcase case "temp1" reterror = 104 endcase case "temp2" reterror = 105 endcase case "temp3" reterror = 106 endcase case "memory4" reterror = 107 endcase case "memory5" reterror = 108 endcase case "memory6" reterror = 109 endcase case "memory7" reterror = 110 endcase case "memory8" reterror = 111 endcase default reterror = 0 endcase endswitch endproc ; get the next command proc get_cmd string tmpstr ; response string from get integer counter ; position in string call nocr_write_user with "flukecom> " ; see if an esc or abort key was hit during operation if (hitkey) kflush if (macroflag) macroflag = 0 fclose macroindex endif endif if (macroflag) ; get input from macro file fgets macroindex tmpstr ftell macroindex macropos ; get pointer where to ; starting from if success ; check for eof if eof macroindex fclose macroindex macroflag = 0 get tmpstr ; aborted out with esc key if (failure) tmpstr = "" endif if (logflag) fputs logindex tmpstr if failure call write_user with "ERROR: cannot write to disk" endif endif call write_user with "" else ; got the string ok call write_user with tmpstr endif else ; end of file, clean up ; need some error indication here fclose macroindex macroflag = 0 get tmpstr ; aborted out with esc key if (failure) tmpstr = "" endif if (logflag) fputs logindex tmpstr if failure call write_user with "ERROR: cannot write to disk" endif endif call write_user with "" endif else ; normal user input get tmpstr ; aborted out with esc key if (failure) tmpstr = "" endif if (logflag) fputs logindex tmpstr if failure call write_user with "ERROR: cannot write to disk" endif endif call write_user with "" endif strlwr tmpstr ; convert to lower case counter = 0 call parse_str with tmpstr,&cmd1,&counter,spacechar call parse_str with tmpstr,&cmd2,&counter,spacechar call parse_str with tmpstr,&cmd3,&counter,spacechar call parse_str with tmpstr,&cmd4,&counter,spacechar endproc ; this routine is an internally called routine from above ; that is used to basically minimize the amount of recalled code ; ; It requires the user pass a string to concatenate onto ; a pointer for the checksum integer ; a value for the maximum number of characters to fetch ; a pointer to an error return which will be 0 if success or 2 if not ; Please note that the error return is checked, if an error value is ; passed in, then the routine will abort ; proc suck_em_up strparm outstr intparm checksum intparm maxget intparm reterror integer pointcount string tmpstr integer newchar ; check the error return if (reterror) return endif ; initialize the string and counter outstr = "" pointcount = 1 ; get the first character comgetcd newchar while (newchar != -1) key2ascii newchar tmpstr ; convert char to string strcat outstr tmpstr checksum = checksum + newchar pointcount++ if (pointcount > maxget) reterror = 0 return endif comgetcd newchar endwhile ; timeout condition reterror = 2 endproc ; this routine gets the response string from the meter ; If the response was succesful, then a string is returned and ; of 0 indicates successful ; of 1 indicates a continuation packet is pending ; of 2 indicates a failure ; NOTE THIS ROUTINE IS LIMITED TO 80 characters per string ; ; input parameter longgrab is normally set to zero for cret acquisition ; If set to extended, then the routine will look for 8 commas, switch to the ; getmeter_long routine to grab the samples, and verify the checksum proc getmeter strparm outstr ; string to return intparm reterror ; error code to return intparm longgrab ; operation code per above integer newchar ; the latest character acquired string newcharstr ; string version of the above integer counter ; length of the string to check for ; overflow of string integer commacount ; number of commas in current string ; used if longgrab = 1 outstr = "" commacount = 0 counter = 0 comgetcd newchar while (newchar != -1) && (newchar != cret) && (commacount < maxcomma) key2ascii newchar newcharstr strcat outstr newcharstr counter++ ; test to see if this is a implicit continuation string ; should never happen except when getting meter configuration if (counter >= maxstrlen) reterror = 1 return endif if (newchar == ',') && (longgrab == extended) commacount++ endif if (commacount != maxcomma) comgetcd newchar endif endwhile if (newchar == cret) && (longgrab == normal) reterror = 0 return endif if (newchar == ',') && (longgrab == extended) ; call the long response handler call getmeter_long with &reterror return endif reterror = 2 endproc ; this routine gets the waveform response ; If the response was succesful, then a string is placed in the globals and ; of 0 indicates successful ; of 2 indicates a failure ; NOTE THIS ROUTINE IS LIMITED TO 80 characters per string proc getmeter_long intparm reterror ; return error code integer newchar ; current character being worked on integer checksum ; calculated checksum ; initialize the checksum checksum = 0 call suck_em_up with &bigresp1,&checksum,maxstrlen,&reterror call suck_em_up with &bigresp2,&checksum,maxstrlen,&reterror call suck_em_up with &bigresp3,&checksum,maxstrlen,&reterror call suck_em_up with &bigresp4,&checksum,maxstrlen,&reterror call suck_em_up with &bigresp5,&checksum,maxstrlen,&reterror call suck_em_up with &bigresp6,&checksum,maxstrlen,&reterror call suck_em_up with &bigresp7,&checksum,shortstrlen,&reterror if (reterror) return endif ; mask the checksum checksum = checksum & 255 ; check checksum comgetcd newchar if (newchar != checksum) reterror = 2 return endif ; all ok reterror = 0 endproc