#!   /usr/bin/env   python
#    coding: utf8
##_________________________________________________________________________________________________
##                                                                                                |
##                                           |TDC PTS|                                            |
##                                                                                                |
##                                         CERN,BE/CO-HT                                          |
##________________________________________________________________________________________________|

##-------------------------------------------------------------------------------------------------
##                                                                                                |
##                                      TDC DAC Calibration                                       |
##                                                                                                |
##-------------------------------------------------------------------------------------------------
##                                                                                                |
## Description  Calibration of the TDC DAC IC2 that controlls the VCXO OSC2 which in turn         |
##              controls the main timekeeping unit of the TDC application, the PLL IC4.           |
##              The test is using the pendulum CNT-91 as pulse generator sending pulses with a    |
##              period of 9 ms. The higher the DAC value, the higher the TDC is measuring the     |
##              the pulse period; for example with the DAC at 1.25V the TDC measures the 9 ms     |
##              period as 4,999967682 ms, whereas with the DAC at 1.65V the TDC measures the 9 ms |
##              period as 5,000000309 ms.                                                         |
##              In this test:
##               1) we start with a bisectomy algorithm to find a first DAC value that brings the |
##                  measurements close to the expected 5 ms; to keep this step short in time, for |
##                  each DAC value we calculate the average of only 128 measurements.             |
##               2) once we have this first rough idea of the location of the optimal DAC value,  |
##                  we continue with focusing on two values around it; in this case, (in order to |
##                  get rid of the +-700ps inpresicion of the TDC), we acquire 12800 measurements |
##                  and calculaate their average.                                                 |
##               3) with these two last values we define a line, as the following figure shows;   |
##                  as final optimal DAC value we consider the one where this line is crossing    |
##                  the x-axis.                                                                   |
##                                                                                                |
##                 /|\                                                                            |
##            error |                                                                             |
##                  |                                                                             |
##                  |                                                                             |
##                  |          * (DAC value a bit above bisectomy reslult from step 1)            |
##                  |            .                                                                |
##                  |              .                                                              |
##                __|________________.________________________________________\                   |
##                  | DAC values       .                                      /                   |
##                                       .                                                        |
##                                         * (DAC value bit below bisectomy reslult from step 1)  |
##                                                                                                |
##               4) finally in order to confirm the value calculated at step 3, we configure      |
##                  the DAC with this value and acquire another 12800 measurements; the average   |
##                  of those should not be exceeding 40 ps.                                       |
##                                                                                                |
##              Note the DAC is configured through its SPI interface.                             |
##                                                                                                |
##                                                                                                |
## FW to load   .bin                                                                              |
## Authors      Evangelia Gousiou (Evangelia.Gousiou@cern.ch)                                     |
## Website      http://www.ohwr.org/projects/pts                                                  |
## Date         11/01/2013                                                                        |
##-------------------------------------------------------------------------------------------------

##-------------------------------------------------------------------------------------------------
##                               GNU LESSER GENERAL PUBLIC LICENSE                                |
##                              ------------------------------------                              |
## This source file is free software; you can redistribute it and/or modify it under the terms of |
## the GNU Lesser General Public License as published by the Free Software Foundation; either     |
## version 2.1 of the License, or (at your option) any later version.                             |
## This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;       |
## without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.      |
## See the GNU Lesser General Public License for more details.                                    |
## You should have received a copy of the GNU Lesser General Public License along with this       |
## source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html                     |
##-------------------------------------------------------------------------------------------------

##-------------------------------------------------------------------------------------------------
##                                            Import                                             --
##-------------------------------------------------------------------------------------------------


# Import system modules
import sys
import time
import os
import math
import pylab
from pylab import *
from datetime import datetime

# Add common modules location tp path
sys.path.append('../../../../')
sys.path.append('../../../../gnurabbit/python/')
sys.path.append('../../../../common/')
sys.path.append('../../../../common/usb_box')
sys.path.append('../../../../common/cp210x')


# Import common modules
from ptsexcept import *
import rr
import csr
import fmc_tdc
import time
from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *

PENDULUM           = "/dev/usbtmc1"
USB_DEVICE         = "/dev/ttyUSB0"
RS232_BAUD         = 57600

