

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
    




class ad9510:
    
    RF_MODE_MASTER = 0;
    RF_MODE_SLAVE = 1;
    
    PIN_STATUS = 0;
    PIN_FUNCTION = 1;
            
    CONF = [[0x00, 0x10],
    [0x02, 0x20],
    [0x04, 0x00],
    [0x05, 0x00],
    [0x06, 0x19],
    [0x07, 0x04],
    [0x08, 0x47], # dig LD

#     [0x08, 0x49], # N divider
#     [0x08, 0x65], #pump up
#     [0x08, 0x61], #pump down
#     [0x08, 0x69], # dig loss of reference (H)
#     [0x08, 0x51], # r divider output
    [0x09, 0x30],
    [0x0A, 0x06],
    [0x0B, 0x00],
    [0x0C, 0x01],
    [0x0D, 0x20],
    [0x34, 0x01],
    [0x35, 0x00],
    [0x36, 0x00],
    [0x37, 0x04],
    [0x38, 0x01],
    [0x39, 0x00],
    [0x3A, 0x00],
    [0x3B, 0x04],
    [0x3C, 0x08],
    [0x3D, 0x0B],
    [0x3E, 0x0B],
    [0x3F, 0x08],
    [0x40, 0x03],
    [0x41, 0x03],
    [0x42, 0x00],
    [0x43, 0x03],
    [0x44, 0x13],
    [0x45, 0x00],
    [0x48, 0x00],
    [0x49, 0x00],
    [0x4A, 0x00],
    [0x4B, 0x00],
    [0x4C, 0x11],
    [0x4D, 0x00],
    [0x4E, 0x44],
    [0x4F, 0x00],
    [0x50, 0x00],
    [0x51, 0x00],
    [0x52, 0x11],
    [0x53, 0x00],
    [0x54, 0x44],
    [0x55, 0x00],
    [0x56, 0x00],
    [0x57, 0x00],
    [0x58, 0x00],
    [0x59, 0x00],
    [0x5A, 0x00]];


    def __init__(self, carrier, mode):
        
        self.carrier = carrier;
        self.mode = mode;
        
        #this pin is reset_n by default
        self.gpio_set( self.PIN_FUNCTION, 0);
        self.gpio_set( self.PIN_FUNCTION, 1);

        self.write_reg( 0,
            ( SDO_INACTIVE(0) | LSB_FIRST(0) | SOFT_RESET(0) | LONG_INSTRUCTION(1) )
            );

        print "AD9510 configuration start.\n"

        self.write_reg(
            0,
            ( SDO_INACTIVE(0) | LSB_FIRST(0) | SOFT_RESET(0) | LONG_INSTRUCTION(1) )
            );

        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );

