// TITLE     : Scilab driver for the ESCORT-3136A Multimeter 
//             (a.k.a. FI-3136A from Française d'Instrumentation Corp.)
//             The ESCORT-3146A device may also be supported (untested)
// SOFTWARE  : for Scilab >= 5.2 : http://www.scilab.org/
// DEPENDENCY: http://atoms.scilab.org/toolboxes/serial must be loaded
// RELEASE HISTORY 
//   05/2011, 1.0 : Initial release
// AUTHOR (c): Samuel GOUGEON - Université du Maine / ENSIM (France)
// LICENSE   : CeCILL-C
//   http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
// DISCLAIMER : No warranty of any kind. Available as is. Be aware and use it 
//   to your own risks & responsability

function r = mm3136A(C,varargin)
// PURPOSE: 
//  This script is a Scilab driver for the ESCORT-3136A = FI-3136A dual display 
//   multimeter. The ESCORT-3146A = FI-3146A model may also be supported 
//   (untested. Addressing the dual display may be different)
//
// REQUIREMENTS: 
//  * 1 serial RS-232 port must be available on the computer. A USB port
//     may be converted into RS-232 ones with a USB-Serial converter
//  * Serial TCL toolbox (E. Segre) + Scilab > 5.2 :
//     http://atoms.scilab.org/toolboxes/serial must be installed
//
// GENERAL equivalent SYNTAXES: 
//  mm3136A(<command>[, <parameter#1>[, <parameter#2>]])
//  mm3136A <command> <parameter#1> <parameter#2>
//
// <command> is a case unsensitive string specifying the action to perform.
// Parameters may be numbers, strings or boolean. Any specified boolean or 
//   number is automatically converted into an equivalent string. Strings
//   are case unsensitive (so for instance "5m" could either be used to 
//   specify the 5mV range, or instead of "5M" for the 5 Mohm range, 
//   depending on the context).
//
// mm3136A... : returns 1 if the operation has been performed successfully,
//              returns 0 in case of failure
// 
// COMMANDS
// ========
// SERIAL OPERATIONS:
// -----------------
// mm3136A open <port_number> : 
//              Opens the serial port that number from 1 to 254 is specified. 
//              Default is "1". The communication parameters are set to 
//               9600 bauds, no parity, 8 databits, 1 stop bit. The parameters
//               set on the device must be these ones (default). 
//              Moreover, a TCL session is created for handling the 
//               communication and the related data.
//              Remark: It is presently not possible to handle more than 1 
//               mm3136A multimeter per computer.
// mm3136A close : Resets the command mode to "local" (front end keyboard), 
//              Closes the serial port communication, and
//              Destroys the related TCL session.
// mm3136A clean : Destroys the TCL session (whether the session has been avorted)
//
// GENERAL SETTINGS:
// ----------------
// mm3136A local : Cancels the "remote" mode. Any action on the device's keyboard
//               is then enabled.
//              Remark: Any command (except "local") sent to the device through 
//               the serial port automatically turns its adressing mode to
//               "REMOTE", if it was formerly in "local" mode.
// mm3136A lock  : Locks the keyboard on device => Disables any command from 
//               the device (except the power on/off switch). The key "local"
//               is also disabled. 
//              Remark: It is impossible to lock the keyboard if the device
//               is currently in trigging mode.
// mm3136A unlock : Releases the locking of the device's keyboard. 
//               => Pressing the key "local" makes possible any input on the
//               device's keyboard afterwards.
// mm3136A reset : Resets the multimeter's parameters to their default values.
//
// mm3136A bright <brightness_level> : Sets the brightness of the displays. 
//              The brightness_level is an integer from 0 to 3.
// mm3136A beeps : Plays an audio 'beep' (checking that communication is ok)
// mm3136A beep  : Toggles the beeper: FEATURE NOT YET IMPLEMENTED (due to 
//               addressing restrictions). When the beeper is "on", each
//              (unlocked) key plays a beep when it is pressed.
//
// ACTIONS:
// -------
// Remark: The default display is always display # 1.
//
// mm3136A setTrig 1 : Turns "on" the trigger mode. The "trig" command may then
//                  be used to trigger a measure and get the related data.
//      setTrig 0 : Turns "off" the trigger mode. 
//
// mm3136A v_ [range [display]] : 
//              Set the specified display in Vdc Direct Current Voltage mode,
//              within the specified voltage range.
//            * range==0 means "Automatic range" (= default)
//              Other available ranges are: 0.5 5 50 500 750 1000 (in Volts). 
//              If another positive range is specified, the nearest 
//              compatible range is set.
//            * display==1 targets the main display of the device (default)
//              display==2 targets the secondary display of the multimeter
//              Combinations of displays are not all possible. 
//              When a specification on Display #2 is incompatible with the
//              current measurement displayed in #1, the command is ignored.
//              Some display assignments may switch the actual displays in 
//              order to comply with possible pairs.
//              When using both displays, after assigning measurement modes, 
//               it is strongly recommanded to check the actual respective 
//               modes assigned to both displays before reading data from 
//               them. => Related command:  mm3136A("infos",["D1" "D2"])
//              See the user handbook for details about compatible displays.
//            * Example: mm3136A v_ 0 1  set the display #1 in Vdc mode in
//               automatic range. Since it is the default, the command can be
//               shortened in: mm3136A v_  
// mm3136A v~ .. : Sets the alternative voltage mode V~ = Vac
//              See "mm3136A v_ .." setting (hereabove) for details. 
//              Range and display specifications are identical.
// mm3136A v+ .. : Sets the dual direct + alternative voltage mode Vac+dc
//              See "mm3136A v_ .." setting (hereabove) for details. 
//              Range and display specifications are identical.
// 
// mm3136A a_ .. : Sets the direct Current mode Adc
// mm3136A a~ .. : Sets the alternative Current mode A~ = Aac
// mm3136A a+ .. : Sets the dual direct + alternative Current mode.
//              For these 3 commands, the syntax to specify the range and
//              display is similar to the mm3136A v_ [range [display]] one
//              detailled hereabove. 
//              Available ranges: "500µ" "5m" "50m" "500m" "5" "10"
//              The range may also be specified by a numerical value (in [A])
//              Then, the nearest litteral compatible range is set.
//              0 still means: Automatic range
//              Examples: 
//                mm3136A A~ 5m 2 ,  mm3136A a~ 0.005 2 , mm3136A a~ 1e-3 2
//              will all do the same settings
//
// mm3136A ohm [range] : Sets the display #1 as ohmeter. 
//             The default range=0 is the automatic ranging mode. 
//             Other settable ranges are: "500" "5k" "50k" "500k" "5M" "50M"
//             specified in ohms. Specifying a numerical value is also 
//             possible. Then, the nearest compatible range is set.
//            Examples : mm3136A ohm , mm3136A("ohm",0) , mm3136A("ohm")
//             all set the ohmeter on display #1 in automatic range mode.
//             mm3136A ohm 3765 : sets the ohmeter with the fixed 5 kohm range.
//             mm3136A ohm 500k : sets the ohmeter with the fixed 500 kohm range.
//
// mm3136A ohmC [range] : Sets the display #1 as ohmeter for tests of continuity.
//             See the "ohm" mode for the syntax, remarks and examples.

