#!   /usr/bin/env   python
#    coding: utf8
##_________________________________________________________________________________________________
##                                                                                                |
##                                           |TDC PTS|                                            |
##                                                                                                |
##                                         CERN,BE/CO-HT                                          |
##________________________________________________________________________________________________|

##-------------------------------------------------------------------------------------------------
##                                                                                                |
##                                        TDC OneWire test                                        |
##                                                                                                |
##-------------------------------------------------------------------------------------------------
##                                                                                                |
## Description  Testing of the "Thermometer & Unique ID, DS18B20" chip on the TDC board (IC14).   |
##              The firmware loaded to the FPGA on the carrier implements the interface for the   |
##              communication between the PCIe bus and the One Wire of the DS18B20; this interface|
##              is a One-Wire WISHBONE master, running with a 50MHz system clock.                 |
##                                                                                                |
##              The One-Wire WISHBONE master can be accessed base address 0x80000.                |
##              The family code of the DS18B20 is x28, predefined in the part number.             |
##                                                                                                |
##              The test reads the unique ID and the temperature and checks if the received       |
##              values are within reasonable limits.                                              |
##                                                                                                |
## FW to load   tdc_allothertests.bit                                                             |
## Authors      Evangelia Gousiou (Evangelia.Gousiou@cern.ch)                                     |
## Website      http://www.ohwr.org/projects/pts                                                  |
## Date         11/01/2013                                                                        |
##-------------------------------------------------------------------------------------------------

##-------------------------------------------------------------------------------------------------
##                               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                                             --
##-------------------------------------------------------------------------------------------------

# Import system modules
import sys
import time
import os

# Add common modules location to path
sys.path.append('../../../../pts/')
sys.path.append('../../../../pts/gnurabbit/python/')
sys.path.append('../../../../pts/common/')

# Import common modules
from ptsexcept import *
import rr
import fmc_tdc


##-------------------------------------------------------------------------------------------------
##                                             main                                              --
##-------------------------------------------------------------------------------------------------
def main (default_directory='.'):


    start_test_time = time.time()

#-----> PCIe address, firmware, loader constants
    # Constants declaration
    FMC_TDC_ADDR            = '1a39:0004/1a39:0004@000B:0000'
    FMC_TDC_BITSTREAM_PATH  = '../firmwares/tdc_allothertests.bit'
    FPGA_LOADER_PATH        = '../../../../pts/gnurabbit/user/fpga_loader'

#-----> One Wire chip constant
    FAMILY_CODE             = 0x28


#-----> FPGA initializations    
    # SPEC object declaration
    spec = rr.Gennum()

    # Bind SPEC object to FMC TDC card
    print "\n-------------------------------------------------------------------"
    print "----------------------------- TDC PTS -----------------------------"
    print "--------------------- 1-Wire TEMPID IC14 test ---------------------\n"
    print ("Test of the One-Wire thermometer with unique ID chip IC14. The test\n"
           "reads the serial unique ID and takes a temperature measurement.\n")

    print "\n_______________________________Info______________________________\n"
    print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
    for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems():
        print "%s:0x%04X"%(name, value)
    spec.bind(FMC_TDC_ADDR)

    print "\n_________________________Initialisations_________________________\n"
    # Load FMC TDC firmware
    print "Loading FMC TDC firmware...",
    firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
    bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
    os.system(firmware_loader + ' ' + bitstream)
    time.sleep(1)
    firmware_loader = os.path.join(default_directory, FPGA_LOADER_PATH)
    bitstream = os.path.join(default_directory, FMC_TDC_BITSTREAM_PATH)
    os.system(firmware_loader + ' ' + bitstream)
    time.sleep(1)
    print "Firmware loaded!"

    # TDC object declaration
    tdc = fmc_tdc.CFMCTDC(spec)

    # Check bitsteam type
    bitstream_type = tdc.read_bitstream_type()
    if(bitstream_type == 0xFFFFFFFF):
        msg = ("FATAL ERROR: No access to TDC core")
        os.close(spec.fd)
        print (msg)
        raise PtsCritical (msg)
    if(bitstream_type != 0x1):
        msg = ("FATAL ERROR: Wrong bitstream type loaded")
        os.close(spec.fd)
        print (msg)
        raise PtsCritical (msg)
    else:
        print('Access to TDC core OK')


#-----> Accessing the One Wire chip
    # Read unique ID and print to log
    print "\n____________________________Unique ID____________________________\n"
    try:
        unique_id = tdc.mezz_get_unique_id()
    except:
        msg = ("ERROR: TEMPID IC14: Cannot access the device")
        os.close(spec.fd)
        print (msg)
        raise PtsError (msg)

    if(unique_id == -1):
        msg = ("ERROR: TEMPID IC14: Cannot access the device")
        os.close(spec.fd)
        print (msg)
        raise PtsError (msg)
    else:
        print('TEMPID IC14: Unique ID: 0x%.12X OK') % unique_id

    if((unique_id & 0xFF) != FAMILY_CODE):
        family_code = unique_id & 0xFF
        msg = (("ERROR: TEMPID IC14: Wrong Family Code: 0x%.2X is different than the expected: 0x%.2X") %(family_code,FAMILY_CODE))
        os.close(spec.fd)
        print (msg)
        raise PtsError (msg)


    # Read temperature and print to log
    print "\n___________________________Temperature___________________________\n"
    temp = tdc.mezz_get_temp()
    if (temp > 60 or temp < 20):
        msg = ("ERROR: TEMPID IC14: Temperature measurement %3.3f°C is out of the accepted limits [20°C .. 100°C] " % temp)
        os.close(spec.fd)
        print (msg)
        raise PtsError (msg)
    else:
        print('TEMPID IC14: Temperature: %3.2f°C OK') % temp


    print "\n\n--------------------------------"
    end_test_time = time.time()
    print "Test elapsed time: %.2f seconds\n\n\n" % (end_test_time-start_test_time)

if __name__ == '__main__' :
    main()
