

import sys
import os

import string

from ctypes import *
import utilities as util

# from ptsexcept import *

# from regs_lib import *


class spec:

    speclib_path = util.speclib_path
 
    
    def __init__(self, projdir, bus = -1):
        
#         self.cwd = os.path.dirname(__file__)
       
        self.projdir = projdir;
        
        self.speclib = CDLL(self.projdir + self.speclib_path);
        self.speclib.spec_readl.restype = c_uint32;

        self.bus = self.verify_bus( bus );

        util.info_msg( "Initializing SPEC board found on bus 0x%.2x..." % self.bus )
  
        self.card = self.speclib.spec_open( c_int(self.bus), c_int(-1) );
        if(self.card < 1):
            util.crit_msg( "SPEC enumeration failed" )
            return -1
        else:
            util.info_msg( "SPEC enumerated successfully" )
        
        
        
    def program( self, firmware ):
        self.firmware = firmware;
        firmware_path = self.projdir + self.firmware
        
        util.info_msg( "Firmware loading from %s "% firmware_path )
        # os.system("ls -l %s" % firmware_path)
        if( self.speclib.spec_load_bitstream(c_void_p( self.card ), c_char_p( firmware_path ) ) == 0 ):
            util.err_msg( "Firmware loader failure" )
            return -1
        else:
            util.info_msg( "Firmware loading succeeded" )
                


    def write(self, addr, data ):
#         basic write function from speclib
#         util.dbg_msg( "Write data: 0x%x address: 0x%x" % (data, addr) )
        self.speclib.spec_writel( c_void_p(self.card), c_uint32(data), c_uint32(addr) );
    
    def read(self, addr ):
#         basic read function from speclib
        tmp = self.speclib.spec_readl( c_void_p(self.card), c_uint32( addr) )
#         util.dbg_msg( "Read address: 0x%x. Found value: 0x%x" % ( addr, tmp ) ) 
        return tmp;
    
    def iwrite(self, bar, offset, width, datum):

        if bar != 0:
            util.crit_msg("spec iread was called with bar argument other then 0")
            raise Exception("spec iread was called with bar argument other then 4")
        
        if width > 4:
            util.crit_msg("spec iread was called with width argument bigger then 4")
            raise Exception("spec iread was called with width argument bigger then 4")
        
        self.write( offset, datum );
    
    def iread(self, bar, offset, width):

        if bar != 0:
            util.crit_msg("spec iread was called with bar argument other then 0")
            raise Exception("spec iread was called with bar argument other then 4")
        
        if width > 4:
            util.crit_msg("spec iread was called with width argument bigger then 4")
            raise Exception("spec iread was called with width argument bigger then 4")
        
        return self.read( offset );
    
    def verify_bus(self, bus):
        # list of files inside directory
        devices = os.listdir("/sys/bus/fmc/devices")
        # there should be one file only
        if len(devices) > 1:
            util.crit_msg("More then one SPEC was found. Remove one device and restart test.")
        elif len(devices) < 1:
            util.crit_msg("No SPEC device was found. Make sure that device is properly mounted and that drivers are loaded")
        if bus == -1:
                # this file has name in format of <string>-<id>
                # so name must by splitted with '-'
                # id is the last element (if string contain '-' there may be more then 2 elements)
                # list[-1] is a last element of list in python
                bus = string.split(devices[0], '-')[-1] 
                # id is in string hex format ie 0100
                # got to take first two chars and convert to int
                return int( bus[0:2], 16)
                
        else:
            if not (string.split(devices[0], '-')[1])[0:2] == "%.2x" % bus:
                util.crit_msg("Could not find SPEC device on specified bus")
            else:
                return bus
    
    
    
    
        