from regs_lib import *
import time
from test.fmcdac600m12b1chadds.python.test02 import carrier


def M_SDA_OUT(carrier, x):
    if(x):
        carrier.writel(DDS_REG_I2CR, carrier.readl(DDS_REG_I2CR) | DDS_I2CR_SDA_OUT());     
    else:
        carrier.writel(DDS_REG_I2CR, carrier.readl(DDS_REG_I2CR) & (~DDS_I2CR_SDA_OUT)); 
        time.sleep(0.01)                                                            


def M_SCL_OUT(carrier, x):                                                 
    if(x):
        carrier.writel(DDS_REG_I2CR, carrier.readl(DDS_REG_I2CR) | DDS_I2CR_SCL_OUT);     
    else:
        carrier.writel(DDS_REG_I2CR, carrier.readl(DDS_REG_I2CR) & (~DDS_I2CR_SCL_OUT)); 
        time.sleep(10);                                                         


def M_SDA_IN(carrier):
    tmp = carrier.readl(DDS_REG_I2CR)
    tmp = 1 if (tmp & DDS_I2CR_SDA_IN) > 0 else 0
    return tmp;
#     return ((carrier.readl(DDS_REG_I2CR) & DDS_I2CR_SDA_IN) ? 1 : 0)

def mi2c_start(dev):
    M_SDA_OUT(dev,0);
    M_SCL_OUT(dev,0);


def mi2c_repeat_start(dev):
    M_SDA_OUT(dev,1);
    M_SCL_OUT(dev,1);
    M_SDA_OUT(dev,0);
    M_SCL_OUT(dev,0);


def mi2c_stop( dev ):
    M_SDA_OUT(dev,0);
    M_SCL_OUT(dev,1);
    M_SDA_OUT(dev,1);

def mi2c_put_byte( dev, data ):
    ack=0;

    for i in range( 8 ):
        data <<= 1;
        M_SDA_OUT(data&0x80);
        M_SCL_OUT(dev,1);
        M_SCL_OUT(dev,0);

    M_SDA_OUT(dev,1);
    M_SCL_OUT(dev,1);

    ack = M_SDA_IN(dev);

    M_SCL_OUT(dev,0);
    M_SDA_OUT(dev,0);

    return -1 if ack != 0 else 0;

def mi2c_get_byte( dev, unsigned char *data, int ack)
{
    dds_decl_private(dev);

    int i;
    unsigned char indata = 0;

    /* assert: scl is low */
    M_SCL_OUT(dev,0);
    M_SDA_OUT(dev,1);
    for (i=0;i<8;i++)
    {
        M_SCL_OUT(dev,1);
        indata <<= 1;
        if ( M_SDA_IN ) indata |= 0x01;
        M_SCL_OUT(dev,0);
    }

    M_SDA_OUT((ack ? 0 : 1));
    M_SCL_OUT(dev,1);
    M_SCL_OUT(dev,0);
    M_SDA_OUT(dev,0);

    *data= indata;
}

void mi2c_init(struct wr_rf_device *dev)
{
    dds_decl_private(dev);

    M_SCL_OUT(dev,1);
    M_SDA_OUT(dev,1);
}

void mi2c_scan(struct wr_rf_device *dev)
{
     int i;
     for(i=0;i<256;i+=2)
     {
          mi2c_start(dev);
        if(!mi2c_put_byte(dev,i))
            dbg("Found device at 0x%x\n", i>>1);
        mi2c_stop(dev);
     }
}

int eeprom_read(struct wr_rf_device *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
    int i;
    unsigned char c;
    for(i=0;i<size;i++)
    {
        mi2c_start(dev);
        if(mi2c_put_byte(dev, i2c_addr << 1) < 0)
        {
            mi2c_stop(dev);
            return -1;
        }

        mi2c_put_byte(dev, (offset >> 8) & 0xff);
        mi2c_put_byte(dev, offset & 0xff);
        offset++;
        mi2c_stop(dev);
        mi2c_start(dev);
        mi2c_put_byte(dev, (i2c_addr << 1) | 1);
        mi2c_get_byte(dev, &c, 0);
        //printf("readback: %x\n", c);
        *buf++ = c;
        mi2c_stop(dev);
     }
     return size;
}

int eeprom_write(struct wr_rf_device *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
    int i, busy;
    for(i=0;i<size;i++)
    {

         mi2c_start(dev);

         if(mi2c_put_byte(dev, i2c_addr << 1) < 0)
         {
             mi2c_stop(dev);
              return -1;
          }

        mi2c_put_byte(dev, (offset >> 8) & 0xff);
        mi2c_put_byte(dev, offset & 0xff);
        mi2c_put_byte(dev, *buf++);
        offset++;
        mi2c_stop(dev);

        int64_t ts = get_tics();
        do /* wait until the chip becomes ready */
        {
            mi2c_start(dev);
            busy = mi2c_put_byte(dev, i2c_addr << 1);
            mi2c_stop(dev);
        } while(busy && ((get_tics()-ts) < 1000000));
        if((get_tics()-ts) >= 1000000)
        {
            dbg("%s has timed out, the EEPROM doesn't become ready\n", __FUNCTION__);
            return -1;
        }
    }
     return size;
}