// mm3136A freq [display] : Sets the frequencemeter mode on the given display
// mm3136A hz   [display] : Same action. The default display is # 1
//            Examples : mm3136A hz    mm3136A freq 2    mm3136A("freq")
//
// mm3136A dBm [display] : Sets the dBm mode on the given display (default = 1) 
//              This mode can be used only is some Voltage measurements (in
//              any of the DC, AC, or AC+DC modes) are shown on the other 
//              display. When the voltage mode is changed or cancelled 
//              (whatever on which display), any preset dBm mode is cancelled.
//              The relationship between Voltage and dBm is the following:
//                     U[dBm] = 30 + 10.log10( U[V]^2 / Zref[ohm])
//              where Zref is the reference impedance. Zref can be tuned. Its
//              default value is 600 ohms.
//
// mm3136A diode : Sets the diode testing mode on Display #1 (mandatory)
//              The only available range is 2.3V
//
// QUERYING DATA:
// -------------
// mm3136A trig  : (trigs and returns a measurement. untested)
// mm3136A read  : Returns the value displayed on the multimeter
//
// GETTING INFOS:
// -------------
// mm3136A ver   : Reads and returns in a column r of 2 strings the version of 
//              the firmware R(1), and the model number of the multimeter R(2)
//
// mm3136A infos property1 property2 ... : 
//             Reads and returns the value or status for one or several 
//             querried property(ies), as a vector of strings.
//             Boolean properties are named with a ending "?" and have values 
//             "0" (for "off") | "1" (for "on")
//             AVAILABLE PROPERTIES are listed herefater.
//
//     port   : Serial port used by the device. The answer is a string
//             #/handle where # is the port number (from 1 to 254) and handle
//             is the TCL handle identifying the port as a special file.
//             Returned sample: 1/file31f9620
//
//     bright : Brightness level of the displays. Level is in {0 1 2 3}
//     beep?  : 1 if the beeper is "on", else 0.
//     trig?  : 1 if the trigger mode is active, 0 else. In trigger mode, 
//              each mm3136A("trig") command triggers a measurement on all
//              active displays, and returns it (or them).
//     lim?   : 1 if the limits mode is active, 0 else.
//     %?     : 1 if the percentage mode is active, 0 else.
//     Rhold? : 1 if the R_HOLD mode is active, 0 else.
//
//     D1     : Measurement mode set on display # 1
//     D2     : Measurement mode set on display # 2
//              Possible answers for "D1" and "D2" queries are:
//              "V_" "V~" "V+" "dBm" "A_" "A~" "A+" "Hz" "ohm" "ohmC" "diode"
//              Meanings: _=DC  ~=AC  += DC+AC   ohmC = Continuity testing
//              If D2 is not set, mm3136A("infos","D2") returns an empty string.
//
//     R1     : Range used on display #1
//     R2     : Range used on display #2
//              Possible answers for "R1" and "R2" queries are:
//          V_ mode: "0.5" "5" "50" "500" "1000" (in volts)
//      V~ V+ modes: "0.5" "5" "50" "500" "750"
//              In automatic mode, the actual instantaneous range is returned.
//   A_ A~ A+ modes: "500µ" "5m" "50m" "500m" "5" "10"  (in amperes)
//   ohm ohmC modes: "500" "5k" "50k" "500k" "5M" "50M" (in ohms)
//          Hz mode: "500" "5k" "50k" "500k" (in Hz)
//       diode mode: "2.3V"
//         dBm mode: "" (empty string)

