#!   /usr/bin/env   python
#    coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin <matthieu.cattin@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org

import sys
import rr
import time
import os


from ptsexcept import *

import fmc_adc

"""
test04: Test Si570 programmable oscillator

Note: Requires test00.py to run first to load the firmware!
"""

SI570_ADDR = 0x55
SI570_XTAL_FREQ_MIN = 114.056
SI570_XTAL_FREQ_MAX = 114.514
SI570_FOUT = 100.000
SI570_FOUT_TOL = 1.0

SI570_RFREQ = 42
SI570_N1 = 7
SI570_HS_DIV = 2

def main (default_directory='.'):

    """
    path_fpga_loader = '../../../gnurabbit/user/fpga_loader';
    path_firmware = '../firmwares/spec_fmcadc100m14b4cha.bin';

    firmware_loader = os.path.join(default_directory, path_fpga_loader)
    bitstream = os.path.join(default_directory, path_firmware)
    print firmware_loader + ' ' + bitstream
    os.system( firmware_loader + ' ' + bitstream )

    time.sleep(2);
    """

    # Objects declaration
    spec = rr.Gennum() # bind to the SPEC board
    fmc = fmc_adc.CFmcAdc100Ms(spec)

    # Scan i2c bus
    periph_addr = fmc.i2c_scan()

    # Check that the EEPROM is detected on the I2C bus
    if(0 == len(periph_addr)):
        raise PtsError('No peripheral detected on I2C bus')
    else:
        if(1 != len(periph_addr)):
            raise PtsError('Signal integrity problem detected on I2C bus, %d devices detected instead of 1'%(len(periph_addr)))
        else:
            if(SI570_ADDR != periph_addr[0]):
                raise PtsError('Wrong device mounted on I2C bus, address is:0x%.2X expected:0x%.2X'%(periph_addr[0],SI570_ADDR))

    # Get Si570 configuration
    rfreq, n1, hs_div = fmc.get_si570_config()
    print("\nPrint Si570 configuration")
    print("RFREQ  : %3.28f") % rfreq
    print("N1     : %d") % n1
    print("HS_DIV : %d") % hs_div

    # Check that HS_DIV is different from 0
    # If HS_DIV register value is "100" or "110" (not used) get_si570_config returns 0
    if (hs_div == 0):
        raise PtsError('Si570 invalid HS_DIV value')

    # Calculate min and max output frequency based on the min and max xtal frequency
    # See http://cp-siliconlabs.kb.net/article.aspx?article=311398&p=12972
    f_out_min = (SI570_XTAL_FREQ_MIN * rfreq) / (float(n1) * float(hs_div))
    f_out_max = (SI570_XTAL_FREQ_MAX * rfreq) / (float(n1) * float(hs_div))

    print("FOUT_MIN  : %3.3f") % f_out_min
    print("FOUT_MAX  : %3.3f") % f_out_max

    # Check that output frequency is within the limits
    f_out_limit_min = SI570_FOUT - SI570_FOUT_TOL
    f_out_limit_max = SI570_FOUT + SI570_FOUT_TOL
    print("FOUT_LIMIT_MIN  : %3.3f") % f_out_limit_min
    print("FOUT_LIMIT_MAX  : %3.3f") % f_out_limit_max
    if (f_out_limit_min < f_out_min) and (f_out_min < SI570_FOUT) and (SI570_FOUT < f_out_max) and (f_out_max < f_out_limit_max):
        print("Si570 frequency output is within tolerance")
    else:
        raise PtsError('Si570 frequency output is outside of the tolerance')


if __name__ == '__main__' :
    main()