BOX_USB_VENDOR_ID  = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID  = 0xea60 # CP210x Composite Device

TEMPID_FAMILY_CODE = 0x28

TEMP_THRES         = 50.0
TEMP_RIPPLE        = 0.3
FIFO_SIZE          = 20
MEAS_SLEEP         = 1

NUM_OF_TSTAMPS     = 100    # number of fill-ups of the TDC memory
                            # ex NUM_OF_TSTAMPS = 100, means aquisition
                            # of 25600 timestamps; in this setup this means
                            # 6400 rising edge timestamps per channel

def pendulum_output_on(meas):
    meas.write("OUTP:TYPE PULS")
    meas.write("SOUR:PULS:PER 0.005")
    meas.write("SOUR:PULS:WIDT 0.001")
    return (1)

def pendulum_output_off(meas):
    meas.write("OUTP:TYPE OFF")
    return (1)

def print_temp(temp):
    # Standard in/out temporary redirection
    tmp_stdout = sys.stdout;
    sys.stdout = sys.__stdout__;
    tmp_stdin = sys.stdin;
    sys.stdin = sys.__stdin__;

def newline():
    # Standard in/out temporary redirection
    tmp_stdout = sys.stdout;
    sys.stdout = sys.__stdout__;
    tmp_stdin = sys.stdin;
    sys.stdin = sys.__stdin__;

    # Print temperature at the same position on the screen
    sys.stdout.write("\n")
    sys.stdout.flush()

    # Restore standard in/out
    sys.stdout = tmp_stdout;
    sys.stdin = tmp_stdin;


##-------------------------------------------------------------------------------------------------
##                                             Main                                              --
##-------------------------------------------------------------------------------------------------