// PRESENT LIMITING FEATURES:
// -------------------------
//  * Only one mm3136A device is supported per computer
//  * Setup commands usually enabled or tuned through the Shift-Setup keys 
//    cannot be remotely set (due to an harware addressing issue)
//

	fn = "mm3136A"				// Function Name (for error messages)

	// STARTING TESTS
	// ==============
	if argn(2)==0, head_comments(fn)
        r = 0
        return
    end
	
	if ~isdef("C","local") | typeof(C)~="string"
		tmp = _("%s: Any command must be specified in arg#1 as a string\n")
		error(msprintf(tmp, fn))
	else c = convstr(C,'l')
	end
	if ~exists('openserial')
        tmp = _("%s: TCL serial toolbox unavailable. Please load it before processing\n")
        error(msprintf(tmp, fn))
	end
	if isdef("varargin","local") & length(varargin)>0
        d = varargin
        d1 = d(1)
	else d = []
	end

	// INITIALIZATIONS
	// ===============
	EOC = ascii([13 10])       // End Of Command
	LF  = ascii(10)            // Line Feed
	dt  = 20                   // Temporisation [ms]
	dtc = 1/1.2                // Tempo per char [ms]
	r   = 0
    
	if c=="clean" 
        if TCL_ExistInterp(fn) TCL_DeleteInterp(fn), end
        r = 1
        return
    end
    if TCL_ExistInterp(fn)
        port = TCL_GetVar("port",fn)	// Recovering the port ids (unique) (1)= #
        ph = port(2)						// (2) = Handle
    else TCL_CreateSlave(fn)
    end
    // Some generic messages:
    notOnD2 = "%s.%s: %s signal can''t be shown on the secondary display"

    // PARSING COMMANDS
    // ================
    if c=="open"						// 'open' [,portNumber=1]
        if isdef("port","local")
            tmp = _("%s: Port #%s is already opened for a mm3136A device. Multiple mm3136A mode is not yet supported. => Ignoring this command\n")
			warning(msprintf(tmp, fn, port(1)))
		else
			ok? = %f
			if ~isdef("d","local")
                d = 1
                ok? = %t
			elseif typeof(d1)=="string" & isnum(d1)
				d = strtod(d1)
				if d==fix(d) & d>0 & d<256, ok?=%t, end
			elseif typeof(d1)=="constant" & d1==fix(d1) & d1>0 & d1<256, 
					d = d1
                    ok? = %t
			end
			if ~ok?
				tmp = _("%s.%s: Port number expected as integer in [1,255] in arg#%d\n")
				error(msprintf(tmp, fn, C, 2))
			end
			ph = openserial(d,"9600,n,8,1"), sleep(50)
			TCL_SetVar("port",[msprintf("%g",d) ph],fn)
			r = ph
		end

	// ----------------------------------------------------------------------

	elseif c=="close"
		mm3136A("local")
		try, r = 1+closeserial(ph)
        catch
            r = 0
            disp("Erreur à la fermeture")
        end
		try, TCL_DeleteInterp(fn), end

	// ----------------------------------------------------------------------

	elseif c=="beeps"								// plays a beep
		r = 1+writeserial(ph,"BON"+EOC)

	// ----------------------------------------------------------------------

	elseif c=="beep"								// Toggle the beeper
		// Shift+local is not interpreted as Setup But quits de remote
		// So, seting up commands through keys are not available
		//tmp=[ 13 13 10 10 15 12 15 16 16]			// Keys sequence
		//tmp="K"+string(tmp)+EOC
		//for t=tmp, r=r+1+writeserial(ph,t), sleep(1000), end

	// ----------------------------------------------------------------------

	elseif c=="ver"
		t = "a"
        while t~=""
            t = readserial(ph)
        end
        writeserial(ph,"RV"+EOC)
        sleep(50)
        r = readserial(ph)
        r = tokens(r,",")

	// ----------------------------------------------------------------------
	
	elseif c=="reset"
		r = 1 + writeserial(ph,"RST"+EOC), 		sleep(4000)

	// ----------------------------------------------------------------------

	elseif c=="lock"
		r = 1 + writeserial(ph,"LLO"+EOC), 			sleep(dt)

	// ----------------------------------------------------------------------

	elseif c=="unlock"
        r = 1 + writeserial(ph,"GTL"+EOC+"RV"+EOC)
        sleep(dt)

	// ----------------------------------------------------------------------

	elseif c=="local"
        r = 1 + writeserial(ph,"GTL"+EOC)
        sleep(dt)

	// ----------------------------------------------------------------------

	elseif c=="settrig"                        // Sets or unset the trigger mode
        if ~isdef("d1","local")
            d1 = "1"
        elseif typeof(d1)=="constant"
            d1 = msprintf("%g",d1)
        end
        if typeof(d1)~="string" | (d1~="0" & d1~="1")
            tmp = _("%s: Argument #%d must be missing or 0 or 1 (default)\n")
            error(msprintf(tmp, fn))
        end
        r = 1+writeserial(ph,"TGS"+d1+EOC)
        sleep(500)

	// ----------------------------------------------------------------------

	elseif c=="trig"                                // Triggers the measurement
		if ~isdef("d1","local")
            d1 = "1"
		elseif typeof(d1)=="constant"
            d1 = msprintf("%g",d1)
		end
		if typeof(d1)~="string" | (d1~="0" & d1~="1")
			tmp = _("%s: Argument #%d must be missing or 0 or 1 (default)\n")
			error(msprintf(tmp, fn))
		end
        t = "a"
        while t~=""                // Clearing the serial buffer
            t = readserial(ph)
        end		
		tmp = 1+writeserial(ph,"TGM"+d1+EOC)
        sleep(3000)	// Optimized tempo
		r = readserial(ph)
        sleep(100)
		if part(r,1:2)=="E>" & mm3136A("infos","trig?")=="0"
			tmp = _("%s.%s: The trigger mode is OFF!=> Turning it on to measure data\n")
			warning(msprintf(tmp, fn,C)+LF)
			mm3136A("setTrig",1)
			r = mm3136A("trig",d1)
		else
			r = strtod(part(r,1:10))
		end
		
	// ----------------------------------------------------------------------

	elseif c=="read"
		ok? = %f
		if d==[]
            d1 = "1"
            ok? = %t
		elseif typeof(d1)=="string" & (d1=="1"|d1=="2")
            ok? = %t
		elseif typeof(d1)=="constant" & (d1==1|d1==2)
			d1 = msprintf("%g",d1)
            ok? = %t
		end

		if ~ok?
			tmp = _("%s.%s: Display # must be 1 or 2 (%s unknown).\n")
			error(msprintf(tmp, fn, C, string(d1))+LF)
		end
		t = " "
        while t~=""        // Cleaning the serial buffer
            t = readserial(ph)
        end
		writeserial(ph,"R"+d1+EOC)
        sleep(150)
        t  = readserial(ph)
		t = tokens(strsubst(t, ascii(13),""),LF)
		if size(t,"*")<2, 
			if d1=="2"
                 tmp = _("%s.%s: This display or the multimeter look OFF\n")
			else tmp = _("%s.%s: The multimeter looks OFF\n")
            end
			warning(msprintf(gettext(tmp)+"\n",fn,C)+LF)
			r = []
		else
			if t(2)~="=>"
				tmp = "%s.%s: "+mm3136A(t(2))
				warning(msprintf(gettext(tmp)+"\n",fn,C)+LF)
				r = []
			else r = strtod(t(1))
			end
		end

	// ----------------------------------------------------------------------

	elseif c=="v_" | c=="v~" | c=="v+"	// v [,range [,display #]]
		if ~isdef("d1","local"), rg=0	 // Default = automatic range
		else
			tmp =["0.5" "5" "50" "500" "750" "1000"]
			tmp2=[0.5 5 50 500 750 1000]
			ok?=%f
			if typeof(d1)=="string"
				if or(tmp==d1)
					rg=find(tmp==d1)
					if rg==6, rg=5, end
					ok?=%t
				elseif isnum(d1), d1=strtod(d1)
				end
			end
			if typeof(d1)=="constant"
				ok?=%t
				if or(tmp2==d1)
					rg=min(find(tmp2==d1),5)
				else 
					if d1<0, ok?=%f
					elseif d1==0, rg=0
					elseif d1<=0.5, rg=1
					elseif d1<=5, rg=2
					elseif d1<=50, rg=3
					elseif d1<=500, rg=4
					elseif d1>500, rg=5
					end	
				end
			end
			if ~ok?
				tmp="%s.%s: Wrong specification of the range."+LF+..
					"arg#2 should be in [0.5 5 50 500 750 1000], "+LF+..
					"or 0 for the automatic range. => Command IGNORED"
				warning(msprintf(gettext(tmp)+"\n",fn,C)+LF)
				return
			end
		end
		// Is the display specified?
		if length(d)>1 & ( (typeof(d(2))=="string" & d(2)=="2") | ..
											 (typeof(d(2))=="constant" & d(2)==2) )
				 D="2"
		else D="1"
		end
		if c=="v+" & D=="2"
				warning(msprintf(gettext(notOnD2)+"\n",fn,C,"Vac+dc")+LF)
		end
		// OK, the command can be sent:
		if c=="v_", f="0", elseif c=="v~", f="1", else f="8", end
		r=1+writeserial(ph,"S"+D+f+msprintf("%i",rg)+EOC)
		sleep(1200)

	// ----------------------------------------------------------------------

	elseif c=="a_" | c=="a~" | c=="a+"	// v [,range [,display #]]
		if ~isdef("d1","local")
			rg=0, ok?=%t										// Automatic mode =default
		else
			ok?=%f
			tmp =["500µ" "5m" "50m" "500m" "5" "10"]
			if typeof(d1)=="constant", d1=msprintf("%g",d1), end
			if typeof(d1)=="string"
				if isnum(d1)
					t=strtod(d1)
					if t<=0, rg=0, ok?=%t
					elseif t<=5e-4, d1="500µ"
					elseif t<=0.005, d1="5m"
					elseif t<=0.05, d1="50m"
					elseif t<=0.5, d1="500m"
					elseif t<=5, d1="5"
					elseif t<=10, d1="10"
					end
				end
				if or(tmp==d1), rg=find(tmp==d1), ok?=%t, end
			end
			if ~ok?
				tmp="%s.%s: Wrong specification of the range."+LF+..
					"arg#2 should be in [''500µ'' ''5m'' ''50m'' "+..
					"''500m'' ''5'' ''10''], "+LF+..
					"or 0 for the automatic range. => Command IGNORED"
				warning(msprintf(gettext(tmp)+"\n",fn,C)+LF)
				return
			end
		end
		// Is the display specified?
		if length(d)>1 & ( (typeof(d(2))=="string" & d(2)=="2") | ..
											 (typeof(d(2))=="constant" & d(2)==2) )
				 D="2"
		else D="1"
		end
		if c=="a+" & D=="2"
				warning(msprintf(gettext(notOnD2)+"\n",fn,C,"Aac+dc")+LF)
		end
		// OK, the command can be sent:
		if c=="a_", f="4", elseif c=="a~", f="5", else f="9", end
		r=1+writeserial(ph,"S"+D+f+msprintf("%i",rg)+EOC)
		if c=="a_" | c=="a~", sleep(1000), else sleep(3000), end

	// ----------------------------------------------------------------------

	elseif c=="ohm" | c=="ohmc"											// ohm [,range ]
		if ~isdef("d1","local")
			rg=0, ok?=%t										// Automatic mode =default
		else
			ok?=%f
			tmp =["500" "5k" "50k" "500k" "5m" "50m"]
			if typeof(d1)=="constant", d1=msprintf("%g",d1), end
			if typeof(d1)=="string"
				if isnum(d1)
					t=strtod(d1)
					if t<0, ok?=%f
					elseif t==0, rg=0, ok?=%t
					elseif t<=500, d1="500"
					elseif t<=5e3, d1="5k"
					elseif t<=5e4, d1="50k"
					elseif t<=5e5, d1="500k"
					elseif t<=5e6, d1="5m"
					else d1="50m"
					end
				else d1=convstr(d1,"l")
				end
				if or(tmp==d1), rg=find(tmp==convstr(d1,'l')),ok?=%t,end
			end
			if ~ok?
				tmp="%s.%s: Wrong specification of the range."+LF+..
					"arg#2 should be in [''500'' ''5k'' ''50k'' "+..
					"''500k'' ''5M'' ''50M''], "+LF+..
					"or 0 for the automatic range. => Command IGNORED"
				warning(msprintf(gettext(tmp)+"\n",fn,C)+LF)
				return
			end
		end
		// OK, the command can be sent:
		if c=="ohm", f="2", else f="A", end
		tmp="S1"+f+msprintf("%i",rg)
		disp(tmp)
		r=1+writeserial(ph,tmp+EOC)
		sleep(1000)

	// ----------------------------------------------------------------------

	elseif c=="freq" | c=="hz"									// [,display # ]
		// Is the display specified?
		D="1"
		if isdef("d1","local")
			if typeof(d1)=="string" & (d1=="1" | d1=="2"), D=d1
			elseif typeof(d1)=="constant" & d1==1 | d1==2,
				D=msprintf("%g",d1)
			end
		end
		// Setting up the MM
		r=1+writeserial(ph,"S"+D+"70"+EOC)
		sleep(1000)

	// ----------------------------------------------------------------------

	elseif c=="diode"							// no param, only on display #1
		r=1+writeserial(ph,"S160"+EOC)
		sleep(1000)

	// ----------------------------------------------------------------------

	elseif c=="dbm"									// [,display # ]
		// Is the display specified?
		D="1"
		if isdef("d1","local")
			if typeof(d1)=="string" & (d1=="1" | d1=="2"), D=d1
			elseif typeof(d1)=="constant" & d1==1 | d1==2,
				D=msprintf("%g",d1)
			end
		end
		// Setting up the MM
		r=1+writeserial(ph,"S"+D+"B0"+EOC)
		sleep(1000)

	// ----------------------------------------------------------------------

	elseif c=="zref"									// v. Referencial impedance
		// NE FONCTIONNE PAS. CAUSE INCONNUE
		tmp=['2' '4' '8' '16' '50' '75' '93' '110' '124' '125' ..
				 '135' '150' '250' '300' '500' '600' '800' '900' ..
				 '1000' '1200' '8000' ]
		i="15"	// Default = 600 ohm (factory setting)
		if isdef("d1","local")
			if typeof(d1)=="constant", d1=msprintf("%g",d1), end
			if typeof(d1)=="string" & or(tmp==d1)
				i=find(tmp==d1)
				i=msprintf("%02.0f",i-1)
			else
				tmp="%s.%s: The reference impedance must be in "+LF+..
				"["+strcat(tmp," ")+"] (ohms)."+LF+" => Command IGNORED"
				warning(msprintf(gettext(tmp)+"\n",fn,C)+LF)
				return
			end
		end
		r=1+writeserial(ph,"S0"+i+EOC)
		sleep(2000)

	// ----------------------------------------------------------------------

	elseif c=="bright"									// [,brightness from 0 to 3]
		if isdef("d1","local")
			if typeof(d1)=="string" & or(["0" "1" "2" "3"]==d1), D=eval(d1)
			elseif typeof(d1)=="constant" & or([0 1 2 3]==d1), D=d1
			else D=3
			end
		else D=3
		end
		// 
		for i=1:3, r=1+writeserial(ph,"K20"+EOC), sleep(20), end
		for i=1:D, r=1+writeserial(ph,"K19"+EOC), sleep(20), end

	// ----------------------------------------------------------------------

	elseif c=="infos"
		t=" ", while t~="",t=readserial(ph),end		// Cleaning the serial buffer
		t = 1+writeserial(ph,"R0"+EOC), sleep(100)
		t = readserial(ph), sleep(100)
		s2 = hex2dec(part(t,6:7))
		tmp = ["D1" "R1" "D2" "R2" "BRIGHT" "%?" "RHOLD?" "BEEP?" "TRIG?" "LIM?"..
				 "PORT"]
		F  =["V_" "V~" "ohm" "" "A_" "A~" "diode" "Hz" "V+" "A+" "ohmC" "dBm" ]
		if ~isdef("d1"), d1=tmp, else d1=convstr(d1,"u"), end
		r=[]
		
		for e = d1		// List of requests
			if e=="BRIGHT", r=[r part(t,5)]			   // Screen brightness
			elseif e=="%?"								// Percentage
				r = [r msprintf("%d",bitand(s2,1))]
			elseif e=="RHOLD?"							// R_Hold status
				r = [r msprintf("%d",bitand(s2,2)/2)]
			elseif e=="BEEP?"							// Beep status
				r = [r msprintf("%d",bitand(s2,4)/4)]
			elseif e=="TRIG?"							// Trigger status
				r = [r msprintf("%d",bitand(s2,8)/8)]
			elseif e=="LIM?"							// Are limits set ?
				r = [r msprintf("%d",bitand(s2,16)/16)]
			elseif e=="PORT"							// Port ids
				tmp = TCL_GetVar("port",fn)
				r = [r strcat(tmp,"/")]
			elseif e=="D1" | e=="D2"
				if e=="D1"
                    f = part(t,8)
                else 
                    f = part(t,10)
                end
				if f~=" " & f~=ascii(13)
                    r = [r F(hex2dec(f)+1)]
                else
                    r = [r ""]
                end
			elseif e=="R1" | e=="R2"
				if e=="R1"
					f = part(t,8)
					a = part(t,9)
				else
					f = part(t,10)
					a = part(t,11)
				end
				if f==" " | f==ascii(13)
                    r = [r ""]
				elseif f=="0" | f=="1" | f=="8"					// V_, V~, V+
					tmp = ["0.5" "5" "50" "500" "750"]
					tmp = tmp(eval(a))
					if f=="0" & tmp=="750", tmp="1000", end
					r = [r tmp]
				elseif f=="4" | f=="5" | f=="9"					// A_, A~, A+
					tmp = ["500µ" "5m" "50m" "500m" "5" "10"]
					r = [r tmp(eval(a))]
				elseif f=="2" | f=="A"							// ohm & ohmC
					tmp = ["500" "5k" "50k" "500k" "5M" "50M"]
					r = [r tmp(eval(a))]
				elseif f=="6"										// Diode
					r = [r "2.3V"]
				elseif f=="7"										// Hz
					tmp = ["500" "5k" "50k" "500k"]
					r = [r tmp(eval(a))]
				elseif f=="B"										// dBm
					r = [r ""]
				end
			end
		end

	// ----------------------------------------------------------------------

	else
		tmp = _("%s: Command ""%s"" unknown.\n")
		error(msprintf(tmp, fn, c)+LF)
	end
endfunction

//=========================================================================

function r = mm3136AErr(c)
    // Translates each error code into the respective documented error message
	if     c=="*>", r = "The multimeter is reinitialized"
	elseif c=="!>", r = "Wrong command" 
	elseif c=="?>", r = "Wrong parameter"
	elseif c=="#>", r = "The LOCAL button is kept pressed"
	elseif c=="S>", r = "Setup mode active"
	elseif c=="@>", r = "No available data. The display is OFF"
	elseif c=="W>", r = "Limits HI and LO would be inverted"
	elseif c=="E>", r = "Operation forbidden"
	else r = "Unkown error"
	end
endfunction

// ---------------------------------------------------------------

