

#include "PROJECT_INCLUDES.H"


#define I2C_SDA_PORT_DIGITAL_MODE 			{P0MDIN	  |= P06_I2C_SDA;}
#define I2C_SCL_PORT_DIGITAL_MODE 			{P0MDIN	  |= P07_I2C_SCL;}


#define I2C_SDA_PORT_PUSH_PULL_OUT_MODE 	{P0MDOUT  |= P06_I2C_SDA;}
#define I2C_SDA_PORT_OPEN_DRAIN_IN_MODE 	{P0MDOUT  &=~P06_I2C_SDA;}

#define I2C_SCL_PORT_PUSH_PULL_OUT_MODE 	{P0MDOUT  |= P07_I2C_SCL;}
#define I2C_SCL_PORT_OPEN_DRAIN_IN_MODE 	{P0MDOUT  &=~P07_I2C_SCL;} 

#define I2C_SDA_HIGH						{P0 |= P06_I2C_SDA;}
#define I2C_SDA_LOW     					{P0 &=~P06_I2C_SDA;}
#define I2C_SCL_HIGH						{P0 |= P07_I2C_SCL;}
#define I2C_SCL_LOW							{P0 &=~P07_I2C_SCL;} 


extern volatile void Delay_us(volatile U32 idata  dlycnt);
extern volatile void I2C_SDA_PORT_OUTPUT(void);
extern volatile void I2C_SDA_PORT_INPUT(void);

extern U32 Grap_Unit1;
/////////////////////////////////////////////////////////////////////////////////////
// I2C
/*xdata volatile unsigned char i2c_delay;

#define I2C_D {i2c_delay = 1; while(--i2c_delay);}

char I2C_put_byte(char x)
{
	char ack;

	I2C_SDA_PORT_PUSH_PULL_OUT_MODE;

	pSDA = (x & 0x80) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;
	pSDA = (x & 0x40) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;
	pSDA = (x & 0x20) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;
	pSDA = (x & 0x10) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;
	pSDA = (x & 0x08) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;
	pSDA = (x & 0x04) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;
	pSDA = (x & 0x02) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;
	pSDA = (x & 0x01) ? 1 : 0; pSCL = HIGH; I2C_D; pSCL = LOW; I2C_D;

	SDA_IN(); I2C_D;
	pSCL = 1; I2C_D; ack = pSDA; pSCL = 0; I2C_D;
	SDA_OUT(); I2C_D;
	
	return ack;
}

char I2C_get_byte(char ack)
{
	char x;

	SDA_IN(); I2C_D;
	pSCL = HIGH; I2C_D; x  = (pSDA) ? 0x80 : 0; pSCL = LOW; I2C_D;
	pSCL = HIGH; I2C_D; x |= (pSDA) ? 0x40 : 0; pSCL = LOW; I2C_D;
	pSCL = HIGH; I2C_D; x |= (pSDA) ? 0x20 : 0; pSCL = LOW; I2C_D;
	pSCL = HIGH; I2C_D; x |= (pSDA) ? 0x10 : 0; pSCL = LOW; I2C_D;
	pSCL = HIGH; I2C_D; x |= (pSDA) ? 0x08 : 0; pSCL = LOW; I2C_D;
	pSCL = HIGH; I2C_D; x |= (pSDA) ? 0x04 : 0; pSCL = LOW; I2C_D;
	pSCL = HIGH; I2C_D; x |= (pSDA) ? 0x02 : 0; pSCL = LOW; I2C_D;
	pSCL = HIGH; I2C_D; x |= (pSDA) ? 0x01 : 0; pSCL = LOW; I2C_D;

	SDA_OUT();  I2C_D;
	pSDA = ack;
	pSCL = 1; I2C_D; pSCL = 0; I2C_D;

	return x;
}*/
/////////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////////
// M24M02 EEPROM
/*void M24M02_write_byte(unsigned long add, unsigned char x)
{
	unsigned char add_high;

	add_high = (add >> 15) & 0x06;

	I2C_start();
	I2C_put_byte(M24M02_CHIP1_ADD | add_high);
	I2C_put_byte((unsigned char)(add >> 8));
	I2C_put_byte((unsigned char)(add));
	I2C_put_byte(x);
	I2C_stop();

	Delay_us(10000);
}

unsigned char M24M02_read_byte(unsigned long add)
{
	unsigned char x;
	unsigned char add_high;

	add_high = (add >> 15) & 0x06;

	I2C_start();
	I2C_put_byte(M24M02_CHIP1_ADD | add_high);
	I2C_put_byte((unsigned char)(add >> 8));
	I2C_put_byte((unsigned char)(add));

	I2C_start();
	I2C_put_byte(M24M02_CHIP1_ADD | add_high | 0x01);
	x = I2C_get_byte(I2C_NACK);
	I2C_stop();

	return x;
}

void M24M02_write_buff(unsigned long add, unsigned char *x, unsigned short len)
{
	unsigned short i;
	unsigned char  add_high;

	add_high = (add >> 15) & 0x06;

	I2C_start();
	I2C_put_byte(M24M02_CHIP1_ADD | add_high);
	I2C_put_byte((unsigned char)(add >> 8));
	I2C_put_byte((unsigned char)(add));

	for(i = 0; i < len; i++)
		I2C_put_byte(x[i]);

	I2C_stop();

	Delay_us(10000);
}


void M24M02_read_buff(unsigned long add, unsigned char *x, unsigned short len)
{
	unsigned short i;
	unsigned char  add_high;

	add_high = (add >> 15) & 0x06;

	I2C_start();
	I2C_put_byte(M24M02_CHIP1_ADD | add_high);
	I2C_put_byte((unsigned char)(add >> 8));
	I2C_put_byte((unsigned char)(add));

	for(i = 0; i < len; i++)
	{
		I2C_start();
		I2C_put_byte(M24M02_CHIP1_ADD | add_high | 0x01);
		x[i] = I2C_get_byte(I2C_NACK);
		I2C_stop();
	}

	//I2C_start();
	//I2C_put_byte(M24M02_CHIP1_ADD | add_high | 0x01);
	//for(i = 1; i < len; i++)
	//{
	//	if(i == len - 1)
	//		x[i] = I2C_get_byte(I2C_NACK);
	//	else 
	//		x[i] = I2C_get_byte(I2C_ACK);
	//}
	//I2C_stop();
}*/
/////////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////////
xdata volatile CHEAD		ph;
xdata volatile CHEAD_INFO	ph_info;
xdata volatile CPOWERS		power;

