/*
*******************************************************************************************************************
*								SERIAL EEPROM DRIVER (ATMEL AT24C256 or compatible)
* Description:  IIC-based serial eeprom driver (ATMEL AT24C256 or compatible)
* File:			at24c256.c
* Software:		Keil C (C51) compiler, Eval version 7.09 under uVision2 IDE v2.40
* Programmer: 	John Leung, TechToys Co. (www.TechToys.com.hk)
* Hardware:		AT89S52-gLCD-STK1
* Date:			14th May 2006
* Version:		1.0
*******************************************************************************************************************
*/

#include <reg52.h>
#include "iic.h"
#include "at24c256.h"

/*
*******************************************************************************************************************
*											BYTE WRITE TO AT24C256 EEPROM
* Function:	 This function writes a single byte to AT24C256 at the address 'dataptr'
* Argument:	'eeprom_addr'		EEPROM address, 0xA0 if pins A0-A2 tighted to GND
*			'dataptr'			address to write
*			'c'					data to write
* Return:	'EEPROM_BUS_ERR' 	if any one of those three i2c_SendByte() calls returns an 'noACK'
*			'EEPROM_BUS_OK' 	if no error
*
* Note:		Need a min 5ms write time (consult data sheet on this)
*******************************************************************************************************************
*/
uchar eeprom_WrByte(uchar eeprom_addr, uint dataptr, uchar c)
{
	uchar dataptrh, dataptrl;
	
	dataptrh = (uchar) (dataptr>>8);
	dataptrl = (uchar) (dataptr);

	if(i2c_SeqWr(eeprom_addr, dataptrh, dataptrl, &c, 1)==noACK) return (EEPROM_BUS_ERR);

	return (EEPROM_BUS_OK);	
}

/*
*******************************************************************************************************************
*								PAGE WRITE A STRING/ARRAY TO AT24C256 EEPROM
*
* Function:	Simply an extension to eeprom_WrByte() above. A string OR and array written to EEPROM.
*			Length of the string\array should be shorter than EEPROM_PAGE_SIZE; 64 in case of AT24C256.	
*			A page write is initiated the same as a byte write, but the microcontroller does not send
*			a stop condition after the first data word is clocked in. Instead, after the EEPROM
*			acknowledges receipt of the first data word, the microcontroller can transmit up to 63
*			more data words.	
*			The data word address lower 6 bits are internally incremented following the receipt of each
*			data word. The higher data word address bits are not incremented, retaining the memory page
*			row location. When the word address, internally generated, reaches the page boundary, the
*			following byte is placed at the beginning of the same page. If more than 64 data words are
*			transmitted to the EEPROM, the data word address will ˇ°roll overˇ± and previous data will be
*			overwritten.
* Argument:	'eeprom_addr'		EEPROM address, being 0xA0 if pins A0-A2 tighted to GND
*			'dataptr'			address to write
*			'*s'				pointer to the string/array to write
*			'length'			length of the string/array
* Return:	'EEPROM_BUS_ERR' 	if any one of those i2c_SendByte() calls returns an 'noACK' 
								-OR- length > EEPROM_PAGE_SIZE
*			'EEPROM_BUS_OK' 	if no error
* Note:		Example :
*					opcode[5] = {0x12,0x34,0x45,0x56,0x34};
*					eeprom_WrPage(0xA0, 0x0000, &s[0], 5);
*
*			Make a delay of 10ms after a PAGE WRITE!
*******************************************************************************************************************
*/
uchar eeprom_WrPage(uchar eeprom_addr, uint dataptr, uchar *s, uchar length)
{
	uchar dataptrh, dataptrl;

	dataptrh = (uchar) (dataptr>>8);
	dataptrl = (uchar) (dataptr);

	if (length>EEPROM_PAGE_SIZE) return (EEPROM_BUS_ERR);
	
	if (i2c_SeqWr(eeprom_addr, dataptrh, dataptrl, &s[0], length)==noACK) return (EEPROM_BUS_ERR);

	return (EEPROM_BUS_OK);
}


/*
*******************************************************************************************************************
*											RANDOM READ FROM AT24C256 EEPROM
*
* Function:	Read a single byte from AT24C256 at the address 'dataptr' and place the result in &s. 
*			A random read requires a "dummy" byte write sequence to load in the data word address.
*			Once the device address and data address are clocked in and acknowledged by the EEPROM,
*			the mcu must generate another start condition. All these encapsulated in i2c_SeqRd().	
* Argument:	'eeprom_addr'		EEPROM address, being 0xA0 if pins A0-A2 tighted to GND
*			'dataptr'			address to read from eeprom
*			'*s'				pointer to string/array holding the byte read
* Return:	'EEPROM_BUS_ERR' 	if any one of those three i2c_SendByte() calls returns an 'noACK'
*			'EEPROM_BUS_OK' 	if no error
* Note:	
*******************************************************************************************************************
*/
uchar eeprom_RdRandomByte(uchar eeprom_addr, uint dataptr, uchar *s)
{
	uchar dataptrh, dataptrl;

	dataptrh = (uchar) (dataptr>>8);
	dataptrl = (uchar) (dataptr);

	if(i2c_SeqRd(eeprom_addr, dataptrh, dataptrl, &s[0], 1)==noACK) return (EEPROM_BUS_ERR);
	
	return (EEPROM_BUS_OK);
}

/*
*******************************************************************************************************************
*										PAGE READ AN ARRAY FROM AT24C256 EEPROM
*
* Function:	This function performs sequential read (page read) by a random address
* Argument:	'eeprom_addr'		EEPROM address, being 0xA0 if pins A0-A2 tighted to GND
*			'dataptr'			address to read from eeprom
*			'*s'				pointer to the string/array holding the bytes read
*			'length'			length of the string/array
* Return:	'EEPROM_BUS_ERR' 	if i2c_SeqRd() returns noACK	-OR- 	length > EEPROM_PAGE_SIZE
*			'EEPROM_BUS_OK' 	if no error
* Note:
*******************************************************************************************************************
*/
uchar eeprom_RdPage(uchar eeprom_addr, uint dataptr, uchar *s, uchar length)
{
	uchar dataptrh, dataptrl;

	dataptrh = (uchar) (dataptr>>8);
	dataptrl = (uchar) (dataptr);

	if (length>EEPROM_PAGE_SIZE) return (EEPROM_BUS_ERR);

	if(i2c_SeqRd(eeprom_addr, dataptrh, dataptrl, &s[0], length)==noACK) return (EEPROM_BUS_ERR);

	return (EEPROM_BUS_OK);
}
