esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

# $Header: /segfs/dserver/classes++/ccd/espia/spec/RCS/frelon2k.mac,v 1.10 2011/05/13 14:25:52 guilloud Exp $
#
#%NAME%
#  FRELON2K.MAC - Macros to control the frelon2k cameras from SPEC
#
#%OVERVIEW%
#  This macro set allows to deal with %B%frelon2k%B% configuration
#  %BR%
#
#%CATEGORY%
#
#%DESCRIPTION%
#  Supported models : frelon2K frelon4M frelon HD ???
#
#%EXAMPLE%
#  %DL%
#  %DT%ccd_%DD%
#  %DT%ccd_%DD%
#  %XDL%
#
#%SETUP%
#
#%END%


need spec_utils

######################################################################
######################                          ######################
######################  FUNC FOR COMPATIBILITY  ######################
######################                          ######################
######################################################################


#%IU% (<force>)
#%MDESC%
#    Declares global variables used by ccd.mac and CCDDEV.
# - <force> : if <force> is 1 then it sets all CCDDEV parameters.
#
# returns 1 if macro fully executed.
# returns 0 if macro aborted because CCDDEV already initialized.
#
def ccd_check_globals(force) '{

    # the main table
    global CCDDEV[]
    # compatibitilty
    global CCD_U CCDSAVE[] CCDSAVE_MODE[] 
    global CCD_DIR[] CCD_PREFIX[] CCD_SUFFIX[] CCD_N[]


    # 
    if (CCDDEV["inited"] && !force){
        return 0
    }

    CCDDEV["preffix"]["set"] = "Set"
    CCDDEV["preffix"]["get"] = "Get"
    CCDDEV["preffix"]["cmd"] = ""

    # parameters that can be "set" / "get"
    CCDDEV["images"       ]["cmd"] = "Frames"
    CCDDEV["preset"       ]["cmd"] = "Exposure"
    CCDDEV["ext_trig"     ]["cmd"] = "Trigger"
    CCDDEV["hw_par"       ]["cmd"] = "HwPar"
    CCDDEV["mode"         ]["cmd"] = "Mode"
    CCDDEV["kinetics"     ]["cmd"] = "Kinetics"
    CCDDEV["kinwinsize"   ]["cmd"] = "KinWinSize"
    CCDDEV["input_channel"]["cmd"] = "Channel"

    # "pseudo" parameters with no direct call associated
    CCDDEV["bin"          ]["cmd"] = "Bin"
    CCDDEV["row_bin"      ]["cmd"] = ""
    CCDDEV["col_bin"      ]["cmd"] = ""
    CCDDEV["roi"          ]["cmd"] = "RoI"
    CCDDEV["row_beg"      ]["cmd"] = ""
    CCDDEV["row_end"      ]["cmd"] = ""
    CCDDEV["col_beg"      ]["cmd"] = ""
    CCDDEV["col_end"      ]["cmd"] = ""
    CCDDEV["file"         ]["cmd"] = "FilePar"
    CCDDEV["file_dir"     ]["cmd"] = ""
    CCDDEV["file_prefix"  ]["cmd"] = ""
    CCDDEV["file_suffix"  ]["cmd"] = ""
    CCDDEV["file_inum"    ]["cmd"] = ""
    
    # commands
    CCDDEV["cols"         ]["cmd"] = "XSize"
    CCDDEV["rows"         ]["cmd"] = "YSize"
    CCDDEV["run"          ]["cmd"] = "Start"
    CCDDEV["halt"         ]["cmd"] = "Stop"
    CCDDEV["get_current"  ]["cmd"] = "GetCurrent"
    CCDDEV["talk"         ]["cmd"] = "Command"

    # serial commands
    CCDDEV["shutter_on"        ]["serial"] = "U"
    CCDDEV["shutter_close_time"]["serial"] = "F"
    CCDDEV["latency_time"      ]["serial"] = "T"

    # value / names
    CCDDEV["kinetics"]["values"] = "0 3"
    CCDDEV["kinetics"]["names"]  = "FFM FTM"
   
    CCDDEV["roi_mode"]["values"] = "0 1 2 3"
    CCDDEV["roi_mode"]["names"]  = "Full-Image Slow Fast Kinetic"

    CCDDEV["ext_trig"]["values"] = "0 1 2 3"
    CCDDEV["ext_trig"]["names"]  = "Software Single Multiple Gate"

    # cached pars
    CCDDEV["preset" ]["cached"] = 1
    CCDDEV["row_bin"]["cached"] = 1
    CCDDEV["col_bin"]["cached"] = 1
    CCDDEV["row_beg"]["cached"] = 1
    CCDDEV["row_end"]["cached"] = 1
    CCDDEV["col_beg"]["cached"] = 1
    CCDDEV["col_end"]["cached"] = 1

    # par groups
    CCDDEV["ccd_mode"          ]["group"] = "chan_mode"
    CCDDEV["cols"              ]["group"] = "chan_mode"
    CCDDEV["rows"              ]["group"] = "chan_mode"
    CCDDEV["input_channel"     ]["group"] = "chan_mode"

    CCDDEV["col_bin"           ]["group"] = "bin"
    CCDDEV["row_bin"           ]["group"] = "bin"

    CCDDEV["col_beg"           ]["group"] = "roi"
    CCDDEV["row_beg"           ]["group"] = "roi"
    CCDDEV["col_end"           ]["group"] = "roi"
    CCDDEV["row_end"           ]["group"] = "roi"
    CCDDEV["roi_mode"          ]["group"] = "roi hw_par"
    CCDDEV["kinlinebeg"        ]["group"] = "roi hw_par"
    CCDDEV["kinwinsize"        ]["group"] = "roi"
    CCDDEV["kinstripes"        ]["group"] = "roi hw_par"

    CCDDEV["col_flip"          ]["group"] = "flip hw_par"
    CCDDEV["row_flip"          ]["group"] = "flip hw_par"
    
    CCDDEV["preset"            ]["group"] = "sync"
    CCDDEV["ext_trig"          ]["group"] = "sync"
    CCDDEV["images"            ]["group"] = "sync"
    CCDDEV["live"              ]["group"] = "sync"
    CCDDEV["shutter_on"        ]["group"] = "sync"
    CCDDEV["shutter_close_time"]["group"] = "sync"
    CCDDEV["latency_time"      ]["group"] = "sync"

    CCDDEV["debug_level"       ]["group"] = "mode"
    CCDDEV["big_buffer"        ]["group"] = "mode"
    CCDDEV["shared_mem"        ]["group"] = "mode"
    CCDDEV["remote_save"       ]["group"] = "mode save"

    CCDDEV["do_save"           ]["group"] =      "save"
    CCDDEV["file_dir"          ]["group"] = "file save"
    CCDDEV["file_prefix"       ]["group"] = "file save"
    CCDDEV["file_suffix"       ]["group"] = "file save"
    CCDDEV["file_inum"         ]["group"] = "file save"

    return 1
}'




def ccd_par_devcmd(par, type) '{
    local ccdcmd

    ccd_check_globals()

    if (par == "state")
        ccdcmd = "DevState"
    else if (par == "status")
        ccdcmd = "DevStatus"
    else
        ccdcmd = sprintf("DevCcd%s%s", CCDDEV["preffix"][type], \
                                       CCDDEV[par]["cmd"])
    return ccdcmd
}'

def ccd_dev_name(_ccd_u) '{
    return image_par(_ccd_u, "device_id")
}'