#         # page 29: A and B Counters
#         # in FD mode A counter is not used
        self.write_reg(
            0x04,
            A_COUNTER(0)
            );

        # page 29: A and B Counters
        # in FD mode B counter can be bypassed by writing in 0x06 - B_BYPASS
        # bypass is disabled here
        # fVCO = (fREF/R) *P*B)
        # 500 = 10M/1 * 1 * 50
        self.write_reg(
            0x05,
            B_COUNTER_MSB(0) # def
            );
    
        if ( mode == self.RF_MODE_MASTER ):
                self.write_reg(
                    0x06,
                    B_COUNTER_LSB(0) # def
                    );
        
        else:
            # on slave B counter is used to divide OSC clk
            # since prescaller is enabled
            # B counter needs to count to 25
            # N = PxB = 2x25 = 50
            self.write_reg(
                0x06,
                B_COUNTER_LSB(25)
                );
        
        
        
        # default
        self.write_reg(
                0x07,
                ( LOR_DEL(0) | LOR_EN(0) )
                );
        
        # default
        self.write_reg(
                0x08,
                ( PFD_POLARITY(0) | PLL_MUX_ON_STATUS(1) | CP_MODE(0) )
                );
        
        #    default
        #    CP current and counters reset
        self.write_reg(
                0x09,
                ( CP_CURRENT(0) | RESET_R(0) | RESET_N(0) | RESET_ALL_CNTRS(0) )
                );
        
        if ( mode == self.RF_MODE_MASTER ):
                # only power down has different default value (1)
                self.write_reg(
                        0x0A,
                        ( B_BYPASS(0) | PRESCALLER(0) | POWER_DOWN(1) )
                        );
        
        else:
            # PLL enabled in FD mode (implicated by prescaller value)
            # B is NOT bypassed
            self.write_reg(
                    0x0A,
                    ( B_BYPASS(0) | PRESCALLER(1) | POWER_DOWN(0) )
                    );
        
        
        
        # default
        #    R divider disabled
        self.write_reg(
                0x0B,
                R_DIVIDER_MSB(0)
                );
        
        self.write_reg(
                0x0C,
                R_DIVIDER_LSB(0)
                );
        
        #    default
        self.write_reg(
                0x0D,
                ( DIGIT_LOCK_DET_EN(0) | DIGIT_LOCK_DET_WND(0) | ANTIBACKSLASH_PLS_WDTH(0) )
                );
        
        # delays
        # left default
        self.write_reg( 0x34,1 );
        self.write_reg( 0x35,0 );
        self.write_reg( 0x36,0 );
        self.write_reg( 0x37,4 );
        self.write_reg( 0x38,1 );
        self.write_reg( 0x39,0 );
        self.write_reg( 0x3A,0 );
        
        # all outputs are enabled if load is connected
        # all default
        # out0
        self.write_reg( 0x3C, 0x08 );
        # out1
        self.write_reg( 0x3D, 0x08 );
        # out2
        self.write_reg( 0x3E, 0x08 );
        # out3
        self.write_reg( 0x3F, 0x08 );
        
        # out4 lvds - off
        self.write_reg( 0x40, 0x02 );
        # out5 lvds - off
        self.write_reg( 0x41, 0x02);
        # out6 lvds - on
        # LVDS, power ON, default current
        self.write_reg( 0x42, CMOS_OUTPUT_POWER( 0 ) | CMOS_OUTPUT_LEVEL( 1 ) | LOGIC_SEL( 0 )  );
        # out7 lvds - off
        self.write_reg( 0x43, 0x03 );
        
        ####### important!!!!!!!!!!!!!!!
        if( mode == self.RF_MODE_MASTER ):
            # default
            self.write_reg(
                    0x45,
                    ( SEL_CLK_IN(1) | CLK1_PD(0) | CLK2_PD( 0 ) |
                        CLK_PLL_PD( 0 ) | REFIN_PD(0) | CLKS_IN_PD(0) )
                    );
        
        else:
            self.write_reg(
                    0x45,
                    ( SEL_CLK_IN(0) | CLK1_PD(0) | CLK2_PD( 0 ) |
                        CLK_PLL_PD( 0 ) | REFIN_PD(0) | CLKS_IN_PD(0) )
                    );
        
        
        self.write_reg( 0x48, 0x22 );
            
        # bypass is different then default
        self.write_reg(
                0x49,
                ( BYPASS(1) | NO_SYNC(0) | FORCE(0) | START_HL(0) | PHASE_OFFSET(0) )
                );
        
        
        # output 3
        # default
        if( self.mode == self.RF_MODE_MASTER ):
            self.write_reg( 0x4E, 0x33 );
            
            # bypass is different then default
            self.write_reg(
                    0x4F,
                    ( BYPASS(1) | NO_SYNC(0) | FORCE(0) | START_HL(0) | PHASE_OFFSET(0) )
                    );
        else:
            self.write_reg( 0x4E, 0x55 );
        
            # bypass is different then default
            self.write_reg(
                0x4F,
                ( BYPASS(0) | NO_SYNC(0) | FORCE(0) | START_HL(0) | PHASE_OFFSET(0) )
                ); 
        
        
        if( self.mode == self.RF_MODE_MASTER ):
            # output 6
            # connected directly to FPGA
            self.write_reg( 0x54, 0 );
            
            # divider bypassed
            self.write_reg(
                    0x55,
                    ( BYPASS(1) | NO_SYNC(0) | FORCE(0) | START_HL(0) | PHASE_OFFSET(0) )
                    );
            
            
        else:
            self.write_reg( 0x54, 4 | (4<<4) );
            
            # divider bypassed
            self.write_reg(
                    0x55,
                    ( BYPASS(0) | NO_SYNC(0) | FORCE(0) | START_HL(0) | PHASE_OFFSET(0) )
                    );
        
        self.write_reg(
                    0x5A,
                    UPDATE_REGISTERS(1)
                    );
    
    def test_config(self):
        print "AD9510 test configuration start.\n"
        
        #this pin is reset_n by default
        self.gpio_set( self.PIN_FUNCTION, 0);
        self.gpio_set( self.PIN_FUNCTION, 1);
        
