//==========================================================
//  Subroutine for EEPROM 24C04
//
//==========================================================
#include <msp430.h> 

#include <Project.h>

#define	BYTE_READ		0xa1		// Serial eeprom Read command
#define	BYTE_WRITE		0xa0		// Serial eeprom Write command

/*
#define	SetSDA()		pSDA = 1
#define	ResSDA()		pSDA = 0
#define	ChkSDA()		pSDA
#define	SetSCL()		pSCL = 1
#define	ResSCL()		pSCL = 0
*/

void SetSDA(void);
void ResSDA(void);
uint8_t ChkSDA(void);
void SetSCL(void);
void ResSCL(void);

void _SendStart(void);
void _SendStop(void);
uint8_t _SendData(uint8_t dat);
void _ReadData(uint8_t *dat);
uint8_t _SendAddr(uint8_t dat);

uint8_t ReadEprom(uint16_t addr, uint8_t *rdata);
uint8_t WriteEprom(uint16_t addr, uint8_t wdata);



//==========================================================
void SetSDA(void)
{
	P3DIR &= EEPROM_SDA;
	P3OUT |= EEPROM_SDA;
}

void ResSDA(void)
{
	P3DIR &= EEPROM_SDA;
	P3OUT &= ~EEPROM_SDA;
}

uint8_t ChkSDA(void)
{
	uint8_t tSDA;
	
	P3DIR &= ~EEPROM_SDA;
	tSDA = (P3IN & EEPROM_SDA) >> 1;
	
	return tSDA;
}

void SetSCL(void)
{
	P3DIR &= EEPROM_CLK;
	P3OUT |= EEPROM_CLK;
}

void ResSCL(void)
{
	P3DIR &= EEPROM_CLK;
	P3OUT &= ~EEPROM_CLK;
}

void _SendStart(void)			// Start condition
{
	SetSDA();
	SetSCL();
	ResSDA();
	ResSCL();
}

void _SendStop(void)				// Stop condition
{
	ResSCL();
	ResSDA();
	SetSCL();
	SetSDA();
}

uint8_t _SendData(uint8_t dat)
{
	uint8_t ack;
	uint8_t	i;

	for (i=0; i<8; i++){			// Write 8 bit
		if (dat & 0x80) SetSDA();
		else            ResSDA();
		SetSCL();
		ResSCL();
		dat <<= 1;
	}

	SetSDA();						// Check ACK
	SetSCL();
	if (!ChkSDA()) ack = 1;
	else           ack = 0;
	ResSCL();

	return ack;
}

void _ReadData(uint8_t *dat)
{
	uint8_t	i;
	uint8_t	rdat = 0;

	SetSDA();						// Read 8 bit
	for (i=0; i<8; i++){
		rdat <<= 1;
		SetSCL();
		if (ChkSDA()) rdat |= 1;
		ResSCL();
	} /* endfor */

	SetSCL();						// Check ACK
	ResSCL();

	*dat = rdat;
}

uint8_t _SendAddr(uint8_t dat)			// Send address
{
	_SendStart();
	return (_SendData(dat));		// return ACK
}

//==========================================================
uint8_t ReadEprom(uint16_t addr, uint8_t *rdata)
{
    uint8_t ack;
	uint8_t	bank;
	uint8_t	dat;
	uint8_t	retry = 50;

	bank = (addr >> 7) & 0x0e;
	addr &= 0xff;

	do {
		ack = _SendAddr(BYTE_WRITE | bank);
	} while ( !ack && --retry );

	if (ack){
		_SendData(addr);
		_SendStart();
		_SendData(BYTE_READ | bank);
		_ReadData(&dat);
	}
	_SendStop();

	if (ack) *rdata = dat;
	return(ack);
	
	//*rdata = dat;
	//return(ack);
}

uint8_t WriteEprom(uint16_t addr, uint8_t wdata)
{
	uint8_t ack;
	uint8_t bank;
	uint8_t retry = 20;

	bank = (addr >> 7) & 0x0e;
	addr &= 0xff;

	do {
		ack = _SendAddr(BYTE_WRITE | bank);
	} while ( !ack && --retry );

	if (ack){
		_SendData(addr);
		_SendData(wdata);
	}
	_SendStop();

	return(ack);
}

/*
//=======================================================================
//	Load & Save Setup value
//=======================================================================
uint8_t LoadEprom(void)
{
	uint8_t	*dp, chksum = 0;
	uint16_t	i;

	dp = (uint8_t *)&setup;
	for (i=0; i<sizeof(setup); i++){
		ReadEprom(i, dp);
		chksum += *dp++;
	}
	if (chksum) return 0;
	return 1;
}

//------------------------------------------------------------------------
void	UpdateEprom(void)
{
	uint8_t	*dp, chksum = 0;
	uint16_t	i;

	dp = (uint8_t *)&setup;
	for (i=0; i<sizeof(setup)-1; i++){
		WriteEprom(i, *dp);
		chksum += *dp++;
	}
	WriteEprom(i, ~chksum + 1);
}
*/
