# Copyright INCAA Computers, 2012
# Author: Bert Gooijer <bert.gooijer@incaacomputers.com>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org

from ptsexcept import *
from PendulumCNT91 import *


import sys
import os
import struct
import signal

import jhash



"""
functions for getting debug information from c library
"""

def redirect_stderr(default_directory):
    
    # redirect stderr(all debug output) to Output.txt
    sys.stderr.flush()
    new_stderr = os.dup(2)
    path = os.path.join(default_directory, './Output.txt')
    opslag = os.open(path, os.O_CREAT | os.O_WRONLY)
    os.dup2(opslag, 2)
    os.close(opslag)
    
    return new_stderr
    
def restore_stderr(new_stderr, default_directory):
    
    # Reopen original stderr
    sys.stderr = os.fdopen(new_stderr, 'w')
    
    # Open Output.txt for display and remove file
    path = os.path.join(default_directory, './Output.txt')
    display = open(path)
    print display.read()
    os.remove(path)
    
def show_stderr(default_directory):
    
    # Open Output.txt for display and empty file
    path = os.path.join(default_directory, './Output.txt')
    display = open(path)
    print display.read()
    os.remove(path)
    opslag = os.open(path, os.O_CREAT | os.O_WRONLY)
    os.dup2(opslag, 2)
    os.close(opslag)


"""
standard in/out temporary redirection for user question/answer
"""

# class redirect:
#     
#     def __init__(self, init):
#         self.redirected = init
#         
#     def InOut(self):
#         if(self.redirected == 0):
#             self.tmp_stdout = sys.stdout
#             sys.stdout = sys.__stdout__
#             self.tmp_stdin = sys.stdin
#             sys.stdin = sys.__stdin__
#             self.redirected = 1
#         else:
#             sys.stdout = self.tmp_stdout;
#             sys.stdin = self.tmp_stdin;
#             self.redirected = 0

"""
setup measuring with Pendulum CNT-91
"""

def pendulum_init(meas):

    # Reset device for known state
    meas.reset()

    # Measure time interval between A (start) and B (stop)
    meas.write("MEAS:TINT?")
    
    # DC coupling
    meas.write("INP:COUP DC")
    meas.write("INP2:COUP DC")
    
    # Set impedance
    meas.write("INP:IMP 1E6")
    meas.write("INP2:IMP 50")
    
    # Trigger on manual
    meas.write("INP:LEV:AUTO OFF")
    meas.write("INP2:LEV:AUTO OFF")
    
    # Set trigger level
    meas.write("INP:LEV 1.5")
    meas.write("INP2:LEV 1.5")
    
    # Enable statistics
    meas.write("CALC:AVER:STAT ON")
    
    # Make 500 measurements
    meas.write("CALC:AVER:COUN 500")

"""
reset measuring Pendulum CNT-91
"""

def pendulum_init_phase(meas):

    # Reset device for known state
    meas.reset()

    # Measure time interval between A (start) and B (stop)
    meas.write("MEAS:TINT?")
    
    # DC coupling
    meas.write("INP:COUP DC")
    meas.write("INP2:COUP DC")
    
    # Set impedance
    meas.write("INP:IMP 50")
    meas.write("INP2:IMP 50")
    
    # Trigger on manual
    meas.write("INP:LEV:AUTO OFF")
    meas.write("INP2:LEV:AUTO OFF")
    
    # Set trigger level
    meas.write("INP:LEV 1.5")
    meas.write("INP2:LEV 1.5")
    
    # Enable statistics
    meas.write("CALC:AVER:STAT ON")
    
    # Make 500 measurements
    meas.write("CALC:AVER:COUN 10000")


def pendulum_reset(meas):
    
    # Disable statistics
    meas.write("CALC:AVER:STAT OFF")
    
    # Enable statistics
    meas.write("CALC:AVER:STAT ON")
    
    # Make 500 measurements
    meas.write("CALC:AVER:COUN 500")

class FDCalibBlock:
    def __init__(self):
	self.frr_poly = [-165202, -29825595, 3801939743082]
	self.tdc_zero_offset = 80000
	self.out_zero_offset = [0, 0, 0, 0]
	self.vcxo_default_tune = 32000
	self.magic = 0xf19ede1a
	self.version = 3
	self.date = 0
	self.size=64
    
    def load(self, filename="sdbfs/calibration"):
	f= open(filename,"rb")
	self.packed= f.read(64)
	f.close()

	self.unpack()

#	print("magic: %x"  % self.magic)
#	print("hash: %x"  % self.hash)
#	print("size: %d"  % self.size)
#	print("version: %d"  % self.version)
#	print("date: %x"  % self.date)
#	print("frr_poly: %d %d %d"  %( self.frr_poly[0],  self.frr_poly[1],  self.frr_poly[2]))
#	print("out_zero_offset: %d %d %d %d"  %( self.out_zero_offset[0], self.out_zero_offset[1], self.out_zero_offset[2], self.out_zero_offset[3]))
#	print("tdc_zero_offset: %d "  %( self.tdc_zero_offset ))
#	print("vcxo_default_tune: %d "  %( self.vcxo_default_tune ))

	sh = self.hash

	self.hash = 0
	self.pack()
	sh_ver = jhash.hashlittle2(self.packed, 0, 0)

    def unpack(self):
	self.magic, self.hash, self.size, self.version, self.date, self.frr_poly[0], self.frr_poly[1], self.frr_poly[2], self.out_zero_offset[0], self.out_zero_offset[1], self.out_zero_offset[2], self.out_zero_offset[3], self.tdc_zero_offset, self.vcxo_default_tune = struct.unpack("!LLHHL3q4llL", self.packed)

    def pack(self):
	self.packed = struct.pack("!LLHHL3q4llL",
	self.magic,
	self.hash,
	self.size,
	self.version,
	self.date,
	self.frr_poly[0],
	self.frr_poly[1],
	self.frr_poly[2],
	self.out_zero_offset[0],
	self.out_zero_offset[1],
	self.out_zero_offset[2],
	self.out_zero_offset[3],
	self.tdc_zero_offset,
	self.vcxo_default_tune )

    def save(self, filename="sdbfs/calibration"):
	self.hash = 0 
	self.pack()
#	print(self.packed, len(self.packed))
	self.hash = jhash.hashlittle2(self.packed, 0, 0)
	self.pack()
	f= open(filename,"wb")
	f.write(self.packed)
	f.close()
    
    



# Register an handler for the timeout
def handler(signum, frame):
    raise Exception("input timeout")

# input with timeout
def timeout_input(message, timeout ):
    # signal.signal(signal.SIGALRM, handler)
    # signal.alarm(timeout)
    try:
        tmp = raw_input(message)
        
    except Exception, exc: 
        tmp = exc
        
    # signal.alarm(0)
    return tmp

def yesnoquestion( message, timeout ):
    
    tmp = timeout_input(message, timeout );
    
    if( isinstance( tmp, str ) ):    
        if ( (tmp.upper() == 'N') or (tmp.upper() == 'NO') ):
            return 0;
        elif ( (tmp.upper() == 'Y') or (tmp.upper() == 'YES') ):
            return 1;
        else:
            return -1;
    else:
        return -1;