def ccd_par_get(_ccd_u, par) '{
    local devcmd
    devcmd = ccd_par_devcmd(par, "get")
    return esrf_io(ccd_dev_name(_ccd_u), devcmd)
}'

def ccd_par_get_arr(_ccd_u, par, larr) '{
    local devcmd
    devcmd = ccd_par_devcmd(par, "get")
    return esrf_io(ccd_dev_name(_ccd_u), devcmd, larr)
}'


def ccd_par_set(_ccd_u, par, val) '{
    local devcmd
    devcmd = ccd_par_devcmd(par, "set")
    return esrf_io(ccd_dev_name(_ccd_u), devcmd, val)
}'

def ccd_par_cmd(_ccd_u, par, val) '{
    local ccddev devcmd

    ccddev = ccd_dev_name(_ccd_u)
    devcmd = ccd_par_devcmd(par, "cmd")

    if (par == "talk")
        return esrf_io(ccddev, devcmd, val)
    else
        return esrf_io(ccddev, devcmd)
}'





######################################################################
###########################                ###########################
###########################  DEBUG / INFO  ###########################
###########################                ###########################
######################################################################


global F2K_DEBUG


#%IU% (<msg>)
#%MDESC%
#    Prints a message in blue prefixed by [FRELON2K]--
def f2k_msg(msg) '{
    #                                     4=blue
    cprint(sprintf("[FRELON2K]--%s\n", msg ), 4)
}'

#%IU% (<error_message>)
#%MDESC%
#    Prints an ERROR message in red prefixed by [FRELON2K]--ERROR--
def f2k_err(error_message) '{
    #                                                      1=red
    cprint(sprintf("[FRELON2K]--ERROR--%s\n", error_message ), 1)
}'

#%IU% (<debug_message>)
#%MDESC%
#    Prints a DEBUG  message in orange prefixed by [FRELON2K]--DEBUG--
def f2k_dbg(debug_message) '{

    if (F2K_DEBUG){
        #                                                        3=orange
        cprint(sprintf("[FRELON2K]--DEBUG--%s\n", debug_message ), 3)
    }

}'


#######################################################################
###################                                  ##################
###################  FRELON2K SERIAL COMMUNICATION ? ##################
###################                                  ##################
#######################################################################



def ccd_serial_cmd(_ccd_u, cmd) '{
    local ret len nexpect npars pars[]

    ret = ccd_par_cmd(_ccd_u, "talk", cmd)
    len = length(ret)
    if (substr(ret, len - 1, 2) == "\r\n")
       ret = substr(ret, 1, len - 2)
    npars = split(ret, pars, ":")
    nexpect = (index(cmd, "?") > 0) ? 2 : 1
    if ((pars[0] != "!OK") || (npars != nexpect)) {
        printf("Error reading serial response to %s: %s\n", cmd, ret)
        return ret
    }
    return (nexpect == 2) ? pars[1] : ""
}'

def ccd_serial_set(_ccd_u, par, val) '{
    local ret cmd

    cmd = sprintf(">%s%s", par, val)
    ret = ccd_serial_cmd(_ccd_u, cmd)
    if (ret != "") {
        printf("Error setting \"%s\" (%s): %s\n", par, cmd, ret)
        return -1
    }
    return 0
}'

def ccd_serial_get(_ccd_u, par) '{
    local ret cmd

    cmd = sprintf(">%s?", par)
    ret = ccd_serial_cmd(_ccd_u, cmd)
    if (ret + 0 != ret) {
        printf("Error reading \"%s\" (%s): %s\n", par, cmd, ret)
        return -1
    }
    return ret + 0
}'

def ccd_conf_serial_par(par) '{
    ccd_check_globals()
    return CCDDEV[par]["serial"]
}'

def ccd_conf_serial_set(_ccd_u, par, newconf) '{
    return ccd_serial_set(_ccd_u, ccd_conf_serial_par(par), newconf[par])
}'

def ccd_conf_serial_get(_ccd_u, par) '{
    return ccd_serial_get(_ccd_u, ccd_conf_serial_par(par))
}'



#%UU% (<_ccd_u>)
#%MDESC%
#    
def ccd_responsive(_ccd_u) '{
    local state responsive

    responsive = image_par(_ccd_u, "responsive")
    if (responsive) {
        esrf_io(ccd_dev_name(_ccd_u), "timeout", 10)
        ESRF_ERR = -1
        state = ccd_par_cmd(_ccd_u, "state")
        responsive = (state != 23)
    }
    if (!responsive) 
        printf("Error: CCD device %d (%s) not responsive!\n", \
               _ccd_u, ccd_dev_name(_ccd_u))
    return responsive
}'


def ccd_acquiring(_ccd_u) '{
    local state
    state = ccd_par_cmd(_ccd_u, "state")
    return (state == 0xc180002)
}'


def ccd_conf_name_val(par, val, retname) '{
    local nval values[] names[] i

    ccd_check_globals()

    nval = split(CCDDEV[par]["values"], values)
    nval = split(CCDDEV[par]["names"], names)
    for (i = 0; i < nval; i++) {
       if (retname && (values[i] == val))
           return names[i]
       else if (!retname && (names[i] == val))
           return values[i]
    }
    
    printf("Error: invalid %s %s: %s\n", par, retname ? "value" : "name", val)
    return -1
}'

def ccd_conf_name2val(par, name) '{
    return ccd_conf_name_val(par, name, 0)
}'

def ccd_conf_val2name(par, val) '{
    return ccd_conf_name_val(par, val, 1)
}'

def ccd_par_array_set(pars, pararr) '{
    local parstr nrpars

    parstr = (pars == 0) ? "" : pars
    nrpars = split(parstr, pararr)
    pararr["nrpars"] = nrpars
    pararr["exclude" ] = ((nrpars > 0) && (substr(pararr[0], 1, 1) == "~")) 
    if (pararr["exclude"])
        pararr[0] = substr(pararr[0], 2)
}'

def ccd_par_array_check(arr, pars) '{
    local i j pararr[] npars allpars group

    ccd_check_globals()

    if (arr["nrpars"] == 0)
        return 1
    else if ((arr["nrpars"] == 1) && (arr[0] == -1))
        return 0

    allpars = pars
    npars = split(allpars, pararr)
    for (j = 0; j < npars; j++) {
        group = CCDDEV[pararr[j]]["group"]
        if (group) 
            allpars = sprintf("%s %s", allpars, group)
    }
    npars = split(allpars, pararr)
    for (i = 0; i < arr["nrpars"]; i++)
        for (j = 0; j < npars; j++)
            if (arr[i] == pararr[j])
                return !pararr["exclude"]
    return pararr["exclude"]
}'

def ccd_conf_par_get(_ccd_u, confarr, pararr, par) '{
    if (ccd_par_array_check(pararr, par))
        confarr[par] = ccd_par_get(_ccd_u, par)
}'

def ccd_conf_serial_par_get(_ccd_u, confarr, pararr, par) '{
    if (ccd_par_array_check(pararr, par))
        confarr[par] = ccd_conf_serial_get(_ccd_u, par)
}'

def ccd_default_config_par(confarr, pararr, par, val) '{
    if (ccd_par_array_check(pararr, par))
        confarr[par] = val
}'

