#!   /usr/bin/env   python

# Copyright Creotech SA, 2016
# Author: Marek Guminski <marek.guminski@creotech.pl>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org


import spec
import fmcmasterfip as fmc
import utilities as util
import time

DEL = 0.5
NRSAMPLES = 10

###############################################################################

def test_sync_input( dut, box ):
    
    result = {}
    
    util.section_msg("Testing synchronisation input")
    
###############################################################################
    
       
    util.info_msg("Setting synchronisation line to input")
    dut.fipcore.write_regname('ext_sync.dir', 0)
    dut.fipcore.write_regname('ext_sync.fpga_io_dir', 0)
    
    util.info_msg("Enabling buffer")
    dut.fipcore.write_regname('ext_sync.oe', 1)
    
    util.info_msg("Disabling termination") 
    dut.fipcore.write_regname('ext_sync.term_en', 0)
    
    util.info_msg("Connecting synchronisation line to low voltage in relay box")
    box.trigger_input_low()
    
    time.sleep(DEL)
    
    if dut.fipcore.read_regname('ext_sync_raw_input') == 0: 
        result['Input low'] = 1
        util.info_msg("Read low input value") 
    else :
        result['Input low'] = 0
        util.err_msg("Read high input value, even though low value is generated in relay box")    
    
###############################################################################

   
    util.info_msg("Connecting synchronisation line to high voltage in relay box")
    box.trigger_input_high()
    
    time.sleep(DEL)
    
    if dut.fipcore.read_regname('ext_sync_raw_input') == 1: 
        result['Input high'] = 1
        util.info_msg("Read high input value") 
    else :
        result['Termination disabled'] = 0
        util.err_msg("Read low input value, even though high value is generated by relay box")
    
    box.trigger_input_low()

    return result

def test_termination( dut, box ):        
    
    result = {}
    
    util.section_msg("Testing termination circuit")

###############################################################################
  
    
    util.info_msg("Setting synchronisation line to input")
    dut.fipcore.write_regname('ext_sync.dir', 0)
    dut.fipcore.write_regname('ext_sync.fpga_io_dir', 0)
    
    util.info_msg("Enabling buffer")
    dut.fipcore.write_regname('ext_sync.oe', 1)
    
    util.info_msg("Disabling termination") 
    dut.fipcore.write_regname('ext_sync.term_en', 0)
    
    util.info_msg("Connecting synchronisation line to high voltage in relay box")
    box.trigger_input_high()
    
    time.sleep(DEL)
    
    if dut.fipcore.read_regname('ext_sync_raw_input') == 1: 
        result['Termination disabled'] = 1
        util.info_msg("Read high input value") 
    else :
        result['Termination disabled'] = 0
        util.err_msg("Read low input value, even though high value is generated by relay box")
        
###############################################################################

    
    util.info_msg("Enabling termination (pulldown)") 
    dut.fipcore.write_regname('ext_sync.term_en', 1)
    
    
    time.sleep(DEL)
    
    if dut.fipcore.read_regname('ext_sync_raw_input') == 0: 
        result['Termination enabled'] = 1
        util.info_msg("Read low input value") 
    else :
        result['Termination enabled'] = 0
        util.err_msg("Read high input value, even though pulldown circuit is enabled")

###############################################################################

    dut.fipcore.write_regname('ext_sync.term_en', 0)
    box.trigger_input_low()
        
    return result


def test_oen( dut, box ):
    
    result = {}
    
    util.section_msg("Testing output enable")
    
###############################################################################
    
       
    util.info_msg("Setting synchronisation line to input")
    dut.fipcore.write_regname('ext_sync.dir', 0)
    dut.fipcore.write_regname('ext_sync.fpga_io_dir', 0)
    
    util.info_msg("Disabling buffer")
    dut.fipcore.write_regname('ext_sync.oe', 0)
    
    util.info_msg("Disabling termination") 
    dut.fipcore.write_regname('ext_sync.term_en', 0)
    
    util.info_msg("Connecting synchronisation line to low voltage in relay box")
    box.trigger_input_low()
    
    time.sleep(DEL)
    
    lowinput = dut.fipcore.read_regname('ext_sync_raw_input')

    if lowinput == 0: 
        util.info_msg("Read low input value")
    else :
        util.info_msg("Read high input value" )    
    
