#!/usr/bin/python

import sys
import rr
import time
import i2c

class Eeprom24AA64OperationError(Exception):
        def __init__(self, addr, msg):
                self.msg = msg
                self.addr = addr
        def __str__(self):
                return ("EEPROM 24AA64 [I2C address:0x%02X]: %s" %(self.addr, self.msg))


class C24AA64:

        PAGE_SIZE = 32 # in bytes
        PAGE_BOUNDARY_MASK = 0xFFFF - (PAGE_SIZE - 1)

	def __init__(self, i2c, i2c_addr):
		self.i2c = i2c
		self.i2c_addr = i2c_addr

	def wr_data(self, mem_addr, data):
                if len(data) > 32:
                        print "Maximum sequence write size is 32 byte!"
                        return -1;
		self.i2c.start(self.i2c_addr, True)
                self.i2c.write((mem_addr >> 8), False)
                self.i2c.write((mem_addr & 0xFF), False)
                #print('24AA64:write: data lenght=%d')%(len(data))
		for i in range(len(data)-1):
                        #print('24AA64:write: i=%d')%(i)
                        self.i2c.write(data[i],False)
                if len(data) > 1:
                        i += 1
                else:
                        i = 0
                #print('24AA64:write:last i=%d')%(i)
                self.i2c.write(data[i],True)
		return 0;

	def rd_data(self, mem_addr, size):
		self.i2c.start(self.i2c_addr, True)
		self.i2c.write((mem_addr >> 8), False)
                self.i2c.write((mem_addr & 0xFF), False)
		self.i2c.start(self.i2c_addr, False)
                data = []
                #print('24AA64:read: data lenght=%d')%(size)
		for i in range(size-1):
                        data.append(self.i2c.read(False))
                        #print('24AA64:read: i=%d')%(i)
                #print('24AA64:read:last i=%d')%(i)
                data.append(self.i2c.read(True))
		return data;

        def wr_byte(self, mem_addr, byte):
                try:
                        self.i2c.start(self.i2c_addr, True)
                        self.i2c.write((mem_addr >> 8), False)
                        self.i2c.write((mem_addr & 0xFF), False)
                        self.i2c.write(byte,True)
                except I2CDeviceOperationError as e:
                        raise Eeprom24AA64OperationError(self.i2c_addr, e)

        def rd_byte(self, mem_addr):
                try:
                        self.i2c.start(self.i2c_addr, True)
                        self.i2c.write((mem_addr >> 8), False)
                        self.i2c.write((mem_addr & 0xFF), False)
                        self.i2c.start(self.i2c_addr, False)
                        return self.i2c.read(True)
                except I2CDeviceOperationError as e:
                        raise Eeprom24AA64OperationError(self.i2c_addr, e)

        def wr_page(self, mem_addr, data):
                try:
                        #print '[24AA64] write data lenght=%d' % (len(data))
                        #print '[24AA64] write addr=%04X' % (mem_addr)
                        if(len(data) == 0):
                                raise Eeprom24AA64OperationError(self.i2c_addr, "Nothing to transmit, data size is 0!")
                        if(len(data) > self.PAGE_SIZE):
                                raise Eeprom24AA64OperationError(self.i2c_addr, "Maximum write size is %d byte!" % self.PAGE_SIZE)
                        if((mem_addr | self.PAGE_BOUNDARY_MASK) ^ self.PAGE_BOUNDARY_MASK):
                                raise Eeprom24AA64OperationError(self.i2c_addr, "Start write address is not aligned to a page boundary!")
                        self.i2c.start(self.i2c_addr, True)
                        self.i2c.write((mem_addr >> 8), False)
                        self.i2c.write((mem_addr & 0xFF), False)
                        #print '[24AA64] write data lenght=%d' % (len(data))
                        i = 0
                        for i in range(len(data)-1):
                                #print '[24AA64] write i=%d' % (i)
                                self.i2c.write(data[i],False)
                        if len(data) > 1:
                                i += 1
                        #print '[24AA64] write last i=%d' % (i)
                        self.i2c.write(data[i],True)
                except I2CDeviceOperationError as e:
                        raise Eeprom24AA64OperationError(self.i2c_addr, e)

	def rd_seq(self, mem_addr, size):
                try:
                        self.i2c.start(self.i2c_addr, True)
                        self.i2c.write((mem_addr >> 8), False)
                        self.i2c.write((mem_addr & 0xFF), False)
                        self.i2c.start(self.i2c_addr, False)
                        data = []
                        #print '[24AA64] read data lenght=%d' % (size)
                        i=0
                        for i in range(size-1):
                                data.append(self.i2c.read(False))
                                #print '[24AA64] read i=%d' % (i)
                        if len(data) > 1:
                                i += 1
                        #print '[24AA64] read last i=%d' % (i)
                        data.append(self.i2c.read(True))
                        return data
                except I2CDeviceOperationError as e:
                        raise Eeprom24AA64OperationError(self.i2c_addr, e)
