From 1ed6c0ee1404b42554f9db664290d3c5019e559e Mon Sep 17 00:00:00 2001 From: David Cussans <David.Cussans@bristol.ac.uk> Date: Fri, 4 May 2018 10:23:07 +0100 Subject: [PATCH] Sorting out scripts --- .../tlu/firmware/hdl/IPBusInterface_rtl.vhd | 261 ----- components/tlu/firmware/hdl/ipbus_ver.vhd | 46 - projects/TLU_v1e/addr_table/TLUaddrmap.xml | 14 +- projects/TLU_v1e/scripts/AD5665R.py | 1 + projects/TLU_v1e/scripts/AIDA_testScript.py | 185 ++++ projects/TLU_v1e/scripts/AIDA_testShutter.py | 141 +++ projects/TLU_v1e/scripts/E24AA025E48T.py | 1 + projects/TLU_v1e/scripts/I2CuHal.py | 1 + projects/TLU_v1e/scripts/PCA9539PW.py | 1 + projects/TLU_v1e/{software => scripts}/README | 0 projects/TLU_v1e/{software => scripts}/SI5344 | 0 projects/TLU_v1e/scripts/TLU_v1e.py | 975 ++++++++++++++++++ projects/TLU_v1e/scripts/TLUaddrmap.xml | 1 + projects/TLU_v1e/scripts/TLUaddrmap.xml.old | 105 ++ projects/TLU_v1e/scripts/TLUconnection.xml | 6 + projects/TLU_v1e/scripts/initTLU.py | 184 ++++ projects/TLU_v1e/scripts/localClock.txt | 394 +++++++ projects/TLU_v1e/scripts/localConf.conf | 90 ++ projects/TLU_v1e/scripts/localIni.ini | 43 + projects/TLU_v1e/scripts/packages/AD5665R.py | 45 + .../TLU_v1e/scripts/packages/E24AA025E48T.py | 20 + .../TLU_v1e/scripts/packages/FmcTluI2c.py | 132 +++ projects/TLU_v1e/scripts/packages/I2CuHal.py | 281 +++++ .../scripts/packages/I2cBusProperties.py | 122 +++ .../TLU_v1e/scripts/packages/PCA9539PW.py | 94 ++ .../TLU_v1e/scripts/packages/RawI2cAccess.py | 261 +++++ .../scripts/packages/TLU_v1e/output.csv | 0 .../scripts/packages/TLUaddrmap_BKP.xml | 105 ++ .../scripts/packages/TLUconnection_BKP.xml | 6 + projects/TLU_v1e/scripts/packages/si5345.py | 140 +++ projects/TLU_v1e/scripts/si5345.py | 1 + projects/TLU_v1e/scripts/startTLU_v1e.py | 235 +++++ projects/TLU_v1e/scripts/startTLU_v1e.sh | 25 + projects/TLU_v1e/scripts/startTLU_v6.py | 232 +++++ projects/TLU_v1e/scripts/test.py | 34 + projects/TLU_v1e/scripts/testTLU_script.py | 79 ++ projects/TLU_v1e/scripts/test_T0.py | 92 ++ projects/TLU_v1e/software/I2CuHal.py | 1 - projects/TLU_v1e/software/board_setup.py | 1 - projects/TLU_v1e/software/check.py | 39 - projects/TLU_v1e/software/connections.xml | 10 - projects/TLU_v1e/software/si5344.py | 1 - projects/TLU_v1e/software/status.py | 18 - 43 files changed, 4039 insertions(+), 384 deletions(-) delete mode 100644 components/tlu/firmware/hdl/IPBusInterface_rtl.vhd delete mode 100644 components/tlu/firmware/hdl/ipbus_ver.vhd create mode 120000 projects/TLU_v1e/scripts/AD5665R.py create mode 100644 projects/TLU_v1e/scripts/AIDA_testScript.py create mode 100644 projects/TLU_v1e/scripts/AIDA_testShutter.py create mode 120000 projects/TLU_v1e/scripts/E24AA025E48T.py create mode 120000 projects/TLU_v1e/scripts/I2CuHal.py create mode 120000 projects/TLU_v1e/scripts/PCA9539PW.py rename projects/TLU_v1e/{software => scripts}/README (100%) rename projects/TLU_v1e/{software => scripts}/SI5344 (100%) create mode 100644 projects/TLU_v1e/scripts/TLU_v1e.py create mode 120000 projects/TLU_v1e/scripts/TLUaddrmap.xml create mode 100644 projects/TLU_v1e/scripts/TLUaddrmap.xml.old create mode 100644 projects/TLU_v1e/scripts/TLUconnection.xml create mode 100644 projects/TLU_v1e/scripts/initTLU.py create mode 100644 projects/TLU_v1e/scripts/localClock.txt create mode 100644 projects/TLU_v1e/scripts/localConf.conf create mode 100644 projects/TLU_v1e/scripts/localIni.ini create mode 100644 projects/TLU_v1e/scripts/packages/AD5665R.py create mode 100644 projects/TLU_v1e/scripts/packages/E24AA025E48T.py create mode 100644 projects/TLU_v1e/scripts/packages/FmcTluI2c.py create mode 100644 projects/TLU_v1e/scripts/packages/I2CuHal.py create mode 100644 projects/TLU_v1e/scripts/packages/I2cBusProperties.py create mode 100644 projects/TLU_v1e/scripts/packages/PCA9539PW.py create mode 100644 projects/TLU_v1e/scripts/packages/RawI2cAccess.py create mode 100644 projects/TLU_v1e/scripts/packages/TLU_v1e/output.csv create mode 100644 projects/TLU_v1e/scripts/packages/TLUaddrmap_BKP.xml create mode 100644 projects/TLU_v1e/scripts/packages/TLUconnection_BKP.xml create mode 100644 projects/TLU_v1e/scripts/packages/si5345.py create mode 120000 projects/TLU_v1e/scripts/si5345.py create mode 100644 projects/TLU_v1e/scripts/startTLU_v1e.py create mode 100644 projects/TLU_v1e/scripts/startTLU_v1e.sh create mode 100644 projects/TLU_v1e/scripts/startTLU_v6.py create mode 100644 projects/TLU_v1e/scripts/test.py create mode 100644 projects/TLU_v1e/scripts/testTLU_script.py create mode 100644 projects/TLU_v1e/scripts/test_T0.py delete mode 120000 projects/TLU_v1e/software/I2CuHal.py delete mode 120000 projects/TLU_v1e/software/board_setup.py delete mode 100755 projects/TLU_v1e/software/check.py delete mode 100644 projects/TLU_v1e/software/connections.xml delete mode 120000 projects/TLU_v1e/software/si5344.py delete mode 100755 projects/TLU_v1e/software/status.py diff --git a/components/tlu/firmware/hdl/IPBusInterface_rtl.vhd b/components/tlu/firmware/hdl/IPBusInterface_rtl.vhd deleted file mode 100644 index aa9bd6de..00000000 --- a/components/tlu/firmware/hdl/IPBusInterface_rtl.vhd +++ /dev/null @@ -1,261 +0,0 @@ ---============================================================================= ---! @file IPBusInterface_rtl.vhd ---============================================================================= --- -------------------------------------------------------------------------------- --- -- --- University of Bristol, High Energy Physics Group. --- -- -------------------------------------------------------------------------------- -- --- VHDL Architecture fmc_mTLU_lib.IPBusInterface.rtl --- --- --- Created using using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21) --- -LIBRARY ieee; -USE ieee.std_logic_1164.all; -USE ieee.numeric_std.all; - -USE work.ipbus.all; - ---! @brief IPBus interface between 1GBit/s Ethernet and IPBus internal bus --- ---! @author David Cussans , David.Cussans@bristol.ac.uk --- ---! @date 16:06:57 11/09/12 --- ---! @version v0.1 --- ---! @details ---! ---! <b>Modified by:</b>\n ---! Author: -------------------------------------------------------------------------------- ---! \n\n<b>Last changes:</b>\n -------------------------------------------------------------------------------- -ENTITY IPBusInterface IS - GENERIC( - NUM_EXT_SLAVES : positive := 5; - BUILD_SIMULATED_ETHERNET : integer := 0 --! Set to 1 to build simulated Ethernet interface using Modelsim FLI - ); - PORT( - gmii_rx_clk_i : IN std_logic; - gmii_rx_dv_i : IN std_logic; - gmii_rx_er_i : IN std_logic; - gmii_rxd_i : IN std_logic_vector (7 DOWNTO 0); - ipbr_i : IN ipb_rbus_array (NUM_EXT_SLAVES-1 DOWNTO 0); --! IPBus read signals - sysclk_n_i : IN std_logic; - sysclk_p_i : IN std_logic; --! 200 MHz xtal clock - clocks_locked_o : OUT std_logic; - gmii_gtx_clk_o : OUT std_logic; - gmii_tx_en_o : OUT std_logic; - gmii_tx_er_o : OUT std_logic; - gmii_txd_o : OUT std_logic_vector (7 DOWNTO 0); - ipb_clk_o : OUT std_logic; --! IPBus clock to slaves - ipb_rst_o : OUT std_logic; --! IPBus reset to slaves - ipbw_o : OUT ipb_wbus_array (NUM_EXT_SLAVES-1 DOWNTO 0); --! IBus write signals - onehz_o : OUT std_logic; - phy_rstb_o : OUT std_logic; - dip_switch_i : IN std_logic_vector (3 DOWNTO 0); --! Used to select IP address - clk_logic_xtal_o : OUT std_logic --! 40MHz clock that can be used for logic if not using external clock - ); - --- Declarations - -END ENTITY IPBusInterface ; - --- -ARCHITECTURE rtl OF IPBusInterface IS - - --! Number of slaves inside the IPBusInterface block. - constant c_NUM_INTERNAL_SLAVES : positive := 1; - - signal clk125, rst_125, rst_ipb: STD_LOGIC; - signal mac_txd, mac_rxd : STD_LOGIC_VECTOR(7 downto 0); - signal mac_txdvld, mac_txack, mac_rxclko, mac_rxdvld, mac_rxgoodframe, mac_rxbadframe : STD_LOGIC; - signal ipb_master_out : ipb_wbus; - signal ipb_master_in : ipb_rbus; - signal mac_addr: std_logic_vector(47 downto 0); - signal mac_tx_data, mac_rx_data: std_logic_vector(7 downto 0); - signal mac_tx_valid, mac_tx_last, mac_tx_error, mac_tx_ready, mac_rx_valid, mac_rx_last, mac_rx_error: std_logic; - - signal ip_addr: std_logic_vector(31 downto 0); - signal s_ipb_clk : std_logic; - signal s_ipbw_internal: ipb_wbus_array (NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1 DOWNTO 0); - signal s_ipbr_internal: ipb_rbus_array (NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1 DOWNTO 0); - signal s_sysclk : std_logic; - signal pkt_rx, pkt_tx, pkt_rx_led, pkt_tx_led, sys_rst: std_logic; - -BEGIN - - -- Connect IPBus clock and reset to output ports. - ipb_clk_o <= s_ipb_clk; - ipb_rst_o <= rst_ipb; - - --! By default generate a physical MAC - generate_physicalmac: if ( BUILD_SIMULATED_ETHERNET /= 1 ) generate - --- DCM clock generation for internal bus, ethernet --- clocks: entity work.clocks_s6_extphy port map( --- sysclk_p => sysclk_p_i, --- sysclk_n => sysclk_n_i, --- clk_logic_xtal_o => clk_logic_xtal_o, --- clko_125 => clk125, --- clko_ipb => s_ipb_clk, --- locked => clocks_locked_o, --- rsto_125 => rst_125, --- rsto_ipb => rst_ipb, --- onehz => onehz_o --- ); - - clocks: entity work.clocks_7s_extphy_Se port map( - sysclk_p => sysclk_p_i, - sysclk_n => sysclk_n_i, - clk_logic_xtal_o => clk_logic_xtal_o, - clko_125 => clk125, - clko_ipb => s_ipb_clk, - locked => clocks_locked_o, - rsto_125 => rst_125, - rsto_ipb => rst_ipb, - onehz => onehz_o - ); - - -- leds <= ('0', '0', locked, onehz); - --- Ethernet MAC core and PHY interface --- In this version, consists of hard MAC core and GMII interface to external PHY --- Can be replaced by any other MAC / PHY combination - --- eth: entity work.eth_s6_gmii port map( --- clk125 => clk125, --- rst => rst_125, --- gmii_gtx_clk => gmii_gtx_clk_o, --- gmii_tx_en => gmii_tx_en_o, --- gmii_tx_er => gmii_tx_er_o, --- gmii_txd => gmii_txd_o, --- gmii_rx_clk => gmii_rx_clk_i, --- gmii_rx_dv => gmii_rx_dv_i, --- gmii_rx_er => gmii_rx_er_i, --- gmii_rxd => gmii_rxd_i, --- tx_data => mac_tx_data, --- tx_valid => mac_tx_valid, --- tx_last => mac_tx_last, --- tx_error => mac_tx_error, --- tx_ready => mac_tx_ready, --- rx_data => mac_rx_data, --- rx_valid => mac_rx_valid, --- rx_last => mac_rx_last, --- rx_error => mac_rx_error --- ); - - eth: entity work.eth_7s_rgmii port map( - clk125 => clk125, - rst => rst_125, - tx_data => mac_tx_data, - tx_valid => mac_tx_valid, - tx_last => mac_tx_last, - tx_error => mac_tx_error, - tx_ready => mac_tx_ready, - rx_data => mac_rx_data, - rx_valid => mac_rx_valid, - rx_last => mac_rx_last, - rx_error => mac_rx_error, - gmii_gtx_clk => gmii_gtx_clk_o, - gmii_tx_en => gmii_tx_en_o, - gmii_tx_er => gmii_tx_er_o, - gmii_txd => gmii_txd_o, - gmii_rx_clk => gmii_rx_clk_i, - gmii_rx_dv => gmii_rx_dv_i, - gmii_rx_er => gmii_rx_er_i, - gmii_rxd => gmii_rxd_i - ); - - end generate generate_physicalmac; - - --! Set generic BUILD_SIMULATED_ETHERNET to 1 to generate a simulated MAC - generate_simulatedmac: if ( BUILD_SIMULATED_ETHERNET = 1 ) generate - - sim_clocks: entity work.clock_sim - port map ( - clko125 => clk125, - clko25 => s_ipb_clk, - clko40 => clk_logic_xtal_o, - nuke => '0', - rsto => rst_125 - ); - rst_ipb <= rst_125; - clocks_locked_o <= '1'; - - -- clk125 <= sysclk_i; -- *must* run this simulation with 125MHz sysclk... - simulated_eth: entity work.eth_mac_sim - port map( - clk => clk125, - rst => rst_125, - tx_data => mac_tx_data, - tx_valid => mac_tx_valid, - tx_last => mac_tx_last, - tx_error => mac_tx_error, - tx_ready => mac_tx_ready, - rx_data => mac_rx_data, - rx_valid => mac_rx_valid, - rx_last => mac_rx_last, - rx_error => mac_rx_error - ); - end generate generate_simulatedmac; - - phy_rstb_o <= '1'; - --- ipbus control logic - ipbus: entity work.ipbus_ctrl - generic map ( - BUFWIDTH => 2) - port map( - mac_clk => clk125, - rst_macclk => rst_125, - ipb_clk => s_ipb_clk, - rst_ipb => rst_ipb, - mac_rx_data => mac_rx_data, - mac_rx_valid => mac_rx_valid, - mac_rx_last => mac_rx_last, - mac_rx_error => mac_rx_error, - mac_tx_data => mac_tx_data, - mac_tx_valid => mac_tx_valid, - mac_tx_last => mac_tx_last, - mac_tx_error => mac_tx_error, - mac_tx_ready => mac_tx_ready, - ipb_out => ipb_master_out, - ipb_in => ipb_master_in, - mac_addr => mac_addr, - ip_addr => ip_addr, - pkt_rx => pkt_rx, - pkt_tx => pkt_tx, - pkt_rx_led => pkt_rx_led, - pkt_tx_led => pkt_tx_led - ); - - - mac_addr <= X"020ddba115" & dip_switch_i & X"0"; -- Careful here, arbitrary addresses do not always work - ip_addr <= X"c0a8c8" & dip_switch_i & X"0"; -- 192.168.200.X - - fabric: entity work.ipbus_fabric - generic map(NSLV => NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES) - port map( - ipb_in => ipb_master_out, - ipb_out => ipb_master_in, - ipb_to_slaves => s_ipbw_internal, - ipb_from_slaves => s_ipbr_internal - ); - - ipbw_o <= s_ipbw_internal(NUM_EXT_SLAVES-1 downto 0); - - s_ipbr_internal(NUM_EXT_SLAVES-1 downto 0) <= ipbr_i; - - -- Slave: firmware ID - firmware_id: entity work.ipbus_ver - port map( - ipbus_in => s_ipbw_internal(NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1), - ipbus_out => s_ipbr_internal(NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1) - ); - -END ARCHITECTURE rtl; - diff --git a/components/tlu/firmware/hdl/ipbus_ver.vhd b/components/tlu/firmware/hdl/ipbus_ver.vhd deleted file mode 100644 index 068f126f..00000000 --- a/components/tlu/firmware/hdl/ipbus_ver.vhd +++ /dev/null @@ -1,46 +0,0 @@ ---============================================================================= ---! @file ipbus_ver.vhd ---============================================================================= - --- Version register, returns a fixed value --- --- To be replaced by a more coherent versioning mechanism later --- --- Dave Newbold, August 2011 - -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use work.ipbus.all; - ---! @brief IPBus fixed register returning Firmware version number -entity ipbus_ver is - port( - ipbus_in: in ipb_wbus; - ipbus_out: out ipb_rbus - ); - -end ipbus_ver; - -architecture rtl of ipbus_ver is - -begin - - ipbus_out.ipb_rdata <= X"a622" & X"1008"; -- Lower 16b are ipbus firmware build ID (temporary arrangement). - ipbus_out.ipb_ack <= ipbus_in.ipb_strobe; - ipbus_out.ipb_err <= '0'; - -end rtl; - --- Build log --- --- build 0x1000 : 22/08/11 : Starting build ID --- build 0x1001 : 29/08/11 : Version for SPI testing --- build 0x1002 : 27/09/11 : Bug fixes, new transactor code; v1.3 candidate --- build 0x1003 : buggy --- build 0x1004 : 18/10/11 : New mini-t top level, bug fixes, 1.3 codebase --- build 0x1005 : 20/10/11 : ipbus address config testing in mini-t --- build 0x1006 : 26/10/11 : trying with jumbo frames --- build 0x1007 : 27/10/11 : new slaves / address map + rhino frames --- build 0x1008 : 31/10/11 : rhino frames + multibus demo - - diff --git a/projects/TLU_v1e/addr_table/TLUaddrmap.xml b/projects/TLU_v1e/addr_table/TLUaddrmap.xml index 1d8f9f87..55d1e873 100644 --- a/projects/TLU_v1e/addr_table/TLUaddrmap.xml +++ b/projects/TLU_v1e/addr_table/TLUaddrmap.xml @@ -17,13 +17,13 @@ </node> <node id="Shutter" address="0x2000" description="Shutter/T0 control" fwinfo="endpoint;width=4"> - <node id="ControlW" address="0x0" permission="w" description="Bit-0 controls if shutter pulses are active. 1 = active"/> - <node id="ShutterSelectW" address="0x1" permission="w" description="Selects which input is used to trigger shutter"/> - <node id="InternalShutterPeriodW" address="0x2" permission="w" description="Internal trig generator period ( units = number of strobe pulses)"/> - <node id="ShutterOnTimeW" address="0x3" permission="w" description="Time between input trigger being received and shutter asserted(T1) ( units = number of strobe pulses)"/> - <node id="ShutterOnTimeW" address="0x4" permission="w" description="time between input trigger and veto being de-asserted(T2) ( units = number of strobe pulses)"/> - <node id="ShutterOnTimeW" address="0x5" permission="w" description="time at which shutter de-asserted(T3) ( units = number of strobe pulses)"/> - <node id="PulseT0" address="0x8" permission="w" description="Writing to Bit-0 of this register causes sync line to pulse for one strobe-pulse interval"/> + <node id="ControlW" address="0x0" permission="rw" description="Bit-0 controls if shutter pulses are active. 1 = active"/> + <node id="ShutterSelectW" address="0x1" permission="rw" description="Selects which input is used to trigger shutter"/> + <node id="InternalShutterPeriodW" address="0x2" permission="rw" description="Internal trig generator period ( units = number of strobe pulses)"/> + <node id="ShutterOnTimeW" address="0x3" permission="rw" description="Time between input trigger being received and shutter asserted(T1) ( units = number of strobe pulses)"/> + <node id="VetoOffTimeW" address="0x4" permission="rw" description="time between input trigger and veto being de-asserted(T2) ( units = number of strobe pulses)"/> + <node id="ShutterOffTimeW" address="0x5" permission="rw" description="time between input trigger and time at which shutter de-asserted and veto reasserted(T3) ( units = number of strobe pulses)"/> + <node id="PulseT0" address="0x8" permission="rw" description="Writing to Bit-0 of this register causes sync line to pulse for one strobe-pulse interval"/> </node> <!-- I2C registers. Tested ok.--> <node id="i2c_master" address="0x3000" description="I2C Master interface" fwinfo="endpoint;width=3"> diff --git a/projects/TLU_v1e/scripts/AD5665R.py b/projects/TLU_v1e/scripts/AD5665R.py new file mode 120000 index 00000000..57e57fb0 --- /dev/null +++ b/projects/TLU_v1e/scripts/AD5665R.py @@ -0,0 +1 @@ +packages/AD5665R.py \ No newline at end of file diff --git a/projects/TLU_v1e/scripts/AIDA_testScript.py b/projects/TLU_v1e/scripts/AIDA_testScript.py new file mode 100644 index 00000000..b8fbcfa9 --- /dev/null +++ b/projects/TLU_v1e/scripts/AIDA_testScript.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +import uhal +from I2CuHal import I2CCore +import time +#import miniTLU +from si5345 import si5345 +from AD5665R import AD5665R +from PCA9539PW import PCA9539PW +from E24AA025E48T import E24AA025E48T + +manager = uhal.ConnectionManager("file://./TLUconnection.xml") +hw = manager.getDevice("tlu") + +# hw.getNode("A").write(255) +reg = hw.getNode("version").read() +hw.dispatch() +print "CHECK REG= ", hex(reg) + + +# #First I2C core +print ("Instantiating master I2C core:") +master_I2C= I2CCore(hw, 10, 5, "i2c_master", None) +master_I2C.state() + + + + +# +# ####################################### +enableCore= True #Only need to run this once, after power-up +if (enableCore): + mystop=True + print " Write RegDir to set I/O[7] to output:" + myslave= 0x21 + mycmd= [0x01, 0x7F] + nwords= 1 + master_I2C.write(myslave, mycmd, mystop) + + + mystop=False + mycmd= [0x01] + master_I2C.write(myslave, mycmd, mystop) + res= master_I2C.read( myslave, nwords) + print "\tPost RegDir: ", res +# ####################################### +# +# time.sleep(0.1) +# #Read the EPROM +# mystop=False +# nwords=6 +# myslave= 0x53 #DUNE EPROM 0x53 (Possibly) +# myaddr= [0xfa]#0xfa +# master_I2C.write( myslave, myaddr, mystop) +# #res= master_I2C.read( 0x50, 6) +# res= master_I2C.read( myslave, nwords) +# print " PCB EPROM: " +# result="\t " +# for iaddr in res: +# result+="%02x "%(iaddr) +# print result +# ####################################### + + +#Second I2C core +#print ("Instantiating SFP I2C core:") +#clock_I2C= I2CCore(hw, 10, 5, "i2c_sfp", None) +#clock_I2C.state() + +# #Third I2C core +# print ("Instantiating clock I2C core:") +# clock_I2C= I2CCore(hw, 10, 5, "i2c_clk", None) +# clock_I2C.state() + + +# #time.sleep(0.01) +# #Read the EPROM +# mystop=False +# nwords=2 +# myslave= 0x68 #DUNE CLOCK CHIP 0x68 +# myaddr= [0x02 ]#0xfa +# clock_I2C.write( myslave, myaddr, mystop) +# #time.sleep(0.1) +# res= clock_I2C.read( myslave, nwords) +# print " CLOCK EPROM: " +# result="\t " +# for iaddr in res: +# result+="%02x "%(iaddr) +# print result + +# + +#CLOCK CONFIGURATION BEGIN +zeClock=si5345(master_I2C, 0x68) +res= zeClock.getDeviceVersion() +zeClock.checkDesignID() +#zeClock.setPage(0, True) +#zeClock.getPage(True) +#clkRegList= zeClock.parse_clk("./../../bitFiles/TLU_CLK_Config_v1e.txt") +clkRegList= zeClock.parse_clk("./localClock.txt") + +zeClock.writeConfiguration(clkRegList)###### +zeClock.writeRegister(0x0536, [0x0A]) #Configures manual switch of inputs +zeClock.writeRegister(0x0949, [0x0F]) #Enable all inputs +zeClock.writeRegister(0x052A, [0x05]) #Configures source of input +iopower= zeClock.readRegister(0x0949, 1) +print " Clock IO power: 0x%X" % iopower[0] +lol= zeClock.readRegister(0x000E, 1) +print " Clock LOL (0x000E): 0x%X" % lol[0] +los= zeClock.readRegister(0x000D, 1) +print " Clock LOS (0x000D): 0x%X" % los[0] +#CLOCK CONFIGURATION END + +#DAC CONFIGURATION BEGIN +zeDAC1=AD5665R(master_I2C, 0x13) +zeDAC1.setIntRef(intRef= False, verbose= True) +zeDAC1.writeDAC(0x0, 7, verbose= True)#7626 + +zeDAC2=AD5665R(master_I2C, 0x1F) +zeDAC2.setIntRef(intRef= False, verbose= True) +zeDAC2.writeDAC(0x2fff, 3, verbose= True) +#DAC CONFIGURATION END + +#EEPROM BEGIN +zeEEPROM= E24AA025E48T(master_I2C, 0x50) +res=zeEEPROM.readEEPROM(0xfa, 6) +result=" EEPROM ID:\n\t" +for iaddr in res: + result+="%02x "%(iaddr) +print result +#EEPROM END + +# #I2C EXPANDER CONFIGURATION BEGIN +IC6=PCA9539PW(master_I2C, 0x74) +#BANK 0 +IC6.setInvertReg(0, 0x00)# 0= normal +IC6.setIOReg(0, 0xFF)# 0= output <<<<<<<<<<<<<<<<<<< +IC6.setOutputs(0, 0xFF) +res= IC6.getInputs(0) +print "IC6 read back bank 0: 0x%X" % res[0] +# +#BANK 1 +IC6.setInvertReg(1, 0x00)# 0= normal +IC6.setIOReg(1, 0xFF)# 0= output <<<<<<<<<<<<<<<<<<< +IC6.setOutputs(1, 0xFF) +res= IC6.getInputs(1) +print "IC6 read back bank 1: 0x%X" % res[0] + +# # # +IC7=PCA9539PW(master_I2C, 0x75) +#BANK 0 +IC7.setInvertReg(0, 0xFF)# 0= normal +IC7.setIOReg(0, 0xFA)# 0= output <<<<<<<<<<<<<<<<<<< +IC7.setOutputs(0, 0xFF) +res= IC7.getInputs(0) +print "IC7 read back bank 0: 0x%X" % res[0] +# +#BANK 1 +IC7.setInvertReg(1, 0x00)# 0= normal +IC7.setIOReg(1, 0x4F)# 0= output <<<<<<<<<<<<<<<<<<< +IC7.setOutputs(1, 0xFF) +res= IC7.getInputs(1) +print "IC7 read back bank 1: 0x%X" % res[0] +# #I2C EXPANDER CONFIGURATION END + + +# #Reset counters +#cmd = int("0x0", 16) #write 0x2 to reset +#hw.getNode("triggerInputs.SerdesRstW").write(cmd) +#restatus= hw.getNode("triggerInputs.SerdesRstR").read() +#hw.dispatch() +#print "Trigger Reset: 0x%X" % restatus +## #Read trigger inputs +#myreg= [-1, -1, -1, -1, -1, -1] +#for inputN in range(0, 6): +# regString= "triggerInputs.ThrCount%dR" % inputN +# myreg[inputN]= hw.getNode(regString).read() +# hw.dispatch() +# print regString, myreg[inputN] + +## Read ev formatter +#cmd = int("0x0", 16) # +##hw.getNode("Event_Formatter.Enable_Record_Data").write(cmd) +#efstatus= hw.getNode("Event_Formatter.CurrentTimestampLR").read() +#hw.dispatch() +#print "Event Formatter Record: 0x%X" % efstatus diff --git a/projects/TLU_v1e/scripts/AIDA_testShutter.py b/projects/TLU_v1e/scripts/AIDA_testShutter.py new file mode 100644 index 00000000..c429f05c --- /dev/null +++ b/projects/TLU_v1e/scripts/AIDA_testShutter.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +# +# Sets up AIDA-2020 TLU to produce shutter signals. +# After running this script there should be shutter signals on all DUT interfaces +# +import uhal +from I2CuHal import I2CCore +import time +#import miniTLU +from si5345 import si5345 +from AD5665R import AD5665R +from PCA9539PW import PCA9539PW +from E24AA025E48T import E24AA025E48T + +manager = uhal.ConnectionManager("file://./TLUconnection.xml") +hw = manager.getDevice("tlu") + +# hw.getNode("A").write(255) +reg = hw.getNode("version").read() +hw.dispatch() +print "Firmware Version Number = ", hex(reg) + + +# #First I2C core +print ("Instantiating master I2C core:") +master_I2C= I2CCore(hw, 10, 5, "i2c_master", None) +master_I2C.state() +# +# ####################################### +enableCore= True #Only need to run this once, after power-up +if (enableCore): + mystop=True + print " Write RegDir to set I/O[7] to output:" + myslave= 0x21 + mycmd= [0x01, 0x7F] + nwords= 1 + master_I2C.write(myslave, mycmd, mystop) + + + mystop=False + mycmd= [0x01] + master_I2C.write(myslave, mycmd, mystop) + res= master_I2C.read( myslave, nwords) + print "\tPost RegDir: ", res + + +#CLOCK CONFIGURATION BEGIN +print "Setting up clock" +zeClock=si5345(master_I2C, 0x68) +res= zeClock.getDeviceVersion() +zeClock.checkDesignID() +#zeClock.setPage(0, True) +#zeClock.getPage(True) +#clkRegList= zeClock.parse_clk("./../../bitFiles/TLU_CLK_Config_v1e.txt") +clkRegList= zeClock.parse_clk("./localClock.txt") + +zeClock.writeConfiguration(clkRegList)###### +zeClock.writeRegister(0x0536, [0x0A]) #Configures manual switch of inputs +zeClock.writeRegister(0x0949, [0x0F]) #Enable all inputs +zeClock.writeRegister(0x052A, [0x05]) #Configures source of input +iopower= zeClock.readRegister(0x0949, 1) +print " Clock IO power: 0x%X" % iopower[0] +lol= zeClock.readRegister(0x000E, 1) +print " Clock LOL (0x000E): 0x%X" % lol[0] +los= zeClock.readRegister(0x000D, 1) +print " Clock LOS (0x000D): 0x%X" % los[0] +#CLOCK CONFIGURATION END + +#DAC CONFIGURATION BEGIN +zeDAC1=AD5665R(master_I2C, 0x13) +zeDAC1.setIntRef(intRef= False, verbose= True) +zeDAC1.writeDAC(0x0, 7, verbose= True)#7626 + +zeDAC2=AD5665R(master_I2C, 0x1F) +zeDAC2.setIntRef(intRef= False, verbose= True) +zeDAC2.writeDAC(0x2fff, 3, verbose= True) +#DAC CONFIGURATION END + +#EEPROM BEGIN +zeEEPROM= E24AA025E48T(master_I2C, 0x50) +res=zeEEPROM.readEEPROM(0xfa, 6) +result=" EEPROM ID:\n\t" +for iaddr in res: + result+="%02x "%(iaddr) +print result +#EEPROM END + +# #I2C EXPANDER CONFIGURATION BEGIN +IC6=PCA9539PW(master_I2C, 0x74) +#BANK 0 +IC6.setInvertReg(0, 0x00)# 0= normal +IC6.setIOReg(0, 0xFF)# 0= output <<<<<<<<<<<<<<<<<<< +IC6.setOutputs(0, 0xFF) +res= IC6.getInputs(0) +print "IC6 read back bank 0: 0x%X" % res[0] +# +#BANK 1 +IC6.setInvertReg(1, 0x00)# 0= normal +IC6.setIOReg(1, 0xFF)# 0= output <<<<<<<<<<<<<<<<<<< +IC6.setOutputs(1, 0xFF) +res= IC6.getInputs(1) +print "IC6 read back bank 1: 0x%X" % res[0] + +# # # +IC7=PCA9539PW(master_I2C, 0x75) +#BANK 0 +IC7.setInvertReg(0, 0xFF)# 0= normal +IC7.setIOReg(0, 0xFA)# 0= output <<<<<<<<<<<<<<<<<<< +IC7.setOutputs(0, 0xFF) +res= IC7.getInputs(0) +print "IC7 read back bank 0: 0x%X" % res[0] +# +#BANK 1 +IC7.setInvertReg(1, 0x00)# 0= normal +IC7.setIOReg(1, 0x4F)# 0= output <<<<<<<<<<<<<<<<<<< +IC7.setOutputs(1, 0xFF) +res= IC7.getInputs(1) +print "IC7 read back bank 1: 0x%X" % res[0] +# #I2C EXPANDER CONFIGURATION END + + +# Set up shutter registers +print "Setting up shutter registers" +shutterPeriod = 1024 +T1 = 100 +T2 = 200 +T3 = 300 +hw.getNode("Shutter.InternalShutterPeriodW").write(shutterPeriod) +hw.getNode("Shutter.ShutterOnTimeW").write(T1) +hw.getNode("Shutter.VetoOffTimeW").write(T2) +hw.getNode("Shutter.ShutterOffTimeW").write(T3) +# Enable shutter signal and internal sequence generator +hw.getNode("Shutter.ControlW").write(2) + +# Enable DUT intefaces +hw.getNode("DUTInterfaces.DutMaskW").write(0xF) +hw.getNode("DUTInterfaces.IgnoreDUTBusyW").write(0xF) + +hw.dispatch() + +print "All done" diff --git a/projects/TLU_v1e/scripts/E24AA025E48T.py b/projects/TLU_v1e/scripts/E24AA025E48T.py new file mode 120000 index 00000000..d7fe7bd0 --- /dev/null +++ b/projects/TLU_v1e/scripts/E24AA025E48T.py @@ -0,0 +1 @@ +packages/E24AA025E48T.py \ No newline at end of file diff --git a/projects/TLU_v1e/scripts/I2CuHal.py b/projects/TLU_v1e/scripts/I2CuHal.py new file mode 120000 index 00000000..334e4f2c --- /dev/null +++ b/projects/TLU_v1e/scripts/I2CuHal.py @@ -0,0 +1 @@ +./packages/I2CuHal.py \ No newline at end of file diff --git a/projects/TLU_v1e/scripts/PCA9539PW.py b/projects/TLU_v1e/scripts/PCA9539PW.py new file mode 120000 index 00000000..36fda817 --- /dev/null +++ b/projects/TLU_v1e/scripts/PCA9539PW.py @@ -0,0 +1 @@ +packages/PCA9539PW.py \ No newline at end of file diff --git a/projects/TLU_v1e/software/README b/projects/TLU_v1e/scripts/README similarity index 100% rename from projects/TLU_v1e/software/README rename to projects/TLU_v1e/scripts/README diff --git a/projects/TLU_v1e/software/SI5344 b/projects/TLU_v1e/scripts/SI5344 similarity index 100% rename from projects/TLU_v1e/software/SI5344 rename to projects/TLU_v1e/scripts/SI5344 diff --git a/projects/TLU_v1e/scripts/TLU_v1e.py b/projects/TLU_v1e/scripts/TLU_v1e.py new file mode 100644 index 00000000..d1e31038 --- /dev/null +++ b/projects/TLU_v1e/scripts/TLU_v1e.py @@ -0,0 +1,975 @@ +# -*- coding: utf-8 -*- +import uhal; +import pprint; +import ConfigParser +#from FmcTluI2c import * +import threading +from ROOT import TFile, TTree, gROOT, AddressOf +from ROOT import * +import time + +from I2CuHal import I2CCore +from si5345 import si5345 # Library for clock chip +from AD5665R import AD5665R # Library for DAC +from PCA9539PW import PCA9539PW # Library for serial line expander + +class TLU: + """docstring for TLU""" + def __init__(self, dev_name, man_file, parsed_cfg): + + self.isRunning= False + + section_name= "Producer.fmctlu" + self.dev_name = dev_name + + #man_file= parsed_cfg.get(section_name, "ConnectionFile") + self.manager= uhal.ConnectionManager(man_file) + self.hw = self.manager.getDevice(self.dev_name) + + # #Get Verbose setting + self.verbose= parsed_cfg.getint(section_name, "verbose") + + #self.nDUTs= 4 #Number of DUT connectors + self.nDUTs= parsed_cfg.getint(section_name, "nDUTs") + + #self.nChannels= 6 #Number of trigger inputs + self.nChannels= parsed_cfg.getint(section_name, "nTrgIn") + + #self.VrefInt= 2.5 #Internal DAC voltage reference + self.VrefInt= parsed_cfg.getfloat(section_name, "VRefInt") + + #self.VrefExt= 1.3 #External DAC voltage reference + self.VrefExt= parsed_cfg.getfloat(section_name, "VRefExt") + + #self.intRefOn= False #Internal reference is OFF by default + self.intRefOn= int(parsed_cfg.get(section_name, "intRefOn")) + + + self.fwVersion = self.hw.getNode("version").read() + self.hw.dispatch() + print "TLU V1E FIRMWARE VERSION= " , hex(self.fwVersion) + + # Instantiate a I2C core to configure components + self.TLU_I2C= I2CCore(self.hw, 10, 5, "i2c_master", None) + #self.TLU_I2C.state() + + enableCore= True #Only need to run this once, after power-up + self.enableCore() + + # Instantiate clock chip and configure it (if necessary) + #self.zeClock=si5345(self.TLU_I2C, 0x68) + clk_addr= int(parsed_cfg.get(section_name, "I2C_CLK_Addr"), 16) + self.zeClock=si5345(self.TLU_I2C, clk_addr) + res= self.zeClock.getDeviceVersion() + if (int(parsed_cfg.get(section_name, "CONFCLOCK"), 16)): + #clkRegList= self.zeClock.parse_clk("./../../bitFiles/TLU_CLK_Config_v1e.txt") + clkRegList= self.zeClock.parse_clk(parsed_cfg.get(section_name, "CLOCK_CFG_FILE")) + self.zeClock.writeConfiguration(clkRegList)###### + + self.zeClock.checkDesignID() + + # Instantiate DACs and configure them to use reference based on TLU setting + #self.zeDAC1=AD5665R(self.TLU_I2C, 0x13) + #self.zeDAC2=AD5665R(self.TLU_I2C, 0x1F) + dac_addr1= int(parsed_cfg.get(section_name, "I2C_DAC1_Addr"), 16) + self.zeDAC1=AD5665R(self.TLU_I2C, dac_addr1) + dac_addr2= int(parsed_cfg.get(section_name, "I2C_DAC2_Addr"), 16) + self.zeDAC2=AD5665R(self.TLU_I2C, dac_addr2) + self.zeDAC1.setIntRef(self.intRefOn, self.verbose) + self.zeDAC2.setIntRef(self.intRefOn, self.verbose) + + # Instantiate the serial line expanders and configure them to default values + #self.IC6=PCA9539PW(self.TLU_I2C, 0x74) + exp1_addr= int(parsed_cfg.get(section_name, "I2C_EXP1_Addr"), 16) + self.IC6=PCA9539PW(self.TLU_I2C, exp1_addr) + self.IC6.setInvertReg(0, 0x00)# 0= normal, 1= inverted + self.IC6.setIOReg(0, 0x00)# 0= output, 1= input + self.IC6.setOutputs(0, 0xFF)# If output, set to XX + + self.IC6.setInvertReg(1, 0x00)# 0= normal, 1= inverted + self.IC6.setIOReg(1, 0x00)# 0= output, 1= input + self.IC6.setOutputs(1, 0xFF)# If output, set to XX + + #self.IC7=PCA9539PW(self.TLU_I2C, 0x75) + exp2_addr= int(parsed_cfg.get(section_name, "I2C_EXP2_Addr"), 16) + self.IC7=PCA9539PW(self.TLU_I2C, exp2_addr) + self.IC7.setInvertReg(0, 0x00)# 0= normal, 1= inverted + self.IC7.setIOReg(0, 0x00)# 0= output, 1= input + self.IC7.setOutputs(0, 0x00)# If output, set to XX + + self.IC7.setInvertReg(1, 0x00)# 0= normal, 1= inverted + self.IC7.setIOReg(1, 0x00)# 0= output, 1= input + self.IC7.setOutputs(1, 0xB0)# If output, set to XX + + +################################################################################################################################## +################################################################################################################################## + def DUTOutputs_old(self, dutN, enable=False, verbose=False): + ## Set the status of the transceivers for a specific HDMI connector. When enable= False the transceivers are disabled and the + ## connector cannot send signals from FPGA to the outside world. When enable= True then signals from the FPGA will be sent out to the HDMI. + ## NOTE: the other direction is always enabled, i.e. signals from the DUTs are always sent to the FPGA. + ## NOTE: CLK direction must be defined separately using DUTClkSrc + ## NOTE: This version changes all the pins together. Use DUTOutputs to control individual pins. + + if (dutN < 0) | (dutN> (self.nDUTs-1)): + print "\tERROR: DUTOutputs. The DUT number must be comprised between 0 and ", self.nDUTs-1 + return -1 + bank= dutN//2 # DUT0 and DUT1 are on bank 0. DUT2 and DUT3 on bank 1 + nibble= dutN%2 # DUT0 and DUT2 are on nibble 0. DUT1 and DUT3 are on nibble 1 + print " Setting DUT:", dutN, "to", enable + if (verbose > 1): + print "\tBank", bank, "Nibble", nibble + res= self.IC6.getOutputs(bank) + oldStatus= res[0] + mask= 0xF << 4*nibble + newStatus= oldStatus & (~mask) + if (not enable): # we want to write 0 to activate the outputs so check opposite of "enable" + newStatus |= mask + self.IC6.setOutputs(bank, newStatus) + + if verbose: + print "\tOldStatus= ", "{0:#0{1}x}".format(oldStatus,4), "Mask=" , hex(mask), "newStatus=", "{0:#0{1}x}".format(newStatus,4) + return newStatus + + def DUTOutputs(self, dutN, enable=0x7, verbose=False): + ## Set the status of the transceivers for a specific HDMI connector. When enable= False the transceivers are disabled and the + ## connector cannot send signals from FPGA to the outside world. When enable= True then signals from the FPGA will be sent out to the HDMI. + ## NOTE: the other direction is always enabled, i.e. signals from the DUTs are always sent to the FPGA. + ## NOTE: CLK direction must be defined separately using DUTClkSrc + + if (dutN < 0) | (dutN> (self.nDUTs-1)): + print "\tERROR: DUTOutputs. The DUT number must be comprised between 0 and ", self.nDUTs-1 + return -1 + bank= dutN//2 # DUT0 and DUT1 are on bank 0. DUT2 and DUT3 on bank 1 + nibble= dutN%2 # DUT0 and DUT2 are on nibble 0. DUT1 and DUT3 are on nibble 1 + print " Setting DUT:", dutN, "pins status to", hex(enable) + if (verbose > 1): + print "\tBank", bank, "Nibble", nibble + res= self.IC6.getOutputs(bank) + oldStatus= res[0] + mask= 0xF << 4*nibble + newnibble= (enable & 0xF) << 4*nibble # bits we want to change are marked with 1 + newStatus= (oldStatus & (~mask)) | (newnibble & mask) + + self.IC6.setOutputs(bank, newStatus) + + if (verbose > 0): + self.getDUTOutpus(dutN, verbose) + if (verbose > 1): + print "\tOldStatus= ", "{0:#0{1}x}".format(oldStatus,4), "Mask=" , hex(mask), "newStatus=", "{0:#0{1}x}".format(newStatus,4) + + return newStatus + + def DUTClkSrc(self, dutN, clkSrc=0, verbose= False): + ## Allows to choose the source of the clock signal sent to the DUTs over HDMI + ## clkSrc= 0: clock disabled + ## clkSrc= 1: clock from Si5345 + ## clkSrc=2: clock from FPGA + if (dutN < 0) | (dutN> (self.nDUTs-1)): + print "\tERROR: DUTClkSrc. The DUT number must be comprised between 0 and ", self.nDUTs-1 + return -1 + if (clkSrc < 0) | (clkSrc> 2): + print "\tERROR: DUTClkSrc. clkSrc can only be 0 (disabled), 1 (Si5345) or 2 (FPGA)" + return -1 + bank=0 + maskLow= 1 << (1* dutN) #CLK FROM FPGA + maskHigh= 1<< (1* dutN +4) #CLK FROM Si5345 + mask= maskLow | maskHigh + res= self.IC7.getOutputs(bank) + oldStatus= res[0] + newStatus= oldStatus & ~mask #set both bits to zero + outStat= "" + if clkSrc==0: + newStatus = newStatus | mask + outStat= "disabled" + elif clkSrc==1: + newStatus = newStatus | maskLow + outStat= "Si5435" + elif clkSrc==2: + newStatus= newStatus | maskHigh + outStat= "FPGA" + print " Setting DUT:", dutN, "clock source to", outStat + if (verbose > 1): + print "\tOldStatus= ", "{0:#0{1}x}".format(oldStatus,4), "Mask=" , hex(mask), "newStatus=", "{0:#0{1}x}".format(newStatus,4) + self.IC7.setOutputs(bank, newStatus) + return newStatus + + def enableClkLEMO(self, enable= False, verbose= False): + ## Enable or disable the output clock to the differential LEMO output + bank=1 + mask= 0x10 + res= self.IC7.getOutputs(bank) + oldStatus= res[0] + newStatus= oldStatus & ~mask + outStat= "enabled" + if (not enable): #A 0 activates the output. A 1 disables it. + newStatus= newStatus | mask + outStat= "disabled" + print " Clk LEMO", outStat + if verbose: + print "\tOldStatus= ", "{0:#0{1}x}".format(oldStatus,4), "Mask=" , hex(mask), "newStatus=", "{0:#0{1}x}".format(newStatus,4) + self.IC7.setOutputs(bank, newStatus) + return newStatus + + def enableCore(self): + ## At power up the Enclustra I2C lines are disabled (tristate buffer is off). + ## This function enables the lines. It is only required once. + mystop=True + print " Enabling I2C bus (expect 127):" + myslave= 0x21 + mycmd= [0x01, 0x7F] + nwords= 1 + self.TLU_I2C.write(myslave, mycmd, mystop) + + mystop=False + mycmd= [0x01] + self.TLU_I2C.write(myslave, mycmd, mystop) + res= self.TLU_I2C.read( myslave, nwords) + print "\tPost RegDir: ", res + + def getDUTOutpus(self, dutN, verbose=0): + if (dutN < 0) | (dutN> (self.nDUTs-1)): + print "\tERROR: DUTOutputs. The DUT number must be comprised between 0 and ", self.nDUTs-1 + return -1 + bank= dutN//2 # DUT0 and DUT1 are on bank 0. DUT2 and DUT3 on bank 1 + nibble= dutN%2 # DUT0 and DUT2 are on nibble 0. DUT1 and DUT3 are on nibble 1 + res= self.IC6.getOutputs(bank) + dut_status= res[0] + dut_lines= ["CONT", "SPARE", "TRIG", "BUSY"] + dut_status= 0x0F & (dut_status >> (4*nibble)) + + if verbose > 0: + for idx, iLine in enumerate(dut_lines): + this_bit= 0x1 & (dut_status >> idx) + if this_bit: + this_status= "ENABLED" + else: + this_status= "DISABLED" + print "\t", iLine, "output is", this_status + + if verbose > 1: + print "\tDUT CURRENT:", hex(dut_status), "Nibble:", nibble, "Bank:", bank + + return dut_status + + def getAllChannelsCounts(self): + chCounts=[] + for ch in range (0,self.nChannels): + chCounts.append(int(self.getChCount(ch))) + return chCounts + + def getChStatus(self): + inputStatus= self.hw.getNode("triggerInputs.SerdesRstR").read() + self.hw.dispatch() + print "\tTRIGGER COUNTERS status= " , hex(inputStatus) + return inputStatus + + def getChCount(self, channel): + regString= "triggerInputs.ThrCount"+ str(channel)+"R" + count = self.hw.getNode(regString).read() + self.hw.dispatch() + print "\tCh", channel, "Count:" , count + return count + + def getClockStatus(self): + clockStatus = self.hw.getNode("logic_clocks.LogicClocksCSR").read() + self.hw.dispatch() + print " CLOCK STATUS [expected 1]" + print "\t", hex(clockStatus) + if ( clockStatus == 0 ): + "ERROR: Clocks in TLU FPGA are not locked." + return clockStatus + + def getDUTmask(self): + DUTMaskR = self.hw.getNode("DUTInterfaces.DutMaskR").read() + self.hw.dispatch() + print "\tDUTMask read back as:" , hex(DUTMaskR) + return DUTMaskR + + def getExternalVeto(self): + extVeto= self.hw.getNode("triggerLogic.ExternalTriggerVetoR").read() + self.hw.dispatch() + print "\tEXTERNAL Veto read back as:", hex(extVeto) + return extVeto + + def getFifoData(self, nWords): + #fifoData= self.hw.getNode("eventBuffer.EventFifoData").read() + fifoData= self.hw.getNode("eventBuffer.EventFifoData").readBlock (nWords); + self.hw.dispatch() + #print "\tFIFO Data:", hex(fifoData) + return fifoData + + def getFifoLevel(self, verbose= 0): + FifoFill= self.hw.getNode("eventBuffer.EventFifoFillLevel").read() + self.hw.dispatch() + if (verbose > 0): + print "\tFIFO level read back as:", hex(FifoFill) + return FifoFill + + def getFifoCSR(self): + FifoCSR= self.hw.getNode("eventBuffer.EventFifoCSR").read() + self.hw.dispatch() + print "\tFIFO CSR read back as:", hex(FifoCSR) + return FifoCSR + + def getFifoFlags(self): + # Useless? + FifoFLAG= self.hw.getNode("eventBuffer.EventFifoFillLevelFlags").read() + self.hw.dispatch() + print "\tFIFO FLAGS read back as:", hex(FifoFLAG) + return FifoFLAG + + def getInternalTrg(self): + trigIntervalR = self.hw.getNode("triggerLogic.InternalTriggerIntervalR").read() + self.hw.dispatch() + print "\tInternal interval read back as:", trigIntervalR + return trigIntervalR + + def getMode(self): + DUTInterfaceModeR = self.hw.getNode("DUTInterfaces.DUTInterfaceModeR").read() + self.hw.dispatch() + print "\tDUT mode read back as:" , hex(DUTInterfaceModeR) + return DUTInterfaceModeR + + def getModeModifier(self): + DUTInterfaceModeModifierR = self.hw.getNode("DUTInterfaces.DUTInterfaceModeModifierR").read() + self.hw.dispatch() + print "\tDUT mode modifier read back as:" , hex(DUTInterfaceModeModifierR) + return DUTInterfaceModeModifierR + + def getSN(self): + epromcontent=self.readEEPROM(0xfa, 6) + print " FMC-TLU serial number (EEPROM):" + result="\t" + for iaddr in epromcontent: + result+="%02x "%(iaddr) + print result + return epromcontent + + def getPostVetoTrg(self): + triggerN = self.hw.getNode("triggerLogic.PostVetoTriggersR").read() + self.hw.dispatch() + print "\tPOST VETO TRIGGER NUMBER:", (triggerN) + return triggerN + + def getPulseDelay(self): + pulseDelayR = self.hw.getNode("triggerLogic.PulseDelayR").read() + self.hw.dispatch() + print "\tPulse delay read back as:", hex(pulseDelayR) + return pulseDelayR + + def getPulseStretch(self): + pulseStretchR = self.hw.getNode("triggerLogic.PulseStretchR").read() + self.hw.dispatch() + print "\tPulse stretch read back as:", hex(pulseStretchR) + return pulseStretchR + + def getRecordDataStatus(self): + RecordStatus= self.hw.getNode("Event_Formatter.Enable_Record_Data").read() + self.hw.dispatch() + print "\tData recording:", RecordStatus + return RecordStatus + + def getTriggerVetoStatus(self): + trgVetoStatus= self.hw.getNode("triggerLogic.TriggerVetoR").read() + self.hw.dispatch() + print "\tTrigger veto status read back as:", trgVetoStatus + return trgVetoStatus + + def getTrgPattern(self): + triggerPattern_low = self.hw.getNode("triggerLogic.TriggerPattern_lowR").read() + triggerPattern_high = self.hw.getNode("triggerLogic.TriggerPattern_highR").read() + self.hw.dispatch() + print "\tTrigger pattern read back as: 0x%08X 0x%08X" %(triggerPattern_high, triggerPattern_low) + return triggerPattern_low, triggerPattern_high + + def getVetoDUT(self): + IgnoreDUTBusyR = self.hw.getNode("DUTInterfaces.IgnoreDUTBusyR").read() + self.hw.dispatch() + print "\tIgnoreDUTBusy read back as:" , hex(IgnoreDUTBusyR) + return IgnoreDUTBusyR + + def getVetoShutters(self): + IgnoreShutterVeto = self.hw.getNode("DUTInterfaces.IgnoreShutterVetoR").read() + self.hw.dispatch() + print "\tIgnoreShutterVeto read back as:" , IgnoreShutterVeto + return IgnoreShutterVeto + + def getShutterControl(self): + shutterControl = self.hw.getNode("Shutter.ControlW").read() + self.hw.dispatch() + print "\tShutter control read back as:" , hex(shutterControl) + return shutterControl + + def getShutterInternalInterval(self): + shutterInternalInterval = self.hw.getNode("Shutter.InternalShutterPeriodW").read() + self.hw.dispatch() + print "\tShutter internal inverval read back as:" , shutterInternalInterval + return shutterInternalInterval + + def getShutterOnTime(self): + shutterontime = self.hw.getNode("Shutter.ShutterOnTimeW").read() + self.hw.dispatch() + print "\tShutter on time:" , shutterontime + return shutterontime + + def getShutterOffTime(self): + shutterofftime = self.hw.getNode("Shutter.ShutterOffTimeW").read() + self.hw.dispatch() + print "\tShutter off time:" , shutterofftime + return shutterofftime + + def getShutterVetoOffTime(self): + vetoofftime = self.hw.getNode("Shutter.VetoOffTimeW").read() + self.hw.dispatch() + print "\tVeto off time:" , vetoofftime + return vetoofftime + + + + def pulseT0(self): + cmd = int("0x1",16) + self.hw.getNode("Shutter.PulseT0").write(cmd) + self.hw.dispatch() + print "\tPulsing T0" + + def readEEPROM(self, startadd, bytes): + mystop= 1 + time.sleep(0.1) + myaddr= [startadd]#0xfa + self.TLU_I2C.write( 0x50, [startadd], mystop) + res= self.TLU_I2C.read( 0x50, bytes) + return res + + def resetClock(self): + # Set the RST pin from the PLL to 1 + print " Clocks reset" + cmd = int("0x1",16) + self.hw.getNode("logic_clocks.LogicRst").write(cmd) + self.hw.dispatch() + + def resetClocks(self): + #Reset clock PLL + self.resetClock() + #Get clock status after reset + self.getClockStatus() + #Restore clock PLL + self.restoreClock() + #Get clock status after restore + self.getClockStatus() + #Get serdes status + self.getChStatus() + + def resetCounters(self): + cmd = int("0x2", 16) #write 0x2 to reset + self.hw.getNode("triggerInputs.SerdesRstW").write(cmd) + restatus= self.hw.getNode("triggerInputs.SerdesRstR").read() + self.hw.dispatch() + cmd = int("0x0", 16) #write 0x2 to reset + self.hw.getNode("triggerInputs.SerdesRstW").write(cmd) + restatus= self.hw.getNode("triggerInputs.SerdesRstR").read() + self.hw.dispatch() + #print "Trigger Reset: 0x%X" % restatus + print "\tTrigger counters reset" + + def resetSerdes(self): + cmd = int("0x3",16) + self.setChStatus(cmd) + inputStatus= self.getChStatus() + print "\t Input status during reset = " , hex(inputStatus) + + cmd = int("0x0",16) + self.setChStatus(cmd) + inputStatus= self.getChStatus() + print "\t Input status after reset = " , hex(inputStatus) + + cmd = int("0x4",16) + self.setChStatus(cmd) + inputStatus= self.getChStatus() + print "\t Input status during calibration = " , hex(inputStatus) + + cmd = int("0x0",16) + self.setChStatus(cmd) + inputStatus= self.getChStatus() + print "\t Input status after calibration = " , hex(inputStatus) + + def restoreClock(self): + # Set the RST pin from the PLL to 0 + print " Clocks restore" + cmd = int("0x0",16) + self.hw.getNode("logic_clocks.LogicRst").write(cmd) + self.hw.dispatch() + + def setChStatus(self, cmd): + self.hw.getNode("triggerInputs.SerdesRstW").write(cmd) + inputStatus= self.hw.getNode("triggerInputs.SerdesRstR").read() + self.hw.dispatch() + print " INPUT STATUS SET TO= " , hex(inputStatus) + + def setClockStatus(self, cmd): + # Only use this for testing. The clock source is actually selected in the Si5345. + self.hw.getNode("logic_clocks.LogicClocksCSR").write(cmd) + self.hw.dispatch() + + def setDUTmask(self, DUTMask): + print " DUT MASK ENABLING: Mask= " , hex(DUTMask) + self.hw.getNode("DUTInterfaces.DutMaskW").write(DUTMask) + self.hw.dispatch() + self.getDUTmask() + + def setFifoCSR(self, cmd): + self.hw.getNode("eventBuffer.EventFifoCSR").write(cmd) + self.hw.dispatch() + self.getFifoCSR() + + def setInternalTrg(self, triggerInterval): + print " TRIGGERS INTERNAL:" + if triggerInterval == 0: + internalTriggerFreq = 0 + print "\tdisabled" + else: + internalTriggerFreq = 160000000.0/triggerInterval + print "\tRequired internal trigger frequency:", triggerInterval, "Hz" + print "\tSetting internal interval to:", internalTriggerFreq + self.hw.getNode("triggerLogic.InternalTriggerIntervalW").write(int(internalTriggerFreq)) + self.hw.dispatch() + self.getInternalTrg() + + def setMode(self, mode): + print " DUT MODE SET TO: ", hex(mode) + self.hw.getNode("DUTInterfaces.DUTInterfaceModeW").write(mode) + self.hw.dispatch() + self.getMode() + + def setModeModifier(self, modifier): + print " DUT MODE MODIFIER:", hex(modifier) + self.hw.getNode("DUTInterfaces.DUTInterfaceModeModifierW").write(modifier) + self.hw.dispatch() + self.getModeModifier() + + def setShutterControl(self, controlWord): + print " SHUTTER CONTROL:", hex(controlWord) + self.hw.getNode("Shutter.ControlW").write(controlWord) + self.hw.dispatch() + self.getShutterControl() + + def setShutterInternalInterval(self, interval): + print " SHUTTER INTERNAL INTERVAL:", interval + self.hw.getNode("Shutter.InternalShutterPeriodW").write(interval) + self.hw.dispatch() + self.getShutterInternalInterval() + + def setShutterOnTime(self, cycles): + print " SHUTTER ON TIME:", cycles + self.hw.getNode("Shutter.ShutterOnTimeW").write(cycles) + self.hw.dispatch() + self.getShutterOnTime() + + def setShutterOffTime(self, cycles): + print " SHUTTER OFF TIME:", cycles + self.hw.getNode("Shutter.ShutterOffTimeW").write(cycles) + self.hw.dispatch() + self.getShutterOffTime() + + def setShutterVetoOffTime(self, cycles): + print " SHUTTER VETO OFF:", cycles + self.hw.getNode("Shutter.VetoOffTimeW").write(cycles) + self.hw.dispatch() + self.getShutterVetoOffTime() + + def setPulseDelay(self, inArray): + print " TRIGGER DELAY SET TO", inArray, "[Units= 160MHz clock, 5-bit values (one per input) packed in to 32-bit word]" + pulseDelay= self.packBits(inArray) + self.hw.getNode("triggerLogic.PulseDelayW").write(pulseDelay) + self.hw.dispatch() + self.getPulseDelay() + + def setPulseStretch(self, inArray): + print " INPUT COINCIDENCE WINDOW SET TO", inArray ,"[Units= 160MHz clock cycles, 5-bit values (one per input) packed in to 32-bit word]" + pulseStretch= self.packBits(inArray) + self.hw.getNode("triggerLogic.PulseStretchW").write(pulseStretch) + self.hw.dispatch() + self.getPulseStretch() + + def setRecordDataStatus(self, status=False): + print " Data recording set:" + self.hw.getNode("Event_Formatter.Enable_Record_Data").write(status) + self.hw.dispatch() + self.getRecordDataStatus() + + def setTriggerVetoStatus(self, status=False): + self.hw.getNode("triggerLogic.TriggerVetoW").write(status) + self.hw.dispatch() + self.getTriggerVetoStatus() + + def setTrgPattern(self, triggerPatternH, triggerPatternL): + triggerPatternL &= 0xffffffff + triggerPatternH &= 0xffffffff + print " TRIGGER PATTERN (for external triggers) SET TO 0x%08X 0x%08X. Two 32-bit words." %(triggerPatternH, triggerPatternL) + self.hw.getNode("triggerLogic.TriggerPattern_lowW").write(triggerPatternL) + self.hw.getNode("triggerLogic.TriggerPattern_highW").write(triggerPatternH) + self.hw.dispatch() + self.getTrgPattern() + + def setVetoDUT(self, ignoreDUTBusy): + print " VETO IGNORE BY DUT BUSY MASK SET TO" , hex(ignoreDUTBusy) + self.hw.getNode("DUTInterfaces.IgnoreDUTBusyW").write(ignoreDUTBusy) + self.hw.dispatch() + self.getVetoDUT() + + def setVetoShutters(self, newState): + if newState: + print " IgnoreShutterVetoW SET TO LISTEN FOR VETO FROM SHUTTER" + cmd= int("0x0",16) + else: + print " IgnoreShutterVetoW SET TO IGNORE VETO FROM SHUTTER" + cmd= int("0x1",16) + self.hw.getNode("DUTInterfaces.IgnoreShutterVetoW").write(cmd) + self.hw.dispatch() + self.getVetoShutters() + + def writeThreshold(self, DACtarget, Vtarget, channel, verbose=False): + #Writes the threshold. The DAC voltage differs from the threshold voltage because + #the range is shifted to be symmetrical around 0V. + + #Check if the DACs are using the internal reference + if (self.intRefOn): + Vref= self.VrefInt + else: + Vref= self.VrefExt + + #Calculate offset voltage (because of the following shifter) + Vdac= ( Vtarget + Vref ) / 2 + print" THRESHOLD setting:" + if channel==7: + print "\tCH: ALL" + else: + print "\tCH:", channel + print "\tTarget V:", Vtarget + dacValue = 0xFFFF * (Vdac / Vref) + DACtarget.writeDAC(int(dacValue), channel, verbose) + + def packBits(self, raw_values): + packed_bits= 0 + if (len(raw_values) != self.nChannels): + print "Error (packBits): wrong number of elements in array" + else: + for idx, iCh in enumerate(raw_values): + tmpint= iCh << idx*5 + packed_bits= packed_bits | tmpint + print "\tPacked =", hex(packed_bits) + return packed_bits + + def parseFifoData(self, fifoData, nEvents, mystruct, root_tree, verbose): + #for index in range(0, len(fifoData)-1, 6): + outList= [] + for index in range(0, (nEvents)*6, 6): + word0= (fifoData[index] << 32) + fifoData[index + 1] + word1= (fifoData[index + 2] << 32) + fifoData[index + 3] + word2= (fifoData[index + 4] << 32) + fifoData[index + 5] + evType= (fifoData[index] & 0xF0000000) >> 28 + inTrig= (fifoData[index] & 0x0FFF0000) >> 16 + tStamp= ((fifoData[index] & 0x0000FFFF) << 32) + fifoData[index + 1] + fineTs= fifoData[index + 2] + evNum= fifoData[index + 3] + fineTsList=[-1]*12 + fineTsList[3]= (fineTs & 0x000000FF) + fineTsList[2]= (fineTs & 0x0000FF00) >> 8 + fineTsList[1]= (fineTs & 0x00FF0000) >> 16 + fineTsList[0]= (fineTs & 0xFF000000) >> 24 + fineTsList[7]= (fifoData[index + 4] & 0x000000FF) + fineTsList[6]= (fifoData[index + 4] & 0x0000FF00) >> 8 + fineTsList[5]= (fifoData[index + 4] & 0x00FF0000) >> 16 + fineTsList[4]= (fifoData[index + 4] & 0xFF000000) >> 24 + fineTsList[11]= (fifoData[index + 5] & 0x000000FF) + fineTsList[10]= (fifoData[index + 5] & 0x0000FF00) >> 8 + fineTsList[9]= (fifoData[index + 5] & 0x00FF0000) >> 16 + fineTsList[8]= (fifoData[index + 5] & 0xFF000000) >> 24 + if verbose: + print "====== EVENT", evNum, "=================================================" + print "[", hex(word0), "]", "\t TYPE", hex(evType), "\t TRIGGER", hex(inTrig), "\t TIMESTAMP", (tStamp) + print "[",hex(word1), "]", "\tEV NUM", evNum, "\tFINETS[0,3]", hex(fineTs) + print "[",hex(word2), "]", "\tFINETS[4,11]", hex(word2) + print fineTsList + fineTsList.insert(0, tStamp) + fineTsList.insert(0, evNum) + if (root_tree != None): + highWord= word0 + lowWord= word1 + extWord= word2 + timeStamp= tStamp + bufPos= 0 + evtNumber= evNum + evtType= evType + trigsFired= inTrig + mystruct.raw0= fifoData[index] + mystruct.raw1= fifoData[index+1] + mystruct.raw2= fifoData[index+2] + mystruct.raw3= fifoData[index+3] + mystruct.raw4= fifoData[index+4] + mystruct.raw5= fifoData[index+5] + mystruct.evtNumber= evNum + mystruct.tluTimeStamp= tStamp + mystruct.tluEvtType= evType + mystruct.tluTrigFired= inTrig + root_tree.Fill() + + outList.insert(len(outList), fineTsList) + #print "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" + #print "EN#\tCOARSE_TS\tFINE_TS0...FINE_TS11" + #pprint.pprint(outList) + return outList + + def plotFifoData(self, outList): + import matplotlib.pyplot as plt + import numpy as np + import matplotlib.mlab as mlab + + coarseColumn= [row[1] for row in outList] + fineColumn= [row[2] for row in outList] + timeStamp= [sum(x) for x in zip(coarseColumn, fineColumn)] + correctTs= [-1]*len(coarseColumn) + coarseVal= 0.000000025 #coarse time value (40 Mhz, 25 ns) + fineVal= 0.00000000078125 #fine time value (1280 MHz, 0.78125 ns) + for iTs in range(0, len(coarseColumn)): + correctTs[iTs]= coarseColumn[iTs]*coarseVal + fineColumn[iTs]*fineVal + #if iTs: + #print correctTs[iTs]-correctTs[iTs-1], "\t ", correctTs[iTs], "\t", coarseColumn[iTs], "\t", fineColumn[iTs] + + xdiff = np.diff(correctTs) + np.all(xdiff[0] == xdiff) + P= 1000000000 #display in ns + nsDeltas = [x * P for x in xdiff] + #centerRange= np.mean(nsDeltas) + centerRange= 476 + windowsns= 30 + minRange= centerRange-windowsns + maxRange= centerRange+windowsns + plt.hist(nsDeltas, 60, range=[minRange, maxRange], facecolor='blue', align='mid', alpha= 0.75) + #plt.hist(nsDeltas, 100, normed=True, facecolor='blue', align='mid', alpha=0.75) + #plt.xlim((min(nsDeltas), max(nsDeltas))) + plt.xlabel('Time (ns)') + plt.ylabel('Entries') + plt.title('Histogram DeltaTime') + plt.grid(True) + + #Superimpose Gauss + mean = np.mean(nsDeltas) + variance = np.var(nsDeltas) + sigma = np.sqrt(variance) + x = np.linspace(min(nsDeltas), max(nsDeltas), 100) + plt.plot(x, mlab.normpdf(x, mean, sigma)) + + #Display plot + plt.show() + + def saveFifoData(self, outList): + import csv + with open("output.csv", "wb") as f: + writer = csv.writer(f) + writer.writerows(outList) + +################################################################################################################################## +################################################################################################################################## + def acquire(self, mystruct, root_tree= None): + print "STARTING ACQUIRE LOOP" + print "Run#" , self.runN, "\n" + self.isRunning= True + index=0 + while (self.isRunning == True): + eventFifoFillLevel= self.getFifoLevel(0) + nFifoWords= int(eventFifoFillLevel) + if (nFifoWords > 0): + fifoData= self.getFifoData(nFifoWords) + outList= self.parseFifoData(fifoData, nFifoWords/6, mystruct, root_tree, False) + + time.sleep(0.1) + index= index + nFifoWords/6 + print "STOPPING ACQUIRE LOOP:", index, "events collected" + return index + + def configure(self, parsed_cfg): + print "\nTLU INITIALIZING..." + section_name= "Producer.fmctlu" + + #READ CONTENT OF EPROM VIA I2C + self.getSN() + + print " Turning on software trigger veto" + cmd = int("0x1",16) + self.setTriggerVetoStatus(cmd) + + # #Get Verbose setting + self.verbose= parsed_cfg.getint(section_name, "verbose") + + + # #SET DACs + self.writeThreshold(self.zeDAC1, parsed_cfg.getfloat(section_name, "DACThreshold0"), 1, self.verbose) + self.writeThreshold(self.zeDAC1, parsed_cfg.getfloat(section_name, "DACThreshold1"), 0, self.verbose) + self.writeThreshold(self.zeDAC2, parsed_cfg.getfloat(section_name, "DACThreshold2"), 3, self.verbose) + self.writeThreshold(self.zeDAC2, parsed_cfg.getfloat(section_name, "DACThreshold3"), 2, self.verbose) + self.writeThreshold(self.zeDAC2, parsed_cfg.getfloat(section_name, "DACThreshold4"), 1, self.verbose) + self.writeThreshold(self.zeDAC2, parsed_cfg.getfloat(section_name, "DACThreshold5"), 0, self.verbose) + + # + # #ENABLE/DISABLE HDMI OUTPUTS + self.DUTOutputs(0, int(parsed_cfg.get(section_name, "HDMI1_set"), 16) , self.verbose) + self.DUTOutputs(1, int(parsed_cfg.get(section_name, "HDMI2_set"), 16) , self.verbose) + self.DUTOutputs(2, int(parsed_cfg.get(section_name, "HDMI3_set"), 16) , self.verbose) + self.DUTOutputs(3, int(parsed_cfg.get(section_name, "HDMI4_set"), 16) , self.verbose) + + # #SELECT CLOCK SOURCE TO HDMI + self.DUTClkSrc(0, int(parsed_cfg.get(section_name, "HDMI1_clk"), 16) , self.verbose) + self.DUTClkSrc(1, int(parsed_cfg.get(section_name, "HDMI2_clk"), 16) , self.verbose) + self.DUTClkSrc(2, int(parsed_cfg.get(section_name, "HDMI3_clk"), 16) , self.verbose) + self.DUTClkSrc(3, int(parsed_cfg.get(section_name, "HDMI4_clk"), 16) , self.verbose) + + # #ENABLE/DISABLE LEMO CLOCK OUTPUT + self.enableClkLEMO(parsed_cfg.getint(section_name, "LEMOclk"), False) + + # + # #Check clock status + self.getClockStatus() + + resetClocks = 0 + resetSerdes = 0 + resetCounters= 0 + if resetClocks: + self.resetClocks() + self.getClockStatus() + if resetSerdes: + self.resetSerdes() + if resetCounters: + self.resetCounters() + + # # Get inputs status and counters + self.getChStatus() + self.getAllChannelsCounts() + + # # Stop internal triggers until setup complete + cmd = int("0x0",16) + self.setInternalTrg(cmd) + + # # Set pulse stretches + str0= parsed_cfg.getint(section_name, "in0_STR") + str1= parsed_cfg.getint(section_name, "in1_STR") + str2= parsed_cfg.getint(section_name, "in2_STR") + str3= parsed_cfg.getint(section_name, "in3_STR") + str4= parsed_cfg.getint(section_name, "in4_STR") + str5= parsed_cfg.getint(section_name, "in5_STR") + self.setPulseStretch([str0, str1, str2, str3, str4, str5]) + + # # Set pulse delays + del0= parsed_cfg.getint(section_name, "in0_DEL") + del1= parsed_cfg.getint(section_name, "in1_DEL") + del2= parsed_cfg.getint(section_name, "in2_DEL") + del3= parsed_cfg.getint(section_name, "in3_DEL") + del4= parsed_cfg.getint(section_name, "in4_DEL") + del5= parsed_cfg.getint(section_name, "in5_DEL") + self.setPulseDelay([del0, del1, del2, del3, del4, del5]) + + # # Set trigger pattern + triggerPattern_low= int(parsed_cfg.get(section_name, "trigMaskLo"), 16) + triggerPattern_high= int(parsed_cfg.get(section_name, "trigMaskHi"), 16) + self.setTrgPattern(triggerPattern_high, triggerPattern_low) + + # # Set active DUTs + DUTMask= int(parsed_cfg.get(section_name, "DutMask"), 16) + self.setDUTmask(DUTMask) + + # # Set mode (AIDA, EUDET) + DUTMode= int(parsed_cfg.get(section_name, "DUTMaskMode"), 16) + self.setMode(DUTMode) + + # # Set modifier + modifier = int(parsed_cfg.get(section_name, "DUTMaskModeModifier"), 16) + self.setModeModifier(modifier) + + # # Set veto shutter + setVetoShutters = int(parsed_cfg.get(section_name, "DUTIgnoreShutterVeto"), 16) + self.setVetoShutters(setVetoShutters) + + # # Set veto by DUT + ignoreDUTBusy = int(parsed_cfg.get(section_name, "DUTIgnoreBusy"), 16) + self.setVetoDUT(ignoreDUTBusy) + + print " Check external veto:" + self.getExternalVeto() + + # # Set trigger interval (use 0 to disable internal triggers) + triggerInterval= parsed_cfg.getint(section_name, "InternalTriggerFreq") + self.setInternalTrg(triggerInterval) + + shutterControl = int(parsed_cfg.get(section_name, "ShutterControl"), 16) + self.setShutterControl(shutterControl) + + shutterInternalInterval = int(parsed_cfg.get(section_name, "InternalShutterInterval"), 10) + self.setShutterInternalInterval(shutterInternalInterval) + + shutterOnTime = int(parsed_cfg.get(section_name, "ShutterOnTime"), 10) + self.setShutterOnTime(shutterOnTime) + + shutterVetoOffTime = int(parsed_cfg.get(section_name, "ShutterVetoOffTime"), 10) + self.setShutterVetoOffTime(shutterVetoOffTime) + + shutterOffTime = int(parsed_cfg.get(section_name, "ShutterOffTime"), 10) + self.setShutterOffTime(shutterOffTime) + + print "TLU INITIALIZED" + +################################################################################################################################## +################################################################################################################################## + def start(self, logtimestamps=False, runN=0, mystruct= None, root_tree= None): + print "TLU STARTING..." + self.runN= runN + + print " FIFO RESET:" + FIFOcmd= 0x2 + self.setFifoCSR(FIFOcmd) + eventFifoFillLevel= self.getFifoLevel() + #cmd = int("0x000",16) + #self.setInternalTrg(cmd) + + if logtimestamps: + self.setRecordDataStatus(True) + else: + self.setRecordDataStatus(False) + + # Pulse T0 + self.pulseT0() + + print " Turning off software trigger veto" + self.setTriggerVetoStatus( int("0x0",16) ) + + print "TLU STARTED" + + nEvents= self.acquire(mystruct, root_tree) + return + + +################################################################################################################################## +################################################################################################################################## + def stop(self, saveD= False, plotD= False): + print "TLU STOPPING..." + + self.getPostVetoTrg() + eventFifoFillLevel= self.getFifoLevel() + self.getFifoFlags() + self.getFifoCSR() + print " Turning on software trigger veto" + self.setTriggerVetoStatus( int("0x1",16) ) + + nFifoWords= int(eventFifoFillLevel) + fifoData= self.getFifoData(nFifoWords) + + outList= self.parseFifoData(fifoData, nFifoWords/6, None, None, True) + if saveD: + self.saveFifoData(outList) + if plotD: + self.plotFifoData(outList) + #outFile = open('./test.txt', 'w') + #for iData in range (0, 30): + # outFile.write("%s\n" % fifoData[iData]) + # print hex(fifoData[iData]) + print "TLU STOPPED" + return diff --git a/projects/TLU_v1e/scripts/TLUaddrmap.xml b/projects/TLU_v1e/scripts/TLUaddrmap.xml new file mode 120000 index 00000000..40fa0333 --- /dev/null +++ b/projects/TLU_v1e/scripts/TLUaddrmap.xml @@ -0,0 +1 @@ +../addr_table/TLUaddrmap.xml \ No newline at end of file diff --git a/projects/TLU_v1e/scripts/TLUaddrmap.xml.old b/projects/TLU_v1e/scripts/TLUaddrmap.xml.old new file mode 100644 index 00000000..65fb5340 --- /dev/null +++ b/projects/TLU_v1e/scripts/TLUaddrmap.xml.old @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<node id="TLU"> + +<!-- Registers for the DUTs. These should be correct --> +<node id="DUTInterfaces" address="0x1000" description="DUT Interfaces control registers"> + <node id="DutMaskW" address="0x0" permission="w" description="" /> + <node id="IgnoreDUTBusyW" address="0x1" permission="w" description="" /> + <node id="IgnoreShutterVetoW" address="0x2" permission="w" description="" /> + <node id="DUTInterfaceModeW" address="0x3" permission="w" description="" /> + <node id="DUTInterfaceModeModifierW" address="0x4" permission="w" description="" /> + <node id="DUTInterfaceModeR" address="0xB" permission="r" description="" /> + <node id="DUTInterfaceModeModifierR" address="0xC" permission="r" description="" /> + <node id="DutMaskR" address="0x8" permission="r" description="" /> + <node id="IgnoreDUTBusyR" address="0x9" permission="r" description="" /> + <node id="IgnoreShutterVetoR" address="0xA" permission="r" description="" /> +</node> + +<node id="Shutter" address="0x2000" description="Shutter/T0 control"> + <node id="ShutterStateW" address="0x0" permission="w" description=""/> + <node id="PulseT0" address="0x1" permission="w" description=""/> +</node> +<!-- I2C registers. Tested ok.--> +<node id="i2c_master" address="0x3000" description="I2C Master interface"> + <node id="i2c_pre_lo" address="0x0" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_pre_hi" address="0x1" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_ctrl" address="0x2" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_rxtx" address="0x3" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_cmdstatus" address="0x4" mask="0x000000ff" permission="rw" description="" /> +</node> +<!-- Not sure about the FillLevelFlags register --> +<node id="eventBuffer" address="0x4000" description="Event buffer"> + <node id="EventFifoData" address="0x0" mode="non-incremental" size="32000" permission="r" description="" /> + <node id="EventFifoFillLevel" address="0x1" permission="r" description="" /> + <node id="EventFifoCSR" address="0x2" permission="rw" description="" /> + <node id="EventFifoFillLevelFlags" address="0x3" permission="r" description="" /> +</node> +<!-- Event formatter registers. Should be ok --> +<node id="Event_Formatter" address="0x5000" description="Event formatter configuration"> + <node id="Enable_Record_Data" address="0x0" permission="rw" description="" /> + <node id="ResetTimestampW" address="0x1" permission="w" description="" /> + <node id="CurrentTimestampLR" address="0x2" permission="r" description="" /> + <node id="CurrentTimestampHR" address="0x3" permission="r" description="" /> +</node> +<!-- This needs checking. The counters work, not sure about the reset --> +<node id="triggerInputs" address="0x6000" description="Inputs configuration"> + <node id="SerdesRstW" address="0x0" permission="w" description="" /> + <node id="SerdesRstR" address="0x8" permission="r" description="" /> + <node id="ThrCount0R" address="0x9" permission="r" description="" /> + <node id="ThrCount1R" address="0xa" permission="r" description="" /> + <node id="ThrCount2R" address="0xb" permission="r" description="" /> + <node id="ThrCount3R" address="0xc" permission="r" description="" /> + <node id="ThrCount4R" address="0xd" permission="r" description="" /> + <node id="ThrCount5R" address="0xe" permission="r" description="" /> +</node> +<!-- Checked. Seems ok now, except for the TriggerVeto that do nothing.--> +<node id="triggerLogic" address="0x7000" description="Trigger logic configuration"> + <node id="PostVetoTriggersR" address="0x10" permission="r" description="" /> + <node id="PreVetoTriggersR" address="0x11" permission="r" description="" /> + <node id="InternalTriggerIntervalW" address="0x2" permission="w" description="" /> + <node id="InternalTriggerIntervalR" address="0x12" permission="r" description="" /> + <!--<node id="TriggerPatternW" address="0x3" permission="w" description="" />--> + <!--<node id="TriggerPatternR" address="0x13" permission="r" description="" />--> + <node id="TriggerVetoW" address="0x4" permission="w" description="" /> + <node id="TriggerVetoR" address="0x14" permission="r" description="" /><!--Wait, this does nothing at the moment...--> + <node id="ExternalTriggerVetoR" address="0x15" permission="r" description="" /> + <node id="PulseStretchW" address="0x6" permission="w" description="" /> + <node id="PulseStretchR" address="0x16" permission="r" description="" /> + <node id="PulseDelayW" address="0x7" permission="w" description="" /> + <node id="PulseDelayR" address="0x17" permission="r" description="" /> + <node id="TriggerHoldOffW" address="0x8" permission="W" description="" /><!--Wait, this does nothing at the moment...--> + <node id="TriggerHoldOffR" address="0x18" permission="r" description="" /><!--Wait, this does nothing at the moment...--> + <node id="AuxTriggerCountR" address="0x19" permission="r" description="" /> + <node id="TriggerPattern_lowW" address="0xA" permission="w" description="" /> + <node id="TriggerPattern_lowR" address="0x1A" permission="r" description="" /> + <node id="TriggerPattern_highW" address="0xB" permission="w" description="" /> + <node id="TriggerPattern_highR" address="0x1B" permission="r" description="" /> + + <!--<node id="PulseStretchW" address="0x6" permission="w" description="" /> OLD REGISTER MAP. WAS BUGGED--> + <!--<node id="PulseStretchR" address="0x16" permission="r" description="" /> OLD REGISTER MAP. WAS BUGGED--> + + <!-- + <node id="ResetCountersW" address="0x6" permission="w" description="" /> + <node id="PulseStretchR" address="0x17" permission="r" description="" /> + <node id="PulseStretchW" address="0x7" permission="w" description="" /> + <node id="TriggerHoldOffR" address="0x18" permission="r" description="" /> + <node id="TriggerHoldOffW" address="0x8" permission="W" description="" /> + <node id="AuxTriggerCountR" address="0x19" permission="r" description="" /> +--> +</node> + +<node id="logic_clocks" address="0x8000" description="Clocks configuration"> + <node id="LogicClocksCSR" address="0x0" permission="rw" description="" /> + <node id="LogicRst" address="0x1" permission="w" description="" /> +</node> + +<node id="version" address="0x1" description="firmware version" permission="r"> +</node> + +<!-- +PulseStretchW 0x00000066 0xffffffff 0 1 +PulseDelayW 0x00000067 0xffffffff 0 1 +PulseDelayR 0x00000077 0xffffffff 1 0 +--> +</node> diff --git a/projects/TLU_v1e/scripts/TLUconnection.xml b/projects/TLU_v1e/scripts/TLUconnection.xml new file mode 100644 index 00000000..fca67f50 --- /dev/null +++ b/projects/TLU_v1e/scripts/TLUconnection.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<connections> + <connection id="tlu" uri="ipbusudp-2.0://192.168.200.30:50001" + address_table="file://./TLUaddrmap.xml" /> +</connections> diff --git a/projects/TLU_v1e/scripts/initTLU.py b/projects/TLU_v1e/scripts/initTLU.py new file mode 100644 index 00000000..eb1ae650 --- /dev/null +++ b/projects/TLU_v1e/scripts/initTLU.py @@ -0,0 +1,184 @@ +# +# Function to initialize TLU +# +# David Cussans, October 2015 +# +# Nasty hack - use both PyChips and uHAL ( for block read ... ) + +from PyChipsUser import * +from FmcTluI2c import * + +import uhal + +import sys +import time + +def startTLU( uhalDevice , pychipsBoard , writeTimestamps): + + print "RESETTING FIFO" + pychipsBoard.write("EventFifoCSR",0x2) + eventFifoFillLevel = pychipsBoard.read("EventFifoFillLevel") + print "FIFO FILL LEVEL AFTER RESET= " , eventFifoFillLevel + + + if writeTimestamps: + print "ENABLING DATA RECORDING" + pychipsBoard.write("Enable_Record_Data",1) + else: + print "Disabling data recording" + pychipsBoard.write("Enable_Record_Data",0) + + print "Pulsing T0" + pychipsBoard.write("PulseT0",1) + + print "Turning off software trigger veto" + pychipsBoard.write("TriggerVetoW",0) + + print "TLU is running" + + +def stopTLU( uhalDevice , pychipsBoard ): + + print "Turning on software trigger veto" + pychipsBoard.write("TriggerVetoW",1) + + print "TLU triggers are stopped" + +def initTLU( uhalDevice , pychipsBoard , listenForTelescopeShutter , pulseDelay , pulseStretch , triggerPattern , DUTMask , ignoreDUTBusy , triggerInterval , thresholdVoltage ): + + print "SETTING UP AIDA TLU" + + fwVersion = uhalDevice.getNode("version").read() + uhalDevice.dispatch() + print "\tVersion (uHAL)= " , hex(fwVersion) + + print "\tTurning on software trigger veto" + pychipsBoard.write("TriggerVetoW",1) + + # Check the bus for I2C devices + pychipsBoardi2c = FmcTluI2c(pychipsBoard) + + print "\tScanning I2C bus:" + scanResults = pychipsBoardi2c.i2c_scan() + #print scanResults + print '\t', ', '.join(scanResults), '\n' + + boardId = pychipsBoardi2c.get_serial_number() + print "\tFMC-TLU serial number= " , boardId + + resetClocks = 0 + resetSerdes = 0 + +# set DACs to -200mV + print "\tSETTING ALL DAC THRESHOLDS TO" , thresholdVoltage , "V" + pychipsBoardi2c.set_threshold_voltage(7, thresholdVoltage) + + clockStatus = pychipsBoard.read("LogicClocksCSR") + print "\tCLOCK STATUS (should be 3 if all clocks locked)= " , hex(clockStatus) + assert ( clockStatus == 3 ) , "Clocks in TLU FPGA are not locked. No point in continuing. Re-prgramme or power cycle board" + + if resetClocks: + print "Resetting clocks" + pychipsBoard.write("LogicRst", 1 ) + + clockStatus = pychipsBoard.read("LogicClocksCSR") + print "Clock status after reset = " , hex(clockStatus) + + inputStatus = pychipsBoard.read("SerdesRstR") + print "Input status = " , hex(inputStatus) + + if resetSerdes: + pychipsBoard.write("SerdesRstW", 0x00000003 ) + inputStatus = pychipsBoard.read("SerdesRstR") + print "Input status during reset = " , hex(inputStatus) + + pychipsBoard.write("SerdesRstW", 0x00000000 ) + inputStatus = pychipsBoard.read("SerdesRstR") + print "Input status after reset = " , hex(inputStatus) + + pychipsBoard.write("SerdesRstW", 0x00000004 ) + inputStatus = pychipsBoard.read("SerdesRstR") + print "Input status during calibration = " , hex(inputStatus) + + pychipsBoard.write("SerdesRstW", 0x00000000 ) + inputStatus = pychipsBoard.read("SerdesRstR") + print "Input status after calibration = " , hex(inputStatus) + + + inputStatus = pychipsBoard.read("SerdesRstR") + print "\tINPUT STATUS= " , hex(inputStatus) + + count0 = pychipsBoard.read("ThrCount0R") + print "\t Count 0= " , count0 + + count1 = pychipsBoard.read("ThrCount1R") + print "\t Count 1= " , count1 + + count2 = pychipsBoard.read("ThrCount2R") + print "\t Count 2= " , count2 + + count3 = pychipsBoard.read("ThrCount3R") + print "\t Count 3= " , count3 + +# Stop internal triggers until setup complete + pychipsBoard.write("InternalTriggerIntervalW",0) + + print "\tSETTING INPUT COINCIDENCE WINDOW TO",pulseStretch,"[Units= 160MHz clock cycles, Four 5-bit values (one per input) packed in to 32-bit word]" + pychipsBoard.write("PulseStretchW",int(pulseStretch)) + pulseStretchR = pychipsBoard.read("PulseStretchR") + print "\t Pulse stretch read back as:", hex(pulseStretchR) + # assert (int(pulseStretch) == pulseStretchR) , "Pulse stretch read-back doesn't equal written value" + + print "\tSETTING INPUT TRIGGER DELAY TO",pulseDelay , "[Units= 160MHz clock cycles, Four 5-bit values (one per input) packed in to 32-bit word]" + pychipsBoard.write("PulseDelayW",int(pulseDelay)) + pulseDelayR = pychipsBoard.read("PulseDelayR") + print "\t Pulse delay read back as:", hex(pulseDelayR) + + print "\tSETTING TRIGGER PATTERN (for external triggers) TO 0x%08X. Two 16-bit patterns packed into 32 bit word " %(triggerPattern) + pychipsBoard.write("TriggerPatternW",int(triggerPattern)) + triggerPatternR = pychipsBoard.read("TriggerPatternR") + print "\t Trigger pattern read back as: 0x%08X " % (triggerPatternR) + + print "\tENABLING DUT(s): Mask= " , hex(DUTMask) + pychipsBoard.write("DUTMaskW",int(DUTMask)) + DUTMaskR = pychipsBoard.read("DUTMaskR") + print "\t DUTMask read back as:" , hex(DUTMaskR) + + print "\tSETTING ALL DUTs IN AIDA MODE" + pychipsBoard.write("DUTInterfaceModeW", 0xFF) + DUTInterfaceModeR = pychipsBoard.read("DUTInterfaceModeR") + print "\t DUT mode read back as:" , DUTInterfaceModeR + + print "\tSET DUT MODE MODIFIER" + pychipsBoard.write("DUTInterfaceModeModifierW", 0xFF) + DUTInterfaceModeModifierR = pychipsBoard.read("DUTInterfaceModeModifierR") + print "\t DUT mode modifier read back as:" , DUTInterfaceModeModifierR + + if listenForTelescopeShutter: + print "\tSET IgnoreShutterVetoW TO LISTEN FOR VETO FROM SHUTTER" + pychipsBoard.write("IgnoreShutterVetoW",0) + else: + print "\tSET IgnoreShutterVetoW TO IGNORE VETO FROM SHUTTER" + pychipsBoard.write("IgnoreShutterVetoW",1) + IgnoreShutterVeto = pychipsBoard.read("IgnoreShutterVetoR") + print "\t IgnoreShutterVeto read back as:" , IgnoreShutterVeto + + print "\tSETTING IGNORE VETO BY DUT BUSY MASK TO" , hex(ignoreDUTBusy) + pychipsBoard.write("IgnoreDUTBusyW",int(ignoreDUTBusy)) + IgnoreDUTBusy = pychipsBoard.read("IgnoreDUTBusyR") + print "\t IgnoreDUTBusy read back as:" , hex(IgnoreDUTBusy) + +#print "Enabling handshake: No-handshake" +#board.write("HandshakeTypeW",1) + + + print "\tSETTING INTERNAL TRIGGER INTERVAL TO" , triggerInterval , "(zero= no internal triggers)" + if triggerInterval == 0: + internalTriggerFreq = 0 + else: + internalTriggerFreq = 160000.0/triggerInterval + print "\tINTERNAL TRIGGER FREQUENCY= " , internalTriggerFreq , " kHz" + pychipsBoard.write("InternalTriggerIntervalW",triggerInterval) #0->Internal pulse generator disabled. Any other value will generate pulses with a frequency of n*6.25ns + trigIntervalR = pychipsBoard.read("InternalTriggerIntervalR") + print "\t Trigger interval read back as:", trigIntervalR + print "AIDA TLU SETUP COMPLETED" diff --git a/projects/TLU_v1e/scripts/localClock.txt b/projects/TLU_v1e/scripts/localClock.txt new file mode 100644 index 00000000..0a7b2d94 --- /dev/null +++ b/projects/TLU_v1e/scripts/localClock.txt @@ -0,0 +1,394 @@ +# Si538x/4x Registers Export +# +# Part: Si5345 +# Project File: P:\cad\designs\fmc-mtlu\trunk\circuit_board\Cadence\worklib\fmc_tlu_toplevel_c\physical\ClockGen\TLU_Si5345-RevB-NEWTLU00-Project.slabtimeproj +# Design ID: TLU1E_01 +# Includes Pre/Post Download Control Register Writes: Yes +# Die Revision: A2 +# Creator: ClockBuilder Pro v2.12.1 [2016-12-15] +# Created On: 2017-08-24 13:37:41 GMT+01:00 +Address,Data +0x0B24,0xD8 +0x0B25,0x00 +0x000B,0x68 +0x0016,0x02 +0x0017,0x1C +0x0018,0x88 +0x0019,0xDD +0x001A,0xDF +0x002B,0x02 +0x002C,0x07 +0x002D,0x15 +0x002E,0x37 +0x002F,0x00 +0x0030,0x37 +0x0031,0x00 +0x0032,0x37 +0x0033,0x00 +0x0034,0x00 +0x0035,0x00 +0x0036,0x37 +0x0037,0x00 +0x0038,0x37 +0x0039,0x00 +0x003A,0x37 +0x003B,0x00 +0x003C,0x00 +0x003D,0x00 +0x003F,0x77 +0x0040,0x04 +0x0041,0x0C +0x0042,0x0C +0x0043,0x0C +0x0044,0x00 +0x0045,0x0C +0x0046,0x32 +0x0047,0x32 +0x0048,0x32 +0x0049,0x00 +0x004A,0x32 +0x004B,0x32 +0x004C,0x32 +0x004D,0x00 +0x004E,0x55 +0x004F,0x05 +0x0051,0x03 +0x0052,0x03 +0x0053,0x03 +0x0054,0x00 +0x0055,0x03 +0x0056,0x03 +0x0057,0x03 +0x0058,0x00 +0x0059,0x3F +0x005A,0xCC +0x005B,0xCC +0x005C,0xCC +0x005D,0x00 +0x005E,0xCC +0x005F,0xCC +0x0060,0xCC +0x0061,0x00 +0x0062,0xCC +0x0063,0xCC +0x0064,0xCC +0x0065,0x00 +0x0066,0x00 +0x0067,0x00 +0x0068,0x00 +0x0069,0x00 +0x0092,0x00 +0x0093,0x00 +0x0095,0x00 +0x0096,0x00 +0x0098,0x00 +0x009A,0x02 +0x009B,0x30 +0x009D,0x00 +0x009E,0x20 +0x00A0,0x00 +0x00A2,0x02 +0x00A8,0x89 +0x00A9,0x70 +0x00AA,0x07 +0x00AB,0x00 +0x00AC,0x00 +0x0102,0x01 +0x0108,0x06 +0x0109,0x09 +0x010A,0x33 +0x010B,0x00 +0x010D,0x06 +0x010E,0x09 +0x010F,0x33 +0x0110,0x00 +0x0112,0x06 +0x0113,0x09 +0x0114,0x33 +0x0115,0x00 +0x0117,0x06 +0x0118,0x09 +0x0119,0x33 +0x011A,0x00 +0x011C,0x06 +0x011D,0x09 +0x011E,0x33 +0x011F,0x00 +0x0121,0x06 +0x0122,0x09 +0x0123,0x33 +0x0124,0x00 +0x0126,0x06 +0x0127,0x09 +0x0128,0x33 +0x0129,0x00 +0x012B,0x06 +0x012C,0x09 +0x012D,0x33 +0x012E,0x00 +0x0130,0x06 +0x0131,0x09 +0x0132,0x33 +0x0133,0x00 +0x013A,0x01 +0x013B,0xCC +0x013C,0x00 +0x013D,0x00 +0x013F,0x00 +0x0140,0x00 +0x0141,0x40 +0x0142,0xFF +0x0202,0x00 +0x0203,0x00 +0x0204,0x00 +0x0205,0x00 +0x0206,0x00 +0x0208,0x14 +0x0209,0x00 +0x020A,0x00 +0x020B,0x00 +0x020C,0x00 +0x020D,0x00 +0x020E,0x01 +0x020F,0x00 +0x0210,0x00 +0x0211,0x00 +0x0212,0x14 +0x0213,0x00 +0x0214,0x00 +0x0215,0x00 +0x0216,0x00 +0x0217,0x00 +0x0218,0x01 +0x0219,0x00 +0x021A,0x00 +0x021B,0x00 +0x021C,0x14 +0x021D,0x00 +0x021E,0x00 +0x021F,0x00 +0x0220,0x00 +0x0221,0x00 +0x0222,0x01 +0x0223,0x00 +0x0224,0x00 +0x0225,0x00 +0x0226,0x00 +0x0227,0x00 +0x0228,0x00 +0x0229,0x00 +0x022A,0x00 +0x022B,0x00 +0x022C,0x00 +0x022D,0x00 +0x022E,0x00 +0x022F,0x00 +0x0231,0x01 +0x0232,0x01 +0x0233,0x01 +0x0234,0x01 +0x0235,0x00 +0x0236,0x00 +0x0237,0x00 +0x0238,0x00 +0x0239,0xA9 +0x023A,0x00 +0x023B,0x00 +0x023C,0x00 +0x023D,0x00 +0x023E,0xA0 +0x024A,0x00 +0x024B,0x00 +0x024C,0x00 +0x024D,0x00 +0x024E,0x00 +0x024F,0x00 +0x0250,0x00 +0x0251,0x00 +0x0252,0x00 +0x0253,0x00 +0x0254,0x00 +0x0255,0x00 +0x0256,0x00 +0x0257,0x00 +0x0258,0x00 +0x0259,0x00 +0x025A,0x00 +0x025B,0x00 +0x025C,0x00 +0x025D,0x00 +0x025E,0x00 +0x025F,0x00 +0x0260,0x00 +0x0261,0x00 +0x0262,0x00 +0x0263,0x00 +0x0264,0x00 +0x0268,0x00 +0x0269,0x00 +0x026A,0x00 +0x026B,0x54 +0x026C,0x4C +0x026D,0x55 +0x026E,0x31 +0x026F,0x45 +0x0270,0x5F +0x0271,0x30 +0x0272,0x31 +0x0302,0x00 +0x0303,0x00 +0x0304,0x00 +0x0305,0x80 +0x0306,0x54 +0x0307,0x00 +0x0308,0x00 +0x0309,0x00 +0x030A,0x00 +0x030B,0x80 +0x030C,0x00 +0x030D,0x00 +0x030E,0x00 +0x030F,0x00 +0x0310,0x00 +0x0311,0x00 +0x0312,0x00 +0x0313,0x00 +0x0314,0x00 +0x0315,0x00 +0x0316,0x00 +0x0317,0x00 +0x0318,0x00 +0x0319,0x00 +0x031A,0x00 +0x031B,0x00 +0x031C,0x00 +0x031D,0x00 +0x031E,0x00 +0x031F,0x00 +0x0320,0x00 +0x0321,0x00 +0x0322,0x00 +0x0323,0x00 +0x0324,0x00 +0x0325,0x00 +0x0326,0x00 +0x0327,0x00 +0x0328,0x00 +0x0329,0x00 +0x032A,0x00 +0x032B,0x00 +0x032C,0x00 +0x032D,0x00 +0x032E,0x00 +0x032F,0x00 +0x0330,0x00 +0x0331,0x00 +0x0332,0x00 +0x0333,0x00 +0x0334,0x00 +0x0335,0x00 +0x0336,0x00 +0x0337,0x00 +0x0338,0x00 +0x0339,0x1F +0x033B,0x00 +0x033C,0x00 +0x033D,0x00 +0x033E,0x00 +0x033F,0x00 +0x0340,0x00 +0x0341,0x00 +0x0342,0x00 +0x0343,0x00 +0x0344,0x00 +0x0345,0x00 +0x0346,0x00 +0x0347,0x00 +0x0348,0x00 +0x0349,0x00 +0x034A,0x00 +0x034B,0x00 +0x034C,0x00 +0x034D,0x00 +0x034E,0x00 +0x034F,0x00 +0x0350,0x00 +0x0351,0x00 +0x0352,0x00 +0x0353,0x00 +0x0354,0x00 +0x0355,0x00 +0x0356,0x00 +0x0357,0x00 +0x0358,0x00 +0x0359,0x00 +0x035A,0x00 +0x035B,0x00 +0x035C,0x00 +0x035D,0x00 +0x035E,0x00 +0x035F,0x00 +0x0360,0x00 +0x0361,0x00 +0x0362,0x00 +0x0487,0x00 +0x0502,0x01 +0x0508,0x14 +0x0509,0x23 +0x050A,0x0C +0x050B,0x0B +0x050C,0x03 +0x050D,0x3F +0x050E,0x17 +0x050F,0x2B +0x0510,0x09 +0x0511,0x08 +0x0512,0x03 +0x0513,0x3F +0x0515,0x00 +0x0516,0x00 +0x0517,0x00 +0x0518,0x00 +0x0519,0xA4 +0x051A,0x02 +0x051B,0x00 +0x051C,0x00 +0x051D,0x00 +0x051E,0x00 +0x051F,0x80 +0x0521,0x21 +0x052A,0x05 +0x052B,0x01 +0x052C,0x0F +0x052D,0x03 +0x052E,0x19 +0x052F,0x19 +0x0531,0x00 +0x0532,0x42 +0x0533,0x03 +0x0534,0x00 +0x0535,0x00 +0x0536,0x08 +0x0537,0x00 +0x0538,0x00 +0x0539,0x00 +0x0802,0x35 +0x0803,0x05 +0x0804,0x00 +0x090E,0x02 +0x0943,0x00 +0x0949,0x07 +0x094A,0x07 +0x0A02,0x00 +0x0A03,0x01 +0x0A04,0x01 +0x0A05,0x01 +0x0B44,0x2F +0x0B46,0x00 +0x0B47,0x00 +0x0B48,0x08 +0x0B4A,0x1E +0x0514,0x01 +0x001C,0x01 +0x0B24,0xDB +0x0B25,0x02 diff --git a/projects/TLU_v1e/scripts/localConf.conf b/projects/TLU_v1e/scripts/localConf.conf new file mode 100644 index 00000000..3746af91 --- /dev/null +++ b/projects/TLU_v1e/scripts/localConf.conf @@ -0,0 +1,90 @@ +[Producer.fmctlu] +verbose= 1 +confid= 20170626 +delayStart= 1000 + +# HDMI pin direction: +# 4-bits to determine direction of HDMI pins +# 1-bit for the clock pair +# 0= pins are not driving signals, 1 pins drive signals (outputs) +HDMI1_set= 0x7 +HDMI2_set= 0x7 +HDMI3_set= 0x7 +HDMI4_set= 0x7 +HDMI1_clk = 1 +HDMI2_clk = 1 +HDMI3_clk = 1 +HDMI4_clk = 1 + +# Enable/disable differential LEMO CLOCK +LEMOclk = 1 + +# Set delay and stretch for trigger pulses +in0_STR = 1 +in0_DEL = 0 +in1_STR = 1 +in1_DEL = 0 +in2_STR = 1 +in2_DEL = 0 +in3_STR = 1 +in3_DEL = 0 +in4_STR = 1 +in4_DEL = 0 +in5_STR = 1 +in5_DEL = 0 +# +trigMaskHi = 0x00000000 +trigMaskLo = 0x00000002 +# +#### DAC THRESHOLD +DACThreshold0 = -0.12 +DACThreshold1 = -0.12 +DACThreshold2 = -0.12 +DACThreshold3 = -0.12 +DACThreshold4 = -0.12 +DACThreshold5 = -0.12 + +# Define which DUTs are ON +DutMask = F + +# Define mode of DUT (00 EUDET, 11 AIDA) +DUTMaskMode= 0xFFFFFFFF + +# Allow asynchronous veto +DUTMaskModeModifier= 0x0 + +# Ignore busy from a specific DUT +DUTIgnoreBusy = F + +# Ignore the SHUTTER veto on a specific DUT +DUTIgnoreShutterVeto = 0x0 + +# Generate internal triggers (in Hz, 0= no triggers) +InternalTriggerFreq = 1000000 + +ShutterControl = 3 +InternalShutterInterval = 1024 +ShutterOnTime = 200 +ShutterVetoOffTime = 300 +ShutterOffTime = 400 + +[LogCollector.log] +# Currently, all LogCollectors have a hardcoded runtime name: log +# nothing + + +[DataCollector.my_dc] +EUDAQ_MON=my_mon +# send assambled event to the monitor with runtime name my_mon; +EUDAQ_FW=native +# the format of data file +EUDAQ_FW_PATTERN=$12D_run$6R$X +# the name pattern of data file +# the $12D will be converted a data/time string with 12 digits. +# the $6R will be converted a run number string with 6 digits. +# the $X will be converted the suffix name of data file. + +[Monitor.my_mon] +EX0_ENABLE_PRINT=0 +EX0_ENABLE_STD_PRINT=0 +EX0_ENABLE_STD_CONVERTER=1 diff --git a/projects/TLU_v1e/scripts/localIni.ini b/projects/TLU_v1e/scripts/localIni.ini new file mode 100644 index 00000000..45920564 --- /dev/null +++ b/projects/TLU_v1e/scripts/localIni.ini @@ -0,0 +1,43 @@ +[Producer.fmctlu] +initid= 20170703 +verbose = 1 +ConnectionFile= "file://./../user/eudet/misc/fmctlu_connection.xml" +DeviceName="fmctlu.udp" +TLUmod= "1e" +# number of HDMI inputs, leave 4 even if you only use fewer inputs +nDUTs = 4 +nTrgIn = 6 +# 0= False (Internal Reference OFF), 1= True +intRefOn = 0 +VRefInt = 2.5 +VRefExt = 1.3 +# I2C address of the bus expander on Enclustra FPGA +I2C_COREEXP_Addr = 0x21 +# I2C address of the Si5345 +I2C_CLK_Addr = 0x68 +# I2C address of 1st AD5665R +I2C_DAC1_Addr = 0x13 +# I2C address of 2nd AD5665R +I2C_DAC2_Addr = 0x1F +# address of unique Id number EEPROM +I2C_ID_Addr = 0x50 +#I2C address of 1st expander PCA9539PW +I2C_EXP1_Addr = 0x74 +#I2C address of 2st expander PCA9539PW +I2C_EXP2_Addr = 0x75 + +##CONFCLOCK 0= skip clock configuration, 1= configure si5345 +CONFCLOCK= 0 +CLOCK_CFG_FILE = /users/phpgb/workspace/myFirmware/AIDA/TLU_v1e/scripts/localClock.txt + + +[LogCollector.log] +# Currently, all LogCollectors have a hardcoded runtime name: log +EULOG_GUI_LOG_FILE_PATTERN = myexample_$12D.log +# the $12D will be converted a data/time string with 12 digits. + +[DataCollector.my_dc] +# nothing + +[Monitor.my_mon] +# nothing diff --git a/projects/TLU_v1e/scripts/packages/AD5665R.py b/projects/TLU_v1e/scripts/packages/AD5665R.py new file mode 100644 index 00000000..d7d507de --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/AD5665R.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +import uhal +from I2CuHal import I2CCore +import StringIO + + +class AD5665R: + #Class to configure the DAC modules + + def __init__(self, i2c, slaveaddr=0x1F): + self.i2c = i2c + self.slaveaddr = slaveaddr + + + def setIntRef(self, intRef=False, verbose=False): + mystop=True + if intRef: + cmdDAC= [0x38,0x00,0x01] + else: + cmdDAC= [0x38,0x00,0x00] + self.i2c.write( self.slaveaddr, cmdDAC, mystop) + if verbose: + print "DAC int ref:", intRef + + + def writeDAC(self, dacCode, channel, verbose=False): + #Vtarget is the required voltage, channel is the DAC channel to target + #intRef indicates whether to use the external voltage reference (True) + #or the internal one (False). + + print "\tDAC value:" , hex(dacCode) + if channel<0 or channel>7: + print "writeDAC ERROR: channel",channel,"not in range 0-7 (bit mask)" + return -1 + if dacCode<0: + print "writeDAC ERROR: value",dacCode,"<0. Default to 0" + dacCode=0 + elif dacCode>0xFFFF : + print "writeDAC ERROR: value",dacCode,">0xFFFF. Default to 0xFFFF" + dacCode=0xFFFF + + sequence=[( 0x18 + ( channel &0x7 ) ) , int(dacCode/256)&0xff , int(dacCode)&0xff] + print "\tWriting DAC string:", sequence + mystop= False + self.i2c.write( self.slaveaddr, sequence, mystop) diff --git a/projects/TLU_v1e/scripts/packages/E24AA025E48T.py b/projects/TLU_v1e/scripts/packages/E24AA025E48T.py new file mode 100644 index 00000000..32cc429c --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/E24AA025E48T.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +import uhal +from I2CuHal import I2CCore +import StringIO + +class E24AA025E48T: + #Class to configure the EEPROM + + def __init__(self, i2c, slaveaddr=0x50): + self.i2c = i2c + self.slaveaddr = slaveaddr + + + def readEEPROM(self, startadd, nBytes): + #Read EEPROM memory locations + mystop= False + myaddr= [startadd]#0xfa + self.i2c.write( self.slaveaddr, [startadd], mystop) + res= self.i2c.read( self.slaveaddr, nBytes) + return res diff --git a/projects/TLU_v1e/scripts/packages/FmcTluI2c.py b/projects/TLU_v1e/scripts/packages/FmcTluI2c.py new file mode 100644 index 00000000..04bf5985 --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/FmcTluI2c.py @@ -0,0 +1,132 @@ +import time +#from PyChipsUser import * +from I2cBusProperties import * +from RawI2cAccess import * + + +class FmcTluI2c: + + + ############################ + ### configure i2c connection + ############################ + def __init__(self,board): + self.board = board + i2cClockPrescale = 0x30 + self.i2cBusProps = I2cBusProperties(self.board, i2cClockPrescale) + return + + + ########################## + ### scan all i2c addresses + ########################## + def i2c_scan(self): + list=[] + for islave in range(128): + i2cscan = RawI2cAccess(self.i2cBusProps, islave) + try: + i2cscan.write([0x00]) + device="slave address "+hex(islave)+" " + if islave==0x1f: + device+="(DAC)" + elif islave==0x50: + device+="(serial number PROM)" + elif islave>=0x54 and islave<=0x57: + device+="(sp601 onboard EEPROM)" + else: + device+="(???)" + pass + list.append(device) + pass + except: + pass + pass + return list + + + ################### + ### write to EEPROM + ################### + def eeprom_write(self,address,value): + if address<0 or address>127: + print "eeprom_write ERROR: address",address,"not in range 0-127" + return + if value<0 or value>255: + print "eeprom_write ERROR: value",value,"not in range 0-255" + return + i2cSlaveAddr = 0x50 # seven bit address, binary 1010000 + prom = RawI2cAccess(self.i2cBusProps, i2cSlaveAddr) + prom.write([address,value]) + time.sleep(0.01) # write cycle time is 5ms. let's wait 10 to make sure. + return + + + #################### + ### read from EEPROM + #################### + def eeprom_read(self,address): + if address<0 or address>255: + print "eeprom_write ERROR: address",address,"not in range 0-127" + return + i2cSlaveAddr = 0x50 # seven bit address, binary 1010000 + prom = RawI2cAccess(self.i2cBusProps, i2cSlaveAddr) + prom.write([address]) + return prom.read(1)[0] + + + ###################### + ### read serial number + ###################### + def get_serial_number(self): + result="" + for iaddr in [0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff]: + result+="%02x "%(self.eeprom_read(iaddr)) + pass + return result + + + ################# + ### set DAC value + ################# + def set_dac(self,channel,value , vrefOn = 0 , i2cSlaveAddrDac = 0x1F): + if channel<0 or channel>7: + print "set_dac ERROR: channel",channel,"not in range 0-7 (bit mask)" + return -1 + if value<0 or value>0xFFFF: + print "set_dac ERROR: value",value,"not in range 0-0xFFFF" + return -1 + # AD5665R chip with A0,A1 tied to ground + #i2cSlaveAddrDac = 0x1F # seven bit address, binary 00011111 + print "I2C address of DAC = " , hex(i2cSlaveAddrDac) + dac = RawI2cAccess(self.i2cBusProps, i2cSlaveAddrDac) + # if we want to enable internal voltage reference: + if vrefOn: + # enter vref-on mode: + print "Turning internal reference ON" + dac.write([0x38,0x00,0x01]) + else: + print "Turning internal reference OFF" + dac.write([0x38,0x00,0x00]) + # now set the actual value + sequence=[( 0x18 + ( channel &0x7 ) ) , (value/256)&0xff , value&0xff] + print sequence + dac.write(sequence) + + + + ################################################## + ### convert required threshold voltage to DAC code + ################################################## + def convert_voltage_to_dac(self, desiredVoltage, Vref=1.300): + Vdaq = ( desiredVoltage + Vref ) / 2 + dacCode = 0xFFFF * Vdaq / Vref + return int(dacCode) + + + ################################################## + ### calculate the DAC code required and set DAC + ################################################## + def set_threshold_voltage(self, channel , voltage ): + dacCode = self.convert_voltage_to_dac(voltage) + print " requested voltage, calculated DAC code = " , voltage , dacCode + self.set_dac(channel , dacCode) diff --git a/projects/TLU_v1e/scripts/packages/I2CuHal.py b/projects/TLU_v1e/scripts/packages/I2CuHal.py new file mode 100644 index 00000000..b51169a7 --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/I2CuHal.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +""" + +""" + +import time + +import uhal + +verbose = True + + + +################################################################################ +# /* +# I2C CORE +# */ +################################################################################ + + + + +class I2CCore: + """I2C communication block.""" + + # Define bits in cmd_stat register + startcmd = 0x1 << 7 + stopcmd = 0x1 << 6 + readcmd = 0x1 << 5 + writecmd = 0x1 << 4 + ack = 0x1 << 3 + intack = 0x1 + + recvdack = 0x1 << 7 + busy = 0x1 << 6 + arblost = 0x1 << 5 + inprogress = 0x1 << 1 + interrupt = 0x1 + + def __init__(self, target, wclk, i2cclk, name="i2c", delay=None): + self.target = target + self.name = name + self.delay = delay + self.prescale_low = self.target.getNode("%s.i2c_pre_lo" % name) + self.prescale_high = self.target.getNode("%s.i2c_pre_hi" % name) + self.ctrl = self.target.getNode("%s.i2c_ctrl" % name) + self.data = self.target.getNode("%s.i2c_rxtx" % name) + self.cmd_stat = self.target.getNode("%s.i2c_cmdstatus" % name) + self.wishboneclock = wclk + self.i2cclock = i2cclk + self.config() + + def state(self): + status = {} + status["ps_low"] = self.prescale_low.read() + status["ps_hi"] = self.prescale_high.read() + status["ctrl"] = self.ctrl.read() + status["data"] = self.data.read() + status["cmd_stat"] = self.cmd_stat.read() + self.target.dispatch() + status["prescale"] = status["ps_hi"] << 8 + status["prescale"] |= status["ps_low"] + for reg in status: + val = status[reg] + bval = bin(int(val)) + if verbose: + print "\treg %s = %d, 0x%x, %s" % (reg, val, val, bval) + + def clearint(self): + self.ctrl.write(0x1) + self.target.dispatch() + + def config(self): + #INITIALIZATION OF THE I2S MASTER CORE + #Disable core + self.ctrl.write(0x0 << 7) + self.target.dispatch() + #Write pre-scale register + #prescale = int(self.wishboneclock / (5.0 * self.i2cclock)) - 1 + prescale = 0x0100 #FOR NOW HARDWIRED, TO BE MODIFIED + #prescale = 0x2710 #FOR NOW HARDWIRED, TO BE MODIFIED + self.prescale_low.write(prescale & 0xff) + self.prescale_high.write((prescale & 0xff00) >> 8) + #Enable core + self.ctrl.write(0x1 << 7) + self.target.dispatch() + + def checkack(self): + inprogress = True + ack = False + while inprogress: + cmd_stat = self.cmd_stat.read() + self.target.dispatch() + inprogress = (cmd_stat & I2CCore.inprogress) > 0 + ack = (cmd_stat & I2CCore.recvdack) == 0 + return ack + + def delayorcheckack(self): + ack = True + if self.delay is None: + ack = self.checkack() + else: + time.sleep(self.delay) + ack = self.checkack()#Remove this? + return ack + +################################################################################ +# /* +# I2C WRITE +# */ +################################################################################ + + + + def write(self, addr, data, stop=True): + """Write data to the device with the given address.""" + # Start transfer with 7 bit address and write bit (0) + nwritten = -1 + addr &= 0x7f + addr = addr << 1 + startcmd = 0x1 << 7 + stopcmd = 0x1 << 6 + writecmd = 0x1 << 4 + #Set transmit register (write operation, LSB=0) + self.data.write(addr) + #Set Command Register to 0x90 (write, start) + self.cmd_stat.write(I2CCore.startcmd | I2CCore.writecmd) + self.target.dispatch() + ack = self.delayorcheckack() + if not ack: + self.cmd_stat.write(I2CCore.stopcmd) + self.target.dispatch() + return nwritten + nwritten += 1 + for val in data: + val &= 0xff + #Write slave memory address + self.data.write(val) + #Set Command Register to 0x10 (write) + self.cmd_stat.write(I2CCore.writecmd) + self.target.dispatch() + ack = self.delayorcheckack() + if not ack: + self.cmd_stat.write(I2CCore.stopcmd) + self.target.dispatch() + return nwritten + nwritten += 1 + if stop: + self.cmd_stat.write(I2CCore.stopcmd) + self.target.dispatch() + return nwritten + +################################################################################ +# /* +# I2C READ +# */ +################################################################################ + def read(self, addr, n): + """Read n bytes of data from the device with the given address.""" + # Start transfer with 7 bit address and read bit (1) + data = [] + addr &= 0x7f + addr = addr << 1 + addr |= 0x1 # read bit + self.data.write(addr) + self.cmd_stat.write(I2CCore.startcmd | I2CCore.writecmd) + self.target.dispatch() + ack = self.delayorcheckack() + if not ack: + self.cmd_stat.write(I2CCore.stopcmd) + self.target.dispatch() + return data + for i in range(n): + if i < (n-1): + self.cmd_stat.write(I2CCore.readcmd) # <--- + else: + self.cmd_stat.write(I2CCore.readcmd | I2CCore.ack | I2CCore.stopcmd) # <--- This tells the slave that it is the last word + self.target.dispatch() + ack = self.delayorcheckack() + val = self.data.read() + self.target.dispatch() + data.append(val & 0xff) + #self.cmd_stat.write(I2CCore.stopcmd) + #self.target.dispatch() + return data + +################################################################################ +# /* +# I2C WRITE-READ +# */ +################################################################################ + + + + # def writeread(self, addr, data, n): + # """Write data to device, then read n bytes back from it.""" + # nwritten = self.write(addr, data, stop=False) + # readdata = [] + # if nwritten == len(data): + # readdata = self.read(addr, n) + # return nwritten, readdata + +""" +SPI core XML: + +<node description="SPI master controller" fwinfo="endpoint;width=3"> + <node id="d0" address="0x0" description="Data reg 0"/> + <node id="d1" address="0x1" description="Data reg 1"/> + <node id="d2" address="0x2" description="Data reg 2"/> + <node id="d3" address="0x3" description="Data reg 3"/> + <node id="ctrl" address="0x4" description="Control reg"/> + <node id="divider" address="0x5" description="Clock divider reg"/> + <node id="ss" address="0x6" description="Slave select reg"/> +</node> +""" +class SPICore: + + go_busy = 0x1 << 8 + rising = 1 + falling = 0 + + + def __init__(self, target, wclk, spiclk, basename="io.spi"): + self.target = target + # Only a single data register is required since all transfers are + # 16 bit long + self.data = target.getNode("%s.d0" % basename) + self.control = target.getNode("%s.ctrl" % basename) + self.control_val = 0b0 + self.divider = target.getNode("%s.divider" % basename) + self.slaveselect = target.getNode("%s.ss" % basename) + self.divider_val = int(wclk / spiclk / 2.0 - 1.0) + self.divider_val = 0x7f + self.configured = False + + def config(self): + "Configure SPI interace for communicating with ADCs." + self.divider_val = int(self.divider_val) % 0xffff + if verbose: + print "Configuring SPI core, divider = 0x%x" % self.divider_val + self.divider.write(self.divider_val) + self.target.dispatch() + self.control_val = 0x0 + self.control_val |= 0x0 << 13 # Automatic slave select + self.control_val |= 0x0 << 12 # No interrupt + self.control_val |= 0x0 << 11 # MSB first + # ADC samples data on rising edge of SCK + self.control_val |= 0x1 << 10 # change ouput on falling edge of SCK + # ADC changes output shortly after falling edge of SCK + self.control_val |= 0x0 << 9 # read input on rising edge + self.control_val |= 0x10 # 16 bit transfers + if verbose: + print "SPI control val = 0x%x = %s" % (self.control_val, bin(self.control_val)) + self.configured = True + + def transmit(self, chip, value): + if not self.configured: + self.config() + assert chip >= 0 and chip < 8 + value &= 0xffff + self.data.write(value) + checkdata = self.data.read() + self.target.dispatch() + assert checkdata == value + self.control.write(self.control_val) + self.slaveselect.write(0xff ^ (0x1 << chip)) + self.target.dispatch() + self.control.write(self.control_val | SPICore.go_busy) + self.target.dispatch() + busy = True + while busy: + status = self.control.read() + self.target.dispatch() + busy = status & SPICore.go_busy > 0 + self.slaveselect.write(0xff) + data = self.data.read() + ss = self.slaveselect.read() + status = self.control.read() + self.target.dispatch() + #print "Received data: 0x%x, status = 0x%x, ss = 0x%x" % (data, status, ss) + return data diff --git a/projects/TLU_v1e/scripts/packages/I2cBusProperties.py b/projects/TLU_v1e/scripts/packages/I2cBusProperties.py new file mode 100644 index 00000000..a23f30cd --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/I2cBusProperties.py @@ -0,0 +1,122 @@ +########################################################## +# I2cBusProperties - simple encapsulation of all items +# required to control an I2C bus. +# +# Carl Jeske, July 2010 +# Refactored by Robert Frazier, May 2011 +########################################################## + + +class I2cBusProperties(object): + """Encapsulates details of an I2C bus master in the form of a host device, a clock prescale value, and seven I2C master registers + + Provide the ChipsBus instance to the device hosting your I2C core, a 16-bit clock prescaling + value for the Serial Clock Line (see I2C core docs for details), and the names of the seven + registers that define/control the bus (assuming these names are not the defaults specified + in the constructor below). The seven registers consist of the two clock pre-scaling + registers (PRElo, PREhi), and five bus master registers (CONTROL, TRANSMIT, RECEIVE, + COMMAND and STATUS). + + Usage: You'll need to create an instance of this class to give to a concrete I2C bus instance, such + as OpenCoresI2cBus. This I2cBusProperties class is simply a container to hold the properties + that define the bus; a class such as OpenCoresI2cBus will make use of these properties. + + Access the items stored by this class via these (deliberately compact) variable names: + + chipsBus -- the ChipsBus device hosting the I2C core + preHiVal -- the top byte of the clock prescale value + preLoVal -- the bottom byte of the clock prescale value + preHiReg -- the register the top byte of the clk prescale value (preHiVal) gets written to + preLoReg -- the register the bottom byte of the clk prescale value (preLoVal) gets written to + ctrlReg -- the I2C Control register + txReg -- the I2C Transmit register + rxReg -- the I2C Receive register + cmdReg -- the I2C Command register + statusReg -- the I2C Status register + + + Compatibility Notes: The seven register names are the registers typically required to operate an + OpenCores or similar I2C Master (Lattice Semiconductor's I2C bus master works + the same way as the OpenCores one). This software is not compatible with your + I2C bus master if it doesn't use this register interface. + """ + + def __init__(self, + chipsBusDevice, + clkPrescaleU16, + clkPrescaleLoByteReg = "i2c_pre_lo", + clkPrescaleHiByteReg = "i2c_pre_hi", + controlReg = "i2c_ctrl", + transmitReg = "i2c_tx", + receiveReg = "i2c_rx", + commandReg = "i2c_cmd", + statusReg = "i2c_status"): + + """Provide a host ChipsBus device that is controlling the I2C bus, and the names of five I2C control registers. + + chipsBusDevice: Provide a ChipsBus instance to the device where the I2C bus is being + controlled. The address table for this device must contain the five registers + that control the bus, as declared next... + + clkPrescaleU16: A 16-bit value used to prescale the Serial Clock Line based on the host + master-clock. This value gets split into two 8-bit values and ultimately will + get written to the two I2C clock-prescale registers as declared below. See + the OpenCores or Lattice Semiconductor I2C documentation for more details. + + clkPrescaleLoByteReg: The register where the lower byte of the clock prescale value is set. The default + name for this register is "i2c_pre_lo". + + clkPrescaleHiByteReg: The register where the higher byte of the clock prescale value is set. The default + name for this register is "i2c_pre_hi" + + controlReg: The CONTROL register, used for enabling/disabling the I2C core, etc. This register is + usually read and write accessible. The default name for this register is "i2c_ctrl". + + transmitReg: The TRANSMIT register, used for holding the data to be transmitted via I2C, etc. This + typically shares the same address as the RECEIVE register, but has write-only access. The default + name for this register is "i2c_tx". + + receiveReg: The RECEIVE register - allows access to the byte received over the I2C bus. This + typically shares the same address as the TRANSMIT register, but has read-only access. The + default name for this register is "i2c_rx". + + commandReg: The COMMAND register - stores the command for the next I2C operation. This typically + shares the same address as the STATUS register, but has write-only access. The default name for + this register is "i2c_cmd". + + statusReg: The STATUS register - allows monitoring of the I2C operations. This typically shares + the same address as the COMMAND register, but has read-only access. The default name for this + register is "i2c_status". + """ + + object.__init__(self) + self.chipsBus = chipsBusDevice + self.preHiVal = ((clkPrescaleU16 & 0xff00) >> 8) + self.preLoVal = (clkPrescaleU16 & 0xff) + + # Check to see all the registers are in the address table + registers = [clkPrescaleLoByteReg, clkPrescaleHiByteReg, controlReg, transmitReg, receiveReg, commandReg, statusReg] + for reg in registers: + if not self.chipsBus.addrTable.checkItem(reg): + raise ChipsException("I2cBusProperties error: register '" + reg + "' is not present in the address table of the device hosting the I2C bus master!") + + # Check that the registers we'll need to write to are indeed writable + writableRegisters = [clkPrescaleLoByteReg, clkPrescaleHiByteReg, controlReg, transmitReg, commandReg] + for wReg in writableRegisters: + if not self.chipsBus.addrTable.getItem(wReg).getWriteFlag(): + raise ChipsException("I2cBusProperties error: register '" + wReg + "' does not have the necessary write permission!") + + # Check that the registers we'll need to read from are indeed readable + readableRegisters = [clkPrescaleLoByteReg, clkPrescaleHiByteReg, controlReg, receiveReg, statusReg] + for rReg in readableRegisters: + if not self.chipsBus.addrTable.getItem(rReg).getReadFlag(): + raise ChipsException("I2cBusProperties error: register '" + rReg + "' does not have the necessary read permission!") + + # Store the various register name strings + self.preHiReg = clkPrescaleHiByteReg + self.preLoReg = clkPrescaleLoByteReg + self.ctrlReg = controlReg + self.txReg = transmitReg + self.rxReg = receiveReg + self.cmdReg = commandReg + self.statusReg = statusReg diff --git a/projects/TLU_v1e/scripts/packages/PCA9539PW.py b/projects/TLU_v1e/scripts/packages/PCA9539PW.py new file mode 100644 index 00000000..723b0ad4 --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/PCA9539PW.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +import uhal +from I2CuHal import I2CCore +import StringIO + +class PCA9539PW: + #Class to configure the expander modules + + def __init__(self, i2c, slaveaddr=0x74): + self.i2c = i2c + self.slaveaddr = slaveaddr + + + def writeReg(self, regN, regContent, verbose=False): + #Basic functionality to write to register. + if (regN < 0) | (regN > 7): + print "PCA9539PW - ERROR: register number should be in range [0:7]" + return + regContent= regContent & 0xFF + mystop=True + cmd= [regN, regContent] + self.i2c.write( self.slaveaddr, cmd, mystop) + + + def readReg(self, regN, nwords, verbose=False): + #Basic functionality to read from register. + if (regN < 0) | (regN > 7): + print "PCA9539PW - ERROR: register number should be in range [0:7]" + return + mystop=False + self.i2c.write( self.slaveaddr, [regN], mystop) + res= self.i2c.read( self.slaveaddr, nwords) + return res + + + def setInvertReg(self, regN, polarity= 0x00): + #Set the content of register 4 or 5 which determine the polarity of the + #ports (0= normal, 1= inverted). + if (regN < 0) | (regN > 1): + print "PCA9539PW - ERROR: regN should be 0 or 1" + return + polarity = polarity & 0xFF + self.writeReg(regN+4, polarity) + + def getInvertReg(self, regN): + #Read the content of register 4 or 5 which determine the polarity of the + #ports (0= normal, 1= inverted). + if (regN < 0) | (regN > 1): + print "PCA9539PW - ERROR: regN should be 0 or 1" + return + res= self.readReg(regN+4, 1) + return res + + def setIOReg(self, regN, direction= 0xFF): + #Set the content of register 6 or 7 which determine the direction of the + #ports (0= output, 1= input). + if (regN < 0) | (regN > 1): + print "PCA9539PW - ERROR: regN should be 0 or 1" + return + direction = direction & 0xFF + self.writeReg(regN+6, direction) + + def getIOReg(self, regN): + #Read the content of register 6 or 7 which determine the polarity of the + #ports (0= normal, 1= inverted). + if (regN < 0) | (regN > 1): + print "PCA9539PW - ERROR: regN should be 0 or 1" + return + res= self.readReg(regN+6, 1) + return res + + def getInputs(self, bank): + #Read the incoming values of the pins for one of the two 8-bit banks. + if (bank < 0) | (bank > 1): + print "PCA9539PW - ERROR: bank should be 0 or 1" + return + res= self.readReg(bank, 1) + return res + + def setOutputs(self, bank, values= 0x00): + #Set the content of the output flip-flops. + if (bank < 0) | (bank > 1): + print "PCA9539PW - ERROR: bank should be 0 or 1" + return + values = values & 0xFF + self.writeReg(bank+2, values) + + def getOutputs(self, bank): + #Read the state of the outputs (i.e. what value is being written to them) + if (bank < 0) | (bank > 1): + print "PCA9539PW - ERROR: bank should be 0 or 1" + return + res= self.readReg(bank+2, 1) + return res diff --git a/projects/TLU_v1e/scripts/packages/RawI2cAccess.py b/projects/TLU_v1e/scripts/packages/RawI2cAccess.py new file mode 100644 index 00000000..28461329 --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/RawI2cAccess.py @@ -0,0 +1,261 @@ +# Created on Sep 10, 2012 +# @author: Kristian Harder, based on code by Carl Jeske + +from I2cBusProperties import I2cBusProperties +from ChipsBus import ChipsBus +from ChipsLog import chipsLog +from ChipsException import ChipsException + + +class RawI2cAccess: + + def __init__(self, i2cBusProps, slaveAddr): + + # For performing read/writes over an OpenCores-compatible I2C bus master + # + # An instance of this class is required to communicate with each + # I2C slave on the I2C bus. + # + # i2cBusProps: an instance of the class I2cBusProperties that contains + # the relevant ChipsBus host and the I2C bus-master registers (if + # they differ from the defaults specified by the I2cBusProperties + # class). + # + #slaveAddr: The address of the I2C slave you wish to communicate with. + # + + self._i2cProps = i2cBusProps # The I2C Bus Properties + self._slaveAddr = 0x7f & slaveAddr # 7-bit slave address + + + def resetI2cBus(self): + + # Resets the I2C bus + # + # This function does the following: + # 1) Disables the I2C core + # 2) Sets the clock prescale registers + # 3) Enables the I2C core + # 4) Sets all writable bus-master registers to default values + + try: + self._chipsBus().queueWrite(self._i2cProps.ctrlReg, 0x00) + #self._chipsBus().getNode(self._i2cProps.ctrlReg).write(0) + self._chipsBus().queueWrite(self._i2cProps.preHiReg, + self._i2cProps.preHiVal) + self._chipsBus().queueWrite(self._i2cProps.preLoReg, + self._i2cProps.preLoVal) + self._chipsBus().queueWrite(self._i2cProps.ctrlReg, 0x80) + self._chipsBus().queueWrite(self._i2cProps.txReg, 0x00) + self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x00) + self._chipsBus().queueRun() + except ChipsException, err: + raise ChipsException("I2C reset error:\n\t" + str(err)) + + + def read(self, numBytes): + + # Performs an I2C read. Returns the 8-bit read result(s). + # + # numBytes: number of bytes expected as response + # + + try: + result = self._privateRead(numBytes) + except ChipsException, err: + raise ChipsException("I2C read error:\n\t" + str(err)) + return result + + + def write(self, listDataU8): + + # Performs an 8-bit I2C write. + # + # listDataU8: The 8-bit data values to be written. + # + + try: + self._privateWrite(listDataU8) + except ChipsException, err: + raise ChipsException("I2C write error:\n\t" + str(err)) + return + + + def _chipsBus(self): + + # Returns the instance of the ChipsBus device that's hosting + # the I2C bus master + + return self._i2cProps.chipsBus + + + def _privateRead(self, numBytes): + + # I2C read implementation. + # + # Fast I2C read implementation, + # i.e. done with the fewest packets possible. + + + # transmit reg definitions + # bits 7-1: 7-bit slave address during address transfer + # or first 7 bits of byte during data transfer + # bit 0: RW flag during address transfer or LSB during data transfer. + # '1' = reading from slave + # '0' = writing to slave + + # command reg definitions + # bit 7: Generate start condition + # bit 6: Generate stop condition + # bit 5: Read from slave + # bit 4: Write to slave + # bit 3: 0 when acknowledgement is received + # bit 2:1: Reserved + # bit 0: Interrupt acknowledge. When set, clears a pending interrupt + + # Reset bus before beginning + self.resetI2cBus() + + # Set slave address in bits 7:1, and set bit 0 to zero + # (i.e. we're writing an address to the bus) + self._chipsBus().queueWrite(self._i2cProps.txReg, + (self._slaveAddr << 1) | 0x01) + # Set start and write bit in command reg + self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x90) + # Run the queue + self._chipsBus().queueRun() + # Wait for transaction to finish. + self._i2cWaitUntilFinished() + + result=[] + for ibyte in range(numBytes): + if ibyte==numBytes-1: + stop_bit=0x40 + ack_bit=0x08 + else: + stop_bit=0 + ack_bit=0 + pass + # Set read bit, acknowledge and stop bit in command reg + self._chipsBus().write(self._i2cProps.cmdReg, 0x20+ack_bit+stop_bit) + # Wait for transaction to finish. + # Don't expect an ACK, do expect bus free at finish. + if stop_bit: + self._i2cWaitUntilFinished(requireAcknowledgement = False, + requireBusIdleAtEnd = True) + else: + self._i2cWaitUntilFinished(requireAcknowledgement = False, + requireBusIdleAtEnd = False) + pass + result.append(self._chipsBus().read(self._i2cProps.rxReg)) + + return result + + + def _privateWrite(self, listDataU8): + + # I2C write implementation. + # + # Fast I2C write implementation, + # i.e. done with the fewest packets possible. + + # transmit reg definitions + # bits 7-1: 7-bit slave address during address transfer + # or first 7 bits of byte during data transfer + # bit 0: RW flag during address transfer or LSB during data transfer. + # '1' = reading from slave + # '0' = writing to slave + + # command reg definitions + # bit 7: Generate start condition + # bit 6: Generate stop condition + # bit 5: Read from slave + # bit 4: Write to slave + # bit 3: 0 when acknowledgement is received + # bit 2:1: Reserved + # bit 0: Interrupt acknowledge. When set, clears a pending interrupt + # Reset bus before beginning + self.resetI2cBus() + + # Set slave address in bits 7:1, and set bit 0 to zero (i.e. "write mode") + self._chipsBus().queueWrite(self._i2cProps.txReg, + (self._slaveAddr << 1) & 0xfe) + # Set start and write bit in command reg + self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x90) + # Run the queue + self._chipsBus().queueRun() + # Wait for transaction to finish. + self._i2cWaitUntilFinished() + + for ibyte in range(len(listDataU8)): + dataU8 = listDataU8[ibyte] + if ibyte==len(listDataU8)-1: + stop_bit=0x40 + else: + stop_bit=0x00 + pass + # Set data to be written in transmit reg + self._chipsBus().queueWrite(self._i2cProps.txReg, (dataU8 & 0xff)) + # Set write and stop bit in command reg + self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x10+stop_bit) + # Run the queue + self._chipsBus().queueRun() + # Wait for transaction to finish. + # Do expect an ACK and do expect bus to be free at finish + if stop_bit: + self._i2cWaitUntilFinished(requireAcknowledgement = True, + requireBusIdleAtEnd = True) + else: + self._i2cWaitUntilFinished(requireAcknowledgement = True, + requireBusIdleAtEnd = False) + pass + pass + + return + + + def _i2cWaitUntilFinished(self, requireAcknowledgement = True, + requireBusIdleAtEnd = False): + + # Ensures the current bus transaction has finished successfully + # before allowing further I2C bus transactions + + # This method monitors the status register + # and will not allow execution to continue until the + # I2C bus has completed properly. It will throw an exception + # if it picks up bus problems or a bus timeout occurs. + + maxRetry = 20 + attempt = 1 + while attempt <= maxRetry: + + # Get the status + i2c_status = self._chipsBus().read(self._i2cProps.statusReg) + + receivedAcknowledge = not bool(i2c_status & 0x80) + busy = bool(i2c_status & 0x40) + arbitrationLost = bool(i2c_status & 0x20) + transferInProgress = bool(i2c_status & 0x02) + interruptFlag = bool(i2c_status & 0x01) + + if arbitrationLost: # This is an instant error at any time + raise ChipsException("I2C error: Arbitration lost!") + + if not transferInProgress: + break # The transfer looks to have completed successfully, pending further checks + + attempt += 1 + + # At this point, we've either had too many retries, or the + # Transfer in Progress (TIP) bit went low. If the TIP bit + # did go low, then we do a couple of other checks to see if + # the bus operated as expected: + + if attempt > maxRetry: + raise ChipsException("I2C error: Transaction timeout - the 'Transfer in Progress' bit remained high for too long!") + + if requireAcknowledgement and not receivedAcknowledge: + raise ChipsException("I2C error: No acknowledge received!") + + if requireBusIdleAtEnd and busy: + raise ChipsException("I2C error: Transfer finished but bus still busy!") diff --git a/projects/TLU_v1e/scripts/packages/TLU_v1e/output.csv b/projects/TLU_v1e/scripts/packages/TLU_v1e/output.csv new file mode 100644 index 00000000..e69de29b diff --git a/projects/TLU_v1e/scripts/packages/TLUaddrmap_BKP.xml b/projects/TLU_v1e/scripts/packages/TLUaddrmap_BKP.xml new file mode 100644 index 00000000..65fb5340 --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/TLUaddrmap_BKP.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<node id="TLU"> + +<!-- Registers for the DUTs. These should be correct --> +<node id="DUTInterfaces" address="0x1000" description="DUT Interfaces control registers"> + <node id="DutMaskW" address="0x0" permission="w" description="" /> + <node id="IgnoreDUTBusyW" address="0x1" permission="w" description="" /> + <node id="IgnoreShutterVetoW" address="0x2" permission="w" description="" /> + <node id="DUTInterfaceModeW" address="0x3" permission="w" description="" /> + <node id="DUTInterfaceModeModifierW" address="0x4" permission="w" description="" /> + <node id="DUTInterfaceModeR" address="0xB" permission="r" description="" /> + <node id="DUTInterfaceModeModifierR" address="0xC" permission="r" description="" /> + <node id="DutMaskR" address="0x8" permission="r" description="" /> + <node id="IgnoreDUTBusyR" address="0x9" permission="r" description="" /> + <node id="IgnoreShutterVetoR" address="0xA" permission="r" description="" /> +</node> + +<node id="Shutter" address="0x2000" description="Shutter/T0 control"> + <node id="ShutterStateW" address="0x0" permission="w" description=""/> + <node id="PulseT0" address="0x1" permission="w" description=""/> +</node> +<!-- I2C registers. Tested ok.--> +<node id="i2c_master" address="0x3000" description="I2C Master interface"> + <node id="i2c_pre_lo" address="0x0" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_pre_hi" address="0x1" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_ctrl" address="0x2" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_rxtx" address="0x3" mask="0x000000ff" permission="rw" description="" /> + <node id="i2c_cmdstatus" address="0x4" mask="0x000000ff" permission="rw" description="" /> +</node> +<!-- Not sure about the FillLevelFlags register --> +<node id="eventBuffer" address="0x4000" description="Event buffer"> + <node id="EventFifoData" address="0x0" mode="non-incremental" size="32000" permission="r" description="" /> + <node id="EventFifoFillLevel" address="0x1" permission="r" description="" /> + <node id="EventFifoCSR" address="0x2" permission="rw" description="" /> + <node id="EventFifoFillLevelFlags" address="0x3" permission="r" description="" /> +</node> +<!-- Event formatter registers. Should be ok --> +<node id="Event_Formatter" address="0x5000" description="Event formatter configuration"> + <node id="Enable_Record_Data" address="0x0" permission="rw" description="" /> + <node id="ResetTimestampW" address="0x1" permission="w" description="" /> + <node id="CurrentTimestampLR" address="0x2" permission="r" description="" /> + <node id="CurrentTimestampHR" address="0x3" permission="r" description="" /> +</node> +<!-- This needs checking. The counters work, not sure about the reset --> +<node id="triggerInputs" address="0x6000" description="Inputs configuration"> + <node id="SerdesRstW" address="0x0" permission="w" description="" /> + <node id="SerdesRstR" address="0x8" permission="r" description="" /> + <node id="ThrCount0R" address="0x9" permission="r" description="" /> + <node id="ThrCount1R" address="0xa" permission="r" description="" /> + <node id="ThrCount2R" address="0xb" permission="r" description="" /> + <node id="ThrCount3R" address="0xc" permission="r" description="" /> + <node id="ThrCount4R" address="0xd" permission="r" description="" /> + <node id="ThrCount5R" address="0xe" permission="r" description="" /> +</node> +<!-- Checked. Seems ok now, except for the TriggerVeto that do nothing.--> +<node id="triggerLogic" address="0x7000" description="Trigger logic configuration"> + <node id="PostVetoTriggersR" address="0x10" permission="r" description="" /> + <node id="PreVetoTriggersR" address="0x11" permission="r" description="" /> + <node id="InternalTriggerIntervalW" address="0x2" permission="w" description="" /> + <node id="InternalTriggerIntervalR" address="0x12" permission="r" description="" /> + <!--<node id="TriggerPatternW" address="0x3" permission="w" description="" />--> + <!--<node id="TriggerPatternR" address="0x13" permission="r" description="" />--> + <node id="TriggerVetoW" address="0x4" permission="w" description="" /> + <node id="TriggerVetoR" address="0x14" permission="r" description="" /><!--Wait, this does nothing at the moment...--> + <node id="ExternalTriggerVetoR" address="0x15" permission="r" description="" /> + <node id="PulseStretchW" address="0x6" permission="w" description="" /> + <node id="PulseStretchR" address="0x16" permission="r" description="" /> + <node id="PulseDelayW" address="0x7" permission="w" description="" /> + <node id="PulseDelayR" address="0x17" permission="r" description="" /> + <node id="TriggerHoldOffW" address="0x8" permission="W" description="" /><!--Wait, this does nothing at the moment...--> + <node id="TriggerHoldOffR" address="0x18" permission="r" description="" /><!--Wait, this does nothing at the moment...--> + <node id="AuxTriggerCountR" address="0x19" permission="r" description="" /> + <node id="TriggerPattern_lowW" address="0xA" permission="w" description="" /> + <node id="TriggerPattern_lowR" address="0x1A" permission="r" description="" /> + <node id="TriggerPattern_highW" address="0xB" permission="w" description="" /> + <node id="TriggerPattern_highR" address="0x1B" permission="r" description="" /> + + <!--<node id="PulseStretchW" address="0x6" permission="w" description="" /> OLD REGISTER MAP. WAS BUGGED--> + <!--<node id="PulseStretchR" address="0x16" permission="r" description="" /> OLD REGISTER MAP. WAS BUGGED--> + + <!-- + <node id="ResetCountersW" address="0x6" permission="w" description="" /> + <node id="PulseStretchR" address="0x17" permission="r" description="" /> + <node id="PulseStretchW" address="0x7" permission="w" description="" /> + <node id="TriggerHoldOffR" address="0x18" permission="r" description="" /> + <node id="TriggerHoldOffW" address="0x8" permission="W" description="" /> + <node id="AuxTriggerCountR" address="0x19" permission="r" description="" /> +--> +</node> + +<node id="logic_clocks" address="0x8000" description="Clocks configuration"> + <node id="LogicClocksCSR" address="0x0" permission="rw" description="" /> + <node id="LogicRst" address="0x1" permission="w" description="" /> +</node> + +<node id="version" address="0x1" description="firmware version" permission="r"> +</node> + +<!-- +PulseStretchW 0x00000066 0xffffffff 0 1 +PulseDelayW 0x00000067 0xffffffff 0 1 +PulseDelayR 0x00000077 0xffffffff 1 0 +--> +</node> diff --git a/projects/TLU_v1e/scripts/packages/TLUconnection_BKP.xml b/projects/TLU_v1e/scripts/packages/TLUconnection_BKP.xml new file mode 100644 index 00000000..fca67f50 --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/TLUconnection_BKP.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<connections> + <connection id="tlu" uri="ipbusudp-2.0://192.168.200.30:50001" + address_table="file://./TLUaddrmap.xml" /> +</connections> diff --git a/projects/TLU_v1e/scripts/packages/si5345.py b/projects/TLU_v1e/scripts/packages/si5345.py new file mode 100644 index 00000000..a1072df0 --- /dev/null +++ b/projects/TLU_v1e/scripts/packages/si5345.py @@ -0,0 +1,140 @@ +import time +import uhal +from I2CuHal import I2CCore +import StringIO +import csv + +class si5345: + #Class to configure the Si5344 clock generator + + def __init__(self, i2c, slaveaddr=0x68): + self.i2c = i2c + self.slaveaddr = slaveaddr + #self.configList= + + #def writeReg(self, address, data): + + def readRegister(self, myaddr, nwords, verbose= False): + ### Read a specific register on the Si5344 chip. There is not check on the validity of the address but + ### the code sets the correct page before reading. + + #First make sure we are on the correct page + currentPg= self.getPage() + requirePg= (myaddr & 0xFF00) >> 8 + if verbose: + print "REG", hex(myaddr), "CURR PG" , hex(currentPg[0]), "REQ PG", hex(requirePg) + if currentPg[0] != requirePg: + self.setPage(requirePg) + #Now read from register. + addr=[] + addr.append(myaddr) + mystop=False + self.i2c.write( self.slaveaddr, addr, mystop) + # time.sleep(0.1) + res= self.i2c.read( self.slaveaddr, nwords) + return res + + def writeRegister(self, myaddr, data, verbose=False): + ### Write a specific register on the Si5344 chip. There is not check on the validity of the address but + ### the code sets the correct page before reading. + ### myaddr is an int + ### data is a list of ints + + #First make sure we are on the correct page + myaddr= myaddr & 0xFFFF + currentPg= self.getPage() + requirePg= (myaddr & 0xFF00) >> 8 + #print "REG", hex(myaddr), "CURR PG" , currentPg, "REQ PG", hex(requirePg) + if currentPg[0] != requirePg: + self.setPage(requirePg) + #Now write to register. + data.insert(0, myaddr) + if verbose: + print " Writing: " + result="\t " + for iaddr in data: + result+="%#02x "%(iaddr) + print result + self.i2c.write( self.slaveaddr, data) + #time.sleep(0.01) + + def setPage(self, page, verbose=False): + #Configure the chip to perform operations on the specified address page. + mystop=True + myaddr= [0x01, page] + self.i2c.write( self.slaveaddr, myaddr, mystop) + #time.sleep(0.01) + if verbose: + print " Si5345 Set Reg Page:", page + + def getPage(self, verbose=False): + #Read the current address page + mystop=False + myaddr= [0x01] + self.i2c.write( self.slaveaddr, myaddr, mystop) + rPage= self.i2c.read( self.slaveaddr, 1) + #time.sleep(0.1) + if verbose: + print "\tPage read:", rPage + return rPage + + def getDeviceVersion(self): + #Read registers containing chip information + mystop=False + nwords=2 + myaddr= [0x02 ]#0xfa + self.setPage(0) + self.i2c.write( self.slaveaddr, myaddr, mystop) + #time.sleep(0.1) + res= self.i2c.read( self.slaveaddr, nwords) + print " Si5345 EPROM: " + result="\t" + for iaddr in reversed(res): + result+="%#02x "%(iaddr) + print result + return res + + def parse_clk(self, filename, verbose= False): + #Parse the configuration file produced by Clockbuilder Pro (Silicon Labs) + deletedcomments="""""" + if verbose: + print "\tParsing file", filename + with open(filename, 'rb') as configfile: + for i, line in enumerate(configfile): + if not line.startswith('#') : + if not line.startswith('Address'): + deletedcomments+=line + csvfile = StringIO.StringIO(deletedcomments) + cvr= csv.reader(csvfile, delimiter=',', quotechar='|') + #print "\tN elements parser:", sum(1 for row in cvr) + #return [addr_list,data_list] + # for item in cvr: + # print "rere" + # regAddr= int(item[0], 16) + # regData[0]= int(item[1], 16) + # print "\t ", hex(regAddr), hex(regData[0]) + #self.configList= cvr + regSettingList= list(cvr) + if verbose: + print "\t ", len(regSettingList), "elements" + return regSettingList + + def writeConfiguration(self, regSettingList): + print " Si5345 Writing configuration:" + #regSettingList= list(regSettingCsv) + counter=0 + for item in regSettingList: + regAddr= int(item[0], 16) + regData=[0] + regData[0]= int(item[1], 16) + print "\t", counter, "Reg:", hex(regAddr), "Data:", regData + counter += 1 + self.writeRegister(regAddr, regData, False) + + def checkDesignID(self): + regAddr= 0x026B + res= self.readRegister(regAddr, 8) + result= " Si5345 design Id:\n\t" + for iaddr in res: + result+=chr(iaddr) + print result diff --git a/projects/TLU_v1e/scripts/si5345.py b/projects/TLU_v1e/scripts/si5345.py new file mode 120000 index 00000000..6763abd8 --- /dev/null +++ b/projects/TLU_v1e/scripts/si5345.py @@ -0,0 +1 @@ +./packages/si5345.py \ No newline at end of file diff --git a/projects/TLU_v1e/scripts/startTLU_v1e.py b/projects/TLU_v1e/scripts/startTLU_v1e.py new file mode 100644 index 00000000..1961e017 --- /dev/null +++ b/projects/TLU_v1e/scripts/startTLU_v1e.py @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- +# miniTLU test script + +#from PyChipsUser import * +#from FmcTluI2c import * +import uhal +import sys +import time +from datetime import datetime +import threading +# from ROOT import TFile, TTree +# from ROOT import gROOT +from datetime import datetime + +from TLU_v1e import TLU +# Use to have interactive shell +import cmd + +# Use to have config file parser +import ConfigParser + +# Use root +from ROOT import TFile, TTree, gROOT, AddressOf +from ROOT import * +import numpy as numpy + + +## Define class that creates the command user inteface +class MyPrompt(cmd.Cmd): + + # def do_initialise(self, args): + # """Processes the INI file and writes its values to the TLU. To use a specific file type:\n + # parseIni path/to/filename.ini\n + # (without quotation marks)""" + # print "COMMAND RECEIVED: PARSE INI" + # parsed_cfg= self.open_cfg_file(args, "/users/phpgb/workspace/myFirmware/AIDA/TLU_v1e/scripts/localIni.ini") + # try: + # theID = parsed_cfg.getint("Producer.fmctlu", "initid") + # print theID + # theSTRING= parsed_cfg.get("Producer.fmctlu", "ConnectionFile") + # print theSTRING + # #TLU= TLU("tlu", theSTRING, parsed_cfg) + # except IOError: + # print "\t Could not retrieve INI data." + # return + + + def do_configure(self, args): + """Processes the CONF file and writes its values to the TLU. To use a specific file type:\n + parseIni path/to/filename.conf\n + (without quotation marks)""" + print "==== COMMAND RECEIVED: PARSE CONFIG" + #self.testme() + parsed_cfg= self.open_cfg_file(args, "./localConf.conf") + try: + theID = parsed_cfg.getint("Producer.fmctlu", "confid") + print "\t", theID + TLU.configure(parsed_cfg) + except IOError: + print "\t Could not retrieve CONF data." + return + + def do_id(self, args): + """Interrogates the TLU and prints it unique ID on screen""" + TLU.getSN() + return + + def do_triggers(self, args): + """Interrogates the TLU and prints the number of triggers seen by the input discriminators""" + TLU.getChStatus() + TLU.getAllChannelsCounts() + TLU.getPostVetoTrg() + return + + def do_startRun(self, args): + """Starts the TLU run. If a number is specified, this number will be appended to the file name as Run_#""" + print "==== COMMAND RECEIVED: STARTING TLU RUN" + #startTLU( uhalDevice = self.hw, pychipsBoard = self.board, writeTimestamps = ( options.writeTimestamps == "True" ) ) + arglist = args.split() + if len(arglist) == 0: + print "\tno run# specified, using 1" + runN= 1 + else: + runN= arglist[0] + + logdata= True + + #TLU.start(logdata) + if (TLU.isRunning): #Prevent double start + print " Run already in progress" + return + else: + now = datetime.now().strftime('%Y%m%d_%H%M%S') + default_filename = "./datafiles/"+ now + "_tluData_" + str(runN) + ".root" + rootFname= default_filename + print "OPENING ROOT FILE:", rootFname + self.root_file = TFile( rootFname, 'RECREATE' ) + # Create a root "tree" + root_tree = TTree( 'T', 'TLU Data' ) + #highWord =0 + #lowWord =0 + #evtNumber=0 + #timeStamp=0 + #evtType=0 + #trigsFired=0 + #bufPos = 0 + + #https://root-forum.cern.ch/t/long-integer/1961/2 + gROOT.ProcessLine( + "struct MyStruct {\ + UInt_t raw0;\ + UInt_t raw1;\ + UInt_t raw2;\ + UInt_t raw3;\ + UInt_t raw4;\ + UInt_t raw5;\ + UInt_t evtNumber;\ + ULong64_t tluTimeStamp;\ + UChar_t tluEvtType;\ + UChar_t tluTrigFired;\ + };" ); + + mystruct= MyStruct() + + + # Create a branch for each piece of data + root_tree.Branch('EVENTS', mystruct, 'raw0/i:raw1/i:raw2/i:raw3/i:raw4/i:raw5/i:evtNumber/i:tluTimeStamp/l:tluEvtType/b:tluTrigFired/b' ) + # root_tree.Branch( 'tluHighWord' , highWord , "HighWord/l") + # root_tree.Branch( 'tluLowWord' , lowWord , "LowWord/l") + # root_tree.Branch( 'tluExtWord' , extWord , "ExtWord/l") + # root_tree.Branch( 'tluTimeStamp' , timeStamp , "TimeStamp/l") + # root_tree.Branch( 'tluBufPos' , bufPos , "Bufpos/s") + # root_tree.Branch( 'tluEvtNumber' , evtNumber , "EvtNumber/i") + # root_tree.Branch( 'tluEvtType' , evtType , "EvtType/b") + # root_tree.Branch( 'tluTrigFired' , trigsFired, "TrigsFired/b") + #self.root_file.Write() + + daq_thread= threading.Thread(target = TLU.start, args=(logdata, runN, mystruct, root_tree)) + daq_thread.start() + + def do_endRun(self, args): + """Stops the TLU run""" + print "==== COMMAND RECEIVED: STOP TLU RUN" + if TLU.isRunning: + TLU.isRunning= False + TLU.stop(False, False) + self.root_file.Write() + self.root_file.Close() + else: + print " No run to stop" + + + def do_quit(self, args): + """Quits the program.""" + print "==== COMMAND RECEIVED: QUITTING TLU CONSOLE" + if TLU.isRunning: + TLU.isRunning= False + TLU.stop(False, False) + self.root_file.Write() + self.root_file.Close() + print "Terminating run" + return True + + def testme(self): + print "This is a test" + + def open_cfg_file(self, args, default_file): + # Parse the user arguments, attempts to opent the file and performs a (minimal) + # check to verify the file exists (but not that its content is correct) + + arglist = args.split() + if len(arglist) == 0: + print "\tno file specified, using default" + fileName= default_file + print "\t", fileName + else: + fileName= arglist[0] + if len(arglist) > 1: + print "\tinvalid: too many arguments. Max 1." + return + + parsed_file = ConfigParser.RawConfigParser() + try: + with open(fileName) as f: + parsed_file.readfp(f) + print "\t", parsed_file.sections() + except IOError: + print "\t Error while parsing the specified file." + return + return parsed_file + +# # Override methods in Cmd object ## +# def preloop(self): +# """Initialization before prompting user for commands. +# Despite the claims in the Cmd documentaion, Cmd.preloop() is not a stub. +# """ +# cmd.Cmd.preloop(self) # # sets up command completion +# self._hist = [] # # No history yet +# self._locals = {} # # Initialize execution namespace for user +# self._globals = {} +# print "\nINITIALIZING" +# now = datetime.now().strftime('%Y-%m-%dT%H_%M_%S') +# default_filename = './rootfiles/tluData_' + now + '.root' +# print "SETTING UP AIDA TLU TO SUPPLY CLOCK AND TRIGGER TO TORCH READOUT\n" +# self.manager = uhal.ConnectionManager("file://./connection.xml") +# self.hw = self.manager.getDevice("minitlu") +# self.device_id = self.hw.id() +# +# # Point to TLU in Pychips +# self.bAddrTab = AddressTable("./aida_mini_tlu_addr_map.txt") +# +# # Assume DIP-switch controlled address. Switches at 2 +# self.board = ChipsBusUdp(self.bAddrTab,"192.168.200.32",50001) + + +################################################# +if __name__ == "__main__": + print "TLU v1E MAIN" + prompt = MyPrompt() + prompt.prompt = '>> ' + + parsed_ini= prompt.open_cfg_file("", "./localIni.ini") + TLU= TLU("tlu", "file://./TLUconnection.xml", parsed_ini) + + ###TLU.configure(parsed_cfg) + ###logdata= True + ###TLU.start(logdata) + ###time.sleep(5) + ###TLU.stop(False, False) + + # Start interactive prompt + print "=+==================================================================" + print "==========================TLU TEST CONSOLE==========================" + print "+===================================================================" + prompt.cmdloop("Type 'help' for a list of commands.") diff --git a/projects/TLU_v1e/scripts/startTLU_v1e.sh b/projects/TLU_v1e/scripts/startTLU_v1e.sh new file mode 100644 index 00000000..f0bb3872 --- /dev/null +++ b/projects/TLU_v1e/scripts/startTLU_v1e.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +echo "==========================" +CURRENT_DIR=${0%/*} +echo "CURRENT DIRECTORY: " $CURRENT_DIR + +echo "============" +echo "SETTING PATHS" +#export PYTHONPATH=$CURRENT_DIR/../../../../../Python_Scripts/PyChips_1_5_0_pre2A/src:$PYTHONPATH +#export PYTHONPATH=~/Python_Scripts/PyChips_1_5_0_pre2A/src:$PYTHONPATH +export PYTHONPATH=../../packages:$PYTHONPATH +echo "PYTHON PATH= " $PYTHONPATH +export LD_LIBRARY_PATH=/opt/cactus/lib:$LD_LIBRARY_PATH +echo "LD_LIBRARY_PATH= " $LD_LIBRARY_PATH +export PATH=/usr/bin/:/opt/cactus/bin:$PATH +echo "PATH= " $PATH + +cd $CURRENT_DIR + +echo "============" +echo "STARTING PYTHON SCRIPT FOR TLU" +#python $CURRENT_DIR/startTLU_v8.py $@ + +python startTLU_v1e.py $@ +#python testTLU_script.py diff --git a/projects/TLU_v1e/scripts/startTLU_v6.py b/projects/TLU_v1e/scripts/startTLU_v6.py new file mode 100644 index 00000000..b7948f20 --- /dev/null +++ b/projects/TLU_v1e/scripts/startTLU_v6.py @@ -0,0 +1,232 @@ +# +# Script to setup AIDA TLU for TPix3 telescope <--> TORCH synchronization +# +# David Cussans, December 2012 +# +# Nasty hack - use both PyChips and uHAL ( for block read ... ) + +from PyChipsUser import * +from FmcTluI2c import * + +import uhal + +import sys + +import time + +from datetime import datetime + +from optparse import OptionParser + +# For single character non-blocking input: +import select +import tty +import termios + +from initTLU import * + +def isData(): + return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []) + +now = datetime.now().strftime('%Y-%m-%dT%H_%M_%S') +default_filename = 'tluData_' + now + '.root' +parser = OptionParser() + +parser.add_option('-r','--rootFname',dest='rootFname', + default=default_filename,help='Path of output file') +parser.add_option('-o','--writeTimestamps',dest='writeTimestamps', + default="True",help='Set True to write timestamps to ROOT file') +parser.add_option('-p','--printTimestamps',dest='printTimestamps', + default="True",help='Set True to print timestamps to screen (nothing printed unless also output to file) ') +parser.add_option('-s','--listenForTelescopeShutter',dest='listenForTelescopeShutter', + default=False,help='Set True to veto triggers when shutter goes high') +parser.add_option('-d','--pulseDelay',dest='pulseDelay', type=int, + default=0x00,help='Delay added to input triggers. Four 5-bit numbers packed into 32-bt word, Units of 6.125ns') +parser.add_option('-w','--pulseStretch',dest='pulseStretch',type=int, + default=0x00,help='Width added to input triggers. Four 5-bit numbers packed into 32-bt word. Units of 6.125ns') +parser.add_option('-t','--triggerPattern',dest='triggerPattern',type=int, + default=0xFFFEFFFE,help='Pattern match to generate trigger. Two 16-bit words packed into 32-bit word.') +parser.add_option('-m','--DUTMask',dest='DUTMask',type=int, + default=0x01,help='Three-bit mask selecting which DUTs are active.') +parser.add_option('-y','--ignoreDUTBusy',dest='ignoreDUTBusy',type=int, + default=0x0F,help='Three-bit mask selecting which DUTs can veto triggers by setting BUSY high. Low = can veto, high = ignore busy.') +parser.add_option('-i','--triggerInterval',dest='triggerInterval',type=int, + default=0,help='Interval between internal trigers ( in units of 6.125ns ). Set to zero to turn off internal triggers') +parser.add_option('-v','--thresholdVoltage',dest='thresholdVoltage',type=float, + default=-0.2,help='Threshold voltage for TLU inputs ( units of volts)') + +(options, args) = parser.parse_args(sys.argv[1:]) + +from ROOT import TFile, TTree +from ROOT import gROOT + +print "SETTING UP AIDA TLU TO SUPPLY CLOCK AND TRIGGER TO TORCH READOUT\n" + +# Point to board in uHAL +manager = uhal.ConnectionManager("file://./connection.xml") +hw = manager.getDevice("minitlu") +device_id = hw.id() + +# Point to TLU in Pychips +bAddrTab = AddressTable("./aida_mini_tlu_addr_map.txt") + +# Assume DIP-switch controlled address. Switches at 2 +board = ChipsBusUdp(bAddrTab,"192.168.200.32",50001) + +# Open Root file +print "OPENING ROOT FILE:", options.rootFname +f = TFile( options.rootFname, 'RECREATE' ) + +# Create a root "tree" +tree = TTree( 'T', 'TLU Data' ) +highWord =0 +lowWord =0 +evtNumber=0 +timeStamp=0 +evtType=0 +trigsFired=0 +bufPos = 0 + +# Create a branch for each piece of data +tree.Branch( 'tluHighWord' , highWord , "HighWord/l") +tree.Branch( 'tluLowWord' , lowWord , "LowWord/l") +tree.Branch( 'tluTimeStamp' , timeStamp , "TimeStamp/l") +tree.Branch( 'tluBufPos' , bufPos , "Bufpos/s") +tree.Branch( 'tluEvtNumber' , evtNumber , "EvtNumber/i") +tree.Branch( 'tluEvtType' , evtType , "EvtType/b") +tree.Branch( 'tluTrigFired' , trigsFired, "TrigsFired/b") + +# Initialize TLU registers +initTLU( uhalDevice = hw, pychipsBoard = board, listenForTelescopeShutter = options.listenForTelescopeShutter, pulseDelay = options.pulseDelay, pulseStretch = options.pulseStretch, triggerPattern = options.triggerPattern , DUTMask = options.DUTMask, ignoreDUTBusy = options.ignoreDUTBusy , triggerInterval = options.triggerInterval, thresholdVoltage = options.thresholdVoltage ) + +loopWait = 0.1 +oldEvtNumber = 0 + +oldPreVetotriggerCount = board.read("PreVetoTriggersR") +oldPostVetotriggerCount = board.read("PostVetoTriggersR") + +oldThresholdCounter0 =0 +oldThresholdCounter1 =0 +oldThresholdCounter2 =0 +oldThresholdCounter3 =0 + +print "STARTING POLLING LOOP" + +eventFifoFillLevel = 0 +loopRunning = True +runStarted = False + +oldTime = time.time() + +# Save old terminal settings +oldTermSettings = termios.tcgetattr(sys.stdin) +tty.setcbreak(sys.stdin.fileno()) + +while loopRunning: + + if isData(): + c = sys.stdin.read(1) + print "\tGOT INPUT:", c + if c == 't': + loopRunning = False + print "\tTERMINATING LOOP" + elif c == 'c': + runStarted = True + print "\tSTARTING RUN" + startTLU( uhalDevice = hw, pychipsBoard = board, writeTimestamps = ( options.writeTimestamps == "True" ) ) + elif c == 'f': + # runStarted = True + print "\tSTOPPING TRIGGERS" + stopTLU( uhalDevice = hw, pychipsBoard = board ) + + + if runStarted: + + eventFifoFillLevel = hw.getNode("eventBuffer.EventFifoFillLevel").read() + + preVetotriggerCount = hw.getNode("triggerLogic.PreVetoTriggersR").read() + postVetotriggerCount = hw.getNode("triggerLogic.PostVetoTriggersR").read() + + timestampHigh = hw.getNode("Event_Formatter.CurrentTimestampHR").read() + timestampLow = hw.getNode("Event_Formatter.CurrentTimestampLR").read() + + thresholdCounter0 = hw.getNode("triggerInputs.ThrCount0R").read() + thresholdCounter1 = hw.getNode("triggerInputs.ThrCount1R").read() + thresholdCounter2 = hw.getNode("triggerInputs.ThrCount2R").read() + thresholdCounter3 = hw.getNode("triggerInputs.ThrCount3R").read() + + hw.dispatch() + + newTime = time.time() + timeDelta = newTime - oldTime + oldTime = newTime + #print "time delta = " , timeDelta + preVetoFreq = (preVetotriggerCount-oldPreVetotriggerCount)/timeDelta + postVetoFreq = (postVetotriggerCount-oldPostVetotriggerCount)/timeDelta + oldPreVetotriggerCount = preVetotriggerCount + oldPostVetotriggerCount = postVetotriggerCount + + deltaCounts0 = thresholdCounter0 - oldThresholdCounter0 + oldThresholdCounter0 = thresholdCounter0 + deltaCounts1 = thresholdCounter1 - oldThresholdCounter1 + oldThresholdCounter1 = thresholdCounter1 + deltaCounts2 = thresholdCounter2 - oldThresholdCounter2 + oldThresholdCounter2 = thresholdCounter2 + deltaCounts3 = thresholdCounter3 - oldThresholdCounter3 + oldThresholdCounter3 = thresholdCounter3 + + print "pre , post veto triggers , pre , post frequency = " , preVetotriggerCount , postVetotriggerCount , preVetoFreq , postVetoFreq + + print "CURRENT TIMESTAMP HIGH, LOW (hex) = " , hex(timestampHigh) , hex(timestampLow) + + print "Input counts 0,1,2,3 = " , thresholdCounter0 , thresholdCounter1 , thresholdCounter2 , thresholdCounter3 + print "Input freq (Hz) 0,1,2,3 = " , deltaCounts0/timeDelta , deltaCounts1/timeDelta , deltaCounts2/timeDelta , deltaCounts3/timeDelta + + nEvents = int(eventFifoFillLevel)//4 # only read out whole events ( 4 x 32-bit words ) + wordsToRead = nEvents*4 + + print "FIFO FILL LEVEL= " , eventFifoFillLevel + + print "# EVENTS IN FIFO = ",nEvents + print "WORDS TO READ FROM FIFO = ",wordsToRead + + # get timestamp data and fifo fill in same outgoing packet. + timestampData = hw.getNode("eventBuffer.EventFifoData").readBlock(wordsToRead) + + hw.dispatch() + + # print timestampData + for bufPos in range (0, nEvents ): + lowWord = timestampData[bufPos*4 + 1] + 0x100000000* timestampData[ (bufPos*4) + 0] # timestamp + + highWord = timestampData[bufPos*4 + 3] + 0x100000000* timestampData[ (bufPos*4) + 2] # evt number + evtNumber = timestampData[bufPos*4 + 3] + + if evtNumber != ( oldEvtNumber + 1 ): + print "***WARNING *** Non sqeuential event numbers *** , evt,oldEvt = ", evtNumber , oldEvtNumber + + oldEvtNumber = evtNumber + + timeStamp = lowWord & 0xFFFFFFFFFFFF + + evtType = timestampData[ (bufPos*4) + 0] >> 28 + + trigsFired = (timestampData[ (bufPos*4) + 0] >> 16) & 0xFFF + + if (options.printTimestamps == "True" ): + print "bufferPos, highWord , lowWord , event-number , timestamp , evtType = %x %016x %016x %08x %012x %01x %03x" % ( bufPos , highWord , lowWord, evtNumber , timeStamp , evtType , trigsFired) + + # Fill root branch - see example in http://wlav.web.cern.ch/wlav/pyroot/tpytree.html : write raw data and decoded data for now. + tree.Fill() + + time.sleep( loopWait) + +# Fixme - at the moment infinite loop. +preVetotriggerCount = board.read("PreVetoTriggersR") +postVetotriggerCount = board.read("PostVetoTriggersR") +print "EXIT POLLING LOOP" +print "\nTRIGGER COUNT AT THE END OF RUN [pre, post]:" , preVetotriggerCount , postVetotriggerCount + +termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldTermSettings) +f.Write() +f.Close() diff --git a/projects/TLU_v1e/scripts/test.py b/projects/TLU_v1e/scripts/test.py new file mode 100644 index 00000000..ac682018 --- /dev/null +++ b/projects/TLU_v1e/scripts/test.py @@ -0,0 +1,34 @@ +import matplotlib.pyplot as plt +import numpy as np +import matplotlib.mlab as mlab + +print "TEST.py" +myFile= "./500ns_23ns.txt" + +with open(myFile) as f: + nsDeltas = map(float, f) + +P= 1000000000 #display in ns +nsDeltas = [x * P for x in nsDeltas] +centerRange= 25 +windowsns= 5 +minRange= centerRange-windowsns +maxRange= centerRange+windowsns +plt.hist(nsDeltas, 60, range=[minRange, maxRange], facecolor='blue', align='mid', alpha= 0.75) +#plt.hist(nsDeltas, 100, normed=True, facecolor='blue', align='mid', alpha=0.75) +#plt.xlim((min(nsDeltas), max(nsDeltas))) +plt.xlabel('Time (ns)') +plt.ylabel('Entries') +plt.title('Histogram DeltaTime') +plt.grid(True) + +#Superimpose Gauss +mean = np.mean(nsDeltas) +variance = np.var(nsDeltas) +sigma = np.sqrt(variance) +x = np.linspace(min(nsDeltas), max(nsDeltas), 100) +plt.plot(x, mlab.normpdf(x, mean, sigma)) +print (mean, sigma) + +#Display plot +plt.show() diff --git a/projects/TLU_v1e/scripts/testTLU_script.py b/projects/TLU_v1e/scripts/testTLU_script.py new file mode 100644 index 00000000..9d8b334b --- /dev/null +++ b/projects/TLU_v1e/scripts/testTLU_script.py @@ -0,0 +1,79 @@ +# miniTLU test script + +from FmcTluI2c import * +import uhal +import sys +import time +from I2CuHal import I2CCore +from miniTLU import MiniTLU +from datetime import datetime + +if __name__ == "__main__": + print "\tTEST TLU SCRIPT" + miniTLU= MiniTLU("minitlu", "file://./connection.xml") + #(self, target, wclk, i2cclk, name="i2c", delay=None) + TLU_I2C= I2CCore(miniTLU.hw, 10, 5, "i2c_master", None) + TLU_I2C.state() + + + #READ CONTENT OF EEPROM ON 24AA02E48 (0xFA - 0XFF) + mystop= 1 + time.sleep(0.1) + myaddr= [0xfa] + TLU_I2C.write( 0x50, myaddr, mystop) + res=TLU_I2C.read( 0x50, 6) + print "Checkin EEPROM:" + result="\t" + for iaddr in res: + result+="%02x "%(iaddr) + print result + + #SCAN I2C ADDRESSES + #WRITE PROM + #WRITE DAC + + + #Convert required threshold voltage to DAC code + #def convert_voltage_to_dac(self, desiredVoltage, Vref=1.300): + print("Writing DAC setting:") + Vref= 1.300 + desiredVoltage= 3.3 + channel= 0 + i2cSlaveAddrDac = 0x1F + vrefOn= 0 + Vdaq = ( desiredVoltage + Vref ) / 2 + dacCode = 0xFFFF * Vdaq / Vref + dacCode= 0x391d + print "\tVreq:", desiredVoltage + print "\tDAC code:" , dacCode + print "\tCH:", channel + print "\tIntRef:", vrefOn + + #Set DAC value + #def set_dac(self,channel,value , vrefOn = 0 , i2cSlaveAddrDac = 0x1F): + if channel<0 or channel>7: + print "set_dac ERROR: channel",channel,"not in range 0-7 (bit mask)" + ##return -1 + if dacCode<0 or dacCode>0xFFFF: + print "set_dac ERROR: value",dacCode ,"not in range 0-0xFFFF" + ##return -1 + # AD5665R chip with A0,A1 tied to ground + #i2cSlaveAddrDac = 0x1F # seven bit address, binary 00011111 + + # print "I2C address of DAC = " , hex(i2cSlaveAddrDac) + # dac = RawI2cAccess(self.i2cBusProps, i2cSlaveAddrDac) + # # if we want to enable internal voltage reference: + + if vrefOn: + # enter vref-on mode: + print "\tTurning internal reference ON" + #dac.write([0x38,0x00,0x01]) + TLU_I2C.write( i2cSlaveAddrDac, [0x38,0x00,0x01], 0) + else: + print "\tTurning internal reference OFF" + #dac.write([0x38,0x00,0x00]) + TLU_I2C.write( i2cSlaveAddrDac, [0x38,0x00,0x00], 0) + # Now set the actual value + sequence=[( 0x18 + ( channel &0x7 ) ) , int(dacCode/256)&0xff , int(dacCode)&0xff] + print "\tWriting byte sequence:", sequence + TLU_I2C.write( i2cSlaveAddrDac, sequence, 0) diff --git a/projects/TLU_v1e/scripts/test_T0.py b/projects/TLU_v1e/scripts/test_T0.py new file mode 100644 index 00000000..cf81b33d --- /dev/null +++ b/projects/TLU_v1e/scripts/test_T0.py @@ -0,0 +1,92 @@ +# +# Script to exercise AIDA mini-TLU +# +# David Cussans, December 2012 +# +# Nasty hack - use both PyChips and uHAL ( for block read ... ) + +from PyChipsUser import * +from FmcTluI2c import * + +import sys +import time + + +# Point to TLU in Pychips +bAddrTab = AddressTable("./aida_mini_tlu_addr_map.txt") +# Assume DIP-switch controlled address. Switches at 2 +board = ChipsBusUdp(bAddrTab,"192.168.200.32",50001) + +# Check the bus for I2C devices +boardi2c = FmcTluI2c(board) + +firmwareID=board.read("FirmwareId") + +print "Firmware (from PyChips) = " , hex(firmwareID) + +print "Scanning I2C bus:" +scanResults = boardi2c.i2c_scan() +print scanResults + +boardId = boardi2c.get_serial_number() +print "FMC-TLU serial number = " , boardId + +resetClocks = 0 + + + +clockStatus = board.read("LogicClocksCSR") +print "Clock status = " , hex(clockStatus) + +if resetClocks: + print "Resetting clocks" + board.write("LogicRst", 1 ) + + clockStatus = board.read("LogicClocksCSR") + print "Clock status after reset = " , hex(clockStatus) + + +board.write("InternalTriggerIntervalW",0) + +print "Enabling DUT 0 and 1" +board.write("DUTMaskW",3) +DUTMask = board.read("DUTMaskR") +print "DUTMaskR = " , DUTMask + +print "Ignore veto on DUT 0 and 1" +board.write("IgnoreDUTBusyW",3) +IgnoreDUTBusy = board.read("IgnoreDUTBusyR") +print "IgnoreDUTBusyR = " , IgnoreDUTBusy + +print "Turning off software trigger veto" +board.write("TriggerVetoW",0) + +print "Reseting FIFO" +board.write("EventFifoCSR",0x2) +eventFifoFillLevel = board.read("EventFifoFillLevel") +print "FIFO fill level after resetting FIFO = " , eventFifoFillLevel + +print "Enabling data recording" +board.write("Enable_Record_Data",1) + +#print "Enabling handshake: No-handshake" +#board.write("HandshakeTypeW",1) + +#TriggerInterval = 400000 +TriggerInterval = 0 +print "Setting internal trigger interval to " , TriggerInterval +board.write("InternalTriggerIntervalW",TriggerInterval) #0->Internal pulse generator disabled. Any other value will generate pulses with a frequency of n*6.25ns +trigInterval = board.read("InternalTriggerIntervalR") +print "Trigger interval read back as ", trigInterval + +print "Setting TPix_maskexternal to ignore external shutter and T0" +board.write("TPix_maskexternal",0x0003) + +numLoops = 500000 +oldEvtNumber = 0 + +for iLoop in range(0,numLoops): + + board.write("TPix_T0", 0x0001) + +# time.sleep( 1.0) diff --git a/projects/TLU_v1e/software/I2CuHal.py b/projects/TLU_v1e/software/I2CuHal.py deleted file mode 120000 index 1eea8d86..00000000 --- a/projects/TLU_v1e/software/I2CuHal.py +++ /dev/null @@ -1 +0,0 @@ -../../../../components/pdts/software/I2CuHal.py \ No newline at end of file diff --git a/projects/TLU_v1e/software/board_setup.py b/projects/TLU_v1e/software/board_setup.py deleted file mode 120000 index 3ca64cb6..00000000 --- a/projects/TLU_v1e/software/board_setup.py +++ /dev/null @@ -1 +0,0 @@ -../../../../components/pdts/software/board_setup.py \ No newline at end of file diff --git a/projects/TLU_v1e/software/check.py b/projects/TLU_v1e/software/check.py deleted file mode 100755 index 82cc5bb3..00000000 --- a/projects/TLU_v1e/software/check.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/python - -import uhal -import time -import sys - -uhal.setLogLevelTo(uhal.LogLevel.NOTICE) -manager = uhal.ConnectionManager("file://connections.xml") -hw_list = [manager.getDevice(i) for i in sys.argv[1:]] - -if len(hw_list) == 0: - print "No targets specified - I'm done" - sys.exit() - -for hw in hw_list: - print hw.id() - hw.getNode("csr.ctrl.prbs_init").write(1); - hw.dispatch() - hw.getNode("csr.ctrl.prbs_init").write(0); - hw.dispatch() - reg = hw.getNode("io.csr.stat").read() - hw.dispatch() - print hex(reg) - -while True: - - time.sleep(1) - for hw in hw_list: - reg = hw.getNode("io.csr.stat").read() - z_sfp = hw.getNode("csr.stat.zflag").read() - z_rj45 = hw.getNode("csr.stat.zflag_rj45").read() - cyc_l = hw.getNode("csr.cyc_ctr_l").read() - cyc_h = hw.getNode("csr.cyc_ctr_h").read() - sfp_l = hw.getNode("csr.sfp_ctr_l").read() - sfp_h = hw.getNode("csr.sfp_ctr_h").read() - rj45_l = hw.getNode("csr.rj45_ctr_l").read() - rj45_h = hw.getNode("csr.rj45_ctr_h").read() - hw.dispatch() - print i, hw.id(), hex(reg), hex(z_sfp), hex(z_rj45), hex(int(cyc_l) + (int(cyc_h) << 32)), hex(int(sfp_l) +(int(sfp_h) << 32)), hex(int(rj45_l) +(int(rj45_h) << 32)) diff --git a/projects/TLU_v1e/software/connections.xml b/projects/TLU_v1e/software/connections.xml deleted file mode 100644 index 9883602d..00000000 --- a/projects/TLU_v1e/software/connections.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<connections> - <connection id="DUNE_FMC_MASTER" uri="ipbusudp-2.0://192.168.200.16:50001" - address_table="file://addrtab/top.xml" /> - <connection id="DUNE_FMC_SLAVE" uri="ipbusudp-2.0://192.168.200.17:50001" - address_table="file://addrtab/top.xml" /> - <connection id="DUNE_FMC_SIM" uri="ipbusudp-2.0://192.168.201.16:50001" - address_table="file://addrtab/top_sim.xml" /> -</connections> diff --git a/projects/TLU_v1e/software/si5344.py b/projects/TLU_v1e/software/si5344.py deleted file mode 120000 index 386a5b60..00000000 --- a/projects/TLU_v1e/software/si5344.py +++ /dev/null @@ -1 +0,0 @@ -../../../../components/pdts/software/si5344.py \ No newline at end of file diff --git a/projects/TLU_v1e/software/status.py b/projects/TLU_v1e/software/status.py deleted file mode 100755 index 6252fe08..00000000 --- a/projects/TLU_v1e/software/status.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/python - -# -*- coding: utf-8 -*- -import uhal -from I2CuHal import I2CCore -import time -from si5344 import si5344 - -uhal.setLogLevelTo(uhal.LogLevel.NOTICE) -manager = uhal.ConnectionManager("file://connections.xml") -hw_tx = manager.getDevice("DUNE_FMC_TX") -hw_rx = manager.getDevice("DUNE_FMC_RX") - -for hw in [hw_tx, hw_rx]: - print hw.id() - reg = hw.getNode("io.csr.stat").read() - hw.dispatch() - print hex(reg) -- GitLab