def ccd_default_config(confarr, pars) '{
    local pararr[]

    ccd_par_array_set(pars, pararr)

    ccd_default_config_par(confarr, pararr, "ccd_mode", "FFM")
    ccd_default_config_par(confarr, pararr, "cols", 2048)
    ccd_default_config_par(confarr, pararr, "rows", 2048)
    ccd_default_config_par(confarr, pararr, "input_channel", 15)

    ccd_default_config_par(confarr, pararr, "col_bin", 1)
    ccd_default_config_par(confarr, pararr, "row_bin", 1)

    ccd_default_config_par(confarr, pararr, "col_beg", 0)
    ccd_default_config_par(confarr, pararr, "row_beg", 0)
    ccd_default_config_par(confarr, pararr, "col_end", confarr["cols"] - 1)
    ccd_default_config_par(confarr, pararr, "row_end", confarr["rows"] - 1)
    ccd_default_config_par(confarr, pararr, "col_flip", 0)
    ccd_default_config_par(confarr, pararr, "row_flip", 0)
    ccd_default_config_par(confarr, pararr, "kinlinebeg", 0)
    ccd_default_config_par(confarr, pararr, "kinstripes", 1)
    ccd_default_config_par(confarr, pararr, "roi_mode", "Full-Image")

    ccd_default_config_par(confarr, pararr, "preset",   1)
    ccd_default_config_par(confarr, pararr, "ext_trig", "Software")
    ccd_default_config_par(confarr, pararr, "images", 1)
    ccd_default_config_par(confarr, pararr, "live",   0)
    ccd_default_config_par(confarr, pararr, "shutter_on",         1)
    ccd_default_config_par(confarr, pararr, "shutter_close_time", 0)
    ccd_default_config_par(confarr, pararr, "latency_time",       0)

    ccd_default_config_par(confarr, pararr, "debug_level",  0)
    ccd_default_config_par(confarr, pararr, "remote_save",  0)
    ccd_default_config_par(confarr, pararr, "big_buffer",   0)
    ccd_default_config_par(confarr, pararr, "shared_mem",   0)
    ccd_default_config_par(confarr, pararr, "save do_save", 0)

    ccd_default_config_par(confarr, pararr, "file_dir",    DATA_DIR)
    ccd_default_config_par(confarr, pararr, "file_prefix", "img_")
    ccd_default_config_par(confarr, pararr, "file_suffix", ".edf")
    ccd_default_config_par(confarr, pararr, "file_inum",   0)

    ccd_conf_check_save(confarr)

    confarr["inited"] = 1
}'

def ccd_get_config_save(_ccd_u, confarr, pararr) '{
    local filearr[] usedef remote_save parstr

    ccd_check_globals()

    if (ccd_par_array_check(pararr, "do_save")) 
        confarr["do_save"] = (CCDSAVE[_ccd_u] || confarr["remote_save"])

    parstr = "file_dir file_prefix file_suffix file_inum"
    if (!ccd_par_array_check(pararr, parstr))
        return 0

    if (confarr["remote_save"]) {
        ccd_par_get_arr(_ccd_u, "file", filearr)
        usedef = (length(filearr[0]) == 0)
    } else 
        usedef = (CCD_DIR[_ccd_u] == 0)
    if (usedef) {
        ccd_default_config(confarr, "file")
        return 0
    }

    remote_save = confarr["remote_save"]
    confarr["file_dir"]    = remote_save ? filearr[0] : CCD_DIR[_ccd_u]
    confarr["file_prefix"] = remote_save ? filearr[1] : CCD_PREFIX[_ccd_u]
    confarr["file_suffix"] = remote_save ? filearr[2] : CCD_SUFFIX[_ccd_u]
    confarr["file_inum"]   = remote_save ? filearr[3] : CCD_N[_ccd_u]
}'

def ccd_get_config(_ccd_u, confarr, pars) '{
    local val valarr[] pararr[] nrval i parstr

    confarr["responsive"] = ccd_responsive(_ccd_u)
    if (!confarr["responsive"]) 
        return -1

    ccd_par_array_set(pars, pararr)

    if (ccd_par_array_check(pararr, "ccd_mode")) {
        val = ccd_par_get(_ccd_u, "kinetics")
        confarr["ccd_mode"] = ccd_conf_val2name("kinetics", val)
    }

    if (ccd_par_array_check(pararr, "cols"))
        confarr["cols"] = ccd_par_cmd(_ccd_u, "cols")
    if (ccd_par_array_check(pararr, "rows"))
        confarr["rows"] = ccd_par_cmd(_ccd_u, "rows")

    ccd_conf_par_get(_ccd_u, confarr, pararr, "input_channel")

    if (ccd_par_array_check(pararr, "col_bin row_bin")) {
        ccd_par_get_arr(_ccd_u, "bin", valarr)
        confarr["col_bin"] = valarr[0]
        confarr["row_bin"] = valarr[1]
    }

    if (ccd_par_array_check(pararr, "col_beg row_beg col_end row_end")) {
        ccd_par_get_arr(_ccd_u, "roi", valarr)
        confarr["col_beg"] = valarr[0]
        confarr["row_beg"] = valarr[1]
        confarr["col_end"] = valarr[2]
        confarr["row_end"] = valarr[3]
    }

    parstr = "col_flip row_flip kinlinebeg kinstripes roi_mode"
    if (ccd_par_array_check(pararr, parstr)) {
        val = ccd_par_get(_ccd_u, "hw_par")
        nrval = split(val, valarr)
        for (i = 0; i < nrval; i++)
            valarr[i] = int(valarr[i])
        confarr["col_flip"] = (valarr[0] & 0x02) >> 1
        confarr["row_flip"] = (valarr[0] & 0x01)
        confarr["kinlinebeg"] = valarr[1]
        confarr["kinstripes"] = valarr[2]
        confarr["roi_mode"] = ccd_conf_val2name("roi_mode", valarr[4])
    }
    ccd_conf_par_get(_ccd_u, confarr, pararr, "kinwinsize")

    if (ccd_par_array_check(pararr, "preset ext_trig")) {
        confarr["preset"] = ccd_par_get(_ccd_u, "preset")
        if (confarr["preset"] == 0)
            confarr["ext_trig"] = "Gate"
        else {
            val = ccd_par_get(_ccd_u, "ext_trig")
            confarr["ext_trig"] = ccd_conf_val2name("ext_trig", val)
        }
    }

    ccd_conf_serial_par_get(_ccd_u, confarr, pararr, "shutter_on")
    ccd_conf_serial_par_get(_ccd_u, confarr, pararr, "shutter_close_time")
    ccd_conf_serial_par_get(_ccd_u, confarr, pararr, "latency_time")

    parstr = "debug_level do_save remote_save big_buffer shared_mem"
    if (ccd_par_array_check(pararr, parstr)) {
        val = ccd_par_get(_ccd_u, "mode")
        confarr["debug_level"] = (val & 0x7ffffc00) >> 10
        confarr["remote_save"] = (val & 0x08) >> 3
        confarr["big_buffer"]  = (val & 0x04) >> 2
        confarr["shared_mem"]  = (val & 0x01) >> 0
    }

    ccd_get_config_save(_ccd_u, confarr, pararr)

    if (ccd_par_array_check(pararr, "images live")) {
        confarr["images"] = ccd_par_get(_ccd_u, "images")
        confarr["live"]   = (confarr["images"] == 0)
    }

    confarr["inited"] = 1
}'


def ccd_par_update(_ccd_u, par, val, dsval) '{
    local change prev hascmd
    
    ccd_check_globals()

    prev = image_par(_ccd_u, par)
    change = (prev != val)
    if (change)
        image_par(_ccd_u, par, val)
    if (CCDDEV[par]["cached"]) {
        hascmd = (CCDDEV[par]["cmd"] != "")
        prev = hascmd ? ccd_par_get(_ccd_u, par) : dsval
        if (prev != val) {
            if (hascmd)
                ccd_par_set(_ccd_u, par, val)
            change = 1
        }
    }
    return change
}'


def ccd_conf_par_update(_ccd_u, par, newconf) '{
    return ccd_par_update(_ccd_u, par, newconf[par])
}'


def ccd_conf_par_update_ds(_ccd_u, par, newconf, dsconf) '{
    return ccd_par_update(_ccd_u, par, newconf[par], dsconf[par])
}'


def ccd_take_image(_ccd_u, preset) '{
    local prevmode prevtrig

    prevmode = image_par(_ccd_u, "mode")
    if (prevmode & 0x08)
        image_par(_ccd_u, "mode", prevmode & ~0x08)

    ccd_par_update(_ccd_u, "preset", preset)
    ccdtake

    if (prevmode & 0x08)
        image_par(_ccd_u, "mode", prevmode)
}'


def ccd_input_channel_check(val, ccdmode) '{
    local validchans[] auxarr[] nchan i str sep

    validchans["FTM"] = "3 12 15"
    validchans["FFM"] = "1 2 4 8 3 12 5 10 15"

    nchan = split(validchans[ccdmode], auxarr)
    for (i = 0; i < nchan; i++)
        if (auxarr[i] == val)
            return 1

    str = ccd_input_channel_str(val)
    printf("Error: invalid input_channel in %s: %s\n", ccdmode, str)
    printf("It must be: ")
    for (i = 0; i < nchan; i++) {
        sep = (i == 0) ? "" : ((i == nchan - 1) ? " or " : ", ")
        printf("%s%s", sep, ccd_input_channel_str(auxarr[i]))
    }
    printf("\n")
    return 0
}'


def ccd_input_channel_val(str) '{
    local i val chnarr[] nchn

    if (str == "0")
        return 15

    val = 0
    nchn = split(str, chnarr, "&")
    for (i = 0; i < nchn; i++)
        val |= (1 << (int(chnarr[i]) - 1))

    return val
}'

def ccd_input_channel_str(val) '{
    local str i

    str = ""
    for (i = 0; i < 4; i++)
        if (val & (1 << i))
            str = sprintf("%s%s%s", str, (str == "") ? "" : "&", i + 1)

    return str
}'

def ccd_set_config_save(_ccd_u, newconf, prevconf) '{
    local warn file_inum

    ccd_check_globals()

    file_inum = prevconf["remote_save"] ? image_par(_ccd_u, "file_inum") : \
                                          CCD_N[_ccd_u]

    warn = (newconf["do_save"] && prevconf["do_save"] && \
            (newconf["file_dir"]    == prevconf["file_dir"])    && \
            (newconf["file_prefix"] == prevconf["file_prefix"]) && \
            (newconf["file_suffix"] == prevconf["file_suffix"]) && \
            (newconf["file_inum"]   <  file_inum))
    if (warn)
        printf("Warning: file \"%s\" might be overwritten!\n", \
               ccd_next_file_name(newconf))

    CCDSAVE[_ccd_u]      = (newconf["do_save"] && !newconf["remote_save"])
    CCDSAVE_MODE[_ccd_u] = 0
    CCD_DIR[_ccd_u]      = newconf["file_dir"]
    CCD_PREFIX[_ccd_u]   = newconf["file_prefix"]
    CCD_SUFFIX[_ccd_u]   = newconf["file_suffix"]
    CCD_N[_ccd_u]        = newconf["file_inum"]

    if (newconf["remote_save"]) {
        image_par(_ccd_u, "file_dir",    newconf["file_dir"])
        image_par(_ccd_u, "file_prefix", newconf["file_prefix"])
        image_par(_ccd_u, "file_suffix", newconf["file_suffix"])
        image_par(_ccd_u, "file_inum",   newconf["file_inum"])
    }
}'




#%IU% (<_ccd_u>, <newconf>)
#%MDESC%
#    
def ccd_set_config(_ccd_u, newconf) '{
    local prevconf[] val later hw_par

    f2k_dbg("enter ccd_set_config")

    # Get (some) current DS conf to see what changes
    if (ccd_get_config(_ccd_u, prevconf, "ccd_mode mode") < 0)
        return -1

    if (ccd_acquiring(_ccd_u)){
        f2k_dbg("stopping ccd")
        ccd_stop(_ccd_u)
    }

    # Not all channels are supported in FTM. If new config has FTM, the
    # channel must be set before. If prev config had FTM, the channel 
    # must be changed "later" (i.e., after setting FFM).
    val = newconf["input_channel"]
    later = 0
    if (!ccd_input_channel_check(val, newconf["ccd_mode"]))
        return -1
    if (!ccd_input_channel_check(val, prevconf["ccd_mode"]))
        later = 1
    if (!later) 
        ccd_conf_par_update(_ccd_u, "input_channel", newconf)

    # Set the FFM/FTM
    f2k_dbg("Set FFM/FTM mode")
    val = newconf["ccd_mode"]
    val = ccd_conf_name2val("kinetics", val)
    if (val == -1) {
        print "Error: invalid ccd_mode:", newconf["ccd_mode"]
        return -1
    }
    ccd_par_update(_ccd_u, "kinetics", val)
    if (image_par(_ccd_u, "rows") != ccd_par_cmd(_ccd_u, "rows"))
        image_par(_ccd_u, "resize")

    # FFM is OK now, set the channel
    if (later) 
        ccd_conf_par_update(_ccd_u, "input_channel", newconf)

    # An image will be taken; be sure that big_buffer and shared_mem are OK
    val = ccd_par_get(_ccd_u, "mode")
    if (prevconf["big_buffer"] && !newconf["big_buffer"])
        val &= ~0x04
    if (!prevconf["shared_mem"] && newconf["shared_mem"])
        val |=  0x01
    ccd_par_update(_ccd_u, "mode", val)

    # kinwinsize resets the binning (internally); it must be set before bin.
    # If in Kinetic RoI, must activate it first.
    val = newconf["col_flip"] << 1 | newconf["row_flip"]
    hw_par = sprintf("%d %d %d 0", \
                     val, newconf["kinlinebeg"], newconf["kinstripes"])
    val = ccd_conf_name2val("roi_mode", newconf["roi_mode"])
    if (val == -1)
        return -1
    hw_par = sprintf("%s %d", hw_par, val)
    if (newconf["roi_mode"] == "Kinetic") {
        ccd_par_update(_ccd_u, "hw_par", hw_par)
        ccd_conf_par_update(_ccd_u, "kinwinsize", newconf)
    }

    # Now the bin and RoI
    f2k_dbg("take an image to sync bin and roi")
    ccd_get_config(_ccd_u, prevconf, "bin")
    ccd_conf_par_update_ds(_ccd_u, "row_bin", newconf, prevconf)
    ccd_conf_par_update_ds(_ccd_u, "col_bin", newconf, prevconf)
    ccd_get_config(_ccd_u, prevconf, "roi")
    ccd_conf_par_update_ds(_ccd_u, "row_beg", newconf, prevconf)
    ccd_conf_par_update_ds(_ccd_u, "row_end", newconf, prevconf)
    ccd_conf_par_update_ds(_ccd_u, "col_beg", newconf, prevconf)
    ccd_conf_par_update_ds(_ccd_u, "col_end", newconf, prevconf)
    # And update the shared memory
    ccd_createarray

    # Force an image so bin & RoI are sync, shared_mem is updated 
    # and internal "oldpreset" variable has always a known (rare) value
    f2k_dbg("take an image to sync bin and roi")
    ccd_take_image(_ccd_u, 0.001)

    # Set flip and roi_mode. If Kinetic, force again kinlinebeg;
    # it could be lost with row_beg
    f2k_dbg("Set flip and roi_mode")
    ccd_par_update(_ccd_u, "hw_par", hw_par)

    # Ext trigger and gate
    f2k_dbg("Ext trigger and gate")
    val = newconf["ext_trig"]
    if (val == "Gate") {
        newconf["preset"] = 0
        val = 1
    }
    else {
        val = ccd_conf_name2val("ext_trig", val)
        if (val == -1)
            return -1
    }
    ccd_par_update(_ccd_u, "ext_trig", val)
    val = (newconf["preset"] != 0)
    ccd_par_update(_ccd_u, "soft_preset", val)

    # The DS will have the requested "preset" value. 
    # SPEC will keep 1 sec, the default if ccdtake is called with no ctime:
    # image_par("run") will force "preset" if ctime != 0.001 (see before).
    f2k_dbg("set preset value")
    ccd_par_set(_ccd_u, "preset", newconf["preset"])
    image_par(_ccd_u, "preset", 1)

    # Disable remote saving if no save
    if (!newconf["do_save"]){
        f2k_dbg("Disable remote saving")
        newconf["remote_save"] = 0
    }

    # All pars in mode
    val  = (newconf["debug_level"] << 10) & 0x7ffffc00
    val |= (newconf["remote_save"] <<  3) & 0x08
    val |= (newconf["big_buffer"]  <<  2) & 0x04
    val |= (newconf["shared_mem"]  <<  0) & 0x01
    ccd_par_update(_ccd_u, "mode", val)

    # Save params
    ccd_get_config(_ccd_u, prevconf, "save")
    ccd_set_config_save(_ccd_u, newconf, prevconf)

    # Live mode and images
    if (newconf["live"])
        newconf["images"] = 0
    else if (newconf["images"] == 0)
        newconf["images"] = 1
    ccd_conf_par_update(_ccd_u, "images", newconf)

    # Other CCD pars
    ccd_conf_serial_set(_ccd_u, "shutter_on",         newconf)
    ccd_conf_serial_set(_ccd_u, "shutter_close_time", newconf)
    ccd_conf_serial_set(_ccd_u, "latency_time",       newconf)

    if (newconf["live"] && !ccd_acquiring(_ccd_u)){
        f2k_dbg("live => starting frelon")
        ccd_start(_ccd_u, newconf, 1, 1)
    }

    f2k_dbg("end of ccd_set_config")

    # Ufff!
    return 0
}'



