// TITLE    : Scilab driver for OLP-15B, OLP-16B, OLP-18B optical power meter 
//            (optical fibers measurement)
// Copyright: Samuel GOUGEON - Université du Maine / ENSIM
// Release  : 1.0 (2012-03-15)
// License  : CeCILL-C
//   http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
// Software : for Scilab : http://www.scilab.org/
// Dependency: http://atoms.scilab.org/toolboxes/serial must be loaded

function out = OLPpower(port, command, varargin)
//
// Scilab Driver for OLP-15B, OLP-16B and OLP-18B powermeter for optical fibers
//    Tested only for the OLP-15B model, but other models should be supported.
//    The powermeter must be connected to a serial RS-232 port and turned on.
//    Several power meters may be connected on their respective ports on the
//    same computer. Each one will be addressed through its own handle.
//
// Input arguments: 
// #1: Serial port number (for the open command), 
//     or serial port handle returned by "open" (for all other commands)
// #2: Command name (case unsensitive)
// #3: Data (unit, wavelength,..), undifferently string or numeric, 
//     case unsensitive.
//
// REQUIREMENTS
// ------------
//  * Scilab > 5.2.0 is required
//  * Serial TCL toolbox 0.2 (E. Segre) must be loaded
//    http://atoms.scilab.org/toolboxes/serial
//  * OS : Windows or Linux plateform. Mac OS X are not supported (for TCL)
//  * The powermeter must be connected to the chosen serial port.
//    For information: Connexion parameters are: 9600 bauds, 8 data bits, 
//     no parity, 1 stop bit, Xon/Xoff protocol.
//
// SERIAL CONNEXION
// ----------------
// port, 'OPEN' : Open the RS-232 communication for the given RS-232 port. 
//          If port is a string, it must follow the format "COM#:" or
//          "/dev/ttyS#" with # stating from 1 in the first case (Windows) and
//          from 0 in the second case (Linux). Else, integer numbers from 0
//          0 or N must be specified.
//          Returns 1 whether the connexion is established, 0 otherwise.
// port, 'CLOSE'  : Close the RS-232 communication for the given port (handle).
//          Returned 1 = OK
//
// COMMANDS, DATA
// --------------
// 'POW?'  : Query and return the measured power (numeric. 4 digits: 
//           OLP-15B:  0.0001 µW < P < 100mW  ==   -70dBm < P < 20dBm
//           In case of too low signal, -80 is returned in [dBm] or [dB] modes, 
//           or 1e-11 is returned if [W] mode.
//
// 'UNIT', 'DBM'|'W'|'DB' : Set the measurement unit to the specified one
// 'UNIT?' : Query the current measurement unit (numeric, in the current unit)
//           Returned strings are "W", "DBM" or "DB"
//
// 'WAV', xxxx : Set the measurement wavelength (integer in [nm])
//           Possible wavelengths xxxx are (OLP-15B): 780, 850, 1300, 1310, 1550
// 'WAV?'  : Query and return the measurement wavelength (numeric integer in [nm])
//
// 'FREQ?' : Query and return the detected modulation frequency (number in [Hz])
// 'REF?'  : Query and return the reference level power (number in [dBm])
// 'LID?'  : Query and return the measured Line-ID
// 'ZEROING' : Start zeroing
//
// 'LANG', Language : Set the language for printout. Supported languages
//         are 'FRAN' (Français), 'ENGL' (English), 'ESPA' (Español),
//             'ITAL' (Italiano), 'DEUT' (Deutsch)
// 'LANG?' : Query and return the current language (4 characters string)
// 'ERR?'  : Query and return the last error code from the device (2-3 characters)

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

// INITIALISATIONS
// ===============
    out = ''
    fname = "OLPpower"    // Name of this function (for error messages)
	if (argn(2)==0 | command=='HELP')
        head_comments(fname)
        return
    end

    NL = ascii(10)        // New Line
    tempoRead = 900       // Delay [ms] after any read operation
                          // This parameter is sensitive... DO NOT change it
    global OLPpower_LOW   // Low level (expressed in the current unit)
    port  = string(port) 
	command = convstr(command,'u');
	if size(varargin)>0
         data = convstr(string(varargin(1)),'u')
    else data = ''
    end
    
	// Checking for the TCL serial toolbox availability:
    if ~exists('writeserial')
        tmp = _("%s: The SERIAL TCL toolbox is missing. Please instal it before processing.\n");
        error(msprintf(tmp,fname));
	end

// =====================================================================
// MAIN COMMAND LOOP
// =====================================================================

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

    if command=='OPEN'
        if length(port)<4
            t = eval(port)
        else 
            t = port
        end
        out = openserial(t,"9600,n,8,1","binary")
        if out<>0 then
            unit = OLPpower(out,"unit?")
            if unit=='W'
                OLPpower_LOW = "1e-11"    // in [W]
            else
                OLPpower_LOW = "-80"      // in [dBm]
            end
        end
        return
     end

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

    if command=='CLOSE'
    	out = string(1+closeserial(port)) // Closing the port
        return
    end
  // ===================================================================
  
    // List of possible commands to the device
	LC = [ "POW?"  "UNIT?" "UNIT" "LANG?" "LANG" "ERR?" "WAV?" "WAV" ..
           "FREQ?" "LID?"  "REF?" "ZEROING" "*IDN?" ]
    C = struct( "POW?" ,"FETCH:POW?",           ..
                "UNIT?","DISP:UNIT?",           ..
                "UNIT" ,"DISP:UNIT "+data,      ..
                "LANG?","SYST:LANG?",           ..
                "LANG" ,"SYST:LANG "+data,      ..
                "ERR?" ,"SYST:ERR?",            ..
                "WAV?" ,"SENS:WAV?",            ..
                "WAV"  ,"SENS:WAV "+data,       ..
                "FREQ?","SENS:AM:INT:FREQ?",    ..
                "LID?" ,"SENS:AM:LID?",         ..
                "REF?" ,"SENS:POW:REF:VAL?",    ..
                "ZEROING","CAL:ZERO:AUTO ONCE", ..
                "*IDN?","SYST:*IDN?")
                
    if or(command==LC)
        tmp = 1 + writeserial(port,C(command)+NL)
        sleep(tempoRead)
        if ~tmp,
            tmp = _("%s: Command ""%s"": OLP device (id ""%s"") does not answer\n")
            error(msprintf(tmp, fname, command, port))
        else 
            tmp = ascii(readserial(port))
            sleep(tempoRead)
            out = ascii(tmp(find(tmp>31 & tmp<123)))
            if command=="POW?"
                if out=="-9.9E+37"
                    out = OLPpower_LOW  // Too low => = low bound value (OLP-16B)
                end  
                out = eval(strsubst(out," ",""))
            elseif or(command==["WAV?" "FREQ?" "LANG?"])
                out = eval(out)
            end
            if command=="LANG?"
                L = ["ENGL" "DEUT" "ESPA" "FRAN" "ITAL"  ]
                out = L(out+1)
            end
            if command=="UNIT"     // OLPpower_LOW must be updated
                if data=='W'
                    OLPpower_LOW = "1e-11"    // in [W]
                else
                    OLPpower_LOW = "-80"      // in [dBm]
                end
            end
            return
        end
    else
        tmp = _("%s : Unknown command ""%s"" to the OLP device (id %s)\n")
        error(msprintf(tmp, fname, command, port))
    end

endfunction