#         self.read_config()

        self.write_reg( 0,
            ( SDO_INACTIVE(0) | LSB_FIRST(0) | SOFT_RESET(0) | LONG_INSTRUCTION(1) )
            );

        for i in range( len( self.CONF ) ):
            self.write_reg( self.CONF[i][0], self.CONF[i][1]);
            
        self.write_reg(
                    0x5A,
                    UPDATE_REGISTERS(1)
                    );
    
#         self.read_config();
    
    def read_config(self):
        print "current configuration\n"
        

        for i in range( len( self.CONF ) ):
            print "%x : %x" % ( self.CONF[i][0], self.read_reg( self.CONF[i][0]) );
            
        
    
    def reset_lor(self):
        
#         Wylaczenie LOR
        self.write_reg(
            0x07,            
            0x00
            );
        
#         LOR na status
        self.write_reg(
            0x08,            
            0x29
            );

        #update
        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );
        
        time.sleep(0.5);
        print "Loss of reference: %d" %  self.gpio_get(self.PIN_STATUS);
        
        #wlaczenie lor     
        self.write_reg(
            0x07,            
            0x04
            );
        
        #update
        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );
            
        
        self.write_reg(
            0x08,            
            0x45
            );
        
        #update
        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );
    
    def r_divider(self):
        self.write_reg(
            0x08,            
            0x51
#             0x12
            );
        
        #update
        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );
    
    def n_divider(self):
        self.write_reg(
            0x08,            
            0x49
#             0x4A
            );
        
        #update
        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );
    
    def pump_up(self):
        self.write_reg(
            0x08,            
            0x61
#             0x62
            );
        
        #update
        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );
    
    def pump_down(self):
        self.write_reg(
            0x08,            
            0x65
#             0x66
            );
        
        #update
        self.write_reg(
            0x5A,
            UPDATE_REGISTERS(1)
            );
       
           
        
      
    def read_reg( self, reg ):
        rval = self.carrier.spi_txrx( DDS_GPIOR_PLL_VCXO_CS_N(), 24, ( (reg & 0xfff) << 8) | (1<<23) )
        return rval & 0xff;

    
    def write_reg(self, reg, val):
#         print "a:%x, d:%x" % (reg,val)
        self.carrier.spi_txrx( DDS_GPIOR_PLL_VCXO_CS_N(), 24, ((reg & 0xfff) << 8) | val );   

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

    def gpio_set(self, pin, value):
        
        if pin == self.PIN_FUNCTION:
            self.carrier.gpio_set( DDS_GPIOR_PLL_VCXO_FUNCTION(), value);
        
    
    def gpio_get(self, pin):
        if pin == self.PIN_FUNCTION:
            return self.carrier.gpio_get( DDS_GPIOR_PLL_VCXO_FUNCTION());
        elif pin == self.PIN_STATUS:
            return self.carrier.gpio_get( DDS_GPIOR_PLL_VCXO_STATUS_N());

    
    
    
 