int get_head_info(void)
{
	volatile int			i;
	volatile POWR_DATA 	sWeek;
	
	for(i = 0; i < 4096; i += 8)
	{
		sflash_fast_read(i, (unsigned char *)&ph, 1);
		if(ph.flag == 0xff)break;
	}

	if(i >= 4096)
	{ 
		i = 0;
		sflash_sector_erase(0, SECTOR_ERASE_DELAY);
	}

	i >>= 3;
	if(i)i--;
	else 
	{
		// head area init
		memset((void *)&ph, 0, sizeof(ph));
		ph.flag = HEAD_FLAG;
		ph.cur.point = DATA_BASE_ADD;
		ph.cur.year = (unsigned char)(event1.years - 2000);
		ph.cur.month = event1.output_month;
		ph.cur.day = event1.output_days;
		sflash_page_program(0, (unsigned char *)&ph, 8);

		// power data area init
		sWeek.Year = ph.cur.year;
		sWeek.Month = ph.cur.month;
		sWeek.Day = ph.cur.year;
		Search_Weekly_SunDay(&sWeek, WEEK_);

		memset((void *)&power, 0xff, POWER_DATA_LENGTH);
		power.flag = POWER_FLAG;
		power.year  = ph.cur.year;
		power.month = ph.cur.month;
		power.day   = ph.cur.day;
		power.week  = sWeek.Week;
		sflash_page_program(ph.cur.point, (unsigned char *)&power, 5);

		ph_info.idx = 0;

		//printf("@@headinit ");
		return 0;
	}

	//printf("@@head %d ", i);
	sflash_fast_read(i<<3, (unsigned char *)&ph, 8);
	ph_info.idx = i;

	return i;
}

