

import sys
import random
import time
import csr
import i2c
import math
import os
import signal

from ctypes import *
from ptsexcept import *

from regs_lib import *
from ad9510_lib import *

#     print massage that have to be logged
def log( msg ):
    print msg

#     print question for user - doesn't need to be logged
def info( msg ):
    print msg
    

RF_MODE_MASTER = 0;
RF_MODE_SLAVE = 1;


class ad9516:


    CONF = ( [ [0x0000, 0x99],
            [0x0001, 0x00],
            [0x0002, 0x10],
            [0x0003, 0xC3],
            [0x0004, 0x00],
            [0x0010, 0x7C],
            [0x0011, 0x05],
            [0x0012, 0x00],
            [0x0013, 0x0C],
            [0x0014, 0x12],
            [0x0015, 0x00],
            [0x0016, 0x05],
            [0x0017, 0x00],
            [0x0018, 0x07],
            [0x0019, 0x00],
            [0x001A, 0x00],
            [0x001B, 0x20],
            [0x001C, 0x02],
            [0x001D, 0x00],
            [0x001E, 0x00],
            [0x001F, 0x0E],
            [0x00A0, 0x01],
            [0x00A1, 0x00],
            [0x00A2, 0x00],
            [0x00A3, 0x01],
            [0x00A4, 0x00],
            [0x00A5, 0x00],
            [0x00A6, 0x01],
            [0x00A7, 0x00],
            [0x00A8, 0x00],
            [0x00A9, 0x01],
            [0x00AA, 0x00],
            [0x00AB, 0x00],
            [0x00F0, 0x08],
            [0x00F1, 0x0A],
            [0x00F2, 0x0A],
            [0x00F3, 0x0A],
            [0x00F4, 0x0A],
            [0x00F5, 0x0A],
            [0x0140, 0x46],
            [0x0141, 0x46],
            [0x0142, 0x46],
            [0x0143, 0x46],
            [0x0190, 0x00],
            [0x0191, 0x80],
            [0x0192, 0x00],
            [0x0193, 0xBB],
            [0x0194, 0x00],
            [0x0195, 0x00],
            [0x0196, 0x00],
            [0x0197, 0x00],
            [0x0198, 0x00],
            [0x0199, 0x11],
            [0x019A, 0x00],
            [0x019B, 0x11],
            [0x019C, 0x20],
            [0x019D, 0x00],
            [0x019E, 0x11],
            [0x019F, 0x00],
            [0x01A0, 0x11],
            [0x01A1, 0x20],
            [0x01A2, 0x00],
            [0x01A3, 0x00],
            [0x01E0, 0x01],
            [0x01E1, 0x02],
            [0x0230, 0x00],
            [0x0231, 0x00],
            [0x0232, 0x00] ]
        )
    
    SYNC_N=0;
    RESET_N=1;
    LD=3;
    
    
    
    def __init__(self, carrier):
        
        self.carrier = carrier;
        
        # remove reset signal
        self.gpio_set( self.SYNC_N, 1);
        
        # set reset signal
        self.gpio_set( self.RESET_N, 0);
        time.sleep(0.1);
        
        # remove reset signal
        self.gpio_set( self.RESET_N, 1);
        time.sleep(0.1);
        
        # set communication method
        self.write_reg( 0, 0x99);
        self.write_reg( 0x232, 1);

        time.sleep(0.5);
 
        # verify SPI communication with AD9516
        if( self.read_reg(0x3) != 0xc3):   
            raise PtsCritical("AD9516 PLL not responding! SPI communication lines might be faulty.")
        else:    
            print "Got respond from AD9516 PLL"
        
        # load configuration
        for i in range( len( self.CONF ) ):
            self.write_reg( self.CONF[i][0], self.CONF[i][1]);
           
        # update loaded registers
        self.write_reg( 0x232, 0);
        time.sleep(0.001);
        self.write_reg( 0x232, 1);
        
        # wait for PLL lock
        for i in range(10):
            if(self.read_reg( 0x1f) & (1 << 0)):
                print "AD9516 PLL locked"
                break    
            if(i == 9):
                raise PtsCritical("AD9516 PLL does NOT lock. This might be caused by placing wrong OSC1/OSC2 oscillator.")
        
        # software sync all outputs
        self.write_reg( 0x230, 1);
        self.write_reg( 0x232, 1);
        self.write_reg( 0x230, 0);
        self.write_reg( 0x232, 1);
        
        if( (self.carrier.readl( DDS_REG_FPGACTRL ) & DDS_FPGACTRL_MAINPLL() ) == 0 ):
            raise PtsCritical("PLL in FPGA did not lock on clock signal from AD9516. Clock line might be corrupted.") 
      
    
    def check_refclk(self):
        # check if reference clock frequency is higher then 1 MHz (if osc is correctly placed)
        if(self.read_reg( 0x1f ) & (1 << 1)):
            print "AD9516 reference clock detected"
        else:
            raise PtsCritical("AD9516: reference frequency lower then 1 MHz! OSC1/OSC2 or their connections to AD9516 might be broken.")
        
    
    def read_reg( self, reg ):
        rval = self.carrier.spi_txrx( DDS_GPIOR_PLL_SYS_CS_N(), 24, ( (reg & 0xfff) << 8) | (1<<23) )
        return rval & 0xff;

    
    def write_reg(self, reg, val):
        self.carrier.spi_txrx( DDS_GPIOR_PLL_SYS_CS_N(), 24, ((reg & 0xfff) << 8) | val );   

    
######################## LOWEST LEVEL FUNCTIONS ####################################

    def gpio_set(self, pin, value):
        if pin == self.SYNC_N:
            self.carrier.gpio_set( DDS_GPIOR_PLL_SYS_SYNC_N(), value);
        elif pin == self.RESET_N:
            self.carrier.gpio_set( DDS_GPIOR_PLL_SYS_RESET_N(), value);
        
    
    def gpio_get(self, pin):
        if pin == self.SYNC_N:
            return self.carrier.gpio_get( DDS_GPIOR_PLL_SYS_SYNC_N());
        elif pin == self.RESET_N:
            return self.carrier.gpio_get( DDS_GPIOR_PLL_SYS_RESET_N());
        elif pin == self.LD:
            return self.carrier.gpio_get( DDS_GPIOR_PLL_SYS_LD());
    
    
    
 