###############################################################################

   
    util.info_msg("Connecting synchronisation line to high voltage in relay box")
    box.trigger_input_high()
    
    time.sleep(DEL)
    
    highinput = dut.fipcore.read_regname('ext_sync_raw_input')

    if highinput == 0: 
        util.info_msg("Read low input value")
    else :
        util.info_msg("Read high input value" )    
    
    box.trigger_input_low()
    time.sleep(DEL)

###############################################################################

    if lowinput == highinput :
        result['Output enable'] = 1
        util.info_msg("Value read from disabled buffer didn't change no matter buffer input")
    else :
        util.info_err_msg("Value read from buffer changed, although output should be disabled")
        result['Output enable'] = 0

    return result

def test_dir( dut, box ):
    
    result = {}
    
    util.section_msg("Testing direction selection")
    util.section_msg("Hack: Synchronisation input test will be repeated, with external buffer set to output")
    util.section_msg("Hack: Value read on FPGA input shouldn't change, although synchronisation input changes")

    
###############################################################################
    
       
    util.info_msg("Setting synchronisation line buffer to OUTPUT")
    dut.fipcore.write_regname('ext_sync.dir', 1)

    util.info_msg("Setting synchronisation IO in FPGA to INPUT")
    dut.fipcore.write_regname('ext_sync.fpga_io_dir', 0)
    
    util.info_msg("Enabling buffer")
    dut.fipcore.write_regname('ext_sync.oe', 1)
    
    util.info_msg("Disabling termination") 
    dut.fipcore.write_regname('ext_sync.term_en', 0)
    
    util.info_msg("Connecting synchronisation line to low voltage in relay box")
    box.trigger_input_low()
    
    time.sleep(DEL)
    
    lowinput = dut.fipcore.read_regname('ext_sync_raw_input')

    if lowinput == 0: 
        util.info_msg("Read low input value")
    else :
        util.info_msg("Read high input value" )    
    
###############################################################################

   
    util.info_msg("Connecting synchronisation line to high voltage in relay box")
    box.trigger_input_high()
    
    time.sleep(DEL)
    
    highinput = dut.fipcore.read_regname('ext_sync_raw_input')

    if highinput == 0: 
        util.info_msg("Read low input value")
    else :
        util.info_msg("Read high input value" )    
    
    box.trigger_input_low()
    dut.fipcore.write_regname('ext_sync.dir', 0)
    time.sleep(DEL)

###############################################################################

    if lowinput == highinput :
        result['Direction selection'] = 1
        util.info_msg("Value read from buffer set to output didn't change no matter buffer input")
    else :
        result['Direction selection'] = 0
        util.info_err_msg("Value read from buffer changed, although buffer should be set to output")

    return result


def main (card=None, default_directory='.',suite=None, serial=""):
    
    testname= "Test06: Trigger Input/Output"
    util.header_msg( testname, [ "Bidirectional Buffer communication",
                                    "Termination switching",
                                    "Reading trigger input" ] )
    
    ###############################################################################
    ############################ initialization ###################################
    ###############################################################################
    box = util.calibration_box_init()
    
    util.section_msg("Hardware initialization")
    abspath = util.find_prj_topdir(util.TOPDIRNAME);
    carrier = spec.spec( abspath );
        
   
    # FPGA bitstream and FMC presence are verified during initialization
    dut = fmc.fmcmasterfip(carrier, abspath, util.FIRMWARE_PATH)
    
    test_results = {}
    
    ###############################################################################
    ############################ actual test ######################################
    ###############################################################################
    
    
    
    
    test_results = util.merge_dictionaries( test_results, test_sync_input( dut, box ) )

    test_results = util.merge_dictionaries( test_results, test_termination( dut, box ) )
    
    test_results = util.merge_dictionaries( test_results, test_oen( dut, box ) )
    
    test_results = util.merge_dictionaries( test_results, test_dir( dut, box ) )
    
       
    ###############################################################################
    ########################## result processing ##################################
    ###############################################################################
    
    errors = util.summarise_test_results( testname, test_results)
        
if __name__ == '__main__' :
    main()