void put_head_info(void)
{
	ph_info.idx++;

	if((ph_info.idx<<3) >= 4096)
	{ 
		ph_info.idx = 0;
		sflash_sector_erase(0, SECTOR_ERASE_DELAY);
	}
	sflash_page_program(ph_info.idx<<3, (unsigned char *)&ph, 8);
}
void Read_PowerInfomation(void)
{
	get_head_info();

	if(ph.flag != HEAD_FLAG)
	{
		sflash_bulk_erase();
		get_head_info();
	}
}

unsigned long get_eeprom_address(CPOWERS_AUG *p, char kind)
{
	volatile unsigned short  rep = 2044;
	volatile unsigned char   sbuff[6] = {0}, test;
	volatile unsigned long 	address;

	if(!p->month || p->month > 12) return 0;
	if(!p->day   || p->day   > 31) return 0;

	address = ph.cur.point;

	while(--rep)
	{
		address -= POWER_DATA_LENGTH;

		if(address < DATA_BASE_ADD)
			address = LAST_FIELD_ADDRESS;

		sflash_fast_read(address, sbuff, 5);
#if 1     // for debugging 
		test=sbuff[0];         // power flag A0
		test=sbuff[1];         //   year
		test=sbuff[2];         //   month
		test=sbuff[3];         //  day
		test=sbuff[4];         // week 
		test=sbuff[5];
		test=p->year;
		test=p->month;
		test=p->day ;
#endif 
#if 1     // for testing OK
		if(sbuff[0] != POWER_FLAG)
			#if 0  // 저장되지 않은 데이터의 경우 데이터가 없으면 그냥 0으로 return 한다 그래서 저장되지 않을  경우를 대비하여 addr 를 return 한다. 
			return 0;
			#else
			return address;
			#endif
#endif 
		if( sbuff[1] == p->year  && \
			sbuff[2] == p->month && \
			sbuff[3] == p->day   && \
			kind     == DAY_K)
		{
			return address;
		}

		if( sbuff[1] == p->year  && \
			sbuff[4] == p->week  && \
			kind     == WEEK_K)
		{
			return address;
		}

		if( sbuff[1] == p->year  && \
			sbuff[2] == p->month && \
			kind     == MONTH_K)
		{
			return address;
		}
	}
	return 0;
}

void head_check(CPOWERS_AUG *p)
{
	char w_flag = 0;

	/*if(!ph.cur.year && !ph.cur.month && !ph.cur.day)
	{
		ph.cur.year = p->year;
		ph.cur.month = p->month;
		ph.cur.day = p->day;
		w_flag = 1;
	}*/

	if(!(ph.cur.year  == p->year  &&	\
		 ph.cur.month == p->month &&	\
		 ph.cur.day   == p->day))
	{
		ph.cur.year = p->year;
		ph.cur.month = p->month;
		ph.cur.day = p->day;

		ph.cur.point += POWER_DATA_LENGTH;

		if(ph.cur.point >= MAX_ADDRESS)
			ph.cur.point = DATA_BASE_ADD;

		memset((void *)&power, 0xff, POWER_DATA_LENGTH);
		power.flag = POWER_FLAG;
		power.year  = p->year;
		power.month = p->month;
		power.day   = p->day;
		power.week  = p->week;
		sflash_page_program(ph.cur.point, (unsigned char *)&power, 5);

		w_flag = 1;
	}

	if(w_flag)put_head_info();
}