# Returns the next file name built from confarr parameter.
def ccd_next_file_name(confarr) '{
    return ccdfilename(confarr["file_dir"],                             \
                       confarr["file_prefix"],                          \
                       confarr["file_inum"],                            \
                       confarr["file_suffix"])
}'



def ccd_print_config(_ccd_u, confarr) '{
    local val

    if (_ccd_u >= 0) 
        printf("CCD %d:             %s\n", _ccd_u, ccd_dev_name(_ccd_u))

    if (!confarr["inited"]) {
        print "Error: CCD configuration not initialized yet!"
        return -1
    }

    printf("CCD mode:          %s\n", confarr["ccd_mode"])

    printf("Img size(VxH):     %dx%d\n", confarr["rows"], confarr["cols"])

    val = confarr["input_channel"]
    printf("Channels:          %s\n", ccd_input_channel_str(val))

    printf("Bin (VxH):         %dx%d\n", confarr["row_bin"], confarr["col_bin"])

    if (ccd_conf_roi_active(confarr)) {
        printf("RoI mode:          %s\n", confarr["roi_mode"])
        printf("RoI (VxH):         [%d-%d]x[%d-%d]\n", \
               confarr["row_beg"], confarr["row_end"], \
               confarr["col_beg"], confarr["col_end"])
        printf("RoI size(VxH):     %dx%d\n", \
               confarr["row_end"] + 1 - confarr["row_beg"], \
               confarr["col_end"] + 1 - confarr["col_beg"])
        if (confarr["roi_mode"] == "Kinetic") {
            printf("Kin-Line-Beg:      %d\n", confarr["kinlinebeg"])
            printf("Kin-Win-Size:      %d\n", confarr["kinwinsize"])
            printf("Kin-Stripes:       %d\n", confarr["kinstripes"])
        }
    } else
        printf("RoI:               Full image\n")

    printf("Flip (VxH):        %sx%s\n", confarr["row_flip"] ? "Yes" : "No", \
                                         confarr["col_flip"] ? "Yes" : "No")

    printf("Ext trigger:       %s\n", confarr["ext_trig"])
    printf("Preset time:       %.3f\n", confarr["preset"])
    printf("Frames:            %d\n", confarr["images"])
    printf("Live mode:         %s\n", confarr["live"] ? "Yes" : "No")

    printf("Big buffer:        %s\n", confarr["big_buffer"] ? "Yes" : "No")
    printf("Shared mem:        %s\n", confarr["shared_mem"] ? "Yes" : "No")
    printf("Debug level:       0x%04x\n", confarr["debug_level"])

    val = confarr["do_save"] ? (confarr["remote_save"]?"DServer":"Spec") : "No"
    printf("Save image:        %s\n", val)
    if (confarr["do_save"]) 
        printf("Save next file:    \"%s\"\n", ccd_next_file_name(confarr))

    printf("Shutter:           %s\n", confarr["shutter_on"] ? "On" : "Off")
    printf("Shut-Cls-Time:     %d\n", confarr["shutter_close_time"])
    printf("Latency Time:      %d\n", confarr["latency_time"])
}'




def ccd_conf_roi_active(confarr) '{
    local rows cols 

    rows = confarr["rows"] / confarr["row_bin"]
    cols = confarr["cols"] / confarr["col_bin"]
    return !((confarr["row_beg"] == 0) && (confarr["row_end"] == rows - 1) && \
             (confarr["col_beg"] == 0) && (confarr["col_end"] == cols - 1)) 
}'


def ccd_min(a, b) '{
    return (a < b) ? a : b
}'


def ccd_max(a, b) '{
    return (a > b) ? a : b
}'



def ccd_check_roi(val, size) '{
    return ccd_min(ccd_max(val, 0), size - 1)
}'




def ccd_conf_set_mode(confarr, mode) '{
    local val roi_active prev_mode offset rbin rows

    val = ccd_conf_name2val("kinetics", mode)
    if (val == -1) {
        print "Error: invalid CCD mode:", mode
        return -1
    }
    
    roi_active = ccd_conf_roi_active(confarr)
    prev_mode = confarr["ccd_mode"]
    confarr["ccd_mode"] = mode
    rows = (mode == "FFM") ? 2048 : 1024
    confarr["rows"] = rows
    rbin = confarr["row_bin"]
    if (roi_active) {
        offset = 512
        if ((mode == "FFM") && (prev_mode == "FTM")) {
            confarr["row_beg"] += offset / rbin
            confarr["row_end"] += offset / rbin
            confarr["kinlinebeg"] += offset
        } else if ((mode == "FTM") && (prev_mode == "FFM")) {
            val = confarr["row_beg"] - offset / rbin
            confarr["row_beg"] = ccd_check_roi(val, rows / rbin)
            val = confarr["row_end"] - offset / rbin
            confarr["row_end"] = ccd_check_roi(val, rows / rbin)
            val = confarr["kinlinebeg"] - offset
            confarr["kinlinebeg"] = ccd_check_roi(val, rows)
            val = confarr["kinlinebeg"] + confarr["kinwinsize"] - 1
            confarr["kinwinsize"] = ccd_check_roi(val, rows) + 1 - \
                                    confarr["kinlinebeg"]
        }
    } else 
        confarr["row_end"] = rows / rbin - 1

    return 0
}'

