##_______________________________________________________________________________________________ ## ## CONV-TTL-RS485 PTS ## ## CERN,BE/CO-HT ##_______________________________________________________________________________________________ ## ##----------------------------------------------------------------------------------------------- ## ## CONV-TTL-RS485 LEDs test ## ##----------------------------------------------------------------------------------------------- ## ## Description Testing the rear-transition module interface of the CONV-TTL-RS485 front module ## board. This is done in conjunction with gateware implemented on the ## CONV-TTL-RS485 FPGA. ## ## The gateware implements pulse repeaters which are controlled by this script to ## send pulses back to inputs. Externally to the RTM, there should be two boards ## containing differential multiplexers, and these are controlled by the FPGA HDL ## through this script such that each channel sends pulses back to itself, in the ## sequence Out1->In, Out2->In, Out3->In. ## ## In short, what this script does is to turn on pulse repetition, sleep for a ## predefined amount of time, and then check that the same number of pulses that has ## been sent at the channel output are received at its input. The checking is done by ## reading the input and output channel pulse counters, implemented in the FPGA HDL. ## Checking is done with input and output terminations ON and OFF (one run of the same ## test sequence for both). ## ## Authors Julian Lewis (Julian.Lewis@cern.ch) ## Theodor-Adrian Stana (t.stana@cern.ch) ## Website http://www.ohwr.org/projects/pts ## Date 11/11/2014 ##----------------------------------------------------------------------------------------------- ## ##------------------------------------------------------------------------------------------------ ## GNU LESSER GENERAL PUBLIC LICENSE ## ------------------------------------ ## This source file is free software; you can redistribute it and/or modify it under the terms of ## the GNU Lesser General Public License as published by the Free Software Foundation; either ## version 2.1 of the License, or (at your option) any later version. ## This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ## without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ## See the GNU Lesser General Public License for more details. ## You should have received a copy of the GNU Lesser General Public License along with this ## source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html ##------------------------------------------------------------------------------------------------- # Import system modules import sys sys.path.append("pyts") import time # Import common modules from ptsexcept import * from vv_pts import * from ptsdefine import * #-------------------------------------------------------------------------------------------------- # Pulse counter class #-------------------------------------------------------------------------------------------------- class CPulseCounter: def __init__(self, bus, base): self.bus = bus self.base = base def wr_reg(self, addr, val): self.bus.vv_write(self.base + addr,val) def rd_reg(self, addr): return self.bus.vv_read(self.base + addr) def wr_out_cnt(self, chan, val): return self.wr_reg((chan-1)*8, val) def wr_in_cnt(self, chan, val): return self.wr_reg((chan-1)*8 + 4, val) def rd_out_cnt(self, chan): return self.rd_reg((chan-1)*8) def rd_in_cnt(self, chan): return self.rd_reg((chan-1)*8 + 4) #-------------------------------------------------------------------------------------------------- # Test sequences #-------------------------------------------------------------------------------------------------- def mux_sel(bus, sel): val = bus.vv_read(CSR) val &= ~(1 << CSR_TSTCS0_OFS) val &= ~(1 << CSR_TSTCS1_OFS) if (sel & 0x1): val |= (1 << CSR_TSTCS0_OFS) if (sel & 0x2): val |= (1 << CSR_TSTCS1_OFS) bus.vv_write(CSR, val) time.sleep(0.1) def en_pulse_gen(bus): val = bus.vv_read(CSR) val |= (1 << CSR_REARPT_OFS) bus.vv_write(CSR, val) time.sleep(0.1) def dis_pulse_gen(bus): val = bus.vv_read(CSR) val &= ~(1 << CSR_REARPT_OFS) bus.vv_write(CSR, val) time.sleep(0.1) def clear_counters(bus): pc = CPulseCounter(bus, PULSE_CNT_BASE) # Clear pulse counters for the TTL channels for i in range(11, 17): pc.wr_out_cnt(i, 0) pc.wr_in_cnt(i, 0) def check_counters(bus, inf, pel): pc = CPulseCounter(bus, PULSE_CNT_BASE) ic_arr = [] oc_arr = [] for i in range(11, 17): ic_arr.append(pc.rd_in_cnt(i)) oc_arr.append(pc.rd_out_cnt(i)) # First, check for all-zeroes in counters, indicating enable NAND gate failure if all(ic == 0 for ic in ic_arr): msg = "ERROR: No pulses received - check tester board connection, or enable NAND gate IC8" pel.set(msg) else: for i in range(len(ic_arr)): if (ic_arr[i] == oc_arr[i]): msg = "Ch%d input counter (%d) matches the output counter (%d) - good\n" % (i+1, ic_arr[i], oc_arr[i]) inf.write(msg) else: msg = "ERROR: Ch%d input counter (%d) does not match output counter (%d)"% (i+1, ic_arr[i], oc_arr[i]) pel.set(msg) def pulse_test(bus, inf, pel, output, term): if (output == 1): disp = 3 elif (output == 2): disp = 2 elif (output == 3): disp = 1 msg = "Testing channel connections: O%d -> IN" % (disp) print(msg) mux_sel(bus, output) clear_counters(bus) inf.write('\n') inf.write(msg+'\n') en_pulse_gen(bus) time.sleep(2) dis_pulse_gen(bus) check_counters(bus, inf, pel) time.sleep(1) ##------------------------------------------------------------------------------------------------- ## main -- ##------------------------------------------------------------------------------------------------- def main(bus, tname, inf, log): """ tests : RS-485 pulse repetition, RS-485 transceivers IC31-IC56, solid-state switches IC56-IC75, solid-state switches IC23-IC28, RS-485 transceivers IC16-IC21, Schmitt trigger inputs IC30, IC45, NAND gate IC8, IC69 Schmitt trigger for the RTM detection lines uses : pts.bit and rs485_pulse_rtm.py """ pel = PTS_ERROR_LOGGER(inf, log) try: # Read RTM lines rtm = (bus.vv_read(CSR) >> CSR_RTM_OFS) & 0x3f if (rtm == 0x09): msg = "RTM detection lines read correctly: 0x%02X" % rtm inf.write(msg+'\n') else: msg = "ERROR: RTM detection lines readout (0x%02X) incorrect - expected 0x09. Check RTM presence or IC69" % rtm pel.set(msg) return pel.get() # First, clear the pulse counters clear_counters(bus) # Ask the user to make the daisy-chain print("Connect the LEMO cable as follows:") print(" - BLU cable to INV-TTL CH A") print(" - GRN cable to INV-TTL CH B") print(" - RED cable to INV-TTL CH C") print(" - YEL cable to INV-TTL CH D") reply = raw_input("Have the connections been made? (yes/no) ") while (1): if "yes" in reply.lower(): break if "no" in reply.lower(): msg = "ERROR: Control connections to RS485 tester not made" pel.set(msg) return pel.get() else: reply = raw_input('Please type "yes" or "no" to continue: ') # Power on the tester card val = bus.vv_read(CSR) val |= (1 << CSR_TSTCVCC_OFS) bus.vv_write(CSR, val) time.sleep(1) # Start running tests (front module terminations off) term = "OFF" inf.write('\n') # Read out fail-safe lines -- should now be high, since the MUXes are # powered but not enabled msg = "Testing RS-485 fail-safe on open-connection case" print(msg) inf.write('\n') inf.write(msg+'\n') val = bus.vv_read(LSR) val >>= LSR_REARFS_OFS if (val == 0x3f): msg = "RS-485 failsafe lines read as expected: 0x%02X\n" % val inf.write(msg) else: msg = "ERROR: Failsafe lines readout (0x%02X) incorrect - expected 0x3F" % val pel.set(msg) # Enable multiplexer print("Enabling multiplexers") val = bus.vv_read(CSR) val |= (1 << CSR_TSTCMUXEN_OFS) bus.vv_write(CSR, val) time.sleep(1) # Fail-safe test msg = "Testing RS-485 fail-safe on short-circuit case" print(msg) mux_sel(bus, 0x0) inf.write('\n') inf.write(msg+'\n') val = bus.vv_read(LSR) val >>= LSR_REARFS_OFS if (val == 0x3f): msg = "RS-485 failsafe lines read as expected: 0x%02X\n" % val inf.write(msg) else: msg = "ERROR: Failsafe lines readout (0x%02X) incorrect - expected 0x3F" % val pel.set(msg) time.sleep(1) # Generate pulses & test correct reception pulse_test(bus, inf, pel, 1, term) pulse_test(bus, inf, pel, 2, term) pulse_test(bus, inf, pel, 3, term) # Disable multiplexer print("Disabling multiplexers") val = bus.vv_read(CSR) val &= ~(1 << CSR_TSTCMUXEN_OFS) bus.vv_write(CSR, val) time.sleep(1) return pel.get() except BusException, e: raise PtsError("SKT Exception: %s" % e) except BusWarning, e: raise PtsError("SKT Warning: %s" % e) finally: val = bus.vv_read(CSR) val &= ~(1 << CSR_TSTCVCC_OFS) val &= ~(1 << CSR_TSTCMUXEN_OFS) val &= ~(1 << CSR_TSTCS0_OFS) val &= ~(1 << CSR_TSTCS1_OFS) bus.vv_write(CSR, val)