#!/usr/bin/python

import sys
import rr
import time
        	
class COpenCoresI2C:
	R_PREL = 0x0
	R_PREH = 0x4
	R_CTR = 0x8
	R_TXR = 0xC
	R_RXR = 0xC
	R_CR = 0x10
	R_SR = 0x10
	
	CTR_EN = (1<<7)
	
	CR_STA = (1<<7)
	CR_STO = (1<<6)
	CR_WR = (1<<4)
	CR_RD = (1<<5)
	CR_NACK = (1<<3)
	
	SR_RXACK = (1<<7)
	SR_TIP = (1<<1)
	
	
	def wr_reg(self, addr, val):
		self.bus.iwrite(0, self.base +  addr, 4, val)

	def rd_reg(self,addr):
		return self.bus.iread(0, self.base + addr, 4)
	
	def __init__(self, bus, base, prescaler):
		self.bus = bus;
		self.base =base;
		self.wr_reg(self.R_CTR, 0);
		self.wr_reg(self.R_PREL, (prescaler & 0xff))
		self.wr_reg(self.R_PREH, (prescaler >> 8))
		self.wr_reg(self.R_CTR, self.CTR_EN);
	
	def wait_busy(self):
		while(self.rd_reg(self.R_SR) & self.SR_TIP):
			pass
	
	def start(self, addr, write_mode):
		addr = addr << 1
		if(write_mode == False):
			addr = addr | 1;
		self.wr_reg(self.R_TXR, addr);
		self.wr_reg(self.R_CR, self.CR_STA | self.CR_WR);
		self.wait_busy()
		
		if(self.rd_reg(self.R_SR) & self.SR_RXACK):
			raise Exception('No ACK upon address (device 0x%x not connected?)' % (addr >> 1))

	def write(self, data, last):
		self.wr_reg(self.R_TXR, data);
		cmd = self.CR_WR;
		if(last):
			cmd = cmd | self.CR_STO;
		self.wr_reg(self.R_CR, cmd);
		self.wait_busy();
		if(self.rd_reg(self.R_SR) & self.SR_RXACK):
			raise Exception('No ACK upon write')

	def read(self, last):
		cmd = self.CR_RD;
		if(last):
			cmd = cmd | self.CR_STO | self.CR_NACK;
		self.wr_reg(self.R_CR, cmd);
		self.wait_busy();
		
		return self.rd_reg(self.R_RXR);


class EEPROM_2AA64T:
	def __init__(self, i2c, addr):
		self.i2c = i2c;
		self.addr = addr;

	def wr_reg8(self, addr, value):
		self.i2c.start(self.addr, True);
		self.i2c.write((addr >> 8) & 0x00FF, False);  # Write Address High Byte
		self.i2c.write((addr & 0x00FF), False);      # Write Address Low Byte
		self.i2c.write(value, True);

		flag = 0;
		while(flag == 0) :
			try:
				self.i2c.start(self.addr, True);
				flag = 1;
			except Exception:
				time.sleep(0.001);
		

	def rd_reg8(self, addr):
		self.i2c.start(self.addr, True);
		self.i2c.write((addr >> 8) & 0x00FF, False);  # Write Address High Byte
		self.i2c.write((addr & 0x00FF), False);      # Write Address Low Byte
		self.i2c.start(self.addr, False);
		return self.i2c.read(True);

gennum = rr.Gennum();
i2c_A = COpenCoresI2C(gennum, 0x40000, 99);

eeprom = EEPROM_2AA64T(i2c_A, 0x50);

# Check the Mezzannine's EEPROM
for addr in range(0,0x2000):
	eeprom.wr_reg8(addr, addr);
	value = eeprom.rd_reg8(addr);

	if (eeprom.rd_reg8(addr) != (addr & 0x00FF) ):
		print "Error. Addr: " + hex(addr & 0x00FF) + ". Written the address, read: " + hex(value)