def ccd_is_power_of_2(val) '{
    return (val != 0) && ((val == 1) || ((val & (val - 1)) == 0))
}'

def ccd_conf_set_bin(confarr, row_bin, col_bin) '{
    local val rfact cfact

    if (!ccd_is_power_of_2(row_bin) || !ccd_is_power_of_2(col_bin)) {
        printf("Error: invalid binning %dx%d: must be a power of 2\n", \
               row_bin, col_bin)
        return -1
    }

    rfact = confarr["row_bin"] / row_bin
    cfact = confarr["col_bin"] / col_bin
    if ((rfact != 1) || (cfact != 1)) {
        confarr["row_beg"] = int(confarr["row_beg"] * rfact)
        confarr["row_end"] = int((confarr["row_end"] + 1) * rfact) - 1
        confarr["col_beg"] = int(confarr["col_beg"] * cfact)
        confarr["col_end"] = int((confarr["col_end"] + 1) * cfact) - 1
    }

    confarr["row_bin"] = row_bin
    confarr["col_bin"] = col_bin

    return 0
}'

def ccd_conf_reset_roi(confarr) '{
    confarr["row_beg"] = 0
    confarr["row_end"] = confarr["rows"] / confarr["row_bin"] - 1
    confarr["col_beg"] = 0
    confarr["col_end"] = confarr["cols"] / confarr["col_bin"] - 1
    confarr["roi_mode"] = "Full-Image"

    confarr["kinlinebeg"] = 0
    confarr["kinwinsize"] = confarr["rows"]

    return 0
}'

def ccd_conf_set_roi(confarr, row_beg, row_end, col_beg, col_end, roi_mode) '{
    local val rows cols rbin

    if ((roi_mode == 0) || (roi_mode == ""))
        roi_mode = "Slow"
    else if (roi_mode == "Full-Image") {
        printf("Error: RoI mode cannot be \"%s\"\n", roi_mode)
        return -1
    }
    val = ccd_conf_name2val("roi_mode", roi_mode)
    if (val == -1) 
        return -1
      
    rows = confarr["rows"] / confarr["row_bin"]
    cols = confarr["cols"] / confarr["col_bin"]
    confarr["row_beg"] = ccd_check_roi(row_beg, rows)
    confarr["row_end"] = ccd_check_roi(row_end, rows)
    confarr["col_beg"] = ccd_check_roi(col_beg, cols)
    confarr["col_end"] = ccd_check_roi(col_end, cols)
    confarr["roi_mode"] = roi_mode

    rbin = confarr["row_bin"]
    confarr["kinlinebeg"] = confarr["row_beg"] * rbin
    confarr["kinwinsize"] = (confarr["row_end"] + 1 - confarr["row_beg"]) * rbin

    return 0
}'

def ccd_conf_set_kinetic(confarr, kinlinebeg, kinwinsize) '{
    local val rows rbeg rend rbin
    
    rows = confarr["rows"]
    rbin = confarr["row_bin"] 

    kinlinebeg = ccd_check_roi(kinlinebeg, rows)
    val = kinlinebeg + kinwinsize - 1
    kinwinsize = ccd_check_roi(val, rows) + 1 - kinlinebeg
    if (kinwinsize % rbin != 0) {
        printf("Error: kinwinsize must be a multiple of row_bin (%d)\n", rbin)
        return -1
    }

    rbeg = kinlinebeg / rbin
    rend = rbeg + kinwinsize / rbin - 1
    ccd_conf_set_roi(confarr, rbeg, rend, \
                     confarr["col_beg"], confarr["col_end"], "Kinetic")

    confarr["kinlinebeg"] = kinlinebeg
    confarr["kinwinsize"] = kinwinsize

    return 0
}'

def ccd_refresh(_ccd_u, confarr) '{
    if (ccd_get_config(_ccd_u, confarr) == -1)
        return -1
    return ccd_set_config(_ccd_u, confarr)
}'

def ccd_start(_ccd_u, confarr, direct_io, no_check) '{
    if (!no_check && (ccd_set_config(_ccd_u, confarr) == -1))
        return -1
    if (direct_io)
        return ccd_par_cmd(_ccd_u, "run")
    else
        return image_par(_ccd_u, "run")
}'

def ccd_stop(_ccd_u) '{
    return image_par(_ccd_u, "halt")
}'

def ccd_conf_yesno(confarr, pararr, par, desc) '{
    local msg

    if (ccd_par_array_check(pararr, par)) {
        msg = sprintf("Do you want the %s", desc)
        confarr[par] = yesno(msg, confarr[par])
    }
}'

def ccd_conf_getval(confarr, pararr, par, desc) '{
    local msg

    if (ccd_par_array_check(pararr, par)) {
        msg = sprintf("Enter the %s", desc)
        confarr[par] = getval(msg, confarr[par])
    }
}'

def ccd_ask_chan_mode(confarr, pararr) '{
    local val

    if (ccd_par_array_check(pararr, "ccd_mode")) {
        while (1) {
            val = confarr["ccd_mode"]
            val = getval("Enter the CCD mode [FFM, FTM]", val)
            if (ccd_conf_set_mode(confarr, val) != -1)
                break
        }
        printf("Img size(VxH): %dx%d\n", confarr["rows"], confarr["cols"])
    }

    if (ccd_par_array_check(pararr, "input_channel")) {
        while (1) {
            val = confarr["input_channel"]
            val = ccd_input_channel_str(val)
            val = getval("Enter the input channel(s) [separated by &, 0=All]",\
                         val)
            val = ccd_input_channel_val(val)
            if (ccd_input_channel_check(val, confarr["ccd_mode"]))
                break
        }
        confarr["input_channel"] = val
    }
}'