int PutEnergyData_OneHour(CPOWERS_AUG *p)
{
	volatile unsigned long address, x;

	if(p->hour >= 24) return 0;
	if(p->channel_num >= MAX_CHANNEL)return 0;

	DATA_READ(ph.cur.point);

	/*if(!power.year && !power.month && !power.day)
	{
		power.year = p->year;
		power.month = p->month;
		power.day = p->day;
		power.week = p->week;
	}*/

	if(!(power.year  == p->year  &&	\
		 power.month == p->month &&	\
		 power.day   == p->day))
	{
		//printf("head_check()  ");
		head_check(p);
	}

	power.value[p->hour][p->channel_num] = p->power;

	address = ph.cur.point + 64 + (p->hour*40) + (p->channel_num * 4);
	sflash_page_program(address, (unsigned char *)&p->power, 4);
	sflash_fast_read   (address, (unsigned char *)&x, 4);


//SRAM 삭제 부분2014.04.12
	//printf("Put%05ld  ", x);

	//if(p->power != x)
	//{
		//printf("sram op ");
	//	DATA_FLASH_WRITE(ph.cur.point);
	//}

//SRAM 삭제 부분2014.04.12

	flash_next_sector_used_check(ph.cur.point);

	return 1;
}

int GetEnergyDataOneHour(CPOWERS_AUG *p)
{
	volatile unsigned long address;
	
	if(p->month >  12)return 0;
	if(p->day   >  31)return 0;
	if(p->hour  >= 24)return 0;
	if(p->channel_num >= MAX_CHANNEL)return 0;


	if( ph.cur.year  == p->year  &&	\
		ph.cur.month == p->month &&	\
		ph.cur.day   == p->day)
	{
		DATA_READ(ph.cur.point);
		if(power.value[p->hour][p->channel_num] == 0xffffffff)
			p->power = 0;
		else
			p->power = power.value[p->hour][p->channel_num];
	}else
	{
		address = get_eeprom_address(p, DAY_K);

		if(!address)return 0;

		DATA_READ(address);

		if(power.value[p->hour][p->channel_num] == 0xffffffff)
			p->power = 0;
		else
			p->power = power.value[p->hour][p->channel_num];
	}
	//printf("\n Hour%05ld  ", p->power);
	///printf("\n OneHour = %ld  ", p->power);
	return 1;
}

int GetEnergyDataOneDay(CPOWERS_AUG *p)
{
	volatile char			i;
	volatile unsigned long	address;
	volatile unsigned long	powerDay = 0;

	if(p->month >  12)return 0;
	if(p->day   >  31)return 0;
	if(p->channel_num >= MAX_CHANNEL)return 0;

	#if 1
	if( ph.cur.year  == p->year  &&	\
		ph.cur.month == p->month &&	\
		ph.cur.day   == p->day)
	{
		DATA_READ(ph.cur.point);
	}else
	{
		address = get_eeprom_address(p, DAY_K);
		if(!address)return 0;
		DATA_READ(address);
	}
	#else
	DATA_READ(ph.cur.point);
	#endif
	
	for(i = 0; i < HOURS; i++)
	{ 
		if(power.value[i][p->channel_num] != 0xffffffff)
		{
			powerDay += power.value[i][p->channel_num];
		}
	}
	power.sum_onehour[p->channel_num]=powerDay;   // store energy one day
	p->power = powerDay;
	//printf("\n Day%05ld  ", p->power);
///	printf("\n Day = %ld  ", p->power);

	return 1;
}
 // thhan 0825
int GetEnergyDataPeakOfWeek(CPOWERS_AUG *p)
{
	volatile char i,j;
	volatile unsigned long address;
	volatile unsigned long powerDay = 0;
	//U8 volatile  Dsp_Level1, test;
	//volatile  U32  test2;
	CPOWERS_AUG *temp;
	
	if(p->month > 12)return 0;
	if(p->channel_num >= MAX_CHANNEL)return 0;


	DATA_READ(ph.cur.point);

	if( power.year == p->year  &&	power.week == p->week)
	{
		address = ph.cur.point;
	}else
	{
		address = get_eeprom_address(p, WEEK_K);
		if(!address)return 0;
	}

	temp = p;
	
	for(j=0;j<7;j++) 
	{
		DATA_READ(address);
		powerDay =0; 

		for(i = 0; i < HOURS; i++)
			if(power.value[i][p->channel_num] != 0xffffffff)
			{
				powerDay += power.value[i][p->channel_num];
				///printf("\n >>>>>>> day=%d, power= %ld, channel_num =%d  ", (U16)power.day, (U32)powerDay, (U16)p->channel_num);
			}

			if(powerDay > Search_Week_Peak_Power[p->channel_num]) 
			{
				Search_Week_Peak_Power[p->channel_num] = powerDay;
		      	///printf("\n ====> GetEnergyDataOneWeek1 powerDay= %ld, Week Peak Power =%ld  ", (U32)powerDay, Search_Week_Peak_Power[p->channel_num]);
			}

		address -= POWER_DATA_LENGTH;
		if(address < DATA_BASE_ADD)
			address = LAST_FIELD_ADDRESS;
	}
	
	return 1;
}

