from __future__ import print_function from __future__ import division ''' # Copyright (C) 2016, Elphel.inc. # Control for the VSC3304 in 393 camera, # NOTE: different connections in 10389 rev 0 and revs A/B # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. @author: Andrey Filippov @copyright: 2015 Elphel, Inc. @license: GPLv3.0+ @contact: andrey@elphel.coml @deffield updated: Updated ''' __author__ = "Andrey Filippov" __copyright__ = "Copyright 2015, Elphel, Inc." __license__ = "GPL" __version__ = "3.0+" __maintainer__ = "Andrey Filippov" __email__ = "andrey@elphel.com" __status__ = "Development" import os from x393_mem import X393Mem #from time import sleep #import shutil VSC_DIR_OLD="/sys/devices/amba.0/e0004000.ps7-i2c/i2c-0/0-0001" VSC_DIR_NEW="/sys/devices/soc0/amba@0/e0004000.ps7-i2c/i2c-0/0-0001" # 10389 rev "0" VSC_DIR = None class x393_vsc3304(object): DRY_MODE= True # True DEBUG_MODE=1 x393_mem=None PCB_CONNECTIONS = { "10389": { "INVERTED_PORTS": ("D","E","G","H"), "ESATA_A": "C", "ESATA_B": "D", "SSD_A": "E", "SSD_B": "F", "ZYNQ_A": "G", "ZYNQ_B": "H"}, "10389B": { "INVERTED_PORTS": ("A","E","G","H"), "ESATA_A": "A", "ESATA_B": "C", "SSD_A": "E", "SSD_B": "F", "ZYNQ_A": "G", "ZYNQ_B": "H"}, } PORT_NUM = {"A":{"OUT": 8,"IN":12}, # I/O port numbers for each port name "B":{"OUT": 9,"IN":13}, "C":{"OUT":10,"IN":14}, "D":{"OUT":11,"IN":15}, "E":{"OUT":12,"IN": 8}, "F":{"OUT":13,"IN": 9}, "G":{"OUT":14,"IN":10}, "H":{"OUT":15,"IN":11}} VSC3304_CONNECTIONS = { "IDLE" : [], "ESATA<->SSD": [{"FROM": "SSD_B", "TO": "ESATA_B"}, {"FROM": "ESATA_A", "TO": "SSD_A"}], "ZYNQ<->SSD": [{"FROM": "ZYNQ_A", "TO": "SSD_A" }, {"FROM": "SSD_B", "TO": "ZYNQ_B"}], "ZYNQ<->ESATA":[{"FROM": "ZYNQ_A", "TO": "ESATA_A" }, {"FROM": "ESATA_B", "TO": "ZYNQ_B"}], "DEBUG_SSD": [{"FROM": "ZYNQ_A", "TO": "SSD_A" }, {"FROM": "SSD_B", "TO": "ZYNQ_B"}, {"FROM": "ZYNQ_A", "TO": "ESATA_A"}, # Copy to external connector for the oscilloscope {"FROM": "SSD_B", "TO": "ESATA_B"}, # Copy to external connector for the oscilloscope ], } PCB_REV = "10389" current_mode = "ESATA<->SSD" def __init__(self, debug_mode=1,dry_mode=False, pcb_rev = "10389"): global VSC_DIR self.DEBUG_MODE=debug_mode if not dry_mode: if not os.path.exists("/dev/xdevcfg"): dry_mode=True print("Program is forced to run in SIMULATED mode as '/dev/xdevcfg' does not exist (not a camera)") else: if os.path.exists(VSC_DIR_OLD): print ('x393_vsc3304: Running on OLD system') VSC_DIR = VSC_DIR_OLD elif os.path.exists(VSC_DIR_NEW): print ('x393_vsc3304: Running on NEW system') VSC_DIR = VSC_DIR_NEW else: print ("Does not seem to be a known system - both %s (old) and %s (new) are not found"%(VSC_DIR_OLD, VSC_DIR_NEW)) return self.DRY_MODE=dry_mode self.x393_mem=X393Mem(debug_mode,dry_mode, 1) if not pcb_rev in self.PCB_CONNECTIONS: print ("Unknown PCB/rev: %s (defined: %s), using %s"%(pcb_rev, str(self.PCB_CONNECTIONS.keys()),self.PCB_REV)) else: self.PCB_REV = pcb_rev def echo(self, what, where): if self.DRY_MODE: print ("'%s' -> '%s'"%(str(what), VSC_DIR+"/"+where)) else: print ("'%s' -> '%s'"%(str(what), VSC_DIR+"/"+where)) with open (VSC_DIR+"/"+where,"w") as f: print (str(what),file=f) def read_vals(self, path): with open(VSC_DIR+"/"+path, 'r') as f: line = f.readline().replace('\n', '') rslt = [] for s in line.split(): rslt.append(int(s)) return rslt def out_port (self, port_name): return "port_%02d"%(self.PORT_NUM[port_name]["OUT"]) def in_port (self, port_name): return "port_%02d"%(self.PORT_NUM[port_name]["IN"]) def in_port_number (self, port_name): return self.PORT_NUM[port_name]["IN"] def port_name(self, diff_pair): return self.PCB_CONNECTIONS[self.PCB_REV][diff_pair] def inverted_ports(self): return self.port_name('INVERTED_PORTS') def reinit(self): #Issue soft reset and re-initialize VSC3304 registers to idle mode self.echo("1","control/soft_reset") for port_letter in self.inverted_ports(): self.echo("1", "input_state_invert/"+self.in_port(port_letter)) self.echo("10","output_mode/"+self.out_port(port_letter)) self.echo("1", "forward_OOB/all") self.current_mode = "IDLE" def connect(self, mode): # Disconnect all existing connections self.echo("1", "input_state_off/all") self.echo("16","connections/all") defconn= "IDLE" try: conns = self.VSC3304_CONNECTIONS[mode] except: print("Invalid connections: %s (defined are: %s), using %s"%(mode, str(self.VSC3304_CONNECTIONS.keys()), defconn)) mode = defconn conns = self.VSC3304_CONNECTIONS[mode] print(str(conns)) #activate inputs for conn in conns: self.echo("0", "input_state_off/"+self.in_port(self.port_name (conn["FROM"]))) #set crosspoint connections for conn in conns: self.echo(self.in_port_number(self.port_name (conn["FROM"])), "connections/"+self.out_port(self.port_name (conn["TO"]))) self.current_mode = mode def disconnect_all(self): self.connect("IDLE") def connect_esata_ssd(self): self.connect("ESATA<->SSD") def connect_zynq_ssd(self): self.connect("ZYNQ<->SSD") def connect_zynq_esata(self): self.connect("ZYNQ<->ESATA") def connect_debug(self): self.connect("DEBUG_SSD") def connection_status(self): print("VSC3304 state: %s"%(self.current_mode)) conns = self.VSC3304_CONNECTIONS[self.current_mode] for conn in conns: in_port = self.in_port(self.port_name (conn["FROM"])) loss = self.read_vals("status/"+in_port)[0] print ("%s -> %s : %s"%(conn["FROM"],conn["TO"], ('ACTIVE','LOST')[loss]))