#!/usr/bin/python

# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Author (modifications): Richard Carrillo <rcarrillo(AT)sevensols.com>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Website: http://www.sevensols.com
# Last modifications: 26/4/2012

# Import standard modules
import sys
import time

# Import specific modules
import rr
from i2c import *

# Class to access the 24AA64 (64K EEPROM) chip.
# It uses the I2C class.

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_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)