int GetEnergyDataOneWeek(CPOWERS_AUG *p)
{
	volatile char rep = 7, i;
	volatile unsigned long address;
	volatile unsigned long powerWeek = 0;

	if(p->month > 12)return 0;
	if(p->channel_num >= MAX_CHANNEL)return 0;


	DATA_READ(ph.cur.point);
	#if 1
	if( power.year == p->year  &&	\
		power.week == p->week)
	{
		address = ph.cur.point;
	}else
	{
		address = get_eeprom_address(p, WEEK_K);
		if(!address)return 0;
	}
	#else
	address = ph.cur.point;
	#endif
	while(rep--)
	{
		DATA_READ(address);

		if(!(power.year == p->year && power.week == p->week))
			break;

		for(i = 0; i < HOURS; i++)
			if(power.value[i][p->channel_num] != 0xffffffff)
				powerWeek += power.value[i][p->channel_num];

		address -= POWER_DATA_LENGTH;
		if(address < DATA_BASE_ADD)
			address = LAST_FIELD_ADDRESS;
	}
	p->power = powerWeek;
	//printf("\n Day%05ld  ", p->power);
///	printf("\n week = %ld  ", p->power);
	return 1;
}


int GetEnergyDataOneMonth(CPOWERS_AUG *p)
{
	volatile char rep = 31, i;
	volatile unsigned long address;///,test;
	volatile unsigned long powerMonth = 0;

	if(p->month > 12) return 0;
	if(p->channel_num >= MAX_CHANNEL) return 0;

	DATA_READ(ph.cur.point);
	if( power.year  == p->year  &&	\
		power.month == p->month)
	{
		address = ph.cur.point;
	}else
	{
		address = get_eeprom_address(p, MONTH_K);
		if(!address)return 0;
	}

	while(rep--)
	{
		DATA_READ(address);

		if(!(power.year == p->year && power.month == p->month))
			break;

		for(i = 0; i < HOURS; i++)
			if(power.value[i][p->channel_num] != 0xffffffff)
				{
				///test=power.value[i][p->channel_num];
				powerMonth += power.value[i][p->channel_num];
				}
		address -= POWER_DATA_LENGTH;

		if(address < DATA_BASE_ADD)
			address = LAST_FIELD_ADDRESS;
	}

	p->power = powerMonth;
///	printf("\n Month = %ld  ", p->power);

	return 1;
}

int GetEnergyDataOneMonthFromToday(CPOWERS_AUG *p)
{
	volatile char rep = 31, i;
	volatile unsigned long address;///,test;
	volatile unsigned long powerMonth = 0;

	if(p->month > 12) return 0;
	if(p->channel_num >= MAX_CHANNEL) return 0;

	DATA_READ(ph.cur.point);
	
	if( power.year  == p->year  &&	power.month == p->month)
	{
		address = ph.cur.point;
	}else
	{
		address = get_eeprom_address(p, MONTH_K);
		if(!address)
		{
			return 0;
		}
	}

	while(rep--)
	{
		DATA_READ(address);

		///if(!(power.year == p->year && power.month == p->month))
		///	break;

		for(i = 0; i < HOURS; i++)
			if(power.value[i][p->channel_num] != 0xffffffff)
			{
				powerMonth += power.value[i][p->channel_num];
			}
		address -= POWER_DATA_LENGTH;

		if(address < DATA_BASE_ADD)
		{
			address = LAST_FIELD_ADDRESS;
		}
	}

	p->power = powerMonth;
	//printf("\n Month = %ld  ", p->power);

	return 1;
}
/////////////////////////////////////////////////////////////////////////////////////