def ccd_ask_bin_roi(confarr, pararr) '{
    local val valarr[] hasroi ask

    ask  = ccd_par_array_check(pararr, "row_bin") << 0
    ask |= ccd_par_array_check(pararr, "col_bin") << 1
    if (ask) {
        while (1) {
            valarr[0] = confarr["row_bin"]
            valarr[1] = confarr["col_bin"]
            if (ask & 1)
                valarr[0] = getval("Enter the vert. binning", valarr[0])
            if (ask & 2)
                valarr[1] = getval("Enter the horz. binning", valarr[1])
            if (ccd_conf_set_bin(confarr, valarr[0], valarr[1]) != -1)
                break
        }
    }

    if (ccd_par_array_check(pararr, "roi_mode")) {
        val = (confarr["roi_mode"] != "Full-Image")
        if (yesno("Do you want to use RoI [No=Full-Image]", val)) {
            while (1) {
                val = confarr["roi_mode"]
                val = (val == "Full-Image") ? "Slow" : val
                val = getval("Enter the RoI mode [Slow, Fast, Kinetic]", val)
                if (ccd_conf_name2val("roi_mode", val) != -1)
                    break
            }
            confarr["roi_mode"] = val
        } else
            ccd_conf_reset_roi(confarr)
    }

    hasroi = (confarr["roi_mode"] != "Full-Image")
    ask  = ccd_par_array_check(pararr, "row_beg") << 0
    ask |= ccd_par_array_check(pararr, "row_end") << 1
    ask |= ccd_par_array_check(pararr, "col_beg") << 2
    ask |= ccd_par_array_check(pararr, "col_end") << 3
    if (hasroi && ask) {
        while (1) {
            valarr[0] = confarr["row_beg"]
            valarr[1] = confarr["row_end"]
            valarr[2] = confarr["col_beg"]
            valarr[3] = confarr["col_end"]
            if (ask & 1)
                valarr[0] = getval("Enter the RoI vert. begin", valarr[0])
            if (ask & 2)
                valarr[1] = getval("Enter the RoI vert. end  ", valarr[1])
            if (ask & 4)
                valarr[2] = getval("Enter the RoI horz. begin", valarr[2])
            if (ask & 8)
                valarr[3] = getval("Enter the RoI horz. end  ", valarr[3])
            if (ccd_conf_set_roi(confarr, \
                                 valarr[0], valarr[1], valarr[2], valarr[3], \
                                 confarr["roi_mode"]) != -1)
                break    
        }
    }
    
    hasroi = (confarr["roi_mode"] == "Kinetic")
    ask  = ccd_par_array_check(pararr, "kinlinebeg") << 0
    ask |= ccd_par_array_check(pararr, "kinwinsize") << 1
    if (hasroi && ask) {
        while (1) {
            valarr[0] = confarr["kinlinebeg"]
            valarr[1] = confarr["kinwinsize"]
            if (ask & 1)
                valarr[0] = getval("Enter the Kinetic line begin ", valarr[0])
            if (ask & 2)
                valarr[1] = getval("Enter the Kinetic window size", valarr[1])
            if (ccd_conf_set_kinetic(confarr, valarr[0], valarr[1]) != -1)
                break    
        }
    }

    ccd_conf_yesno(confarr, pararr, "row_flip", "vert. mirror")
    ccd_conf_yesno(confarr, pararr, "col_flip", "horz. mirror")
}'

def ccd_ask_sync(confarr, pararr) '{
    local val msg

    if (ccd_par_array_check(pararr, "ext_trig")) {
        while (1) {
            val = confarr["ext_trig"]
            msg = "Enter the ext. trigger [Software, Single, Multiple, Gate]"
            val = getval(msg, val)
            if (ccd_conf_name2val("ext_trig", val) != -1)
                break
        }
        confarr["ext_trig"] = val
    }

    if (confarr["ext_trig"] == "Gate")
        confarr["preset"] = 0
    else {
        if (ccd_par_array_check(pararr, "preset")) {
            while (1) {
                val = getval("Enter the exposure time (s)", confarr["preset"])
                if (val > 0)
                    break
                print "Error: invalid preset time:", val
            }
            confarr["preset"] = val
        }
    }

    ccd_conf_yesno(confarr, pararr, "live", "live mode active")

    if (confarr["live"]) {
        confarr["images"] = 0
    } else {
        if (confarr["images"] == 0)
            confarr["images"] = 1
        if (ccd_par_array_check(pararr, "images")) {
            while (1) {
                val = getval("Enter the nr. of frames", confarr["images"])
                if (val > 0)
                    break
                print "Error: invalid nr. of frames:", val
            }
            confarr["images"] = val
        }
    }

    ccd_ask_shutter_latency(confarr, pararr)
}'   

def ccd_ask_mode_save(confarr, pararr) '{
    
    ccd_conf_yesno(confarr, pararr, "big_buffer", "big buffer")
    ccd_conf_yesno(confarr, pararr, "shared_mem", "DS image on shared mem")
    ccd_conf_yesno(confarr, pararr, "do_save",    "save image on disk")
    if (!confarr["do_save"]) 
        return 0

    ccd_conf_yesno(confarr, pararr, "remote_save", \
                                    "remote save [No=Spec, Yes=DServer]")
    if (confarr["file_dir"] == 0)
        ccd_default_config(confarr, "file")
      
    ccd_conf_getval(confarr, pararr, "file_dir",    "save directory")
    ccd_conf_getval(confarr, pararr, "file_prefix", "save file prefix")
    ccd_conf_getval(confarr, pararr, "file_suffix", "save file suffix")
    ccd_conf_getval(confarr, pararr, "file_inum",   "save file index")

    ccd_conf_check_save(confarr)
}'

def ccd_conf_check_save(confarr) '{
    local dir

    dir = confarr["file_dir"]
    if (substr(dir, length(dir), 1) == "/")
        dir = substr(dir, 1, length(dir) - 1)
    if (substr(dir, 1, 1) != "/")
        dir = sprintf("%s/%s", CWD, dir)
    confarr["file_dir"] = dir
}'

def ccd_conf_update_save(_ccd_u, confarr) '{
    local filearr[] do_update

    ccd_par_get_arr(_ccd_u, "file", filearr)

    do_update = ((filearr[0] == confarr["file_dir"])    && \
                 (filearr[1] == confarr["file_prefix"]) && \
                 (filearr[2] == confarr["file_suffix"]) && \
                 (filearr[3] >  confarr["file_inum"]))
    if (do_update)
        confarr["file_inum"] = filearr[3]
    return do_update
}'



def ccd_ask_shutter_latency(confarr, pararr) '{
    local val ask

    ccd_conf_yesno(confarr, pararr, "shutter_on", "shutter active")

    ask = ccd_par_array_check(pararr, "shutter_close_time")
    if (confarr["shutter_on"] && ask) {
        while (1) {
            val = confarr["shutter_close_time"]
            val = getval("Enter the shutter closing time (ms)", val)
            if ((val >= 0) && (val < 65536))
                break
            print "Error: invalid shutter closing time:", val
        }
        confarr["shutter_close_time"] = val
    } else if (!confarr["shutter_on"])
        confarr["shutter_close_time"] = 0

    if (ccd_par_array_check(pararr, "latency_time")) {
        while (1) {
            val = confarr["latency_time"]
            val = getval("Enter the latency time (ms)", val)
            if ((val >= 0) && (val < 65536))
                break
            print "Error: invalid latency time:", val
        }
        confarr["latency_time"] = val
    }
}'



def ccd_ask_config(confarr, pars) '{
    local pararr[] ask

    ccd_par_array_set(pars, pararr)

    ccd_ask_chan_mode(confarr, pararr)
    ccd_ask_bin_roi(confarr, pararr)

    ccd_ask_sync(confarr, pararr)
    ccd_ask_mode_save(confarr, pararr)

    confarr["inited"] = 1
}'




def ccd_get_status(_ccd_u) '{
    local status status_val devname prefix pos

    devname = image_par(_ccd_u, "device_id")
    status = esrf_io(devname, "DevStatus")
    prefix = "CCD Status: "
    pos = index(status, prefix)
    if (pos == 0) {
        print "Oops, did not find the prefix!"
        exit
    }
    status_val = substr(status, pos + length(prefix), 4) + 0
    return status_val
}'



def ccd_wait_readout_end(_ccd_u) '{
    local status
    while (1) {
        status = ccd_get_status(_ccd_u)
        # bits 3,4,5 are all unset: 
        #   not exposing, closing the shutter or reading out
        if ((status & 0x38) == 0){
            break
        }
    }
}'



#%IU% ()
#%MDESC%
#    calls definition of CCDDEV if not already done.
def ccd_define_globals_2k() '{
    global FRELON2KCONF[]

    ccd_check_globals()
}'




