#!/usr/bin/python
#coding: utf8

# Copyright Seven Solutions S.L., 2012
# Author: Richard Carrillo <rcarrillo(AT)sevensols.com>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Website: http://www.sevensols.com
# Version: 0.1 (Last modifications: 1/4/2012)


from ptsexcept import *
from dio_fmc import *

import rr
import os

"""
test03: Check fmc-dio-5chttl-board ports as inputs (DAC, LVDS comparator)
Conditions: fmc-dio-5chttl-board ports work as outputs (test02 passed) and I2C bus works (test00 passed)
User intervention required: No
Procedure details:
- Load firmware.
- Test mezzanine presence line.
- Check the voltage of all ports (be means of the DAC) when port output set to 0 and when it is set to 1
"""

class test03:
   def __init__(self, spec):
      """ check FMC PRESENT-pin state """
      try:
         self.dio = CFmcDio(spec, 0x80000, True)
      except CFmcDioError as e:
         err_msg="While fmc-dio-5chttla initialization: "+str(e)
         if e.bus_name == "FMC":
            raise PtsCritical(err_msg) # Critical error: the fmc-dio-5chttl-board is apparently not present
         else:
            raise PtsError(err_msg) # Non-critical error: further tests could be performed successfully

   def test_port_in(self):
      """ Port (LEMO 00 connectors) input check """
      print "Ensure that nothing is connected to the fmc-dio-5chttla-board ports"
      print "(Termination resistors disabled, port outputs enabled)"
      port_th=[]
      port_warnlow=[]
      port_warnhigh=[]
      for lemon in range(5):
         self.dio.set_term(lemon, 0) # Disable termination resistor
         self.dio.set_out(lemon,0) # set port output value to 0
         self.dio.set_dir(lemon,1) # Enable port output
         try:
            th0=self.dio.find_port_voltage(lemon,0.0,0.08)  # Find the voltage (threshold) when out=0
            self.dio.set_out(lemon,1) # set port output state to 1
            th1=self.dio.find_port_voltage(lemon,3.28,3.3)  # Find the voltage (threshold) when out=1
         except CFmcDioError as e:
            print str(e)
            raise PtsError("While setting CDAC5578 channel value: "+str(e))
         self.dio.set_dir(lemon,0) # Disable port output
         if th0>0.1:
            th0_warn="Warning: Strangely-high value "
            port_warnhigh.append(lemon)
         else:
            th0_warn="OK "
         if th1<3.2:
            th1_warn="Warning: Strangely-low value "
            port_warnlow.append(lemon)
         else:
            th1_warn="OK"
         print "Port {} apparent input voltage when out=0: {:.3f}V {}".format(lemon,th0,th0_warn)
         print "\t\t\t      when out=1: {:.3f}V {}".format(th1,th1_warn)
         port_th.insert(lemon,[th0,th1])
      port_err=[]
      for lemon in range(len(port_th)):
         if port_th[lemon][0]>0.8 or port_th[lemon][1]<2.0: # normal operating conditions
            port_err.append(lemon)
      if port_err: # Some errors were detected
         ret_error=["E","TSTERR02: Proper voltage reading not obtained in ports: {} when output enable=1".format(port_err)]
         print ret_error[1]
      else:
         if port_warnlow or port_warnhigh: # Some warning were generated
            warn_msg=""	
            if port_warnlow:
               warn_msg=warn_msg+"TSTWRN00: Strangely-low voltage value obtained in ports: {} when output=1. ".format(port_warnlow)
            if port_warnhigh:
               warn_msg=warn_msg+"TSTWRN01: Strangely-high voltage value obtained in ports: {} when output=0. ".format(port_warnhigh)
            ret_error=["W",warn_msg]
         else:
            ret_error=None
      return ret_error

def main(default_directory="."):
   # Configure the FPGA using the program fpga_loader
   path_fpga_loader = '../firmwares/fpga_loader'
   path_firmware = '../firmwares/spec_top.bin'
   firmware_loader = os.path.join(default_directory, path_fpga_loader)
   bitstream = os.path.join(default_directory, path_firmware)
   print "Loading firmware: %s" % (firmware_loader + ' ' + bitstream)
   os.system( firmware_loader + ' ' + bitstream )

   # Load board library and open the corresponding device
   print "Loading hardware access library and opening device\n"
   spec = rr.Gennum()

   print "Test Start"

   init_test_time = time.time()
   print "Configuring and checking fmc-dio-5chttla devices"
   test=test03(spec)

   print "\nChecking input operation of board ports"
   ret_error=test.test_port_in()

   end_test_time = time.time()
   print "\nEnd of Test"
   print "RESULT: [{}]".format("FAIL" if ret_error and ret_error[0]=="E" else ("OK with warnings" if ret_error and ret_error[0]=="W" else "OK"))
   print 'Test03 elapsed time: {:.2f} seconds'.format(end_test_time-init_test_time)
   if ret_error:
      if ret_error[0]=="W": # Warning message returned by test funciton
         raise PtsWarning(ret_error[1])
      else:  # Error message returned by test funciton
         raise PtsError(ret_error[1])

if __name__ == "__main__":
    main(".")