def main (default_directory='.'):

    # Constants declaration
    FMC_TDC_ADDR             = '1a39:0004/1a39:0004@0001:0000'#'1a39:0004/1a39:0004@000B:0000'
    FMC_TDC_BITSTREAM_PATH   = '../firmwares/tdc.bin'
    FPGA_LOADER_PATH         = '../../../../gnurabbit/user/fpga_loader'


    DAC_CALIBR_FILENAME = "DAC_calibration_data.txt"
    DAC_CALIBR_FILENAME = os.path.join(default_directory, DAC_CALIBR_FILENAME)
    f_out = open(DAC_CALIBR_FILENAME, 'w')
    start_test_time = time.time()

    # SPEC object declaration
    spec = rr.Gennum()

    # Bind SPEC object to FMC TDC card
    print "\n-------------------------------------------------------------------"
    print "----------------------------- FMC TDC -----------------------------"
    print "------------------------- DAC Calibration -------------------------\n"

    print ("Calibration of the DAC IC2 on the TDC board that controlls the VCXO\n"
           "OSC2 which in turn controls the main timekeeping unit PLL IC4.\n"
           "The higher the DAC setting the longer the pulses are being measured;\n"
           "here we are seeking for the optimal DAC value.\n")

    print "\n_______________________________Info______________________________\n"
    print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
    for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems():
        print "%s:0x%04X"%(name, value)
    spec.bind(FMC_TDC_ADDR)

    # Load FMC TDC firmware
    print "\n_________________________Initialisations_________________________\n"
    print "Loading FMC TDC firmware...",
    firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
    bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
    os.system(firmware_loader + ' ' + bitstream)
    time.sleep(1)
    print "Firmware loaded!"

    # TDC object declaration
    tdc = fmc_tdc.CFMCTDC(spec)

    # Check bitsteam type
    bitstream_type = tdc.read_bitstream_type()
    if(bitstream_type == 0xFFFFFFFF):
        msg = ("FATAL ERROR: No access to TDC core")
        print (msg)
        raise PtsError (msg)
    if(bitstream_type != 0x2):
        msg = ("FATAL ERROR: Wrong bitstream type loaded 0x%08X") %bitstream_type
        print (msg)
        raise PtsError (msg)
    else:
        print('Access to TDC core OK')


    tdc.configure_mezz_dac(0xA8F5)

    # Configure ACAM and TDC core registers
    print "\n__________________________Configuration__________________________\n"
    tdc.config_acam()
    time.sleep(1)
    tdc.reset_acam()
    acam_status_test = tdc.read_acam_status()-0xC4000800
    if acam_status_test == 0:
        print "ACAM IC8: Status register OK"
    else:
        msg = ("ERROR: ACAM IC8: No communication")
        print (msg)
    acam_readback_regs = []
    acam_readback_regs = tdc.readback_acam_config()
    for i in range(len(tdc.ACAM_READBACK_REGS)): 
        if (acam_readback_regs[i] == tdc.ACAM_READBACK_REGS[i]):
            print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i])
        else:
            msg = ("ERROR: ACAM IC8: Configuration registers failure; reg 0x%2X: received 0x%8X, expected 0x%8X"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i], tdc.ACAM_READBACK_REGS[i]))
            print (msg)
            raise PtsError (msg)

    # Interrupts
    print "\n_______________________________IRQs_______________________________\n"
    print('Set IRQ enable mask: %.4X')%tdc.set_irq_en_mask(0x1F)
    tdc.set_irq_tstamp_thresh(0x100)
    tdc.set_irq_time_thresh(0xFFFFF)

    # Communication with Pendulum
    print "\n__________________________USB Pendulum_____________________________"
    try:
        meas = PendulumCNT91(PENDULUM)
    except OSError:
        raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
    a = pendulum_output_off(meas)


    # Communication and Setup of Interconnection box
    print "______________________USB interconnection box______________________\n"
    box_tty = CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
    print("Device: %s" % box_tty[0])
    box = CCalibr_box(box_tty[0])
    box.select_trigger_loopback(0)


    print "\n\n________________TDC board temperature stablilization_______________\n"
    # Access Temperature-and-Unique-ID chip
    try:
        unique_id = tdc.mezz_get_unique_id()
    except:
        msg = ("ERROR: TEMPID IC14: Cannot access the device")
        print (msg)
        raise PtsError (msg)

    if(unique_id == -1):
        msg = ("ERROR: TEMPID IC14: Cannot access the device")
        print (msg)
        raise PtsError (msg)
    else:
        print('TEMPID IC14: Unique ID: 0x%.12X OK') % unique_id

    if((unique_id & 0xFF) != TEMPID_FAMILY_CODE):
        family_code = unique_id & 0xFF
        msg = (("ERROR: TEMPID IC14: Wrong Family Code: 0x%.2X is different than the expected: 0x%.2X") %(family_code,TEMPID_FAMILY_CODE))
        print (msg)
        raise PtsError (msg)

    # Read temperature and print to log
    fmc_temp = []
    fmc_temp.append(tdc.mezz_get_temp())
    print "FMC temperature: %3.3f°C" % fmc_temp[-1]


    # Wait for the FMC temperature to reach threshold
    print "\nWaiting for FMC temperature to reach %2.1f°C.."%TEMP_THRES
    t0 = time.time()
    while fmc_temp[-1] < TEMP_THRES:
        fmc_temp.append(tdc.mezz_get_temp())
        print "FMC temperature: %3.3f°C" % fmc_temp[-1]
        #print_temp(fmc_temp[-1])
        fmc_temp.pop(0)
        #acq_channels(fmc, carrier)
        time.sleep(MEAS_SLEEP)
    t1 = time.time()
    print "FMC temperature reached %2.1f°C after %10.3fs\n"%(TEMP_THRES, t1-t0)

    # Wait for the FMC temperature to be stable
    print "Waiting for FMC temperature to stabilize.."
    fmc_temp_cnt = 0
    while True:
        fmc_temp.append(tdc.mezz_get_temp())
        #print_temp(fmc_temp[-1])
        if fmc_temp_cnt >= FIFO_SIZE:
            temp_diff = (max(fmc_temp) - min(fmc_temp))
            fmc_temp.pop(0)
            print "[%4d] fmc temp: %3.3f°C, temp diff: %3.3f°C"%(fmc_temp_cnt, fmc_temp[-1], temp_diff)
            if temp_diff < TEMP_RIPPLE:
                print "Temperature difference in the last %d measurements is less than %2.1f°C"%(FIFO_SIZE, TEMP_RIPPLE)
                #newline()
                break
            else:
                print "%4d fmc temp:%3.3f°C"%(fmc_temp_cnt, fmc_temp[-1])
        fmc_temp_cnt += 1
        #acq_channels(fmc, carrier)
        time.sleep(MEAS_SLEEP)
    t2 = time.time()
    print "FMC temperature is stable after %10.3fs\n"%(t2-t0)


    # Enable timestamps aquisition (TDC_START_FPGA pulse sent at this step) 
    print "\n______________________ACAM aquisition start________________________\n"
    # Enable channels and terminations of all channels
    tdc.enable_channels()
    tdc.channel_term(1, 1)
    tdc.channel_term(2, 1)
    tdc.channel_term(3, 1)
    tdc.channel_term(4, 1)
    tdc.channel_term(5, 1)
    tdc.start_acq()
    time.sleep(1)


    #------------> 1) bisectomy
    # bisectomy algorithm to find a first DAC value; at every iteration only 128 measurements are taken
    print "\n_______________________Bisectomy Algorithm_________________________\n"
    print "\n-----------------------------------------------------------------\n"

    all_iterat_error = []
    all_iterat_dac   = []
    dac_high         = 0xFFFF
    dac_low          = 0x0000
    eurika           = 0
    span             = 0

    for i in range(20): # bisectomy algorithm max iterations: 20

        # bisectomy algorithm
        if i > 0:

            if (abs(all_iterat_error[i-1]) < 60):
                bisectomy_rslt = all_iterat_dac[i-1]
                print "Bisectomy result: DAC value: 0x%4X\n"%bisectomy_rslt
                eurika = 1
                break
            elif span < 1400: # confirm that the previous iteration was OK (otherwise the same DAC value is repeated)
                print "Iteration         : %d"%(i)
                if all_iterat_error[i-1] > 0:
                    dac_low = all_iterat_dac[i-1]
                else:
                    dac_high = all_iterat_dac[i-1]
        new_dac = (dac_high + dac_low)/2

        # DAC configuration with new value
        tdc.configure_mezz_dac(new_dac)
        all_iterat_dac.append(new_dac)

        # pendulum  ON sending pulses
        a = pendulum_output_on(meas)

        # TDC acquiring 256 timestamps = 64 rising edge tstamps on ch1 (remember channel 2 is also connected receiving pulses)
        tdc.check_irq(0)
        print "TDC Write pointer : %d"%(tdc.get_pointer())
        print "TDC Overflows     : %d"%(tdc.get_overflow_counter())

        # pendulum OFF
        a = pendulum_output_off(meas)

        # clear interrupt
        tdc.clear_irq_src(int(math.log(tdc.get_irq_src(),2)))

        # keep only rising edge timestamps
        timestamps, data      = tdc.get_timestamps(0)
        r_edge_timestamps_ch1 = []

        for m in range(len(timestamps)):
            if (timestamps[m][2] == 1)   and (timestamps[m][1] == 0): # rising tstamps ch1
                r_edge_timestamps_ch1.append(timestamps[m][0])
        if len(r_edge_timestamps_ch1) > 62:
            print "Ch1 tstamps       : %d"%(len(r_edge_timestamps_ch1))
            r_edge_timestamps_ch1.sort()
        else:
            msg = ("ERROR: Unexpected error with interrupts; Ch1 registered timestamps: %d; expected: 64 \n")%len(r_edge_timestamps_ch1)
            print (msg)
            raise PtsError (msg)

        measurs = []
        for k in range(0,len(r_edge_timestamps_ch1)-1,1):
            measur = r_edge_timestamps_ch1[k+1] - r_edge_timestamps_ch1[k]
            if (measur > 4999000000 and measur < 5000999999): # to discard values from previous iterations
                measurs.append(measur)
        avg   = sum(measurs, 0.0) / len(measurs)
        error = 5000000000  - avg
        all_iterat_error.append(error)

        span = abs((max(measurs))-(min(measurs)))
        print "error             : %.2f ps"%(error)
        print "avg               : %.2f ps"%(avg)
        print "span              : %.2f ps"%span
        print "samples           : %d"%(len(measurs))
        print "max : sample %d %.2f ps"%(measurs.index(max(measurs)), max(measurs))
        print "min : sample %d %.2f ps"%(measurs.index(min(measurs)),min(measurs))
        print "-----------------------------------------------------------------\n"

    # confirm that pendulum is OFF
    a = pendulum_output_off(meas)

    if eurika == 0:
        msg = ("ERROR: DAC calibration failure: bisectomy method failed; max number of iterations exceeded")
        print (msg)
        raise PtsError (msg)
    else:

        #------------> 2) Focus on two DAC values around the bisectomy result
        # here 12800 measurements are taken per DAC value
        print "\n________________Two points around the bisectomy result_____________\n"

        # ------> Point A: bisectomy_rslt + 100
        point_a = bisectomy_rslt + 100
        tdc.configure_mezz_dac(point_a)
        r_edge_timestamps_ch1_point_a = []

        # pendulum  ON sending pulses
        a = pendulum_output_on(meas)

        # TDC aquisition of NUM_OF_TSTAMPS*64 timestamps per channel;
        # note that we are only interested in pulses on channel 1,however through the usb_box, channel 2 is also receiving pulses
        for j in range(NUM_OF_TSTAMPS):

            tdc.check_irq(0)
            timestamps, data = tdc.get_timestamps(0)

            # keep only rising edge timestamps
            for m in range(len(timestamps)):
                if (timestamps[m][2] == 1)   and (timestamps[m][1] == 0):       # rising tstamps ch1
                    r_edge_timestamps_ch1_point_a.append(timestamps[m][0])

            tdc.clear_irq_src(int(math.log(tdc.get_irq_src(),2)))

        # pendulum output off
        a = pendulum_output_off(meas)

        if len(r_edge_timestamps_ch1_point_a) > NUM_OF_TSTAMPS*63:
            r_edge_timestamps_ch1_point_a.sort()
        else:
            msg = ("ERROR: Unexpected error with interrupts; Ch1 registered timestamps: %d; expected: %d \n")%len(r_edge_timestamps_ch1_point_a, NUM_OF_TSTAMPS*64)
            print (msg)
            raise PtsError (msg)

        measurs = []
        for k in range(0,len(r_edge_timestamps_ch1_point_a)-1,1):
            measur = r_edge_timestamps_ch1_point_a[k+1] - r_edge_timestamps_ch1_point_a[k]
            if (measur > 4999992000 and measur < 5000002000): # to discard values from previous iterations or +-4ns issue
                measurs.append(measur)
        print "Samples           : %d"%(len(measurs))
        avg   = sum(measurs, 0.0) / len(measurs)
        error_point_a = 5000000000  - avg
        print ("Point A           : (DAC value, error in ps) = (0x%04X, %.2f)")%(point_a,error_point_a)

        # confirm that pendulum output is off
        a = pendulum_output_off(meas)

        print "-----------------------------------------------------------------\n"
        # ------> Point B: bisectomy_rslt - 100
        point_b = bisectomy_rslt - 100
        tdc.configure_mezz_dac(point_b)
        r_edge_timestamps_ch1_point_b = []

        # pendulum  ON sending pulses
        a = pendulum_output_on(meas)

        # TDC aquisition of NUM_OF_TSTAMPS*64 timestamps per channel
        # note that we are only interested in pulses on channel 1,however through the usb_box, channel 2 is also receiving pulses
        for j in range(NUM_OF_TSTAMPS):

            tdc.check_irq(0)
            timestamps, data = tdc.get_timestamps(0)

            # keep only rising edge timestamps
            for m in range(len(timestamps)):
                if (timestamps[m][2] == 1)   and (timestamps[m][1] == 0):       # rising tstamps ch1
                    r_edge_timestamps_ch1_point_b.append(timestamps[m][0])

            tdc.clear_irq_src(int(math.log(tdc.get_irq_src(),2)))

        # pendulum output off
        a = pendulum_output_off(meas)

        if len(r_edge_timestamps_ch1_point_b) > NUM_OF_TSTAMPS*63:
            r_edge_timestamps_ch1_point_b.sort()
        else:
            msg = ("ERROR: Unexpected error with interrupts; Ch1 registered timestamps: %d; expected: %d \n")%len(r_edge_timestamps_ch1_point_b, NUM_OF_TSTAMPS*64)
            print (msg)
            raise PtsError (msg)


        measurs = []
        for k in range(0,len(r_edge_timestamps_ch1_point_b)-1,1):
            measur = r_edge_timestamps_ch1_point_b[k+1] - r_edge_timestamps_ch1_point_b[k]
            if (measur > 4999992000 and measur < 5000002000): # to discard values from previous iterations or +-4ns issue
                measurs.append(measur)
        print "Samples           : %d"%(len(measurs))
        avg   = sum(measurs, 0.0) / len(measurs)
        error_point_b = 5000000000  - avg
        print ("Point B           : (DAC value, error in ps) = (0x%04X, %.2f)")%(point_b,error_point_b)


        #------------> 3) DAC final calibration value calculation
        print "\n\n_______________________DAC calibration value_______________________\n"
        # determine the line passing from points A and B
        slope = float(((error_point_a - error_point_b)/(point_a - point_b)))
        # calculate the DAC value that makes the error = 0 ps
        DAC_calibr_value = int(((slope * point_a)-error_point_a)/slope)
        print "--> DAC calibration value : 0x%4X"%(DAC_calibr_value)

        # confirm that pendulum output is off
        a = pendulum_output_off(meas)

        #------------> 4) DAC final calibration value verification
        print "\nVerification.."
        # DAC configuration with the DAC_calibr_value
        tdc.configure_mezz_dac(DAC_calibr_value)
        r_edge_timestamps_ch1_DAC_calibr_value = []

        # pendulum  ON sending pulses
        a = pendulum_output_on(meas)

        # TDC aquisition of NUM_OF_TSTAMPS*64 timestamps for Channel 1
        for j in range(NUM_OF_TSTAMPS):

            tdc.check_irq(0)
            timestamps, data = tdc.get_timestamps(0)

            # keep only rising edge timestamps
            for m in range(len(timestamps)):
                if (timestamps[m][2] == 1)   and (timestamps[m][1] == 0):       # rising tstamps ch1
                    r_edge_timestamps_ch1_DAC_calibr_value.append(timestamps[m][0])

            tdc.clear_irq_src(int(math.log(tdc.get_irq_src(),2)))

        # pendulum output off
        a = pendulum_output_off(meas)

        if len(r_edge_timestamps_ch1_DAC_calibr_value) > NUM_OF_TSTAMPS*63:
            r_edge_timestamps_ch1_DAC_calibr_value.sort()
        else:
            msg = ("ERROR: Unexpected error with interrupts; Ch1 registered timestamps: %d; expected: %d \n")%(len(r_edge_timestamps_ch1_DAC_calibr_value), 64*NUM_OF_TSTAMPS)
            print (msg)
            raise PtsError (msg)

        measurs = []
        for k in range(0,len(r_edge_timestamps_ch1_DAC_calibr_value)-1,1):
            measur = r_edge_timestamps_ch1_DAC_calibr_value[k+1] - r_edge_timestamps_ch1_DAC_calibr_value[k]
            if (measur > 4999992000 and measur < 5000002000): # to discard values from previous iterations or +-4ns issue
                measurs.append(measur)
        print "Samples           : %d"%(len(measurs))
        avg   = sum(measurs, 0.0) / len(measurs)
        error_DAC_calibr_value = 5000000000  - avg
        if abs(error_DAC_calibr_value) < 40:
            print ("DAC calibration value 0x%4X OK!\nerror: %.2f ps within +-40 ps acceptance limits")%(DAC_calibr_value,error_DAC_calibr_value)
            f_out.write('0x%.8X\n'%(DAC_calibr_value))
            print "\nDAC calibration value written in file: %s"%DAC_CALIBR_FILENAME
        else:
            msg = ("ERROR: DAC calibration value 0x%4X not ok;\nerror: %.2f ps is outside +-40 ps acceptance limits\n")%(DAC_calibr_value,error_DAC_calibr_value)
            print (msg)
            raise PtsError (msg)


   #------------> Get last temperature measurement
    # Read temperature and print to log
    temp = tdc.mezz_get_temp()
    print "Temperature measurement %3.2f°C written in file: %s"%(temp,DAC_CALIBR_FILENAME)
    f_out.write('0x%.8X\n'%(temp))


    f_out.close()
    print "\n\n--------------------------------"
    end_test_time = time.time()
    print "Test elapsed time: %.2f seconds\n\n\n" % (end_test_time-start_test_time)


if __name__ == '__main__' :
    main()