#%UU%
#%MDESC%
#    
def resetup2k '{

    f2k_dbg("enter resetup2k")

    ccd_define_globals_2k()

    if (ccd_responsive(CCD_U)) {
        if (FRELON2KCONF["inited"] == 0) {
            print "Running Frelon resetup2k for the first time"
            if (ccd_get_config(CCD_U, FRELON2KCONF) < 0){
                exit
            }

            if (yesno("Do you want to set the camera config now", 1)) {
                ccdsetup2k
            }
        }

        ccd_conf_update_save(CCD_U, FRELON2KCONF)
        print "Setting the following Frelon2k configuration:"
        ccd_print_config(CCD_U, FRELON2KCONF)
        ccd_set_config(CCD_U, FRELON2KCONF)
    }
}'



#%UU% [param]
#%MDESC%
#    
def refresh2k '{
    ccd_define_globals_2k()

    print "Getting the Frelon2k configuration from server:"
    ccd_get_config(CCD_U, FRELON2KCONF)
    ccd_set_config(CCD_U, FRELON2KCONF)
    if ($1 != -1)
        ccd_print_config(CCD_U, FRELON2KCONF)
}'



#%UU% [params]
#%MDESC%
#    
def ccdsetup2k '{
    ccd_define_globals_2k()
    ccd_conf_update_save(CCD_U, FRELON2KCONF)
    ccd_ask_config(FRELON2KCONF, "$*")
    ccd_set_config(CCD_U, FRELON2KCONF)
}'



#%IU% [parma]
#%MDESC%
#    
def ccd_set_ccdmode(mode) '{
    ccd_define_globals_2k()

    if (!ccd_responsive(CCD_U))
        return -1

    print "Getting the Frelon2k configuration from server:"
    ccd_get_config(CCD_U, FRELON2KCONF)
    if (ccd_conf_set_mode(FRELON2KCONF, mode) == 0) {
        print "Setting Frelon2k configuration for mode [", FRELON2KCONF["ccd_mode"], "]"
        ccd_set_config(CCD_U, FRELON2KCONF)
    } else {
        return -1
    }
}'



#%IU% [parma]
#%MDESC%
#    
def ccd_set_shutter(shut_on, shut_time) '{
    local newconf[]
    ccd_define_globals_2k()

    if (!ccd_responsive(CCD_U))
        return -1

    newconf["shutter_on"] = shut_on ? 1 : 0
    if (shut_on) {
       if ((shut_time >= 0) && (shut_time < 65536))
           newconf["shutter_close_time"] = shut_time
       else
           return -1
    } else {
       newconf["shutter_close_time"] = 0
    }

    ccd_conf_serial_set(CCD_U, "shutter_on",         newconf)
    ccd_conf_serial_set(CCD_U, "shutter_close_time", newconf)

    return 0
}'
    


#%UU% [param]
#%MDESC%
#    
def ccdbin2k '{
    local ybin xbin

    ccd_define_globals_2k()

    if (($# != 0) && ($# != 2)) {
        print "Usage: ccdbin [Ybin Xbin]"
        exit
    }

    if ($# == 0) {
        ccdsetup2k row_bin col_bin
    } else {
        ybin = $1; xbin = $2
        if (ccd_conf_set_bin(FRELON2KCONF, ybin, xbin) == -1)
            exit
        ccd_set_config(CCD_U, FRELON2KCONF)
    }
}'



#%UU% [param]
#%MDESC%
#    
def ccdroi2k '{
    local mode ybeg yend xbeg xend ret

    ccd_define_globals_2k()

    if (($# != 0) && ($# != 5)) {
        print "Usage: ccdroi [mode Ybeg Yend Xbeg Xend]"
        exit
    }

    if ($# == 0) {
        ccdsetup2k roi_mode row_beg row_end col_beg col_end
    } else {
        mode = ccd_conf_val2name("roi_mode", $1)
        if (mode == -1)
            exit

        if (mode == "Full-Image") {
            ret = ccd_conf_reset_roi(FRELON2KCONF)
        } else {
            ybeg = $2; yend = $3; xbeg = $4; xend = $5
            ret = ccd_conf_set_roi(FRELON2KCONF, ybeg, yend, xbeg, xend, mode)
        }
        if (ret == -1)
            exit
        ccd_set_config(CCD_U, FRELON2KCONF)
    }
}'



#%UU% <no_read_conf>
#%MDESC%
#    Put -1 as argument to avoid to read the config of the camera.
def ccdstop2k '{
    local no_read_conf
    ccd_define_globals_2k()

    no_read_conf = ($# > 0) ? ($1 == -1) : 0

    if (!no_read_conf){
        ccd_get_config(CCD_U, FRELON2KCONF)
    }

    if (FRELON2KCONF["live"]) {
        FRELON2KCONF["live"] = 0
        ccd_set_config(CCD_U, FRELON2KCONF)
    }
    else{
        ccd_stop(CCD_U)
    }
}'


#%UU% <params>
#%MDESC%
#    
def ccdnewfile2k '{
    ccd_new_file_low_2k("$*")
}'



def ccd_new_file_low_2k(pars) '{
    local npars pararr[] devconf[] do_save

    ccd_define_globals_2k()

    npars = split(pars, pararr)
    do_save = pararr[0]
    if ((npars != 0) && ((npars != 1) || do_save) && (npars != 6)) {
        print "Usage: ccdnewfile [do_save [remote dir prefix suffix num]]"
        exit
    }
    
    if (npars == 0) {
        ccdsetup2k save
    } else {
        FRELON2KCONF["do_save"] = do_save
        if (do_save) {
            FRELON2KCONF["remote_save"] = pararr[1]
            FRELON2KCONF["file_dir"]    = pararr[2]
            FRELON2KCONF["file_prefix"] = pararr[3]
            FRELON2KCONF["file_suffix"] = pararr[4]
            FRELON2KCONF["file_inum"]   = pararr[5]
        }

        ccd_set_config(CCD_U, FRELON2KCONF)
    }

    if (FRELON2KCONF["do_save"]){
        printf("Save next file:    \"%s\"\n", ccd_next_file_name(FRELON2KCONF))
    }
}'


#%UU% [<exposure_time>]
#%MDESC%
#    
def ccdlive2k '{
    local exp_time

    ccd_define_globals_2k()

    ccd_get_config(CCD_U, FRELON2KCONF)
    exp_time = ($# > 0) ? $1 : FRELON2KCONF["preset"]
    print "Starting live mode on", ccd_dev_name(CCD_U), "-", exp_time, "secs"

    FRELON2KCONF["preset"] = exp_time
    FRELON2KCONF["live"] = 1

    ccd_set_config(CCD_U, FRELON2KCONF)
}'


#%UU% [<camera_number>]
#%MDESC% The camera will be started automatically at every scan point.
#  Frelon2k version
def ccdon2k '{
    local __ccd_u

    f2k_dbg("ccdon2k")

    if ($#){
        __ccd_u = $1
    }
    else{
        __ccd_u = CCD_U
    }

    CCD_ON[__ccd_u] = 1

    image_par(__ccd_u, "auto_run", 1)

}'


#%UU% <camera_number>
#%MDESC% The camera will not longer be started at every scan point.
#  Frelon2k version
def ccdoff2k '{
    local __ccd_u

    f2k_dbg("ccdoff2k")

    if ($#){
        __ccd_u = $1
    }
    else{
        __ccd_u = CCD_U
    }

    CCD_ON[__ccd_u] = 0

    image_par(__ccd_u, "auto_run", 0)

}'





#%AUTHOR%
# A.Homs
#%TOC%