Commit c665e3a9 authored by Evangelia Gousiou's avatar Evangelia Gousiou

rewrote all the functionality tests so as to make use of the pendulum rather…

rewrote all the functionality tests so as to make use of the pendulum rather than a Fine Delay board; like this the setup for the functionality and the calibration tests is the same
parent 58136c35
...@@ -5,10 +5,20 @@ ...@@ -5,10 +5,20 @@
# Licence: GPL v2 or later. # Licence: GPL v2 or later.
# Website: http://www.ohwr.org # Website: http://www.ohwr.org
LOGDIR=./log_fmctdc1ns5cha
sudo rmmod cp210x
cd ~/fmc-tdc-1ns-5cha-tst/pts
sudo insmod ./cp210x-driver/cp210x.ko
cd usbdriver
sudo ./usbtmc_load
cd ..
cd ~/fmc-tdc-1ns-5cha-tst/pts
LOGDIR=../logs/log_fmctdc1ns5cha
mkdir -p $LOGDIR mkdir -p $LOGDIR
sudo rm -fr $LOGDIR/pts* sudo rm -fr $LOGDIR/fmc-tdc-1ns-5cha-tst*
serial=$1 serial=$1
if [ x$1 = x"" ]; then if [ x$1 = x"" ]; then
...@@ -47,7 +57,18 @@ do ...@@ -47,7 +57,18 @@ do
echo "Test series run $nb_test out of $nb_test_limit" echo "Test series run $nb_test out of $nb_test_limit"
echo " " echo " "
sudo ./pts.py -b FmcTdc1ns5cha -s $serial -e $extra_serial -t./test/fmctdc1ns5cha/python -l $LOGDIR 00 01 02 03 04 05 06 07 08 09 10 11 12 echo "--- Functionality tests ---"
sudo ./pts.py -b FmcTdc1ns5cha_funct -s $serial -e $extra_serial -t ../test/fmctdc1ns5cha/functionality/python -l $LOGDIR 00 #01 02 03 04 05 06 07 08 09 10 11 12
echo -n "Do you wish to continue with the calibration tests [y,n]? "
read reply
if [ "$reply" = "y" ]
then
echo "--- Calibration tests ---\n"
LOGDIR=../logs/log_fmctdc1ns5cha_calib
sudo ./pts.py -b FmcTdc1ns5cha_calib -s $serial -e $extra_serial -t ../test/fmctdc1ns5cha/calibration/python -l $LOGDIR 16 17 18 #13 14 15 16 17 18
fi
if [ "$nb_test" != "$nb_test_limit" ] if [ "$nb_test" != "$nb_test_limit" ]
then then
......
...@@ -56,7 +56,8 @@ do ...@@ -56,7 +56,8 @@ do
echo "Test series run $nb_test out of $nb_test_limit" echo "Test series run $nb_test out of $nb_test_limit"
echo " " echo " "
sudo ./pts.py -b FmcTdc1ns5cha -s $serial -e $extra_serial -t ../test/fmctdc1ns5cha/calibration/python -l $LOGDIR 00 01 02 03 echo "--- Calibration tests ---"
sudo ./pts.py -b FmcTdc1ns5cha_calib -s $serial -e $extra_serial -t ../test/fmctdc1ns5cha/calibration/python -l $LOGDIR 13 14 15 16 17 18
if [ "$nb_test" != "$nb_test_limit" ] if [ "$nb_test" != "$nb_test_limit" ]
then then
......
#!/bin/sh
# Copyright CERN, 2011
# Author: Evangelia Gousiou <egousiou@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
sudo rmmod cp210x
cd ~/pts_cleanup
sudo insmod ./cp210x-driver/cp210x.ko
cd usbdriver
sudo ./usbtmc_load
cd ..
LOGDIR=./log_fmctdc1ns5cha_wrcalib
mkdir -p $LOGDIR
sudo rm -fr $LOGDIR/pts*
serial=$1
if [ x$1 = x"" ]; then
echo -n "Please scan CERN serial number bar-code, then press [ENTER]: "
read serial
fi
if [ x$serial = x"" ]; then
serial=0000
fi
if [ -e serial.txt ]; then
sudo rm -f serial.txt
fi
echo $serial >> serial.txt
extra_serial=$2
if [ x$2 = x"" ]; then
echo -n "If needed input extra serial number and press [ENTER] OR just press [ENTER]: "
read extra_serial
fi
if [ x$extra_serial = x"" ]; then
extra_serial=0000
fi
echo " "
nb_test_limit=2
nb_test=1
while [ "$nb_test" -le "$nb_test_limit" ]
do
echo "--------------------------------------------------------------"
echo "Test series run $nb_test out of $nb_test_limit"
echo " "
sudo ./pts.py -b FmcTdc1ns5cha -s $serial -e $extra_serial -t./test/fmctdc1ns5cha/calibration/python -l $LOGDIR 00 01 02 03 04 05
if [ "$nb_test" != "$nb_test_limit" ]
then
echo " "
echo -n "Do you want to run the test series again [y,n]? "
read reply
if [ "$reply" != "y" ]
then
break
fi
fi
nb_test=$(($nb_test+1))
done
echo "--------------------------------------------------------------"
echo " "
echo -n "End of the test, do you want to switch the computer OFF? [y,n]"
read reply
if [ "$reply" = "y" ]
then
sudo poweroff
fi
...@@ -13,7 +13,7 @@ class CCP210x: ...@@ -13,7 +13,7 @@ class CCP210x:
self.fd = open(device, 'wb') self.fd = open(device, 'wb')
def gpio_set(self, mask): def gpio_set(self, mask):
print("gpio_set %x" % mask), #print("gpio_set %x" % mask),
f = array.array('L', [0]) f = array.array('L', [0])
f[0] = (mask << 8) | 0xff; f[0] = (mask << 8) | 0xff;
fcntl.ioctl(self.fd, 0x8001, f, 0) fcntl.ioctl(self.fd, 0x8001, f, 0)
......
...@@ -109,7 +109,7 @@ BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device ...@@ -109,7 +109,7 @@ BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
TEMPID_FAMILY_CODE = 0x28 TEMPID_FAMILY_CODE = 0x28
TEMP_THRES = 46.0 TEMP_THRES = 43.0
TEMP_RIPPLE = 0.3 TEMP_RIPPLE = 0.3
FIFO_SIZE = 20 FIFO_SIZE = 20
MEAS_SLEEP = 1 MEAS_SLEEP = 1
......
...@@ -58,7 +58,7 @@ from numpy import * ...@@ -58,7 +58,7 @@ from numpy import *
from ctypes import * from ctypes import *
from datetime import datetime from datetime import datetime
# Add common modules location tp path # Add common modules location to path
sys.path.append('../../../../pts/') sys.path.append('../../../../pts/')
sys.path.append('../../../../pts/gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../../pts/common/') sys.path.append('../../../../pts/common/')
......
#! /bin/bash #! /bin/bash
ln -s ch_calib.py test00.py ln -s ch_calib.py test13.py
ln -s DAC_calib.py test01.py ln -s DAC_calib.py test14.py
ln -s write_eeprom.py test02.py ln -s write_eeprom.py test15.py
ln -s verify_calib.py test03.py ln -s verify_calib.py test16.py
ln -s wrabbit_calib.py test04.py ln -s wrabbit_calib.py test17.py
ln -s wrabbit_write_eeprom.py test05.py ln -s wrabbit_write_eeprom.py test18.py
#! /bin/bash #! /bin/bash
rm -f test00.py rm -f test13.py
rm -f test01.py rm -f test14.py
rm -f test02.py rm -f test15.py
rm -f test03.py rm -f test16.py
rm -f test04.py rm -f test18.py
rm -f test05.py rm -f test18.py
rm -f test*.pyc rm -f test*.pyc
\ No newline at end of file rm -f test*.py~
...@@ -74,12 +74,12 @@ import math ...@@ -74,12 +74,12 @@ import math
from datetime import datetime from datetime import datetime
# Add common modules location to path # Add common modules location to path
sys.path.append('../../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../../common/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../../common/cp210x') sys.path.append('../../../../pts/common/fmceeprom/python')
sys.path.append('../../../../common/usb_box') sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../fmceeprom/python/') sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
...@@ -147,7 +147,7 @@ def main (default_directory='.'): ...@@ -147,7 +147,7 @@ def main (default_directory='.'):
# Constants declaration # Constants declaration
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/wrabbit_tdc.bin' FMC_TDC_BITSTREAM_PATH = '../firmwares/wrabbit_tdc.bin'
FPGA_LOADER_PATH = '../../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FAMILY_CODE = 0x28 FAMILY_CODE = 0x28
WRABBIT_CLK_LOCK_MASK = 0x10 WRABBIT_CLK_LOCK_MASK = 0x10
WRABBIT_CALIB_FILENAME = "wrabbit_calib_data.txt" WRABBIT_CALIB_FILENAME = "wrabbit_calib_data.txt"
......
...@@ -58,10 +58,12 @@ import os ...@@ -58,10 +58,12 @@ import os
import numpy as np import numpy as np
# Add common modules and libraries location to path # Add common modules and libraries location to path
sys.path.append('../../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../../common/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../fmceeprom/python/') sys.path.append('../../../../pts/common/fmceeprom/python')
sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
...@@ -106,9 +108,9 @@ def main (default_directory='.'): ...@@ -106,9 +108,9 @@ def main (default_directory='.'):
start_test_time = time.time() start_test_time = time.time()
# Constants declaration # Constants declaration
FMC_TDC_ADDR = '1a39:0004/1a39:0004@0001:0000'#'1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc.bin'#spec-fmc-tdcDBG.bin' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc.bin'
FPGA_LOADER_PATH = '../../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
......
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
## | ## |
## Description Testing of the communication with the ACAM chip IC8 of the TDC board. | ## Description Testing of the communication with the ACAM chip IC8 of the TDC board. |
## The test configures the ACAM chip and then checks the status of all its registers.| ## The test configures the ACAM chip and then checks the status of all its registers.|
## In detal these lines are tested: TDC_D[27..0], TDC_ADR[3..0], RESET_N, TDC_WRN, | ## In detail these lines are tested: TDC_D[27..0], TDC_ADR[3..0], RESET_N, TDC_WRN, |
## TDC_RDN, TDC_CSN, TDC_OEN | ## TDC_RDN, TDC_CSN, TDC_OEN |
## | ## |
## | ## |
## FW to load .bin | ## FW to load tdc_allothertests.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -50,16 +50,14 @@ import math ...@@ -50,16 +50,14 @@ import math
from datetime import datetime from datetime import datetime
# Add common modules location tp path # Add common modules location tp path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
...@@ -69,11 +67,16 @@ import fmc_tdc ...@@ -69,11 +67,16 @@ import fmc_tdc
def main (default_directory='.'): def main (default_directory='.'):
start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
# Constants declaration # Constants declaration
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
...@@ -81,8 +84,9 @@ def main (default_directory='.'): ...@@ -81,8 +84,9 @@ def main (default_directory='.'):
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "-------------------- ACAM IC8 communication test ------------------\n" print "-------------------- ACAM IC8 communication test ------------------\n"
print ("Testing of the communication with the ACAM chip IC8." print ("Testing of the communication with the ACAM chip IC8.\n"
" The test\nconfigures the ACAM and then checks the status of its registers.\n") "The test configures the ACAM and then checks the status of all\n"
"its registers.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
...@@ -121,6 +125,8 @@ def main (default_directory='.'): ...@@ -121,6 +125,8 @@ def main (default_directory='.'):
else: else:
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> TDC configuration
# TDC configuration # TDC configuration
print "\n__________________________Configuration__________________________\n" print "\n__________________________Configuration__________________________\n"
tdc.config_acam() tdc.config_acam()
...@@ -152,8 +158,10 @@ def main (default_directory='.'): ...@@ -152,8 +158,10 @@ def main (default_directory='.'):
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
os.close(spec.fd)
print "\n-----------------------------------------------------------------\n\n\n" 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__' : if __name__ == '__main__' :
......
...@@ -15,8 +15,9 @@ ...@@ -15,8 +15,9 @@
## | ## |
## Description Testing of the ACAM IC8 timestamps, TDC_START_FPGA signal, TDC_STOP signals, | ## Description Testing of the ACAM IC8 timestamps, TDC_START_FPGA signal, TDC_STOP signals, |
## TDC_INT signal, TDC_EMPTY_FLAG signals. | ## TDC_INT signal, TDC_EMPTY_FLAG signals. |
## The Fine Delay is used as pulse generator sending pulses to all the TDC channels. | ## The test is using the Pendulum as pulse generator that in collaboration with the |
## The test is retrieving the pulses and is checking their accuracy. | ## Timetech Fanout and the USB-interconnection-box is sending pulses to each one of |
## the TDC channels. The test is retrieving the pulses and is checking their accuracy|
## | ## |
## | ## |
## FW to load tdc_allothertests.bit | ## FW to load tdc_allothertests.bit |
...@@ -48,23 +49,50 @@ import sys ...@@ -48,23 +49,50 @@ import sys
import time import time
import os import os
import math import math
from numpy import *
from ctypes import *
from datetime import datetime from datetime import datetime
# Add common modules location tp path # Add common modules location to path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
sys.path.append('../../../common/fmc_delay/software/python/') from cp210x_eeprom import *
import fdelay_lib from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *
# Pendulum
PENDULUM = "/dev/usbtmc1"
USB_DEVICE = "/dev/ttyUSB0"
RS232_BAUD = 57600
def pendulum_output_on(meas):
meas.write("OUTP:TYPE PULS")
meas.write("SOUR:PULS:PER 0.008")
meas.write("SOUR:PULS:WIDT 0.0002")
return (1)
def pendulum_output_off(meas):
meas.write("OUTP:TYPE OFF")
return (1)
# USB-interconnection-box
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
NUM_OF_TSTAMPS = 10 # number of fill-ups of the TDC memory
# ex NUM_OF_TSTAMPS = 10, means aquisition
# of 2560 timestamps; in this setup this means
# 640 rising edge timestamps per channel
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
## Main -- ## Main --
...@@ -72,27 +100,28 @@ import fdelay_lib ...@@ -72,27 +100,28 @@ import fdelay_lib
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FMC_DELAY_BITSTREAM_PATH = '../firmwares/fmc_delay_spec.bin'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader'
FMC_TDC_CHANNEL_NB = 5
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
#-----> TDC
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "-------------------- TDC_STOP channels test -----------------------\n" print "---------------------- ACAM accuracy test -------------------------\n"
print ("Test of the accuracy of the ACAM timestamps for each one of the channels.\n" print ("Test of the accuracy of the ACAM timestamps for each one of the\n"
"The test is using the Fine Delay board as pulse generator, sending\n" "channels. The test is using the Pendulum as pulse generator that\n"
"several pulses to each one of the TDC channels. The test configures\n" "in collaboration with the Timetech Fanout and the\n"
"the ACAM chip and then retrieves and evaluates the generated timestamps.\n") "USB-interconnection-box is sending pulses to each one of the TDC\n"
"channels. The test configures the ACAM chip and then retrieves\n"
"and evaluates the generated timestamps.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems(): for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems():
...@@ -106,10 +135,6 @@ def main (default_directory='.'): ...@@ -106,10 +135,6 @@ def main (default_directory='.'):
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH) bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream) os.system(firmware_loader + ' ' + bitstream)
time.sleep(1) time.sleep(1)
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!" print "Firmware loaded!"
# TDC object declaration # TDC object declaration
...@@ -119,17 +144,17 @@ def main (default_directory='.'): ...@@ -119,17 +144,17 @@ def main (default_directory='.'):
bitstream_type = tdc.read_bitstream_type() bitstream_type = tdc.read_bitstream_type()
if(bitstream_type == 0xFFFFFFFF): if(bitstream_type == 0xFFFFFFFF):
msg = ("FATAL ERROR: No access to TDC core") msg = ("FATAL ERROR: No access to TDC core")
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsError (msg)
if(bitstream_type != 0x1): if(bitstream_type != 0x1):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded 0x%08X") %bitstream_type
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsError (msg)
else: else:
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> ACAM and TDC configuration
# Configure ACAM and TDC core registers # Configure ACAM and TDC core registers
print "\n__________________________Configuration__________________________\n" print "\n__________________________Configuration__________________________\n"
tdc.config_acam() tdc.config_acam()
...@@ -140,9 +165,7 @@ def main (default_directory='.'): ...@@ -140,9 +165,7 @@ def main (default_directory='.'):
print "ACAM IC8: Status register OK" print "ACAM IC8: Status register OK"
else: else:
msg = ("ERROR: ACAM IC8: No communication") msg = ("ERROR: ACAM IC8: No communication")
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg)
acam_readback_regs = [] acam_readback_regs = []
acam_readback_regs = tdc.readback_acam_config() acam_readback_regs = tdc.readback_acam_config()
for i in range(len(tdc.ACAM_READBACK_REGS)): for i in range(len(tdc.ACAM_READBACK_REGS)):
...@@ -150,174 +173,162 @@ def main (default_directory='.'): ...@@ -150,174 +173,162 @@ def main (default_directory='.'):
print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i]) print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i])
else: 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])) 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]))
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
# DAC
tdc.configure_mezz_dac(0xA9CF)
# Enable terminations of channels 1,2,3,4 # Interrupts
# channels 4 and 5 are receiving the same Fine Delay pulse; only channel 5 termination activated print "\n____________________________IRQs_________________________________\n"
tdc.enable_channels() print('Set IRQ enable mask: %.4X')%tdc.set_irq_en_mask(0x1F)
tdc.channel_term(1, 1) tdc.set_irq_tstamp_thresh(0x100)
tdc.channel_term(2, 1) tdc.set_irq_time_thresh(0xFFFFF)
tdc.channel_term(3, 1)
tdc.channel_term(4, 1)
# Enable timestamps aquisition (TDC_START_FPGA pulse sent at this step)
tdc.start_acq()
#-----> USB-interconnection-box
# Communication and setup of Interconnection box
print "\n_____________________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)
box.select_output(4)
#-----> Fine Delay
# Bind SPEC object to FMC Fine Delay card
print "\n___________________________Fine Delay____________________________"
print "\nFine Delay initializations.."
print "Fine Delay address to parse %s"%(FMC_DELAY_ADDR)
for name, value in spec.parse_addr(FMC_DELAY_ADDR).iteritems():
print "%s:0x%04X"%(name, value)
spec.bind(FMC_DELAY_ADDR)
# Load FMC Fine Delay firmware
print "\nLoading FMC Fine Delay firmware...",
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_DELAY_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(2)
print "Firmware loaded!"
time.sleep(2)
# Fine Delay object declaration #-----> Pendulum
# Communication with Pendulum
print "\n__________________________USB Pendulum_____________________________\n"
try: try:
fdelay = fdelay_lib.FineDelay(spec.get_fd()) meas = PendulumCNT91(PENDULUM)
except: except OSError:
msg = ("ERROR: Fine Delay board Initiliazation failed") raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
os.close(spec.fd) a = pendulum_output_off(meas)
print (msg)
raise PtsError (msg)
# Set UTC and Coarse time in the Fine Delay
fdelay.set_time(0, 0)
fd_time = fdelay_lib.fd_timestamp()
fd_time = fdelay.get_time()
# Configure the Fine Delay as a pulse generator #-----> TDC
enable = 1 # Enable channels and start timestamps acquisition (TDC_START_FPGA pulse sent at this step)
t_start_coarse = 0 print "\n______________________ACAM acquisition start________________________\n"
width = 100000 # pulse width 100 ns
delta = 200000 # rising edges every 200 ns
count = 6
# 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)
# string to keep the ERROR messages from all the channels tdc.start_acq()
all_msg = "" print ("Sending pulses of period 8 ms to each TDC STOP channel")
for i in range(4): # one iteration per channel; # string to keep the ERROR messages from all the channels
# channels 4 and 5 receive pulses at the same time all_msg = ""
time.sleep(0.5) # needed between iterations #-----> Sending pulses to all the channels
for i in range(4): # for the 4 pairs of channels (1,2), (1,3), (1,4), (1,5)
otherch = i+1
r_edge_timestamps_ch1 = []
r_edge_timestamps_otherch = []
all_measurs = []
r_edge_timestamps = [] # USB-interconnection-box
r_edge_timestamps_ch5 = [] box.select_trigger_loopback(0)
all_measurs = [] box.select_output(4-i)
all_measurs_ch5 = []
#-----> Fine Delay # pendulum output on
# Bind SPEC object to FMC Fine Delay card a = pendulum_output_on(meas)
spec.bind(FMC_DELAY_ADDR)
channel = i+1
t_start_utc = fdelay.get_time().utc+1 # starting in 1 sec
fdelay.conf_pulsegen(channel, enable, t_start_utc, t_start_coarse, width, delta, count)
#-----> TDC # TDC acquisition of NUM_OF_TSTAMPS*64 timestamps per channel
# Bind SPEC object to FMC TDC card for j in range(NUM_OF_TSTAMPS):
spec.bind(FMC_TDC_ADDR) tdc.check_irq(0)
# Check if timestamps arrived
print "\n_________________________TDC_STOP%d test____________________________\n" %(i+1)
time.sleep(1.5)
print "The time now is : %s" %datetime.now()
print "The temperature now is : %3.3f°C" %tdc.mezz_get_temp()
print "Fine Delay sent : %d pulses of 200ns period"%(count)
print "TDC Write pointer : %d"%(tdc.get_pointer())
if (tdc.get_pointer()) != 0:
timestamps, data = tdc.get_timestamps(0) timestamps, data = tdc.get_timestamps(0)
# keep only rising edge timestamps belonging to channel under test # keep only rising edge timestamps
for m in range(len(timestamps)): for m in range(len(timestamps)):
if ((timestamps[m][2] == 1) and (timestamps[m][1] == channel-1)): if (timestamps[m][2] == 1) and (timestamps[m][1] == 0): # rising tstamps ch1
r_edge_timestamps.append(timestamps[m][0]) r_edge_timestamps_ch1.append(timestamps[m][0])
if ((timestamps[m][2] == 1) and (timestamps[m][1] == 4)): elif (timestamps[m][2] == 1) and (timestamps[m][1] == otherch): # rising tstamps pair channel
r_edge_timestamps_ch5.append(timestamps[m][0]) r_edge_timestamps_otherch.append(timestamps[m][0])
# clear interrupt
# check number of pulses arrived tdc.clear_irq_src(int(math.log(tdc.get_irq_src(),2)))
if ((len(r_edge_timestamps)) == 0):
msg = (("ERROR: TDC_STOP%d: No pulse arrived ") %channel) # pendulum output off
print (msg) a = pendulum_output_off(meas)
all_msg+=msg
if ((len(r_edge_timestamps_ch5) == 0) and i == 3): # keep only rising edge timestamps
msg = ("ERROR: TDC_STOP5: No pulse arrived ") tdc_write_pointer_now = tdc.get_pointer()
print (msg) tdc_overflows_now = tdc.get_overflow_counter()
all_msg+=msg if tdc_overflows_now != NUM_OF_TSTAMPS*(i+1):
elif (len(r_edge_timestamps)) == 6: msg = ("ERROR: Unexpected error with interrupts; expected overflows: %d; received overflows: %d")%((NUM_OF_TSTAMPS*(i+1)),tdc_overflows_now)
print "Number of rising edge timestamps : %d"%(len(r_edge_timestamps))
else:
msg = (("ERROR: TDC_STOP%d: Unexpected number of pulses arrived; expected 6, arrived %d ")%(channel, (len(r_edge_timestamps))))
print (msg) print (msg)
all_msg+=msg all_msg+=msg
# if corrent number of timestamps has arrived, continue with the math # data manipulation for channel 1
if (len(r_edge_timestamps)) == 6: if i == 0:
print "\n_________________________TDC_STOP%d test____________________________\n" %(i+1)
# evaluate timestamps: for each pulse, calculate the delta; should be 200 ns print "Ch1 tstamps : %d"%(len(r_edge_timestamps_ch1))
for k in range(0,len(r_edge_timestamps),2): print "TDC write pointer: %d"%(tdc_write_pointer_now)
measur = r_edge_timestamps[k+1] - r_edge_timestamps[k] print "TDC overflows : %d"%(tdc_overflows_now)
all_measurs.append(measur) measurs_ch1 = []
# check number of pulses arrived
# average the delta from the 6 pulses if (len(r_edge_timestamps_ch1) > 63*NUM_OF_TSTAMPS) or (len(r_edge_timestamps_ch1) < 60*NUM_OF_TSTAMPS):
avg = (sum(all_measurs, 0.0) / len(all_measurs)) r_edge_timestamps_ch1.sort()
if (avg > 198800) and (avg < 201200): # +/-1200 ps acceptance limits (+/-500 ps from FD plus +/-700ps from TDC)
print "Pulse delta measurement : %.2f ps"%(avg) # analyse the timestamps for Ch1
else: for k in range(0, len(r_edge_timestamps_ch1)-1, 1):
msg = (("ERROR: ACAM IC8: Wrong timestamps; pulse delta %.2f ps is outside accepted limits [198800 ps..201200 ps] ") %avg[i]) measur = r_edge_timestamps_ch1[k+1] - r_edge_timestamps_ch1[k]
print (msg) if (measur < 8999995000) or (measur < 9000005000):
all_msg+=msg measurs_ch1.append (measur)
print "samples : %d"%(len(measurs_ch1))
if i == 3: # for channel 5 that receives pulses along with channel 4 # evaluate the timestamps for Ch1
if (len(measurs_ch1) < 600) or (len(measurs_ch1) > 650):
print "\n________________________TDC_STOP5 test__________________________\n" msg = ("ERROR: Ch1 received %d timestamps of 8ms period; expected: around %d \n")%(len(measurs_ch1), 64*NUM_OF_TSTAMPS)
# check number of pulses arrived
if (len(r_edge_timestamps_ch5)) == 0:
msg = ("ERROR: TDC_STOP5: No pulse arrived ")
print (msg) print (msg)
all_msg+=msg all_msg+=msg
elif (len(r_edge_timestamps_ch5)) == 6:
print "Number of rising edge timestamps : %d"%(len(r_edge_timestamps_ch5))
else: else:
msg = (("ERROR: TDC_STOP5: Unexpected number of pulses arrived; expected 6, arrived %d ")%((len(r_edge_timestamps_ch5)))) avg = ((sum(measurs_ch1, 0.0) / len(measurs_ch1))/1e9) # in ms
print (msg) print "average : %.2f ms"%(avg)
all_msg+=msg print "span : %.2f ps"%((max(measurs_ch1))-(min(measurs_ch1)))
print "max iter %d %.2f ps"%(measurs_ch1.index(max(measurs_ch1)), (max(measurs_ch1)))
if ((len(r_edge_timestamps_ch5)) == 6): print "min iter %d %.2f ps"%(measurs_ch1.index(min(measurs_ch1)), (min(measurs_ch1)))
# channel 5: for each pulse, calculate the delta; should be 200 ns print ("\nACAM Ch1 OK! Received %d timestamps of average period %.2f ms\n\n")%(len(measurs_ch1), avg)
for k in range(0,len(r_edge_timestamps_ch5),2):
measur = r_edge_timestamps_ch5[k+1] - r_edge_timestamps_ch5[k] else:
all_measurs_ch5.append(measur) msg = ("ERROR: Ch1 registered timestamps: %d; expected: around %d \n")%(len(r_edge_timestamps_ch1), 64*NUM_OF_TSTAMPS)
print (msg)
all_msg+=msg
# channel 5: average the delta from the 6 pulses # data manipulation for the other channel
avg = ((sum(all_measurs_ch5, 0.0) / len(all_measurs_ch5))) print "_________________________TDC_STOP%d test____________________________\n" %(i+2)
if (avg > 198800) and (avg < 201200): print "Ch%d tstamps : %d"%(i+2, len(r_edge_timestamps_otherch))
print "Pulse delta measurement : %.2f ps"%(avg) print "TDC write pointer: %d"%(tdc_write_pointer_now)
else: print "TDC overflows : %d"%(tdc_overflows_now)
msg = (("ERROR: ACAM IC8: Wrong timestamps; pulse delta %.2f ps is outside accepted limits [198800 ps..201200 ps] ") %avg) measurs_otherch = []
print (msg) if len(r_edge_timestamps_otherch) > 63*NUM_OF_TSTAMPS:
all_msg+=msg r_edge_timestamps_otherch.sort()
for k in range(0, len(r_edge_timestamps_otherch)-1, 1):
measur = r_edge_timestamps_otherch[k+1] - r_edge_timestamps_otherch[k]
if (measur < 8999995000) or (measur < 9000005000):
measurs_otherch.append (measur)
print "samples : %d"%(len(measurs_otherch))
# evaluate the timestamps for Ch1
if (len(measurs_otherch) < 630) or (len(measurs_otherch) > 650):
msg = ("ERROR: Ch%d received %d timestamps of 8ms period; expected: around %d \n")%(i+2, len(measurs_otherch), 64*NUM_OF_TSTAMPS)
print (msg)
all_msg+=msg
else:
avg = ((sum(measurs_otherch, 0.0) / len(measurs_otherch))/1e9) # in ms
print "average : %.2f ms"%(avg)
print "span : %.2f ps"%((max(measurs_otherch))-(min(measurs_otherch)))
print "max iter %d %.2f ps"%(measurs_otherch.index(max(measurs_otherch)), (max(measurs_otherch)))
print "min iter %d %.2f ps"%(measurs_otherch.index(min(measurs_otherch)),(min(measurs_otherch)))
print ("\nACAM Ch%d OK! Received %d timestamps of average period %.2f ms\n\n")%(i+2, len(measurs_otherch), avg)
else:
msg = ("ERROR: Ch%d registered timestamps: %d; expected: around %d \n")%(i+2, len(r_edge_timestamps_otherch), 64*NUM_OF_TSTAMPS)
print (msg)
all_msg+=msg
del r_edge_timestamps
del all_measurs
if (all_msg != ""): if (all_msg != ""):
os.close(spec.fd) os.close(spec.fd)
...@@ -325,8 +336,9 @@ def main (default_directory='.'): ...@@ -325,8 +336,9 @@ def main (default_directory='.'):
raise PtsError (all_msg) raise PtsError (all_msg)
os.close(spec.fd) print "\n--------------------------------"
print "\n-----------------------------------------------------------------\n\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__' : if __name__ == '__main__' :
......
...@@ -15,16 +15,17 @@ ...@@ -15,16 +15,17 @@
## | ## |
## Description Testing of the TDC_ERR signal coming from the ACAM. | ## Description Testing of the TDC_ERR signal coming from the ACAM. |
## Through the configuration register 11, the ERR flag is configured to get activated| ## Through the configuration register 11, the ERR flag is configured to get activated|
## upon overflow on the interface FIFOs; an overflow occurs when the timestamps | ## upon overflow on the Hit FIFOs; an overflow occurs when the timestamps arrival |
## arrival rate is higher than 31.25MHz. | ## arrival rate is higher than 31.25 MHz. |
## The test is using the Fine Delay as pulse generator sending pulses to the five | ## The test is using the Pendulum as pulse generator that in collaboration with the |
## channels with a total rate of 100MHz and is monitiring the TDC_ERR signal. | ## Timetech Fanout and the USB-interconnection-box is sending pulses at 50 MHz to two|
## TDC channels simultaneously and is monitoring the TDC_ERR signal. |
## | ## |
## The TDC_ERR signal can be accessed at PCIe address: 0xC0048 | ## The TDC_ERR signal can be accessed at PCIe address: 0xC0048 |
## The TDC_ERR register can be reset by writing '1' at PCIe address: 0xC004C | ## The TDC_ERR register can be reset by writing '1' at PCIe address: 0xC004C |
## | ## |
## | ## |
## FW to load .bin | ## FW to load tdc_allothertests.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -55,22 +56,41 @@ import os ...@@ -55,22 +56,41 @@ import os
import math import math
from datetime import datetime from datetime import datetime
# Add common modules location tp path # Add common modules location tp path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
from cp210x_eeprom import *
from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *
import fmc_tdc
# Pendulum
PENDULUM = "/dev/usbtmc1"
USB_DEVICE = "/dev/ttyUSB0"
RS232_BAUD = 57600
# Import specific modules def pendulum_output_on(meas):
import fmc_tdc meas.write("OUTP:TYPE PULS")
sys.path.append('../../../common/fmc_delay/software/python/') meas.write("SOUR:PULS:PER 0.00000002")
import fdelay_lib meas.write("SOUR:PULS:WIDT 0.00000001")
return (1)
def pendulum_output_off(meas):
meas.write("OUTP:TYPE OFF")
return (1)
# USB-interconnection-box
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
...@@ -79,33 +99,34 @@ import fdelay_lib ...@@ -79,33 +99,34 @@ import fdelay_lib
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FMC_DELAY_BITSTREAM_PATH = '../firmwares/fmc_delay_spec.bin'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader'
#-----> FPGA constants
FMC_TDC_CHANNEL_NB = 5 FMC_TDC_CHANNEL_NB = 5
ERRFLAG_BASE = 0xC0000 ERRFLAG_BASE = 0xC0000
ERRFLAG_REG = 0x48 ERRFLAG_REG = 0x48
RST_ERRFLAG_REG = 0x4C RST_ERRFLAG_REG = 0x4C
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
#-----> TDC
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "-------------------- TDC ACAM ERROR FLAG test ---------------------\n" print "-------------------- TDC ACAM ERROR FLAG test ---------------------\n"
print ("Testing of the ACAM TDC_ERR signal. The ERR flag is configured to\n" print ("Testing of the ACAM TDC_ERR signal. The ERR flag is configured to\n"
"get activated upon overflow on the interface FIFOs; an overflow\n" "get activated upon overflow on the Hit FIFOs; an overflow occurs\n"
"occurs when the timestamps arrival rate is higher than 31.25MHz.\n" "when the timestamps arrival rate is higher than 31.25 MHz.\n"
"The test is using the Fine Delay as pulse generator sending pulses\n" "The test is using the Pendulum as pulse generator sending pulses\n"
"to the all the TDC channels with a total rate of 100MHz and is\n" "to two TDC channels simultaneously at a rate of 50 MHz and\n"
"monitiring the TDC_ERR signal.\n") "is monitoring the TDC_ERR signal.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
...@@ -139,12 +160,14 @@ def main (default_directory='.'): ...@@ -139,12 +160,14 @@ def main (default_directory='.'):
raise PtsCritical (msg) raise PtsCritical (msg)
if(bitstream_type != 0x1): if(bitstream_type != 0x1):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded")
os.close(spec.fd) #os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) #raise PtsCritical (msg)
else: else:
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> ACAM configuration
# Configure ACAM and TDC core registers # Configure ACAM and TDC core registers
print "\n__________________________Configuration__________________________\n" print "\n__________________________Configuration__________________________\n"
tdc.config_acam() tdc.config_acam()
...@@ -169,15 +192,17 @@ def main (default_directory='.'): ...@@ -169,15 +192,17 @@ def main (default_directory='.'):
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
# Enable terminations of channels 1,2,3,4
# channels 4 and 5 are receiving the same Fine Delay pulse; only channel 4 termination activated #-----> TDC configuration
# Enable terminations of channels 1,2,3,4,5
tdc.enable_channels() tdc.enable_channels()
tdc.channel_term(1, 1) tdc.channel_term(1, 1)
tdc.channel_term(2, 1) tdc.channel_term(2, 1)
tdc.channel_term(3, 1) tdc.channel_term(3, 1)
tdc.channel_term(4, 1)
tdc.channel_term(5, 1) tdc.channel_term(5, 1)
# Enable timestamps aquisition (TDC_START_FPGA pulse sent at this step) # Enable timestamps acquisition (TDC_START_FPGA pulse sent at this step)
tdc.start_acq() tdc.start_acq()
# Check Effflag register # Check Effflag register
...@@ -193,78 +218,55 @@ def main (default_directory='.'): ...@@ -193,78 +218,55 @@ def main (default_directory='.'):
print ("ACAM Error Flag initial value: 0x%08X OK" %(acam_errflag_init)) print ("ACAM Error Flag initial value: 0x%08X OK" %(acam_errflag_init))
#-----> Fine Delay #-----> USB-interconnection-box
# Bind SPEC object to FMC Fine Delay card # Communication and setup of Interconnection box
print "\n___________________________Fine Delay____________________________" print "\n_____________________USB interconnection box______________________\n"
print "\nFine Delay initializations.." box_tty = CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
print "Fine Delay address to parse %s"%(FMC_DELAY_ADDR) print("Device: %s" % box_tty[0])
for name, value in spec.parse_addr(FMC_DELAY_ADDR).iteritems(): box = CCalibr_box(box_tty[0])
print "%s:0x%04X"%(name, value) box.select_trigger_loopback(0)
spec.bind(FMC_DELAY_ADDR) box.select_output(4)
# Load FMC Fine Delay firmware
print "\nLoading FMC Fine Delay firmware...",
sys.stdout.flush()
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_DELAY_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1)
print "Firmware loaded!"
# Fine Delay object declaration #-----> Pendulum
# Communication with Pendulum
print "\n__________________________USB Pendulum_____________________________\n"
try: try:
fdelay = fdelay_lib.FineDelay(spec.get_fd()) meas = PendulumCNT91(PENDULUM)
except: except OSError:
msg = ("ERROR: Fine Delay board Initiliazation failed") raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
os.close(spec.fd)
print (msg)
raise PtsError (msg)
# Set UTC and Coarse time in the Fine Delay # Pendulum output on
fdelay.set_time(0, 0) a = pendulum_output_on(meas)
fd_time = fdelay_lib.fd_timestamp()
fd_time = fdelay.get_time()
# Configure the Fine Delay as a pulse generator
enable = 1
t_start_coarse = 0
width = 50000 # pulse width 50 ns
delta = 100000 # rising edges every 100 ns
count = 1000
# sending pulses to all the channels, so as to trigger the Error Flag of the Interface FIFOs
print "\n____________________Fine Delay sending pulses____________________"
print "\n...pulses being sent to all the channels at a rate > 40MHz\n"
t_start_utc = fdelay.get_time().utc+1
fdelay.conf_pulsegen(1, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(2, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(3, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(4, enable, t_start_utc, t_start_coarse, width, delta, count)
# Pendulum sending pulses
time.sleep(5) time.sleep(5)
#-----> TDC # Pendulum outsput off
# Bind SPEC object to FMC TDC card a = pendulum_output_off(meas)
spec.bind(FMC_TDC_ADDR)
#-----> Check Errflag
# Check if timestamps arrived # Check if timestamps arrived
print "\n______________________ACAM ErrorFlag test________________________\n" print "\n______________________ACAM ErrorFlag test________________________\n"
print "The time now is : %s" %datetime.now() print "The time now is : %s" %datetime.now()
print "The temperature now is : %3.3f°C" %tdc.mezz_get_temp() print "The temperature now is : %3.3f°C" %tdc.mezz_get_temp()
print "Fine Delay sent : 1000 pulses to each TDC channel" print "TDC overflows counter : %d"%(tdc.get_overflow_counter())
print "TDC Write pointer : %d"%(tdc.get_pointer())
if ((ERRFLAG_BASE.rd_reg(ERRFLAG_REG)) != 0): if ((ERRFLAG_BASE.rd_reg(ERRFLAG_REG)) != 0):
print ("ACAM Error Flag : 0x%08X OK!" %(ERRFLAG_BASE.rd_reg(ERRFLAG_REG))) print ("ACAM Error Flag : 0x%08X OK!" %(ERRFLAG_BASE.rd_reg(ERRFLAG_REG)))
else: else:
msg = ("ERROR: ACAM IC8: Error Flag: not activated as expected") msg = ("ERROR: ACAM IC8: Error Flag: not activated as expected: 0x%08X")%(ERRFLAG_BASE.rd_reg(ERRFLAG_REG))
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
a = pendulum_output_off(meas)
os.close(spec.fd) print "\n\n--------------------------------"
print "\n-----------------------------------------------------------------\n\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__' : if __name__ == '__main__' :
......
...@@ -14,16 +14,18 @@ ...@@ -14,16 +14,18 @@
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
## | ## |
## Description Testing of the ENABLE_INPUTS signal. | ## Description Testing of the ENABLE_INPUTS signal. |
## The Fine Delay is used as pulse generator sending pulses to each one of the TDC | ## The test is using the Pendulum as pulse generator that in collaboration with the |
## channels. On the TDC board the ACAM chip is registering the arriving pulses. | ## Timetech Fanout and the USB-interconnection-box is sending pulses to each one of |
## the TDC channels. |
## On the TDC board the ACAM chip is registering the arriving pulses. |
## The test starts with the ENABLE_INPUTS activated and is checking if the expected | ## The test starts with the ENABLE_INPUTS activated and is checking if the expected |
## amount of pulses is arriving to each channel. | ## amount of pulses is arriving to each channel. |
## Then the ENABLE_INPUTS is deactivated and the test is checking if pulses arrive | ## Then the ENABLE_INPUTS is deactivated and the test is checking if pulses arrive |
## to any of the channels. | ## to any of the channels. |
## | ## |
## Note that the tdc_pts_inputs_fpga_enable.py is a similar test enabling and | ## Note that the fpga_inputs_disable.py is a similar test enabling and disabling |
## disabling the ENABLE_INPUTS signal and testing for pulses on the TDC_IN_FPGA | ## the ENABLE_INPUTS signal and testing for pulses on the TDC_IN_FPGA lines, rather |
## lines, rather than the TDC_STOP lines that are tested in this test. | ## than the TDC_STOP lines that are tested in this test. |
## | ## |
## FW to load tdc_allothertests.bit | ## FW to load tdc_allothertests.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
...@@ -54,23 +56,51 @@ import sys ...@@ -54,23 +56,51 @@ import sys
import time import time
import os import os
import math import math
from numpy import *
from ctypes import *
from datetime import datetime from datetime import datetime
# Add common modules location tp path # Add common modules location to path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
sys.path.append('../../../common/fmc_delay/software/python/') from cp210x_eeprom import *
import fdelay_lib from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *
# Pendulum
PENDULUM = "/dev/usbtmc1"
USB_DEVICE = "/dev/ttyUSB0"
RS232_BAUD = 57600
def pendulum_output_on(meas):
meas.write("OUTP:TYPE PULS")
meas.write("SOUR:PULS:PER 0.008")
meas.write("SOUR:PULS:WIDT 0.0002")
return (1)
def pendulum_output_off(meas):
meas.write("OUTP:TYPE OFF")
return (1)
# USB-interconnection-box
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
NUM_OF_TSTAMPS = 10 # number of fill-ups of the TDC memory
# ex NUM_OF_TSTAMPS = 10, means aquisition
# of 2560 timestamps; in this setup this means
# 640 rising edge timestamps per channel
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
## Main -- ## Main --
...@@ -78,26 +108,26 @@ import fdelay_lib ...@@ -78,26 +108,26 @@ import fdelay_lib
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FMC_DELAY_BITSTREAM_PATH = '../firmwares/fmc_delay_spec.bin'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader'
FMC_TDC_CHANNEL_NB = 5
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
#-----> TDC
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "----------------- TDC_STOP channels disable test ------------------\n" print "----------------- TDC_STOP channels disable test ------------------\n"
print ("Test of EN_INPUTS signal. The test is using the Fine Delay board as\n" print ("Test of EN_INPUTS signal. The test is using the Pendulum as\n"
"pulse generator, sending pulses to each one of the TDC channels.\n" "pulse generator, sending pulses to each one of the TDC channels.\n"
"The test configures the ACAM chip and then retrieves the generated timestamps.\n" "The test configures the ACAM chip and then retrieves the generated "
"timestamps.\n"
"When the EN_INPUTS is disabled no pulse should be retrieved.\n") "When the EN_INPUTS is disabled no pulse should be retrieved.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
...@@ -113,10 +143,6 @@ def main (default_directory='.'): ...@@ -113,10 +143,6 @@ def main (default_directory='.'):
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH) bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream) os.system(firmware_loader + ' ' + bitstream)
time.sleep(1) time.sleep(1)
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!" print "Firmware loaded!"
# TDC object declaration # TDC object declaration
...@@ -126,17 +152,17 @@ def main (default_directory='.'): ...@@ -126,17 +152,17 @@ def main (default_directory='.'):
bitstream_type = tdc.read_bitstream_type() bitstream_type = tdc.read_bitstream_type()
if(bitstream_type == 0xFFFFFFFF): if(bitstream_type == 0xFFFFFFFF):
msg = ("FATAL ERROR: No access to TDC core") msg = ("FATAL ERROR: No access to TDC core")
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsError (msg)
if(bitstream_type != 0x1): if(bitstream_type != 0x2):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded 0x%08X") %bitstream_type
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) #raise PtsError (msg)
else: else:
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> ACAM and TDC configuration
# Configure ACAM and TDC core registers # Configure ACAM and TDC core registers
print "\n__________________________Configuration__________________________\n" print "\n__________________________Configuration__________________________\n"
tdc.config_acam() tdc.config_acam()
...@@ -147,9 +173,7 @@ def main (default_directory='.'): ...@@ -147,9 +173,7 @@ def main (default_directory='.'):
print "ACAM IC8: Status register OK" print "ACAM IC8: Status register OK"
else: else:
msg = ("ERROR: ACAM IC8: No communication") msg = ("ERROR: ACAM IC8: No communication")
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg)
acam_readback_regs = [] acam_readback_regs = []
acam_readback_regs = tdc.readback_acam_config() acam_readback_regs = tdc.readback_acam_config()
for i in range(len(tdc.ACAM_READBACK_REGS)): for i in range(len(tdc.ACAM_READBACK_REGS)):
...@@ -157,131 +181,132 @@ def main (default_directory='.'): ...@@ -157,131 +181,132 @@ def main (default_directory='.'):
print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i]) print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i])
else: 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])) 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]))
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
# DAC
tdc.configure_mezz_dac(0xA9CF)
# 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)
# Enable terminations of channels 1,2,3,4,5
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)
#-----> USB-interconnection-box
# Communication and setup of Interconnection box
print "\n_____________________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)
box.select_output(4)
#-----> Pendulum
# Communication with Pendulum
print "\n__________________________USB Pendulum_____________________________\n"
try:
meas = PendulumCNT91(PENDULUM)
except OSError:
raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
a = pendulum_output_off(meas)
#-----> TDC
# Enable channels and start timestamps acquisition (TDC_START_FPGA pulse sent at this step)
print "\n______________________ACAM acquisition start________________________\n"
# Disable the 5 TDC channels # Disable the 5 TDC channels
tdc.disable_channels() tdc.disable_channels()
for ch in range(1,FMC_TDC_CHANNEL_NB+1): for ch in range(1,6):
tdc.channel_term(ch, 1) tdc.channel_term(ch, 1)
# Enable timestamps aquisition (TDC_START_FPGA pulse sent at this step)
tdc.start_acq() tdc.start_acq()
print ("Sending pulses of period 8 ms to each TDC STOP channel")
print "\n-----------------------------------------------------------------\n\n\n"
# string to keep the ERROR messages from all the channels
#-----> Fine Delay
# Bind SPEC object to FMC Fine Delay card
print "\n___________________________Fine Delay____________________________"
print "\nFine Delay initializations.."
print "Fine Delay address to parse %s"%(FMC_DELAY_ADDR)
for name, value in spec.parse_addr(FMC_DELAY_ADDR).iteritems():
print "%s:0x%04X"%(name, value)
spec.bind(FMC_DELAY_ADDR)
# Load FMC Fine Delay firmware
print "\nLoading FMC Fine Delay firmware...",
sys.stdout.flush()
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_DELAY_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1)
print "Firmware loaded!"
# Fine Delay object declaration
try:
fdelay = fdelay_lib.FineDelay(spec.get_fd())
except:
msg = ("ERROR: Fine Delay board Initiliazation failed")
os.close(spec.fd)
print (msg)
raise PtsError (msg)
# Set UTC and Coarse time in the Fine Delay
fdelay.set_time(0, 0)
fd_time = fdelay_lib.fd_timestamp()
fd_time = fdelay.get_time()
# Configure the Fine Delay as a pulse generator
enable = 1
t_start_coarse = 0
width = 100000000 # pulse width 100 ms
delta = 200000000 # rising edges every 200 ms
# string to keep the ERROR messages from all the channels
all_msg = "" all_msg = ""
for i in range(4): # one iteration per channel; #-----> Sending pulses to all the channels
# channels 4 and 5 receive pulses at the same time for i in range(4): # for the 4 pairs of channels (1,2), (1,3), (1,4), (1,5)
time.sleep(0.5) # needed between iterations
#-----> Fine Delay otherch = i+1
# Bind SPEC object to FMC Fine Delay card r_edge_timestamps_ch1 = []
spec.bind(FMC_DELAY_ADDR) r_edge_timestamps_otherch = []
channel = i+1 all_measurs = []
count = 6+(2*i)
t_start_utc = fdelay.get_time().utc+1 # starting in 1 sec
fdelay.conf_pulsegen(channel, enable, t_start_utc, t_start_coarse, width, delta, count)
#-----> TDC # USB-interconnection-box
# Bind SPEC object to FMC TDC card box.select_trigger_loopback(0)
spec.bind(FMC_TDC_ADDR) box.select_output(4-i)
# Check if timestamps arrived
print "\n____________________TDC_STOP%d disable test_____________________\n" %channel
time.sleep(1.5)
print "The time now is : %s" %datetime.now()
print "The temperature now is : %3.3f°C" %tdc.mezz_get_temp()
print "Fine Delay sent : %d pulses of 200ns period"%(count)
print "TDC Write pointer : %d"%(tdc.get_pointer())
timestamps, data = tdc.get_timestamps(0)
if (i < 3): # pendulum output on
a = pendulum_output_on(meas)
timestamp_arrived = 0 # TDC acquisition of NUM_OF_TSTAMPS*64 timestamps per channel
for j in range(NUM_OF_TSTAMPS):
time.sleep(1)
timestamps, data = tdc.get_timestamps(0)
# keep only rising edge timestamps
for m in range(len(timestamps)): for m in range(len(timestamps)):
if ((timestamps[m][2] == 1) and (timestamps[m][1] == i)): if (timestamps[m][2] == 1) and (timestamps[m][1] == 0): # rising tstamps ch1
timestamp_arrived = timestamp_arrived+1 r_edge_timestamps_ch1.append(timestamps[m][0])
if (timestamp_arrived != 0): elif (timestamps[m][2] == 1) and (timestamps[m][1] == otherch): # rising tstamps pair channel
msg = (("ERROR: ENABLE_INPUTS disabled: TDC_STOP%d failure; %d pulses sent, %d pulses received") %(channel, count, timestamp_arrived)) r_edge_timestamps_otherch.append(timestamps[m][0])
# pendulum output off
a = pendulum_output_off(meas)
# keep only rising edge timestamps
tdc_write_pointer_now = tdc.get_pointer()
tdc_overflows_now = tdc.get_overflow_counter()
# data manipulation
if i == 0:
print "\n_________________________TDC_STOP%d test____________________________\n" %(i+1)
print "Ch1 tstamps : %d"%(len(r_edge_timestamps_ch1))
print "TDC write pointer : %d"%(tdc_write_pointer_now)
print "TDC overflows : %d"%(tdc_overflows_now)
# check if pulses arrived
if (len(r_edge_timestamps_ch1) != 0):
msg = ("ERROR: ENABLE_INPUTS disabled: TDC_STOP1 failure; %d pulses received \n")%(len(r_edge_timestamps_ch1))
print (msg) print (msg)
all_msg+=msg all_msg+=msg
else: else:
print("Channel disabling : OK! no pulses arrived") print("Channel disabling : OK! no pulses arrived")
else: # channels 4 and 5 are receiving timestamps at the same time
timestamp_arrived_ch4 = 0
timestamp_arrived_ch5 = 0
for m in range(len(timestamps)):
if ((timestamps[m][2] == 1) and (timestamps[m][1] == 3)):
timestamp_arrived_ch4 = timestamp_arrived_ch4+1
elif ((timestamps[m][2] == 1) and (timestamps[m][1] == 4)):
timestamp_arrived_ch5 = timestamp_arrived_ch5+1
if (timestamp_arrived_ch4 != 0):
msg = (("ERROR: ENABLE_INPUTS disabled: TDC_STOP%d failure; %d pulses sent, %d pulses received") %(channel, count, timestamp_arrived_ch4))
print (msg)
all_msg+=msg
else:
print("Channel disabling : OK! no pulses arrived")
if (timestamp_arrived_ch5 != 0): print "\n_________________________TDC_STOP%d test____________________________\n" %(i+2)
print "\n___________________TDC_STOP5 disable test____________________\n" print "Ch%d tstamps : %d"%(i+2, len(r_edge_timestamps_otherch))
msg = (("ERROR: ENABLE_INPUTS disabled: TDC_STOP5 failure; %d pulses sent, %d pulses received") %(count, timestamp_arrived_ch5)) print "TDC write pointer : %d"%(tdc_write_pointer_now)
print (msg) print "TDC overflows : %d"%(tdc_overflows_now)
all_msg+=msg # check if pulses arrived
else: if (len(r_edge_timestamps_otherch) != 0):
print "\n___________________TDC_STOP5 disable test____________________\n" msg = ("ERROR: ENABLE_INPUTS disabled: TDC_STOP%d failure; %d pulses received \n")%(i+2,len(r_edge_timestamps_otherch))
print("Channel disabling : OK! no pulses arrived") print (msg)
all_msg+=msg
else:
print("Channel disabling : OK! no pulses arrived")
if (all_msg != ""): if (all_msg != ""):
os.close(spec.fd) os.close(spec.fd)
print (all_msg)
raise PtsError (all_msg) raise PtsError (all_msg)
os.close(spec.fd)
print "\n-----------------------------------------------------------------\n\n\n" 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__' : if __name__ == '__main__' :
......
...@@ -15,11 +15,12 @@ ...@@ -15,11 +15,12 @@
## | ## |
## Description Testing of the TDC_START_DIS and TDC_STOP_DIS signals; when activated no | ## Description Testing of the TDC_START_DIS and TDC_STOP_DIS signals; when activated no |
## timestamps should be registered by the ACAM. | ## timestamps should be registered by the ACAM. |
## The test is using thr Fine Delay as pulse generator sending pulses to all the TDC | ## The test is using the Pendulum as pulse generator that in collaboration with the |
## channels; if there are registered pulses one or both signals are faulty. | ## Timetech Fanout and the USB-interconnection-box is sending pulses to each one of |
## the TDC channels; if there are registered pulses one or both signals are faulty. |
## | ## |
## | ## |
## FW to load .bin | ## FW to load tdc_allothertests.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -48,22 +49,45 @@ import sys ...@@ -48,22 +49,45 @@ import sys
import time import time
import os import os
import math import math
from numpy import *
from ctypes import *
from datetime import datetime from datetime import datetime
# Add common modules location tp path # Add common modules location to path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
sys.path.append('../../../common/fmc_delay/software/python/') from cp210x_eeprom import *
import fdelay_lib from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *
# Pendulum
PENDULUM = "/dev/usbtmc1"
USB_DEVICE = "/dev/ttyUSB0"
RS232_BAUD = 57600
def pendulum_output_on(meas):
meas.write("OUTP:TYPE PULS")
meas.write("SOUR:PULS:PER 0.5")
meas.write("SOUR:PULS:WIDT 0.1")
return (1)
def pendulum_output_off(meas):
meas.write("OUTP:TYPE OFF")
return (1)
# USB-interconnection-box
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
...@@ -72,39 +96,41 @@ import fdelay_lib ...@@ -72,39 +96,41 @@ import fdelay_lib
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FMC_DELAY_BITSTREAM_PATH = '../firmwares/fmc_delay_spec.bin'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader'
#-----> FPGA constants
FMC_TDC_CHANNEL_NB = 5 FMC_TDC_CHANNEL_NB = 5
CARRIER_CSR = 0xC0000 CARRIER_CSR = 0xC0000
ACAM_STARTDIS = 0x40 ACAM_STARTDIS = 0x40
ACAM_STOPDIS = 0x44 ACAM_STOPDIS = 0x44
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
#-----> TDC
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "------------------ TDC_START_DIS, TDC_STOP_DIS test ---------------\n" print "------------------ TDC_START_DIS, TDC_STOP_DIS test ---------------\n"
print ("Testing of the TDC_START_DIS and TDC_STOP_DIS signals;\n" print ("Testing of the TDC_START_DIS and TDC_STOP_DIS signals;\n"
"upon activation, no timestamps should be registered by the ACAM.\n" "upon activation, no timestamps should be registered by the ACAM.\n"
"The test configures the ACAM and is using thr Fine Delay as pulse\n" "The test configures the ACAM and is using the Pendulum as pulse\n"
"generator sending pulses to all the TDC channels; if there are\n" "generator that in collaboration with the Timetech Fanout and the\n"
"registered pulses one or both signals are faulty.\n") "USB-interconnection-box is sending pulses to each one of the TDC\n"
"channels; if there are registered pulses one or both signals are\n"
"faulty.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems(): for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems():
print "%s:0x%04X"%(name, value) print "%s:0x%04X"%(name, value)
spec.bind(FMC_TDC_ADDR) spec.bind(FMC_TDC_ADDR)
carrier_csr = csr.CCSR(spec, CARRIER_CSR)
# Load FMC TDC firmware # Load FMC TDC firmware
print "\n_________________________Initialisations_________________________\n" print "\n_________________________Initialisations_________________________\n"
...@@ -113,10 +139,6 @@ def main (default_directory='.'): ...@@ -113,10 +139,6 @@ def main (default_directory='.'):
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH) bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream) os.system(firmware_loader + ' ' + bitstream)
time.sleep(1) time.sleep(1)
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!" print "Firmware loaded!"
# TDC object declaration # TDC object declaration
...@@ -126,17 +148,17 @@ def main (default_directory='.'): ...@@ -126,17 +148,17 @@ def main (default_directory='.'):
bitstream_type = tdc.read_bitstream_type() bitstream_type = tdc.read_bitstream_type()
if(bitstream_type == 0xFFFFFFFF): if(bitstream_type == 0xFFFFFFFF):
msg = ("FATAL ERROR: No access to TDC core") msg = ("FATAL ERROR: No access to TDC core")
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsError (msg)
if(bitstream_type != 0x1): if(bitstream_type != 0x1):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded 0x%08X") %bitstream_type
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) #raise PtsError (msg)
else: else:
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> ACAM and TDC configuration
# Configure ACAM and TDC core registers # Configure ACAM and TDC core registers
print "\n__________________________Configuration__________________________\n" print "\n__________________________Configuration__________________________\n"
tdc.config_acam() tdc.config_acam()
...@@ -147,9 +169,7 @@ def main (default_directory='.'): ...@@ -147,9 +169,7 @@ def main (default_directory='.'):
print "ACAM IC8: Status register OK" print "ACAM IC8: Status register OK"
else: else:
msg = ("ERROR: ACAM IC8: No communication") msg = ("ERROR: ACAM IC8: No communication")
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg)
acam_readback_regs = [] acam_readback_regs = []
acam_readback_regs = tdc.readback_acam_config() acam_readback_regs = tdc.readback_acam_config()
for i in range(len(tdc.ACAM_READBACK_REGS)): for i in range(len(tdc.ACAM_READBACK_REGS)):
...@@ -157,99 +177,102 @@ def main (default_directory='.'): ...@@ -157,99 +177,102 @@ def main (default_directory='.'):
print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i]) print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i])
else: 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])) 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]))
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
# DAC
tdc.configure_mezz_dac(0xA9CF)
# Enable terminations of channels 1,2,3,4 # Interrupts
# channels 4 and 5 are receiving the same Fine Delay pulse; only channel 5 termination activated 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)
# Enable channels and terminations of all channels
tdc.enable_channels() tdc.enable_channels()
tdc.channel_term(1, 1) tdc.channel_term(1, 1)
tdc.channel_term(2, 1) tdc.channel_term(2, 1)
tdc.channel_term(3, 1) tdc.channel_term(3, 1)
tdc.channel_term(4, 1)
tdc.channel_term(5, 1) tdc.channel_term(5, 1)
# Enable timestamps aquisition (TDC_START_FPGA pulse sent at this step)
#-----> USB-interconnection-box
# Communication and setup of Interconnection box
print "\n_____________________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)
box.select_output(4)
#-----> Pendulum
# Communication with Pendulum
print "\n__________________________USB Pendulum_____________________________\n"
try:
meas = PendulumCNT91(PENDULUM)
except OSError:
raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
a = pendulum_output_off(meas)
#-----> TDC
# Enable channels and start timestamps acquisition (TDC_START_FPGA pulse sent at this step)
print "\n______________________ACAM acquisition start________________________\n"
tdc.start_acq() tdc.start_acq()
print ("Sending the ACAM START pulse\n")
# StartDis, StopDis # StartDis, StopDis
carrier_csr = csr.CCSR(spec, CARRIER_CSR)
carrier_csr.wr_reg(ACAM_STARTDIS,0x1) carrier_csr.wr_reg(ACAM_STARTDIS,0x1)
carrier_csr.wr_reg(ACAM_STOPDIS,0x1) carrier_csr.wr_reg(ACAM_STOPDIS,0x1)
# sending pulses to all the channels
print ("Sending pulses of period 8 ms to each TDC STOP channel")
for i in range(4): # for the 4 pairs of channels (1,2), (1,3), (1,4), (1,5)
#-----> Fine Delay otherch = i+1
# Bind SPEC object to FMC Fine Delay card r_edge_timestamps_ch1 = []
print "\n___________________________Fine Delay____________________________" r_edge_timestamps_otherch = []
print "\nFine Delay initializations.." all_measurs = []
print "Fine Delay address to parse %s"%(FMC_DELAY_ADDR)
for name, value in spec.parse_addr(FMC_DELAY_ADDR).iteritems():
print "%s:0x%04X"%(name, value)
spec.bind(FMC_DELAY_ADDR)
# Load FMC Fine Delay firmware # USB-interconnection-box
print "\nLoading FMC Fine Delay firmware...", box.select_trigger_loopback(0)
sys.stdout.flush() box.select_output(4-i)
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_DELAY_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1)
print "Firmware loaded!"
# Fine Delay object declaration # pendulum output on
try: a = pendulum_output_on(meas)
fdelay = fdelay_lib.FineDelay(spec.get_fd())
except:
msg = ("ERROR: Fine Delay board Initiliazation failed")
os.close(spec.fd)
print (msg)
raise PtsError (msg)
# Set UTC and Coarse time in the Fine Delay # pendulum sending pulses
fdelay.set_time(0, 0) time.sleep(1.2)
fd_time = fdelay_lib.fd_timestamp()
fd_time = fdelay.get_time() # pendulum output off
a = pendulum_output_off(meas)
# Configure the Fine Delay as a pulse generator
enable = 1
t_start_coarse = 0
width = 100000 # pulse width 100 ns
delta = 200000 # rising edges every 200 ns
count = 6
all_measurs = []
avg = []
for i in range(4): # one iteration per channel;
# channels 4 and 5 receive pulses at the same time
#-----> Fine Delay
time.sleep(0.5) # needed between iterations
channel = i+1
t_start_utc = fdelay.get_time().utc+1 # starting in 1 sec
fdelay.conf_pulsegen(channel, enable, t_start_utc, t_start_coarse, width, delta, count)
#-----> TDC
# Bind SPEC object to FMC TDC card
spec.bind(FMC_TDC_ADDR)
# Check if any timestamp arrived # Check if any timestamp arrived
time.sleep(1) time.sleep(1)
print "\n___________________ACAM StartDis, StopDis test___________________\n" print "\n___________________ACAM StartDis, StopDis test___________________\n"
print "The time now is : %s" %datetime.now() print "The time now is : %s" %datetime.now()
print "The temperature now is : %3.3f°C" %tdc.mezz_get_temp() print "The temperature now is : %3.3f°C" %tdc.mezz_get_temp()
print "Fine Delay sent : 6 pulses of 200ns period to each TDC channel" print "TDC write pointer : %d"%(tdc.get_pointer())
print "TDC Write pointer : %d"%(tdc.get_pointer()) print "TDC overflows : %d"%(tdc.get_overflow_counter())
if (tdc.get_pointer() == 0): if (tdc.get_pointer() == 0 and tdc.get_overflow_counter() == 0):
print ("ACAM StartDis and StopDis signals : OK!") print ("ACAM StartDis and StopDis signals : OK!")
else: else:
msg = (("ERROR: ACAM IC8: StartDis and/or StopDis: pulses registered, despite disabling;\n" msg = (("ERROR: ACAM IC8: StartDis and/or StopDis: pulses registered, despite disabling;\n"
" in total %d pulses sent, %d timestamps registered") %(count*FMC_TDC_CHANNEL_NB,(tdc.get_pointer()/32))) " 16 pulses sent, %d timestamps registered") %((tdc.get_pointer()/32))) # assuming get_overflow_counter=0
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
os.close(spec.fd)
print "\n-----------------------------------------------------------------\n\n\n" 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__' : if __name__ == '__main__' :
......
...@@ -60,27 +60,28 @@ import os ...@@ -60,27 +60,28 @@ import os
import math import math
# Add common modules location tp path # Add common modules location tp path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_clks.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_clks.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
#-----> FPGA constants
# Addressing for the retrieval of carrier csr information # Addressing for the retrieval of carrier csr information
CARRIER_CSR = 0x00000 # base address CARRIER_CSR = 0x00000 # base address
CSR_TYPE_VER = 0x00 CSR_TYPE_VER = 0x00
...@@ -98,7 +99,9 @@ def main (default_directory='.'): ...@@ -98,7 +99,9 @@ def main (default_directory='.'):
EN_COUNTERS = 0x28 EN_COUNTERS = 0x28
CLK_31M25_COUNTER = 0x2C CLK_31M25_COUNTER = 0x2C
CLK_125M_COUNTER = 0x3C CLK_125M_COUNTER = 0x3C
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
...@@ -107,8 +110,9 @@ def main (default_directory='.'): ...@@ -107,8 +110,9 @@ def main (default_directory='.'):
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "--------------------------- Clocks test ---------------------------\n" print "--------------------------- Clocks test ---------------------------\n"
print ("Test of the PLL clocks: 31.25MHz FPGA_TDC_REF_CLK and 125MHz CLK125.\n" print ("Test of the PLL clocks: 31.25MHz FPGA_TDC_REF_CLK and 125MHz CLK125.\n"
"The test starts by configuring the PLL IC4. Then, to verify the clock\n" "The test starts by configuring the PLL IC4. Then, to verify the\n"
"frequencies, there are dedicated counters implemented in the carrier FPGA.\n") "clock frequencies, there are dedicated counters implemented in the\n"
"carrier FPGA.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
...@@ -165,9 +169,9 @@ def main (default_directory='.'): ...@@ -165,9 +169,9 @@ def main (default_directory='.'):
else: else:
print("Mezzanine present : OK") print("Mezzanine present : OK")
time.sleep(3) time.sleep(3)
#-----> Check the clocks
print "\n\n___________________________PLL status____________________________\n" print "\n\n___________________________PLL status____________________________\n"
pll_status = carrier_csr.rd_reg(PLL_STATUS) pll_status = carrier_csr.rd_reg(PLL_STATUS)
if pll_status == 1: if pll_status == 1:
...@@ -189,7 +193,7 @@ def main (default_directory='.'): ...@@ -189,7 +193,7 @@ def main (default_directory='.'):
clk_125M = ((carrier_csr.rd_reg(CLK_125M_COUNTER))/ (2*1e6)) clk_125M = ((carrier_csr.rd_reg(CLK_125M_COUNTER))/ (2*1e6))
# FPGA_TDC_REF_CLK 31.25MHz clock evaluation # FPGA_TDC_REF_CLK 31.25MHz clock evaluation
if (clk_31M25 > 32.8) or (clk_31M25 < 29.6): # 5% limits due to software inacuracies if (clk_31M25 > 32.8) or (clk_31M25 < 29.6): # 5% limits due to software inaccuracies
msg = (("ERROR: PLL IC4: FPGA_TDC_REF_CLK: measured frequency %.2f MHz is out of accepted limits [29.6MHz..32.8MHz]") % (clk_31M25)) msg = (("ERROR: PLL IC4: FPGA_TDC_REF_CLK: measured frequency %.2f MHz is out of accepted limits [29.6MHz..32.8MHz]") % (clk_31M25))
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
...@@ -198,7 +202,7 @@ def main (default_directory='.'): ...@@ -198,7 +202,7 @@ def main (default_directory='.'):
print("FPGA_TDC_REF_CLK: measured frequency: %.2f MHz OK") % (clk_31M25) print("FPGA_TDC_REF_CLK: measured frequency: %.2f MHz OK") % (clk_31M25)
# CLK125 125MHz clock evaluation # CLK125 125MHz clock evaluation
if (clk_125M > 131) or (clk_125M < 118): # 5% limits due to software inacuracies in time measurement (time.sleep(2)) if (clk_125M > 131) or (clk_125M < 118): # 5% limits due to software inaccuracies in time measurement (time.sleep(2))
msg = (("ERROR: PLL IC4: CLK125: measured frequency %.2f MHz is out of accepted limits [118MHz..131MHz]") % (clk_125M)) msg = (("ERROR: PLL IC4: CLK125: measured frequency %.2f MHz is out of accepted limits [118MHz..131MHz]") % (clk_125M))
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
...@@ -207,8 +211,9 @@ def main (default_directory='.'): ...@@ -207,8 +211,9 @@ def main (default_directory='.'):
print("CLK125: measured frequency: %.2f MHz OK") % (clk_125M) print("CLK125: measured frequency: %.2f MHz OK") % (clk_125M)
os.close(spec.fd) print "\n\n--------------------------------"
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__' : if __name__ == '__main__' :
main() main()
...@@ -13,14 +13,15 @@ ...@@ -13,14 +13,15 @@
## | ## |
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
## | ## |
## Description Testing of the DAC IC2. The test is using the Fine Delay board as pulse generator,| ## Description Testing of the DAC IC2. The test is using the Pendulum as pulse generator, sending|
## sending 1 Hz pulses to TDC channel 1. The firmware loaded on the carrier FPGA | ## sending 1 Hz pulses to TDC channel 1. The firmware loaded on the carrier FPGA |
## configures the ACAM; it also configures the DAC through its SPI interface. | ## configures the ACAM; it also configures the DAC through its SPI interface. |
## Two values are set in the DAC: first, a low one (0V) and then a higher one (1.6V).| ## Two values are set in the DAC: first, a low one (0V) and then a higher one (1.6V).|
## The ACAM timestamps are retrieved and evaluated: the pulse duration is expected | ## The ACAM timestamps are retrieved and evaluated: the pulse duration is expected |
## to be higher when the DAC value is high and lower when the DAC value is low. | ## to be higher when the DAC value is high and lower when the DAC value is low. |
## | ## |
## FW to load .bin | ## |
### FW to load tdc_allothertests.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -43,30 +44,56 @@ ...@@ -43,30 +44,56 @@
## Import -- ## Import --
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
# Import system modules # Import system modules
import sys import sys
import time import time
import os import os
import math import math
from numpy import *
from ctypes import *
from datetime import datetime from datetime import datetime
# Add common modules location to path
# Add common modules location tp path sys.path.append('../../../../pts/')
sys.path.append('../../../') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
sys.path.append('../../../common/fmc_delay/software/python/') from cp210x_eeprom import *
import fdelay_lib from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *
# Pendulum
PENDULUM = "/dev/usbtmc1"
USB_DEVICE = "/dev/ttyUSB0"
RS232_BAUD = 57600
def pendulum_output_on(meas):
meas.write("OUTP:TYPE PULS")
meas.write("SOUR:PULS:PER 0.008")
meas.write("SOUR:PULS:WIDT 0.0002")
return (1)
def pendulum_output_off(meas):
meas.write("OUTP:TYPE OFF")
return (1)
# USB-interconnection-box
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
NUM_OF_TSTAMPS = 10 # number of fill-ups of the TDC memory
# ex NUM_OF_TSTAMPS = 10, means aquisition
# of 2560 timestamps; in this setup this means
# 640 rising edge timestamps per channel
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
## Main -- ## Main --
...@@ -74,29 +101,28 @@ import fdelay_lib ...@@ -74,29 +101,28 @@ import fdelay_lib
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FMC_DELAY_BITSTREAM_PATH = '../firmwares/fmc_delay_spec.bin'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader'
FMC_TDC_CHANNEL_NB = 5
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
#-----> TDC
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "---------------------------- DAC test -----------------------------\n" print "---------------------------- DAC test -----------------------------\n"
print ("Testing of the DAC IC2. The test is using the Fine Delay board as pulse\n" print ("Testing of the DAC IC2. The test is using the Pendulum as pulse\n"
"generator, sending 1 Hz pulses to TDC channel 1. The test configures the\n" "generator, sending 1 Hz pulses to TDC channel 1. The test configures\n"
"ACAM and then the DAC through its SPI interface. Two values are set in the\n" "the ACAM and then the DAC through its SPI interface. Two values are\n"
"DAC: first, a low one (0V) and then a higher one (1.6V). The ACAM timestamps\n" "set in the DAC: first, a low one (0V) and then a higher one (1.6V).\n"
"are retrieved and evaluated: the pulse duration is expected to be higher\n" "The ACAM timestamps are retrieved and evaluated: the pulse duration\n"
"when the DAC value is high and lower when the DAC value is low.\n") "is expected to be higher when the DAC value is high and lower when\n"
"the DAC value is low.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
...@@ -111,10 +137,6 @@ def main (default_directory='.'): ...@@ -111,10 +137,6 @@ def main (default_directory='.'):
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH) bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream) os.system(firmware_loader + ' ' + bitstream)
time.sleep(1) time.sleep(1)
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!" print "Firmware loaded!"
# TDC object declaration # TDC object declaration
...@@ -124,17 +146,17 @@ def main (default_directory='.'): ...@@ -124,17 +146,17 @@ def main (default_directory='.'):
bitstream_type = tdc.read_bitstream_type() bitstream_type = tdc.read_bitstream_type()
if(bitstream_type == 0xFFFFFFFF): if(bitstream_type == 0xFFFFFFFF):
msg = ("FATAL ERROR: No access to TDC core") msg = ("FATAL ERROR: No access to TDC core")
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsError (msg)
if(bitstream_type != 0x1): if(bitstream_type != 0x1):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded 0x%08X") %bitstream_type
os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsError (msg)
else: else:
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> ACAM and TDC configuration
# Configure ACAM and TDC core registers # Configure ACAM and TDC core registers
print "\n__________________________Configuration__________________________\n" print "\n__________________________Configuration__________________________\n"
tdc.config_acam() tdc.config_acam()
...@@ -145,9 +167,7 @@ def main (default_directory='.'): ...@@ -145,9 +167,7 @@ def main (default_directory='.'):
print "ACAM IC8: Status register OK" print "ACAM IC8: Status register OK"
else: else:
msg = ("ERROR: ACAM IC8: No communication") msg = ("ERROR: ACAM IC8: No communication")
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg)
acam_readback_regs = [] acam_readback_regs = []
acam_readback_regs = tdc.readback_acam_config() acam_readback_regs = tdc.readback_acam_config()
for i in range(len(tdc.ACAM_READBACK_REGS)): for i in range(len(tdc.ACAM_READBACK_REGS)):
...@@ -155,139 +175,189 @@ def main (default_directory='.'): ...@@ -155,139 +175,189 @@ def main (default_directory='.'):
print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i]) print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(tdc.ACAM_READBACK_ADDR[i], acam_readback_regs[i])
else: 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])) 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]))
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
# Enable termination of channel 1 # DAC
tdc.configure_mezz_dac(0xA9CF)
# 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)
# Enable channels and terminations of all channels
tdc.enable_channels() tdc.enable_channels()
tdc.channel_term(1, 1) 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)
# Enable timestamps aquisition (TDC_START_FPGA pulse sent at this step)
tdc.start_acq()
#-----> USB-interconnection-box
# Communication and Setup of Interconnection box
print "\n_____________________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)
box.select_output(4)
#-----> Fine Delay
# Bind SPEC object to FMC Fine Delay card
print "\n___________________________Fine Delay____________________________"
print "\nFine Delay initializations.."
print "Fine Delay address to parse %s"%(FMC_DELAY_ADDR)
for name, value in spec.parse_addr(FMC_DELAY_ADDR).iteritems():
print "%s:0x%04X"%(name, value)
spec.bind(FMC_DELAY_ADDR)
# Load FMC Fine Delay firmware #-----> Pendulum
print "\nLoading FMC Fine Delay firmware...", # Communication with Pendulum
sys.stdout.flush() print "\n__________________________USB Pendulum_____________________________\n"
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_DELAY_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1)
print "Firmware loaded!"
# Fine Delay object declaration
try: try:
fdelay = fdelay_lib.FineDelay(spec.get_fd()) meas = PendulumCNT91(PENDULUM)
except: except OSError:
msg = ("ERROR: Fine Delay board Initiliazation failed") raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
os.close(spec.fd) a = pendulum_output_off(meas)
# dummy sequence, coz it has been noted that otherwise few pulses of the
# configuration of test10 are being sent before switching to the new configuration
a = pendulum_output_on(meas)
time.sleep(0.2)
a = pendulum_output_off(meas)
#-----> TDC
# Enable channels and start timestamps acquisition (TDC_START_FPGA pulse sent at this step)
print "\n______________________ACAM acquisition start________________________\n"
tdc.start_acq()
print ("Sending pulses of period 8 ms to the TDC_STOP1 channel")
#-----> ############## DAC: 0x0000 ##############
print "\n____________________DAC 0x0000: 0V test______________________\n"
tdc.configure_mezz_dac(0x0)
r_edge_timestamps_ch1 = []
all_measurs = []
# pendulum output on
a = pendulum_output_on(meas)
# TDC aquisition of NUM_OF_TSTAMPS*64 timestamps per channel
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.append(timestamps[m][0])
# clear interrupt
tdc.clear_irq_src(int(math.log(tdc.get_irq_src(),2)))
# pendulum output off
a = pendulum_output_off(meas)
# keep only rising edge timestamps
tdc_write_pointer_now = tdc.get_pointer()
tdc_overflows_now = tdc.get_overflow_counter()
if tdc_overflows_now != NUM_OF_TSTAMPS:
msg = ("ERROR: Unexpected error with interrupts; expected overflows: %d; received overflows: %d")%((NUM_OF_TSTAMPS*(i+1)),tdc_overflows_now)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
# Set UTC and Coarse time in the Fine Delay print "Ch1 tstamps : %d"%(len(r_edge_timestamps_ch1))
fdelay.set_time(0, 0) print "TDC write pointer: %d"%(tdc_write_pointer_now)
fd_time = fdelay_lib.fd_timestamp() print "TDC overflows : %d"%(tdc_overflows_now)
fd_time = fdelay.get_time() measurs_ch1 = []
# check number of pulses arrived
if (len(r_edge_timestamps_ch1) > 63*NUM_OF_TSTAMPS) or (len(r_edge_timestamps_ch1) < 60*NUM_OF_TSTAMPS):
r_edge_timestamps_ch1.sort()
# analyse the timestamps for Ch1
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 < 8999995000) or (measur < 9000005000):
measurs_ch1.append (measur)
print "samples : %d"%(len(measurs_ch1))
# evaluate the timestamps for Ch1
if (len(measurs_ch1) < 600) or (len(measurs_ch1) > 650):
msg = ("ERROR: Ch1 received %d timestamps of 8ms period; expected: around %d \n")%(len(measurs_ch1), 64*NUM_OF_TSTAMPS)
print (msg)
raise PtsError (msg)
else:
avg_0x0000 = ((sum(measurs_ch1, 0.0) / len(measurs_ch1)))
print "span : %.2f ps"%((max(measurs_ch1))-(min(measurs_ch1)))
print "average : %.2f ms"%(avg_0x0000)
print "max iter %d %.2f ps"%(measurs_ch1.index(max(measurs_ch1)), (max(measurs_ch1)))
print "min iter %d %.2f ps"%(measurs_ch1.index(min(measurs_ch1)), (min(measurs_ch1)))
else:
msg = ("ERROR: Ch1 registered timestamps: %d; expected: around %d \n")%(len(r_edge_timestamps_ch1), 64*NUM_OF_TSTAMPS)
print (msg)
raise PtsError (msg)
# Configure the Fine Delay as a pulse generator
channel = 1
enable = 1
t_start_coarse = 0
width = 100000 # pulse width 100 ns
delta = 100000000000 # rising edges every 1 sec
count = 6
one_sec_measur_list_0x0000 = [] #-----> ############## DAC: 0xAA57 ##############
one_sec_measur_list_0xAA57 = [] print "\n____________________DAC 0xAA57: 0V test______________________\n"
tdc.configure_mezz_dac(0xAA57)
for m in range(2): # 2 iterations; one with DAC at 0x0000, one with DAC 0xAA57 r_edge_timestamps_ch1 = []
all_measurs = []
time.sleep(0.5) # somehow needed # pendulum output on
a = pendulum_output_on(meas)
#-----> Fine Delay # TDC acquisition of NUM_OF_TSTAMPS*64 timestamps per channel
# Bind SPEC object to FMC Fine Delay card for j in range(NUM_OF_TSTAMPS):
spec.bind(FMC_DELAY_ADDR) 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.append(timestamps[m][0])
# clear interrupt
tdc.clear_irq_src(int(math.log(tdc.get_irq_src(),2)))
t_start_utc = fdelay.get_time().utc+1 # starting in 1 sec # pendulum output off
fdelay.conf_pulsegen(channel, enable, t_start_utc, t_start_coarse, width, delta, count) a = pendulum_output_off(meas)
#-----> TDC # data manipulation
# Bind SPEC object to FMC TDC card
spec.bind(FMC_TDC_ADDR)
# Configuring DAC # keep only rising edge timestamps
if m == 0: tdc_write_pointer_now = tdc.get_pointer()
print "\n____________________DAC 0x0000: 0V test______________________\n" tdc_overflows_now = tdc.get_overflow_counter()
tdc.configure_mezz_dac(0x0) if tdc_overflows_now != NUM_OF_TSTAMPS*2:
else: msg = ("ERROR: Unexpected error with interrupts; expected overflows: %d; received overflows: %d")%((NUM_OF_TSTAMPS*(i+1)),tdc_overflows_now)
print "\n____________________DAC 0xAA57: 1.6V test____________________\n" print (msg)
tdc.configure_mezz_dac(0xAA57) raise PtsError (msg)
time.sleep(7)
print "The time now is : %s" %datetime.now()
print "The temperature now is : %3.3f°C" %tdc.mezz_get_temp()
print "Fine Delay sent : %d pulses of 1s period to TDC channel 1"%(count)
print "TDC Write pointer : %d"%(tdc.get_pointer())
if (tdc.get_pointer()) == 0: print "Ch1 tstamps : %d"%(len(r_edge_timestamps_ch1))
msg = ("ERROR: TDC_IN_FPGA1: No pulse arrived") print "TDC write pointer: %d"%(tdc_write_pointer_now)
os.close(spec.fd) print "TDC overflows : %d"%(tdc_overflows_now)
measurs_ch1 = []
# check number of pulses arrived
if (len(r_edge_timestamps_ch1) > 63*NUM_OF_TSTAMPS) or (len(r_edge_timestamps_ch1) < 60*NUM_OF_TSTAMPS):
r_edge_timestamps_ch1.sort()
# analyse the timestamps for Ch1
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 < 8999995000) or (measur < 9000005000):
measurs_ch1.append (measur)
print "samples : %d"%(len(measurs_ch1))
# evaluate the timestamps for Ch1
if (len(measurs_ch1) < 600) or (len(measurs_ch1) > 650):
msg = ("ERROR: Ch1 received %d timestamps of 8ms period; expected: around %d \n")%(len(measurs_ch1), 64*NUM_OF_TSTAMPS)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
else: else:
timestamps, data = tdc.get_timestamps(0) print "span : %.2f ps"%((max(measurs_ch1))-(min(measurs_ch1)))
avg_0xaa57 = ((sum(measurs_ch1, 0.0) / len(measurs_ch1)))
# keep rising edge timestamps print "average : %.2f ms"%(avg_0xaa57)
r_edge_timestamps = [] print "max iter %d %.2f ps"%(measurs_ch1.index(max(measurs_ch1)), (max(measurs_ch1)))
for i in range(len(timestamps)): print "min iter %d %.2f ps"%(measurs_ch1.index(min(measurs_ch1)), (min(measurs_ch1)))
if ((timestamps[i][2] == 1)): else:
r_edge_timestamps.append(timestamps[i][0]) msg = ("ERROR: Ch1 registered timestamps: %d; expected: around %d \n")%(len(r_edge_timestamps_ch1), 64*NUM_OF_TSTAMPS)
r_edge_lgth = len(r_edge_timestamps) print (msg)
print "Number of rising edge timestamps : %d"%(r_edge_lgth) raise PtsError (msg)
if m == 0:
if (r_edge_lgth) != 6:
msg = (("ERROR: TDC_IN_FPGA1: %d pulses arrived; 6 were expected") %(r_edge_lgth))
os.close(spec.fd)
print (msg)
raise PtsError (msg)
for k in range(0,len(r_edge_timestamps),2):
one_sec_measur_0x0000 = r_edge_timestamps[k+1] - r_edge_timestamps[k]
one_sec_measur_list_0x0000.append(one_sec_measur_0x0000)
avg_dac_0x0000 = (sum(one_sec_measur_list_0x0000, 0.0) / len(one_sec_measur_list_0x0000))
print "\nDAC 0x0000: One second measurement: %.2f ps"%avg_dac_0x0000
else:
if (r_edge_lgth) != 12:
msg = (("ERROR: TDC_IN_FPGA1: %d pulses arrived; 6 were expected") %(r_edge_lgth))
os.close(spec.fd)
print (msg)
raise PtsError (msg)
for k in range(6,len(r_edge_timestamps),2):
one_sec_measur_0xAA57 = r_edge_timestamps[k+1] - r_edge_timestamps[k]
one_sec_measur_list_0xAA57.append(one_sec_measur_0xAA57)
avg_dac_0xAA57 = (sum(one_sec_measur_list_0xAA57, 0.0) / len(one_sec_measur_list_0xAA57))
print "\nDAC 0xAA57: One second measurement: %.2f ps"%avg_dac_0xAA57
print "\n_______________________DAC Test Result_______________________\n" print "\n_______________________DAC Test Result_______________________\n"
if (avg_dac_0xAA57 > avg_dac_0x0000 + 1000000): if (avg_0xaa57 > avg_0x0000 + 100000):
print("DAC test OK!") print("DAC test OK!")
else: else:
msg = ("ERROR: DAC IC14: Changes in DAC are not affecting the clocks") msg = ("ERROR: DAC IC14: Changes in DAC are not affecting the clocks")
...@@ -295,9 +365,10 @@ def main (default_directory='.'): ...@@ -295,9 +365,10 @@ def main (default_directory='.'):
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
tdc.stop_acq()
os.close(spec.fd) print "\n\n--------------------------------"
print "\n-----------------------------------------------------------------\n\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__' : if __name__ == '__main__' :
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
## | ## |
## The test attempts several writings and readbacks on different EEPROM locations. | ## The test attempts several writings and readbacks on different EEPROM locations. |
## | ## |
## FW to load .bin | ## FW to load tdc_allothertests.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -51,30 +51,36 @@ import sys ...@@ -51,30 +51,36 @@ import sys
import time import time
import os import os
# Add common modules location tp path # Add common modules location to path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
# Import specific modules
import fmc_tdc import fmc_tdc
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
## main -- ## main --
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
def main (default_directory='.'): def main (default_directory='.'):
start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
# Constants declaration # Constants declaration
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'#tdc_counters.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
#-----> EEPROM chip constant
EEPROM_ADDR = 0x50 EEPROM_ADDR = 0x50
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
...@@ -92,7 +98,7 @@ def main (default_directory='.'): ...@@ -92,7 +98,7 @@ def main (default_directory='.'):
# Load FMC TDC firmware # Load FMC TDC firmware
print "\n_________________________Initialisations_________________________\n" print "\n_________________________Initialisations_________________________\n"
print "Loading FMC Fine Delay firmware...", print "Loading FMC TDC firmware...",
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH) firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH) bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream) os.system(firmware_loader + ' ' + bitstream)
...@@ -121,6 +127,8 @@ def main (default_directory='.'): ...@@ -121,6 +127,8 @@ def main (default_directory='.'):
else: else:
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> Accessing the mezzanine EEPROM chip
print "\n__________________________EEPROM IC10 test_______________________\n" print "\n__________________________EEPROM IC10 test_______________________\n"
# Scan FMC I2C bus # Scan FMC I2C bus
try: try:
...@@ -170,8 +178,10 @@ def main (default_directory='.'): ...@@ -170,8 +178,10 @@ def main (default_directory='.'):
else: else:
print('\nEEPROM IC5: Data comparison OK') print('\nEEPROM IC5: Data comparison OK')
os.close(spec.fd)
print "\n\n-----------------------------------------------------------------" 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__' : if __name__ == '__main__' :
main() main()
...@@ -16,13 +16,13 @@ ...@@ -16,13 +16,13 @@
## Description Testing of the presence of the TDC board on the SPEC carrier. | ## Description Testing of the presence of the TDC board on the SPEC carrier. |
## | ## |
## The test retrieves information on the carrier board: pcb version, carrier type, | ## The test retrieves information on the carrier board: pcb version, carrier type, |
## status, control, mezzzanine presence. | ## status, control, mezzanine presence. |
## Note that the mezzanine presence flag comes from the FMC pin prsnt_m2c_n_i. | ## Note that the mezzanine presence flag comes from the FMC pin prsnt_m2c_n_i. |
## | ## |
## The WISHBONE master can be accessed at PCIe base address xC0000. | ## The WISHBONE master can be accessed at PCIe base address xC0000. |
## | ## |
## | ## |
## FW to load .bin | ## FW to load tdc_pts_presence.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -52,26 +52,27 @@ import time ...@@ -52,26 +52,27 @@ import time
import os import os
# Add common modules location tp path # Add common modules location tp path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_presence.bit'#top_tdc.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_presence.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
#-----> FPGA constants
# Addressing for the retrieval of carrier csr information # Addressing for the retrieval of carrier csr information
CARRIER_CSR = 0x00000 # base address CARRIER_CSR = 0x00000 # base address
CSR_TYPE_VER = 0x00 CSR_TYPE_VER = 0x00
...@@ -82,14 +83,16 @@ def main (default_directory='.'): ...@@ -82,14 +83,16 @@ def main (default_directory='.'):
PCB_VER_MASK = 0x000F PCB_VER_MASK = 0x000F
CARRIER_TYPE_MASK = 0xFFFF0000 CARRIER_TYPE_MASK = 0xFFFF0000
STATUS_FMC_PRES = (1<<0) STATUS_FMC_PRES = (1<<0)
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "---------------------------- FMC TDC ---------------------------- " print "----------------------------- FMC TDC ----------------------------- "
print "-------------------- Mezzanine presence test --------------------\n" print "--------------------- Mezzanine presence test ---------------------\n"
print ("Test of the presence of the mezzanine, on the SPEC carrier.\n") print ("Test of the presence of the mezzanine, on the SPEC carrier.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
...@@ -113,7 +116,7 @@ def main (default_directory='.'): ...@@ -113,7 +116,7 @@ def main (default_directory='.'):
# Check bitsteam type # Check bitsteam type
bitstream_type = carrier_csr.rd_reg(CSR_BSTM_TYPE) bitstream_type = carrier_csr.rd_reg(CSR_BSTM_TYPE)
print('Bitstream type :%.8X') % bitstream_type print('Bitstream type : %.8X') % bitstream_type
if(bitstream_type == 0xFFFFFFFF): if(bitstream_type == 0xFFFFFFFF):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded")
os.close(spec.fd) os.close(spec.fd)
...@@ -148,8 +151,10 @@ def main (default_directory='.'): ...@@ -148,8 +151,10 @@ def main (default_directory='.'):
else: else:
print("Mezzanine present OK\n") print("Mezzanine present OK\n")
os.close(spec.fd)
print "\n\n-----------------------------------------------------------------" 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__' : if __name__ == '__main__' :
main() main()
...@@ -60,7 +60,7 @@ class CFMCTDC: ...@@ -60,7 +60,7 @@ class CFMCTDC:
# ACAM register addresses and expected register contents # ACAM register addresses and expected register contents
ACAM_READBACK_ADDR = [0x40, 0x44, 0x48, 0x4C, 0X50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x78] ACAM_READBACK_ADDR = [0x40, 0x44, 0x48, 0x4C, 0X50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x78]
ACAM_READBACK_REGS = [0xC1F0FC81, 0xC0000000, 0xC0000E02, 0xC0000000, 0xC200000F, 0xC00007D0, 0xC00000FC, 0xC0001FEA, 0x00000000, 0x00000000, 0x00000000, 0xC3000000, 0xC4000800, 0xC0000000] ACAM_READBACK_REGS = [0xC1F0FC81, 0xC0000000, 0xC0000E02, 0xC0000000, 0xC200000F, 0xC00007D0, 0xC00000FC, 0xC0001FEA, 0x00000000, 0x00000000, 0x00000000, 0xC01F0000, 0xC4000800, 0xC0000000]
# DMA length in bytes # DMA length in bytes
DMA_LENGTH = 4096 DMA_LENGTH = 4096
...@@ -175,8 +175,8 @@ class CFMCTDC: ...@@ -175,8 +175,8 @@ class CFMCTDC:
self.tdc_regs.wr_reg(0x14, 0x7D0) self.tdc_regs.wr_reg(0x14, 0x7D0)
self.tdc_regs.wr_reg(0x18, 0x3) self.tdc_regs.wr_reg(0x18, 0x3)
self.tdc_regs.wr_reg(0x1C, 0x1FEA) self.tdc_regs.wr_reg(0x1C, 0x1FEA)
#self.tdc_regs.wr_reg(0x2C, 0xFF0000) self.tdc_regs.wr_reg(0x2C, 0x1F0000)
self.tdc_regs.wr_reg(0x2C, 0x03000000) #self.tdc_regs.wr_reg(0x2C, 0x03000000)
self.tdc_regs.wr_reg(0x30, 0x4000000) self.tdc_regs.wr_reg(0x30, 0x4000000)
self.tdc_regs.wr_reg(0x38, 0x0) self.tdc_regs.wr_reg(0x38, 0x0)
self.tdc_regs.wr_reg(0xFC, 0x4) self.tdc_regs.wr_reg(0xFC, 0x4)
......
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin <matthieu.cattin@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Import system modules
import sys
import time
import os
import math
# Import common modules
import rr
from ptsexcept import *
import csr
import gn4124
import i2c
import onewire
import ds18b20
import eeprom_24aa64
# Add common modules location tp path
sys.path.append('../../../../')
sys.path.append('../../../../gnurabbit/python/')
sys.path.append('../../../../common/')
"""
FMC TDC class
"""
class CFMCTDC:
# DMA WISHBONE adress
GNUM_CSR_ADDR = 0x04000
# Carrier One Wire
CARR_ONEWIRE_ADDR = 0x04800
# Carrier CSR info
CARRIER_CSR_ADDR = 0x04C00
CSR_BSTM_TYPE = 0x04
# TDC core WISHBONE adress
TDC_CORE_ADDR = 0x05000
# IRQ controller
IRQ_CONTROLLER_ADDR = 0x05400
IRQ_CTRL_SRC = 0x04
IRQ_CTRL_EN_MASK = 0x08
# Mezzanine I2C
MEZZ_I2C_ADDR = 0x05800
MEZZ_EEPROM_ADDR = 0x50
# Mezzanine One Wire
MEZZ_ONEWIRE_ADDR = 0x05C00
# ACAM register addresses and expected register contents
ACAM_READBACK_ADDR = [0x40, 0x44, 0x48, 0x4C, 0X50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x78]
ACAM_READBACK_REGS = [0xC1F0FC81, 0xC0000000, 0xC0000E02, 0xC0000000, 0xC200000F, 0xC00007D0, 0xC00000FC, 0xC0001FEA, 0x00000000, 0x00000000, 0x00000000, 0xC3000000, 0xC4000800, 0xC0000000]
# DMA length in bytes
DMA_LENGTH = 4096
# Write pointer register
WP_MASK = 0xFFF
WP_OVERFLOW_MASK = 0xFFFFF000
# Timestamp meta-data
META_CHANNEL_MASK = 0x07 #0xF
META_SLOPE_MASK = 0x10 #0xF0
META_FIFO_LF_MASK = 0xF00
META_FIFO_EF_MASK = 0xF000
META_SLOPE = ['falling', 'rising']
###############################################################################################
def __init__(self, bus):
# Objects delcaration
self.bus = bus;
self.gnum = gn4124.CGN4124(self.bus, self.GNUM_CSR_ADDR)
self.tdc_regs = csr.CCSR(self.bus, self.TDC_CORE_ADDR)
self.irq_controller = csr.CCSR(self.bus, self.IRQ_CONTROLLER_ADDR)
self.carrier_csr = csr.CCSR(self.bus, self.CARRIER_CSR_ADDR)
# Set GNUM local bus frequency
self.gnum.set_local_bus_freq(160)
print "Gennum local bus clock %d MHz"%(self.gnum.get_local_bus_freq())
time.sleep(2)
# Reset FPGA
print "Resetting FPGA"
self.gnum.rstout33_cycle()
time.sleep(3)
# I2C mezzanine
self.mezz_i2c = i2c.COpenCoresI2C(self.bus, self.MEZZ_I2C_ADDR, 249)
self.mezz_eeprom_24aa64 = eeprom_24aa64.C24AA64(self.mezz_i2c, self.MEZZ_EEPROM_ADDR)
# One Wire mezzanine
self.mezz_onewire = onewire.COpenCoresOneWire(self.bus, self.MEZZ_ONEWIRE_ADDR, 624, 124)
self.mezz_ds18b20 = ds18b20.CDS18B20(self.mezz_onewire, 0)
# One Wire carrier
self.carr_onewire = onewire.COpenCoresOneWire(self.bus, self.CARR_ONEWIRE_ADDR, 624, 124)
self.carr_ds18b20 = ds18b20.CDS18B20(self.carr_onewire, 0)
# Get physical addresses of the memory pages for DMA transfer
self.dma_pages = self.gnum.get_physical_addr()
###############################################################################################
# Read bitstream type
def read_bitstream_type(self):
return self.carrier_csr.rd_reg(0x04)
# Returns mezzanine unique ID
def mezz_get_unique_id(self):
return self.mezz_ds18b20.read_serial_number()
# Returns mezzanine temperature
def mezz_get_temp(self):
serial_number = self.mezz_ds18b20.read_serial_number()
if(serial_number == -1):
return -1
else:
return self.mezz_ds18b20.read_temp(serial_number)
# Returns carrier unique ID
def carr_get_unique_id(self):
return self.carr_ds18b20.read_serial_number()
# Returns carrier temperature
def carr_get_temp(self):
serial_number = self.carr_ds18b20.read_serial_number()
if(serial_number == -1):
return -1
else:
return self.carr_ds18b20.read_temp(serial_number)
# scan FMC i2c bus
def mezz_i2c_scan(self):
print 'Scanning I2C bus...',
return self.mezz_i2c.scan()
# write to EEPROM on system i2c bus
def mezz_i2c_eeprom_write(self, addr, data):
return self.mezz_eeprom_24aa64.wr_data(addr, data)
# read from EEPROM on system i2c bus
def mezz_i2c_eeprom_read(self, addr, size):
return self.mezz_eeprom_24aa64.rd_data(addr, size)
# write to EEPROM on system i2c bus
def mezz_i2c_eeprom_write_page(self, data):
byte_to_write = len(data)
addr = 0
while byte_to_write:
if byte_to_write > 32:
size = 32
else:
size = byte_to_write
self.mezz_eeprom_24aa64.wr_page(addr,data[addr:(addr+size)])
byte_to_write -= size
addr += size
time.sleep(0.005) # have to wait between writes otherwise the eeprom gives NACK on the i2c bus
# read from EEPROM on system i2c bus
def mezz_i2c_eeprom_read_chunk(self, addr, size):
return self.mezz_eeprom_24aa64.rd_seq(addr, size)
# Configures ACAM
def config_acam(self):
print "Loading ACAM and TDC core registers"
time.sleep(1)
self.tdc_regs.wr_reg(0x00, 0x1F0FC81)
self.tdc_regs.wr_reg(0x04, 0x0)
self.tdc_regs.wr_reg(0x08, 0xE02)
time.sleep(1)
self.tdc_regs.wr_reg(0x0C, 0x0)
self.tdc_regs.wr_reg(0x10, 0x200000F)
self.tdc_regs.wr_reg(0x14, 0x7D0)
self.tdc_regs.wr_reg(0x18, 0x3)
self.tdc_regs.wr_reg(0x1C, 0x1FEA)
#self.tdc_regs.wr_reg(0x2C, 0xFF0000)
self.tdc_regs.wr_reg(0x2C, 0x03000000)
self.tdc_regs.wr_reg(0x30, 0x4000000)
self.tdc_regs.wr_reg(0x38, 0x0)
self.tdc_regs.wr_reg(0xFC, 0x4)
time.sleep(1)
def load_acam_config(self):
print "Loading ACAM configuration"
self.tdc_regs.wr_reg(0xFC, 0x4)
time.sleep(1)
def reset_acam(self):
print "Reseting ACAM"
self.tdc_regs.wr_reg(0xFC, 0x100)
time.sleep(1)
# Configures DAC and PLL
def configure_mezz_dac(self, dac_word):
print "\nConfiguring mezzanine DAC 0x%4X"%dac_word
self.tdc_regs.wr_reg(0x98, dac_word) # default: xA8F5, max: xFFFF, min: x0000
self.tdc_regs.wr_reg(0xFC, 0x800)
time.sleep(2)
# def readback_acam_config(self):
# self.tdc_regs.wr_reg(0xFC, 0x8)
# time.sleep(1)
# acam_regs = []
# for i in range(len(self.ACAM_READBACK_REGS)):
# acam_regs.append (self.tdc_regs.rd_reg(i))
# if (self.tdc_regs.rd_reg(i) == self.ACAM_READBACK_REGS[i]):
# print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(i, self.tdc_regs.rd_reg(i))
# else:
# print "ERROR! ACAM IC8: reg 0x%02X: received 0x%08X; expected 0x%08X"%(i, self.tdc_regs.rd_reg(i), self.ACAM_READBACK_REGS[i])
# return acam_regs
def readback_acam_config(self):
self.tdc_regs.wr_reg(0xFC, 0x8)
time.sleep(1)
acam_regs = []
for i in self.ACAM_READBACK_ADDR:
acam_regs.append (self.tdc_regs.rd_reg(i))
#print "ACAM IC8: reg 0x%02X: 0x%08X OK"%(i, self.tdc_regs.rd_reg(i))
return acam_regs
# Read ACAM status register
def read_acam_status(self):
self.tdc_regs.wr_reg(0xFC, 0x10)
return self.tdc_regs.rd_reg(0x70)
def enable_channels(self):
print "Enabling channels"
self.tdc_regs.wr_bit(0x84, 7, 1)
def disable_channels(self):
print "Disabling channels"
self.tdc_regs.wr_bit(0x84, 7, 0)
def channel_term(self, channel, enable):
self.tdc_regs.wr_bit(0x84, channel-1, enable)
#print "0x%08X"%self.tdc_regs.rd_reg(0x84)
def set_utc(self, utc):
self.tdc_regs.wr_reg(0x80, utc)
self.tdc_regs.wr_reg(0xFC, 0x200)
def get_utc(self):
return self.tdc_regs.rd_reg(0xA0)
def start_acq(self):
self.tdc_regs.wr_reg(0xFC, 0x1)
print "Aquisition started!"
def tdc_core_test(self):
for i in range(0,150,4):
print "Iteration %d: reg[%.3X]: 0x%.8X" %(i/4, i, self.tdc_regs.rd_reg(i))
time.sleep(0.5)
return self.tdc_regs.rd_reg(0xFC)
#...dummy...#
def generate_dummy_irq(self):
self.tdc_regs.wr_reg(0xFC, 0x80000000)
print "Generating dummy IRQ.."
#...dummy...#
def set_irq_tstamp_thresh(self,tstamp_thresh):
print "Setting IRQ timestamps threshold"
self.tdc_regs.wr_reg(0x90, tstamp_thresh) # irq tstaps threshold; only 9 LSbits are significant
def set_irq_time_thresh(self, time_thresh):
print "Setting IRQ time threshold"
self.tdc_regs.wr_reg(0x94, time_thresh) # irq time (sec) threshold
def stop_acq(self):
self.tdc_regs.wr_reg(0xFC, 0x2)
print "Aquisition stopped."
def get_pointer(self):
return (self.WP_MASK & self.tdc_regs.rd_reg(0xA8))
def get_pointer2(self):
return (self.tdc_regs.rd_reg(0xA8))
def get_overflow_counter(self):
return ((self.WP_OVERFLOW_MASK & self.tdc_regs.rd_reg(0xA8)) >> 12)
# Set IRQ enable mask
def set_irq_en_mask(self, mask):
self.irq_controller.wr_reg(self.IRQ_CTRL_EN_MASK, mask)
return self.irq_controller.rd_reg(self.IRQ_CTRL_EN_MASK)
# Get IRQ source
def get_irq_src(self):
return self.irq_controller.rd_reg(self.IRQ_CTRL_SRC)
# Clear IRQ source
def clear_irq_src(self, src):
self.irq_controller.wr_bit(self.IRQ_CTRL_SRC, src, 1)
# Check for IRQs
def check_irq(self, verbose=0):
self.gnum.irq_en()
self.gnum.wait_irq()
if(verbose):
print('#################!!!!GN4124 interrupt occured!!!!#################')
def get_timestamps(self, verbose=0):
# Read the number of bytes to be read from the board
dma_length_tmp = self.get_pointer()
if dma_length_tmp == 0: # add overflow> 0
dma_length = 4096
else:
dma_length = dma_length_tmp
carrier_addr = 0x0
# Calculate the number of DMA item required to get the data
items_required = int(math.ceil(dma_length/float(self.DMA_LENGTH)))
if(128 < items_required):
print('Required items: %d')%items_required
raise Exception('Current gn4124 class only supports up to 128 items.')
if(verbose):
print('Required items: %d')%items_required
# Configure DMA
for num in range(items_required):
if(items_required == num+1):
next_item = 0
item_length = (dma_length-(num*self.DMA_LENGTH))
else:
next_item = 1
item_length = self.DMA_LENGTH
if(0 == num):
item_start_addr = carrier_addr
else:
item_start_addr = carrier_addr + (num*self.DMA_LENGTH)
if(verbose):
print("item nb:%d item_carrier_addr:0x%.8X item_host_addr:0x%.8X item_length:%d next_item:%d)")%(num,item_start_addr,self.dma_pages[num+1],item_length,next_item)
self.gnum.add_dma_item(item_start_addr, self.dma_pages[num+1], item_length, 0, next_item)
if(verbose):
if(items_required > 1):
items = self.gnum.get_memory_page(0)
print('DMA items:')
for i in range(items_required*8):
print('%.4X: %.8X')%(i*4,items[i])
# Start DMA
dma_finished = 0
if(verbose):
print "Start DMA"
self.gnum.start_dma()
"""
# Poll on DMA status
print "Wait for DMA done"
while('Done' == self.gnum.get_dma_status()):
time.sleep(0.01)
print "DMA done!"
"""
# Wait for end of DMA interrupt
if(verbose):
print('Wait GN4124 interrupt')
self.gnum.wait_irq()
if(verbose):
print('GN4124 interrupt occured')
"""
print('irq mask:%.4X')%self.get_irq_en_mask() if(verbose)
while(0 == dma_finished):
irq_src = self.get_irq_source()
if(verbose):
print('IRQ source : %.4X')%irq_src
print('DMA status: %s')%self.gnum.get_dma_status()
if(irq_src & self.IRQ_SRC_DMA_END):
print('IRQ source : %.4X')%irq_src if(verbose)
self.clear_irq_source(self.IRQ_SRC_DMA_END)
print('IRQ source : %.4X')%self.get_irq_source() if(verbose)
dma_finished = 1
time.sleep(0.005)
print('DMA finished!') if(verbose)
"""
# Retrieve data from host memory
data = []
for i in range(items_required):
data += self.gnum.get_memory_page(i+1)
if(verbose):
print('data length:%d')%(len(data)*4)
for i in range(len(data)):
print data[i]
# Format timestamps
if(verbose):
print "Timestamps retreived:"
raw_timestamps = []
timestamps = []
for i in range(0,dma_length/4,4):
# timestamp value
timestamp = data[i+2] * 1E12 + data[i+1] * 8E3 + data[i] * 81.03
# timestamp metadata
channel = self.META_CHANNEL_MASK & data[i+3]
slope = ((self.META_SLOPE_MASK & data[i+3]) >> 4)
fifo_lf = ((self.META_FIFO_LF_MASK & data[i+3]) >> 8)
fifo_ef = ((self.META_FIFO_EF_MASK & data[i+3]) >> 12)
# putting everything together
raw_timestamps.append((data[i+3]<<96)+(data[i+2]<<64)+(data[i+1]<<32)+data[i])
timestamps.append([timestamp, channel, slope, fifo_lf, fifo_ef])
#if(verbose):
# print "[%03d] sec:%20.3f channel:%d slope:%7s fifo_lf:%d fifo_ef:%d"%(i/4,timestamp, channel, self.META_SLOPE[slope], fifo_lf, fifo_ef)
eurika = 0
for i in range(0,dma_length/4,8):
# for debug check if UTC second changes
if (data[i+2] != data[i+6]):
#print "Euriika! second changed in these timestamps"
eurika = 1
if(verbose):
print "Number of timestamps = %d" % (len(timestamps))
for i in range(len(timestamps)):
print timestamps[i]
return timestamps, data
if __name__ == '__main__' :
main()
...@@ -15,13 +15,32 @@ ...@@ -15,13 +15,32 @@
## | ## |
## Description Testing of the TDC_IN_FPGA lines of the TDC board. | ## Description Testing of the TDC_IN_FPGA lines of the TDC board. |
## | ## |
## The test uses the Fine Delay as pulse genrator. A 1 ms pulse is sent to each TDC | ## In order to simplify the testing procedure, this test uses the same setup that is |
## channel and is being registered by the dedicated counters in the FPGA. | ## used for the TDC calibration (*). |
## Each FPGA counter is running with 100 MHz clock, therefore around 1K cycles are | ## The Pendulum serves as the pulse generator; it is programmed to send pulses of |
## expected to be counted. | ## 100 ms pulse width, 500 ms period. |
## The channels enable and terminations enable should be functional for the test to | ## The output of the Pendulum is fed to a Timetech Fanout unit, from where we use |
## succeed. | ## two outputs. |
## Note that for this test none of the ACAM logic is used. | ## The USB-interconnection-box is used for the distribution of the two Timetech |
## Fanout outputs to the five TDC input channels. |
## The USB-interconnection-box channel 1 is constantly connected to the |
## TDC-under-test channel 1. The other Timetech Fanout output can be sent to any of |
## the TDC-under-test channels 2, 3, 4, 5, according to the command sent to the box. |
## |
## During the test we send pulses to each one of the TDC channels; inside the FPGA, |
## a dedicated counter per channel is running at 100 MHz (=cycles of 10 ns) and is |
## counting the number of cycles when the corresponding channel is at '1'. |
## For each channel, the Pendulum stays ON for one second; with 100 ms pulse width |
## and 500 ms period, we are expecting two 100 ms pulses to arrive to the FPGA. |
## Therefore, inside the FPGA, a counter is expected to count 20 M cycles. |
## Note however that because of the nature of the USB-interconnection-box, we cannot |
## be sending pulses to all the channels simultaneously, but only to the pairs: |
## (ch 1, ch 2), (ch 1, ch 3), (ch 1, ch 4), (ch 1, ch 5). |
## This means that channel 1 is expected to register 4 times more cycles that the |
## rest of the channels, that is 80 M. |
## Note also that he channels-enable and terminations-enable signals should be |
## functional for the test to succeed. |
## Note finally that for this test none of the ACAM logic is used. |
## | ## |
## The counter for TDC_IN_FPGA_1 can be accessed at PCIe address x00080 | ## The counter for TDC_IN_FPGA_1 can be accessed at PCIe address x00080 |
## The counter for TDC_IN_FPGA_2 can be accessed at PCIe address x00084 | ## The counter for TDC_IN_FPGA_2 can be accessed at PCIe address x00084 |
...@@ -37,6 +56,10 @@ ...@@ -37,6 +56,10 @@
## bit 4: TERM_EN_4 | ## bit 4: TERM_EN_4 |
## bit 5: TERM_EN_5 | ## bit 5: TERM_EN_5 |
## | ## |
## (*) For this test it would have been more straight-forward to use five outputs |
## of the Timetech Fanout unit; however, not to change the setup that is essential |
## for the calibration tests that follow, we are only using two channels and the |
## USB-interconnection-box. |
## | ## |
## FW to load tdc_pts_input_pulse.bit | ## FW to load tdc_pts_input_pulse.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
...@@ -67,36 +90,57 @@ import sys ...@@ -67,36 +90,57 @@ import sys
import time import time
import os import os
import math import math
from numpy import *
from ctypes import *
from datetime import datetime from datetime import datetime
# Add common modules location to path
# Add common modules location tp path sys.path.append('../../../../pts/')
sys.path.append('../../../') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
# Import specific modules
import fmc_tdc import fmc_tdc
sys.path.append('../../../common/fmc_delay/software/python/') from cp210x_eeprom import *
import fdelay_lib from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *
# Pendulum
PENDULUM = "/dev/usbtmc1"
USB_DEVICE = "/dev/ttyUSB0"
RS232_BAUD = 57600
def pendulum_output_on(meas):
meas.write("OUTP:TYPE PULS")
meas.write("SOUR:PULS:PER 0.5")
meas.write("SOUR:PULS:WIDT 0.1")
return (1)
def pendulum_output_off(meas):
meas.write("OUTP:TYPE OFF")
return (1)
# USB-interconnection-box
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_input_pulse.bit' #-----> PCIe address, firmware, loader constants
FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_DELAY_BITSTREAM_PATH = '../firmwares/fmc_delay_spec.bin' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_input_pulse.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FMC_TDC_CHANNEL_NB = 5
#-----> FPGA constants
# Addressing for the retrieval of carrier csr information # Addressing for the retrieval of carrier csr information
CARRIER_CSR = 0x00000 # base address CARRIER_CSR = 0x00000 # base address
CSR_TYPE_VER = 0x00 CSR_TYPE_VER = 0x00
...@@ -117,18 +161,23 @@ def main (default_directory='.'): ...@@ -117,18 +161,23 @@ def main (default_directory='.'):
CHANNEL_5_COUNTER = 0x90 CHANNEL_5_COUNTER = 0x90
CHANNEL_COUNTERS = [0x80, 0x84, 0x88, 0x8C, 0x90] CHANNEL_COUNTERS = [0x80, 0x84, 0x88, 0x8C, 0x90]
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
#-----> TDC
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "------------------------- TDC_IN_FPGA test ------------------------\n" print "------------------------- TDC_IN_FPGA test ------------------------\n"
print ("Test of the TDC_IN_FPGA[5..1] signals. The test is using the Fine Delay\n" print ("Test of the TDC_IN_FPGA[5..1] signals. The test is using the\n"
"board as pulse generator, sending pulses to each one of the TDC channels.\n" "Pendulum as pulse generator as well as the Timetch Fanout and the\n"
"Dedicated counters in the carrier FPGA are counting the duration of the pulses.\n") "USB-interconnection-box for the distribution of the pulses to all\n"
"the TDC input channels.\n"
"Dedicated counters in the carrier FPGA are counting the duration\n"
"of the pulses.\n"
"Note that for this test none of the ACAM logic is used.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems(): for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems():
...@@ -142,19 +191,17 @@ def main (default_directory='.'): ...@@ -142,19 +191,17 @@ def main (default_directory='.'):
print "Loading FMC TDC firmware...", print "Loading FMC TDC firmware...",
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH) firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH) bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream) os.system(firmware_loader + ' ' + bitstream )
time.sleep(1) time.sleep(1)
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH) os.system(firmware_loader + ' ' + bitstream )
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1) time.sleep(1)
print "Firmware loaded!" print "Firmware loaded!"
# Check bitsteam type # Check bitsteam type
bitstream_type = carrier_csr.rd_reg(CSR_BSTM_TYPE) bitstream_type = carrier_csr.rd_reg(CSR_BSTM_TYPE)
print('Bitstream type : 0x%.8X') % bitstream_type print('Bitstream type :%.8X') % bitstream_type
if(bitstream_type == 0xFFFFFFFF): if(bitstream_type == 0xFFFFFFFF):
msg = ("FATAL ERROR: Firmware not properly loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded")
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsCritical (msg)
...@@ -162,9 +209,11 @@ def main (default_directory='.'): ...@@ -162,9 +209,11 @@ def main (default_directory='.'):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded")
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsCritical (msg)
# Carrier Information
print "\n___________________________Carrier info__________________________\n"
print("PCB version : %d") % (PCB_VER_MASK & carrier_csr.rd_reg(CSR_TYPE_VER)) print("PCB version : %d") % (PCB_VER_MASK & carrier_csr.rd_reg(CSR_TYPE_VER))
print("Carrier type : %d") % ((CARRIER_TYPE_MASK & carrier_csr.rd_reg(CSR_TYPE_VER))>>16) print("Carrier type : %d") % ((CARRIER_TYPE_MASK & carrier_csr.rd_reg(CSR_TYPE_VER))>>16)
print("Bitstream type : 0x%.8X") % (carrier_csr.rd_reg(CSR_BSTM_TYPE)) print("Bitstream type : 0x%.8X") % (carrier_csr.rd_reg(CSR_BSTM_TYPE))
...@@ -173,85 +222,75 @@ def main (default_directory='.'): ...@@ -173,85 +222,75 @@ def main (default_directory='.'):
print("Control : 0x%.8X") % (carrier_csr.rd_reg(CSR_CTRL)) print("Control : 0x%.8X") % (carrier_csr.rd_reg(CSR_CTRL))
# Check mezzanine presence flag # Check mezzanine presence flag
print "\n__________________________Presence test__________________________\n"
status = carrier_csr.rd_reg(CSR_STATUS) status = carrier_csr.rd_reg(CSR_STATUS)
if(status & STATUS_FMC_PRES): if(status & STATUS_FMC_PRES):
print('Carrier csr status : 0x%.8X') % status print('Carrier csr status :%.8X') % status
msg = ("FATAL ERROR: Mezzanine appears missing.") msg = ("ERROR: Mezzanine appears missing.")
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsCritical (msg)
else: else:
print("Mezzanine present : OK") print("Mezzanine present OK\n")
#-----> TDC setup
# Enable input logic # Enable input logic
# Channels enable activated # Channels enable activated
# Termination enable of channels 1,2,3,4 activated; # Termination enable of all the channels activated;
# channels 4 and 5 are receiving the same Fine Delay pulse, only ch 4 termination activated carrier_csr.wr_reg(INPUT_EN, 0x3F)
carrier_csr.wr_reg(INPUT_EN, 0x1F)
# Check FPGA counters # Check FPGA counters
counter_error = 0 counter_error = 0
for i in CHANNEL_COUNTERS: for i in CHANNEL_COUNTERS:
if (carrier_csr.rd_reg(i) != 0): if (carrier_csr.rd_reg(i) != 0):
msg = (("ERROR: Unexpected failure of FPGA counter 0x%.2X; received 0x%.8X, expected 0x00000000")%(i, carrier_csr.rd_reg(i))) msg = (("ERROR: Unexpected failure of FPGA counter 0x%.2X; received 0x%.8X, expected 0x00000000")%(i, carrier_csr.rd_reg(i)))
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
counter_error = 1 counter_error = 1
if (counter_error == 0): if (counter_error == 0):
print("Counters init : OK") print("Counters init : OK")
#-----> Fine Delay #-----> Interconnection Box
print "\n___________________________Fine Delay____________________________" # Communication and setup of Interconnection box
print "\nFine Delay initializations.." print "\n_____________________USB interconnection box______________________\n"
# Bind SPEC object to FMC Fine Delay card box_tty = CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
print "Fine Delay address to parse %s"%(FMC_DELAY_ADDR) print("Device: %s" % box_tty[0])
for name, value in spec.parse_addr(FMC_DELAY_ADDR).iteritems(): box = CCalibr_box(box_tty[0])
print "%s:0x%04X"%(name, value) box.select_trigger_loopback(0)
spec.bind(FMC_DELAY_ADDR) box.select_output(4)
#-----> Pendulum
print "\n__________________________USB Pendulum_____________________________\n"
try:
meas = PendulumCNT91(PENDULUM)
except OSError:
raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
a = pendulum_output_off(meas)
# Load FMC Fine Delay firmware
print "\nLoading FMC Fine Delay firmware...",
sys.stdout.flush()
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_DELAY_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1)
print "Firmware loaded!"
# Fine Delay object declaration #-----> Sending pulses to all the channels
try: for i in range(4): # for the 4 pairs of channels (1,2), (1,3), (1,4), (1,5)
fdelay = fdelay_lib.FineDelay(spec.get_fd())
except: otherch = i+1
msg = ("ERROR: Fine Delay board Initiliazation failed") r_edge_timestamps_ch1 = []
os.close(spec.fd) r_edge_timestamps_otherch = []
print (msg) all_measurs = []
raise PtsError (msg)
# USB-interconnection-box
# Set UTC and Coarse time in the Fine Delay box.select_trigger_loopback(0)
fdelay.set_time(0, 0) box.select_output(4-i)
fd_time = fdelay_lib.fd_timestamp()
fd_time = fdelay.get_time()
# Configure the Fine Delay as a pulse generator
enable = 1
t_start_coarse = 0
width = 1000000000 # pulse width 1 ms
delta = 2000000000
count = 1
t_start_utc = fdelay.get_time().utc+1 # starting in 1 sec
fdelay.conf_pulsegen(1, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(2, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(3, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(4, enable, t_start_utc, t_start_coarse, width, delta, count)
print ("\nFine delay sending one pulse per channel of 1ms width..")
#-----> TDC
time.sleep(2)
# Bind SPEC object to FMC TDC card
spec.bind(FMC_TDC_ADDR)
# pendulum output on
a = pendulum_output_on(meas)
# pendulum sending pulses
time.sleep(1.2)
# pendulum output off
a = pendulum_output_off(meas)
#-----> Results
print "\n___________________________Results_______________________________\n" print "\n___________________________Results_______________________________\n"
# string to keep the ERROR messages from all the channels # string to keep the ERROR messages from all the channels
...@@ -263,21 +302,29 @@ def main (default_directory='.'): ...@@ -263,21 +302,29 @@ def main (default_directory='.'):
msg = (("ERROR: TDC_IN_FPGA%d: No pulse arrived ")%(CHANNEL_COUNTERS.index(i)+1)) msg = (("ERROR: TDC_IN_FPGA%d: No pulse arrived ")%(CHANNEL_COUNTERS.index(i)+1))
print (msg) print (msg)
all_msg+=msg all_msg+=msg
elif (carrier_csr.rd_reg(i) > 100500) or (carrier_csr.rd_reg(i) < 95000): # 0.5% acceptance limit
msg = (("ERROR: TDC_IN_FPGA%d: Pulse width %.5f ms is outside accepted limits [1.005 ms .. 0.995 ms] ")%(CHANNEL_COUNTERS.index(i)+1, carrier_csr.rd_reg(i)/1e5)) # channel 1 should have registered 4 times more cycles
elif (((CHANNEL_COUNTERS.index(i)+1)== 1) and ((round(carrier_csr.rd_reg(i)/1e6) > 4* 30) or (round(carrier_csr.rd_reg(i)/1e6) < 4*10))):
msg = (("ERROR: TDC_IN_FPGA%d: Counted %dM cycles; expected 80M")%(CHANNEL_COUNTERS.index(i)+1, round(carrier_csr.rd_reg(i)/1e6)))
print (msg)
all_msg+=msg
# rest of channels
elif (((CHANNEL_COUNTERS.index(i)+1) > 1) and ((round(carrier_csr.rd_reg(i)/1e6) > 30) or (round(carrier_csr.rd_reg(i)/1e6) < 10))): # 0.5% acceptance limit
msg = (("ERROR: TDC_IN_FPGA%d: Counted %dM cycles; expected 20M ")%(CHANNEL_COUNTERS.index(i)+1, round(carrier_csr.rd_reg(i)/1e6)))
print (msg) print (msg)
all_msg+=msg all_msg+=msg
else: else:
print("TDC_IN_FPGA%d: Pulse width %.5f ms OK")%(CHANNEL_COUNTERS.index(i)+1, carrier_csr.rd_reg(i)/1e5) print("TDC_IN_FPGA%d: Counted %dM cycles OK")%(CHANNEL_COUNTERS.index(i)+1, round(carrier_csr.rd_reg(i)/1e6))
if (all_msg != ""): if (all_msg != ""):
os.close(spec.fd)
raise PtsError (all_msg) raise PtsError (all_msg)
os.close(spec.fd) print "\n\n--------------------------------"
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__' : if __name__ == '__main__' :
main() main()
...@@ -13,11 +13,20 @@ ...@@ -13,11 +13,20 @@
## | ## |
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
## | ## |
## Description Testing of the ENABLE_INPUTS signal of the TDC board. | ## Description Testing of the TDC_IN_FPGA lines of the TDC board. |
## | ## |
## The test uses the Fine Delay as pulse genrator. Pulses are sent to all the | ## In order to simplify the testing procedure, this test uses the same setup that is |
## inputs with the enable activated and then deactivated. | ## used for the TDC calibration (*). |
## Through the TDC_IN_FPGA signals we monitor the arrival of the pulses. | ## The Pendulum serves as the pulse generator; it is programmed to send pulses of |
## 100 ms pulse width, 500 ms period. |
## The output of the Pendulum is fed to a Timetech Fanout unit, from where we use |
## two outputs. |
## The USB-interconnection-box is used for the distribution of the two Timetech |
## Fanout outputs to the five TDC input channels. |
## The USB-interconnection-box channel 1 is constantly connected to the |
## TDC-under-test channel 1. The other Timetech Fanout output can be sent to any of |
## the TDC-under-test channels 2, 3, 4, 5, according to the command sent to the box. |
## Pulses are sent to all the inputs with the enable activated and then deactivated. |
## Dedicated counters in the FPGA register the input pulses. | ## Dedicated counters in the FPGA register the input pulses. |
## Note that for this test none of the ACAM logic is used. | ## Note that for this test none of the ACAM logic is used. |
## | ## |
...@@ -26,7 +35,6 @@ ...@@ -26,7 +35,6 @@
## The counter for TDC_IN_FPGA_3 can be accessed at PCIe address x00088 | ## The counter for TDC_IN_FPGA_3 can be accessed at PCIe address x00088 |
## The counter for TDC_IN_FPGA_4 can be accessed at PCIe address x0008C | ## The counter for TDC_IN_FPGA_4 can be accessed at PCIe address x0008C |
## The counter for TDC_IN_FPGA_5 can be accessed at PCIe address x00090 | ## The counter for TDC_IN_FPGA_5 can be accessed at PCIe address x00090 |
## The counters reset can be accessed at PCIe address x00024 |
## | ## |
## The channels and terminations enable can be accessed at PCIe address x000A0: | ## The channels and terminations enable can be accessed at PCIe address x000A0: |
## bit 0: ENABLE_INPUTS | ## bit 0: ENABLE_INPUTS |
...@@ -66,38 +74,57 @@ import sys ...@@ -66,38 +74,57 @@ import sys
import time import time
import os import os
import math import math
from numpy import *
from ctypes import *
from datetime import datetime from datetime import datetime
# Add common modules location to path
# Add common modules location tp path sys.path.append('../../../../pts/')
sys.path.append('../../../') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/common/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/usb_box')
sys.path.append('../../../../pts/common/cp210x')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
import csr import csr
import fmc_tdc
from cp210x_eeprom import *
from PendulumCNT91 import *
from calibr_box import *
from find_usb_tty import *
# Pendulum
PENDULUM = "/dev/usbtmc1"
USB_DEVICE = "/dev/ttyUSB0"
RS232_BAUD = 57600
# Import specific modules def pendulum_output_on(meas):
import fmc_tdc meas.write("OUTP:TYPE PULS")
sys.path.append('../../../common/fmc_delay/software/python/') meas.write("SOUR:PULS:PER 0.5")
import fdelay_lib meas.write("SOUR:PULS:WIDT 0.1")
return (1)
def pendulum_output_off(meas):
meas.write("OUTP:TYPE OFF")
return (1)
# USB-interconnection-box
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
def main (default_directory='.'): def main (default_directory='.'):
# Constants declaration start_test_time = time.time()
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_input_pulse.bit' #-----> PCIe address, firmware, loader constants
FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_DELAY_BITSTREAM_PATH = '../firmwares/fmc_delay_spec.bin' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_input_pulse.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
FMC_TDC_CHANNEL_NB = 5
#-----> FPGA constants
# Addressing for the retrieval of carrier csr information # Addressing for the retrieval of carrier csr information
CARRIER_CSR = 0x00000 # base address CARRIER_CSR = 0x00000 # base address
CSR_TYPE_VER = 0x00 CSR_TYPE_VER = 0x00
...@@ -119,20 +146,24 @@ def main (default_directory='.'): ...@@ -119,20 +146,24 @@ def main (default_directory='.'):
CHANNEL_5_COUNTER = 0x90 CHANNEL_5_COUNTER = 0x90
CHANNEL_COUNTERS = [0x80, 0x84, 0x88, 0x8C, 0x90] CHANNEL_COUNTERS = [0x80, 0x84, 0x88, 0x8C, 0x90]
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
#-----> TDC
# Bind SPEC object to FMC TDC card # Bind SPEC object to FMC TDC card
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- FMC TDC -----------------------------" print "----------------------------- FMC TDC -----------------------------"
print "--------------------- TDC_IN_FPGA disable test --------------------\n" print "--------------------- TDC_IN_FPGA disable test --------------------\n"
print ("Test of the EN_INPUTS signal. The test is using the Fine Delay board\n" print ("Test of the EN_INPUTS signal. The test is using the Pendulum\n"
"as pulse generator, sending pulses to each one of the TDC channels.\n" "as pulse generator as well as the Timetch Fanout and the\n"
"Dedicated counters in the carrier FPGA are counting the duration of the pulses.\n" "USB-interconnection-box for the distribution of the pulses to\n"
"When the EN_INPUTS is active, pulses should be arriving to all the channels;\n" "all the TDC input channels.\n"
"when the EN_INPUTS is disabled no pulse should arrive.\n") "Dedicated counters in the carrier FPGA are counting the duration\n"
"of the pulses. When the EN_INPUTS is active, pulses should be\n"
"arriving to all the channels; when the EN_INPUTS is disabled no\n"
"pulse should arrive.\n"
"Note that for this test none of the ACAM logic is used.\n")
print "\n_______________________________Info______________________________\n" print "\n_______________________________Info______________________________\n"
print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR) print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
...@@ -147,18 +178,17 @@ def main (default_directory='.'): ...@@ -147,18 +178,17 @@ def main (default_directory='.'):
print "Loading FMC TDC firmware...", print "Loading FMC TDC firmware...",
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH) firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH) bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream) os.system(firmware_loader + ' ' + bitstream )
time.sleep(1) time.sleep(1)
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH) os.system(firmware_loader + ' ' + bitstream )
bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1) time.sleep(1)
print "Firmware loaded!" print "Firmware loaded!"
# Check bitsteam type # Check bitsteam type
bitstream_type = carrier_csr.rd_reg(CSR_BSTM_TYPE) bitstream_type = carrier_csr.rd_reg(CSR_BSTM_TYPE)
print('Bitstream type :%.8X') % bitstream_type
if(bitstream_type == 0xFFFFFFFF): if(bitstream_type == 0xFFFFFFFF):
msg = ("FATAL ERROR: Firmware not properly loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded")
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsCritical (msg)
...@@ -166,8 +196,10 @@ def main (default_directory='.'): ...@@ -166,8 +196,10 @@ def main (default_directory='.'):
msg = ("FATAL ERROR: Wrong bitstream type loaded") msg = ("FATAL ERROR: Wrong bitstream type loaded")
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsCritical (msg)
# Carrier Information
print "\n___________________________Carrier info__________________________\n"
print("PCB version : %d") % (PCB_VER_MASK & carrier_csr.rd_reg(CSR_TYPE_VER)) print("PCB version : %d") % (PCB_VER_MASK & carrier_csr.rd_reg(CSR_TYPE_VER))
print("Carrier type : %d") % ((CARRIER_TYPE_MASK & carrier_csr.rd_reg(CSR_TYPE_VER))>>16) print("Carrier type : %d") % ((CARRIER_TYPE_MASK & carrier_csr.rd_reg(CSR_TYPE_VER))>>16)
print("Bitstream type : 0x%.8X") % (carrier_csr.rd_reg(CSR_BSTM_TYPE)) print("Bitstream type : 0x%.8X") % (carrier_csr.rd_reg(CSR_BSTM_TYPE))
...@@ -175,82 +207,71 @@ def main (default_directory='.'): ...@@ -175,82 +207,71 @@ def main (default_directory='.'):
print("Status : 0x%.8X") % (carrier_csr.rd_reg(CSR_STATUS)) print("Status : 0x%.8X") % (carrier_csr.rd_reg(CSR_STATUS))
print("Control : 0x%.8X") % (carrier_csr.rd_reg(CSR_CTRL)) print("Control : 0x%.8X") % (carrier_csr.rd_reg(CSR_CTRL))
# Check mezzanine presence flag
print "\n__________________________Presence test__________________________\n"
status = carrier_csr.rd_reg(CSR_STATUS) status = carrier_csr.rd_reg(CSR_STATUS)
if(status & STATUS_FMC_PRES): if(status & STATUS_FMC_PRES):
msg = ('FATAL ERROR: Mezzanine appears missing.') print('Carrier csr status :%.8X') % status
msg = ("ERROR: Mezzanine appears missing.")
os.close(spec.fd) os.close(spec.fd)
print (msg) print (msg)
raise PtsCritical (msg) raise PtsCritical (msg)
else: else:
print("Mezzanine present : OK") print("Mezzanine present OK\n")
#-----> ############## Input logic Disabled ##############
carrier_csr.wr_reg(INPUT_EN, 0x00)
# Check FPGA counters # Check FPGA counters
counter_error = 0 counter_error = 0
for i in CHANNEL_COUNTERS: for i in CHANNEL_COUNTERS:
if (carrier_csr.rd_reg(i) != 0): if (carrier_csr.rd_reg(i) != 0):
msg = (("ERROR: Unexpected failure of FPGA counter 0x%.2X; received 0x%.8X, expected 0x00000000")%(i, carrier_csr.rd_reg(i))) msg = (("ERROR: Unexpected failure of FPGA counter 0x%.2X; received 0x%.8X, expected 0x00000000")%(i, carrier_csr.rd_reg(i)))
os.close(spec.fd)
print (msg) print (msg)
raise PtsError (msg) raise PtsError (msg)
counter_error = 1 counter_error = 1
if (counter_error == 0): if (counter_error == 0):
print("Counters init : OK") print("Counters init : OK")
#-----> Interconnection Box
# Communication and setup of Interconnection box
print "\n_____________________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)
box.select_output(4)
#-----> Pendulum
# Communication with Pendulum
print "\n__________________________USB Pendulum_____________________________\n"
try:
meas = PendulumCNT91(PENDULUM)
except OSError:
raise PtsError('CNT-91 is not switched on or badly connected, aborting.')
a = pendulum_output_off(meas)
################################## Input logic Disabled ################################## #-----> Sending pulses
carrier_csr.wr_reg(INPUT_EN, 0x00) for i in range(4): # for the 4 pairs of channels (1,2), (1,3), (1,4), (1,5)
otherch = i+1
r_edge_timestamps_ch1 = []
r_edge_timestamps_otherch = []
all_measurs = []
#-----> Fine Delay # USB-interconnection-box
print "\n___________________________Fine Delay____________________________" box.select_trigger_loopback(0)
print "\nFine Delay initializations.." box.select_output(4-i)
# Bind SPEC object to FMC Fine Delay card
print "Fine Delay address to parse %s"%(FMC_DELAY_ADDR)
for name, value in spec.parse_addr(FMC_DELAY_ADDR).iteritems():
print "%s:0x%04X"%(name, value)
spec.bind(FMC_DELAY_ADDR)
# Load FMC Fine Delay firmware # pendulum output on
print "\nLoading FMC Fine Delay firmware...", a = pendulum_output_on(meas)
sys.stdout.flush()
firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH) # pendulum sending pulses
bitstream = os.path.join(default_directory, FMC_DELAY_BITSTREAM_PATH) time.sleep(1.2)
os.system(firmware_loader + ' ' + bitstream)
time.sleep(1) # pendulum output off
print "Firmware loaded!" a = pendulum_output_off(meas)
# Fine Delay object declaration
try:
fdelay = fdelay_lib.FineDelay(spec.get_fd())
except:
msg = ("ERROR: Fine Delay board Initiliazation failed")
os.close(spec.fd)
print (msg)
raise PtsError (msg)
# Set UTC and Coarse time in the Fine Delay
fdelay.set_time(0, 0)
fd_time = fdelay_lib.fd_timestamp()
fd_time = fdelay.get_time()
# Configure the Fine Delay as a pulse generator
enable = 1
t_start_coarse = 0
width = 1000000000 # pulse width 1 ms
delta = 2000000000
count = 1
t_start_utc = fdelay.get_time().utc+1 # starting in 1 sec
fdelay.conf_pulsegen(1, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(2, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(3, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(4, enable, t_start_utc, t_start_coarse, width, delta, count)
print ("\nFine delay sending one pulse per channel of 1ms width..")
#-----> TDC
time.sleep(2)
# Bind SPEC object to FMC TDC card
spec.bind(FMC_TDC_ADDR)
# string to keep the ERROR messages from all the channels # string to keep the ERROR messages from all the channels
all_msg = "" all_msg = ""
...@@ -260,39 +281,46 @@ def main (default_directory='.'): ...@@ -260,39 +281,46 @@ def main (default_directory='.'):
# Read counters # Read counters
for i in CHANNEL_COUNTERS: for i in CHANNEL_COUNTERS:
if (carrier_csr.rd_reg(i) != 0): if (carrier_csr.rd_reg(i) != 0):
msg = (("ERROR: ENABLE_INPUTS disabled: TDC_IN_FPGA%d failure; pulse of %.5f ms arrived ")%(CHANNEL_COUNTERS.index(i)+1,carrier_csr.rd_reg(i)/1e5)) msg = (("ERROR: ENABLE_INPUTS disabled: TDC_IN_FPGA%d failure; Counted %dM cycles")%(CHANNEL_COUNTERS.index(i)+1,round(carrier_csr.rd_reg(i)/1e6)))
print (msg) print (msg)
all_msg+=msg all_msg+=msg
else: else:
print("ENABLE_INPUTS disabled: TDC_IN_FPGA%d OK") %(CHANNEL_COUNTERS.index(i)+1) print("ENABLE_INPUTS disabled: TDC_IN_FPGA%d OK") %(CHANNEL_COUNTERS.index(i)+1)
################################## Input logic Enabled ################################## #-----> ############## Input logic Enabled ##############
carrier_csr.wr_reg(INPUT_EN, 0x1F) carrier_csr.wr_reg(INPUT_EN, 0x1F)
carrier_csr.wr_reg(RST_COUNTERS,0x1) carrier_csr.wr_reg(RST_COUNTERS,0x1)
time.sleep(0.1) time.sleep(0.1)
carrier_csr.wr_reg(RST_COUNTERS,0x0) carrier_csr.wr_reg(RST_COUNTERS,0x0)
#-----> Sending pulses
for i in range(4): # for the 4 pairs of channels (1,2), (1,3), (1,4), (1,5)
#-----> Fine Delay otherch = i+1
spec.bind(FMC_DELAY_ADDR) r_edge_timestamps_ch1 = []
t_start_utc = fdelay.get_time().utc+1 # starting in 1 sec r_edge_timestamps_otherch = []
fdelay.conf_pulsegen(1, enable, t_start_utc, t_start_coarse, width, delta, count) all_measurs = []
fdelay.conf_pulsegen(2, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(3, enable, t_start_utc, t_start_coarse, width, delta, count)
fdelay.conf_pulsegen(4, enable, t_start_utc, t_start_coarse, width, delta, count)
#-----> TDC # USB-interconnection-box
time.sleep(2) box.select_trigger_loopback(0)
# Bind SPEC object to FMC TDC card box.select_output(4-i)
spec.bind(FMC_TDC_ADDR)
# pendulum output on
a = pendulum_output_on(meas)
# pendulum sending pulses
time.sleep(1.2)
# pendulum output off
a = pendulum_output_off(meas)
print "\n______________________Input logic Enabled________________________\n" print "\n______________________Input logic Enabled________________________\n"
# Read counters # Read counters
for i in CHANNEL_COUNTERS: for i in CHANNEL_COUNTERS:
if (carrier_csr.rd_reg(i) != 0): if (carrier_csr.rd_reg(i) != 0):
print("ENABLE_INPUTS enabled: TDC_IN_FPGA%d OK")%(CHANNEL_COUNTERS.index(i)+1) print("ENABLE_INPUTS enabled: TDC_IN_FPGA%d OK! Counted %dM cycles ")%(CHANNEL_COUNTERS.index(i)+1,round(carrier_csr.rd_reg(i)/1e6))
else: else:
msg = (("ERROR: ENABLE_INPUTS enabled: TDC_IN_FPGA%d: No pulse arrived ")%(CHANNEL_COUNTERS.index(i)+1)) msg = (("ERROR: ENABLE_INPUTS enabled: TDC_IN_FPGA%d: No pulse arrived ")%(CHANNEL_COUNTERS.index(i)+1))
print (msg) print (msg)
...@@ -302,8 +330,10 @@ def main (default_directory='.'): ...@@ -302,8 +330,10 @@ def main (default_directory='.'):
os.close(spec.fd) os.close(spec.fd)
raise PtsError (all_msg) raise PtsError (all_msg)
os.close(spec.fd)
print "\n\n-----------------------------------------------------------------" 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__' : if __name__ == '__main__' :
main() main()
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
## if all the LEDs are blinking as expected. | ## if all the LEDs are blinking as expected. |
## | ## |
## | ## |
## FW to load .bin | ## FW to load tdc_pts_leds.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -49,11 +49,13 @@ ...@@ -49,11 +49,13 @@
import sys import sys
import time import time
import os import os
import math
from datetime import datetime
# Add common modules location tp path # Add common modules location tp path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
...@@ -61,24 +63,27 @@ import rr ...@@ -61,24 +63,27 @@ import rr
import csr import csr
def main (default_directory='.'): def main (default_directory='.'):
start_test_time = time.time()
# Constants declaration # Constants declaration
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_leds.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_pts_leds.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
print "\n-------------------------------------------------------------------" print "\n-------------------------------------------------------------------"
print "----------------------------- TDC PTS -----------------------------" print "----------------------------- TDC PTS -----------------------------"
print "---------------------------- LEDs test ----------------------------\n" print "---------------------------- LEDs test ----------------------------\n"
print ("Test of the front panel LEDs. For this test the operator’s intervention\n" print ("Test of the front panel LEDs. For this test the operator’s\n"
"is needed; when prompted, the operator should visually inspect the LEDs.\n") "intervention is needed; when prompted, the operator should visually\n"
"inspect the LEDs.\n")
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
print "\n_________________________Initialisations_________________________\n" print "\n_________________________Initialisations_________________________\n"
# Load FMC TDC firmware # Load FMC TDC firmware
print "Loading FMC TDC firmware...", print "Loading FMC TDC firmware...",
...@@ -89,6 +94,7 @@ def main (default_directory='.'): ...@@ -89,6 +94,7 @@ def main (default_directory='.'):
print "Firmware loaded!" print "Firmware loaded!"
#-----> LEDs inspection
print "\n_________________________LEDs inspection_________________________\n" print "\n_________________________LEDs inspection_________________________\n"
# Standard in/out temporary redirection # Standard in/out temporary redirection
...@@ -112,8 +118,10 @@ def main (default_directory='.'): ...@@ -112,8 +118,10 @@ def main (default_directory='.'):
else: else:
print ("LEDs inspected OK!") print ("LEDs inspected OK!")
os.close(spec.fd)
print "\n\n-----------------------------------------------------------------" 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__' : if __name__ == '__main__' :
......
#! /bin/bash
ln -s fmc_presence.py test00.py
ln -s clocks.py test01.py
ln -s fpga_inputs.py test02.py
ln -s fpga_inputs_disable.py test03.py
ln -s onewire_test.py test04.py
ln -s eeprom.py test05.py
ln -s acam.py test06.py
ln -s acam_accuracy.py test07.py
ln -s acam_inputs_disable.py test08.py
ln -s acam_startdis_stopdis.py test09.py
ln -s acam_errflag.py test10.py
ln -s dac.py test11.py
ln -s leds.py test12.py
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
## The test reads the unique ID and the temperature and checks if the received | ## The test reads the unique ID and the temperature and checks if the received |
## values are within reasonable limits. | ## values are within reasonable limits. |
## | ## |
## FW to load .bin | ## FW to load tdc_allothertests.bit |
## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) | ## Authors Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
## Website http://www.ohwr.org/projects/pts | ## Website http://www.ohwr.org/projects/pts |
## Date 11/01/2013 | ## Date 11/01/2013 |
...@@ -52,16 +52,14 @@ import sys ...@@ -52,16 +52,14 @@ import sys
import time import time
import os import os
# Add common modules location tp path # Add common modules location to path
sys.path.append('../../../') sys.path.append('../../../../pts/')
sys.path.append('../../../gnurabbit/python/') sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../common/') sys.path.append('../../../../pts/common/')
# Import common modules # Import common modules
from ptsexcept import * from ptsexcept import *
import rr import rr
# Import specific modules
import fmc_tdc import fmc_tdc
...@@ -70,13 +68,20 @@ import fmc_tdc ...@@ -70,13 +68,20 @@ import fmc_tdc
##------------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------------
def main (default_directory='.'): def main (default_directory='.'):
start_test_time = time.time()
#-----> PCIe address, firmware, loader constants
# Constants declaration # Constants declaration
FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000' FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit' FMC_TDC_BITSTREAM_PATH = '../firmwares/tdc_allothertests.bit'
FPGA_LOADER_PATH = '../../../gnurabbit/user/fpga_loader' FPGA_LOADER_PATH = '../../../../pts/gnurabbit/user/fpga_loader'
#-----> One Wire chip constant
FAMILY_CODE = 0x28 FAMILY_CODE = 0x28
#-----> FPGA initializations
# SPEC object declaration # SPEC object declaration
spec = rr.Gennum() spec = rr.Gennum()
...@@ -125,6 +130,7 @@ def main (default_directory='.'): ...@@ -125,6 +130,7 @@ def main (default_directory='.'):
print('Access to TDC core OK') print('Access to TDC core OK')
#-----> Accessing the One Wire chip
# Read unique ID and print to log # Read unique ID and print to log
print "\n____________________________Unique ID____________________________\n" print "\n____________________________Unique ID____________________________\n"
try: try:
...@@ -162,8 +168,10 @@ def main (default_directory='.'): ...@@ -162,8 +168,10 @@ def main (default_directory='.'):
else: else:
print('TEMPID IC14: Temperature: %3.2f°C OK') % temp print('TEMPID IC14: Temperature: %3.2f°C OK') % temp
os.close(spec.fd)
print "\n\n-----------------------------------------------------------------" 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__' : if __name__ == '__main__' :
main() main()
#! /bin/bash
rm -f test00.py
rm -f test01.py
rm -f test02.py
rm -f test03.py
rm -f test04.py
rm -f test05.py
rm -f test06.py
rm -f test07.py
rm -f test08.py
rm -f test09.py
rm -f test10.py
rm -f test11.py
rm -f test12.py
rm -f test*.pyc
rm -f test*.py~
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment