
#include "PROJECT_INCLUDES.H"


#define	pSCK		P2_1
#define	pMISO		P2_2
#define	pMOSI		P2_3
#define	pNSS		P2_4
#define	pRAM_CS		P2_5

#define SM_DELAY()	{sm_delay = 1; while(--sm_delay);}


volatile unsigned char sm_delay;
volatile unsigned int  flash_time;
volatile CFLASH_STATE  fs;

void flash_delay(unsigned char ms)
{
	flash_time = ms;
	while(flash_time);
}

void serial_memory_init(void)
{
	unsigned long x = 0xffffffff;

	// PORT21 : SCK0(output)
	P2MDIN	 |=  (0x01 << 1);	// not configured for analog mode
	P2MDOUT  |=  (0x01 << 1);	// Output is push-pull

	// PORT22 : MISO(input)
	P2MDIN	 |=  (0x01 << 2);	// not configured for analog mode
	P2MDOUT  &= ~(0x01 << 2);	// Output is open-drain	
	pMISO = 1;

	// PORT23 : MOSI(output)
	P2MDIN	 |=  (0x01 << 3);	// not configured for analog mode
	P2MDOUT  |=  (0x01 << 3);	// Output is push-pull

	// PORT24 : NSS(output)
	P2MDIN	 |=  (0x01 << 4);	// not configured for analog mode
	P2MDOUT  |=  (0x01 << 4);	// Output is push-pull

	// PORT25 : RAM_CS(output)
	P2MDIN	 |=  (0x01 << 5);	// not configured for analog mode
	P2MDOUT  |=  (0x01 << 5);	// Output is push-pull

	// serial ram init
	sram_WRSR(0x40);			// sequential mode
	sram_write(DATA_SRAM_FLASH_ADD, (unsigned char *)&x, 4);
}


void sflash_put_byte(unsigned char ch)
{
	unsigned char i;

	for(i = 0; i < 8; i++)
	{
		if(ch & 0x80)
			pMOSI = 1;
		else 
			pMOSI = 0;

		SCK();

		ch <<= 1;
	}
}

unsigned char sflash_get_byte(void)
{
	unsigned char i; 
	unsigned char ch = 0;

	for(i = 0; i < 8; i++)
	{
		ch <<= 1;

		if(pMISO)ch |= 0x01;

		SCK();
	}
	return ch;
}

void sflash_WREN(void)
{
	pNSS = 0; 
	sflash_put_byte(WREN); 
	pNSS = 1; 
}

void sflash_WRDI(void)
{
	pNSS = 0; 
	sflash_put_byte(WRDI); 
	pNSS = 1; 
}

unsigned char sflash_RDSR(void)
{
	unsigned char ch;

	pNSS = 0; 
	sflash_put_byte(RDSR);
	ch = sflash_get_byte();
	pNSS = 1; 

	return ch;
}

void sflash_WRSR(unsigned char ch)
{
	sflash_WREN();
	pNSS = 0; 
	sflash_put_byte(WRSR);
	sflash_put_byte(ch);
	pNSS = 1; 
	sflash_WRDI();
}

unsigned char sflash_read_byte(unsigned long add)
{
	unsigned char ch;

	pNSS = 0;
	sflash_put_byte(SM_READ);
	sflash_put_byte((unsigned char)((add & 0x00ff0000) >> 16));
	sflash_put_byte((unsigned char)((add & 0x0000ff00) >> 8));
	sflash_put_byte((unsigned char) (add & 0x000000ff));

	ch = sflash_get_byte();
	pNSS = 1;

	return ch;
}

void sflash_fast_read(unsigned long add, unsigned char *buff, int len)
{
	unsigned int i;

	pNSS = 0;

	sflash_put_byte(FAST_READ);
	sflash_put_byte((unsigned char)((add & 0x00ff0000) >> 16));
	sflash_put_byte((unsigned char)((add & 0x0000ff00) >> 8));
	sflash_put_byte((unsigned char) (add & 0x000000ff));

	// dummy byte
	sflash_put_byte(0xff);

	for(i = 0; i < len; i++)
		buff[i] = sflash_get_byte();

	pNSS = 1;
}

unsigned char sflash_page_program(unsigned long add, unsigned char *buff, int len)
{
	int i = 0;

	while(sflash_RDSR() & 0x01)
	{
		SM_DELAY();
		if(++i > WRITE_PROG_DELAY)return 0;
	}

	sflash_WREN();

	pNSS = 0;

	sflash_put_byte(PAGE_PROGRAM);
	sflash_put_byte((unsigned char)((add & 0x00ff0000) >> 16));
	sflash_put_byte((unsigned char)((add & 0x0000ff00) >> 8));
	sflash_put_byte((unsigned char) (add & 0x000000ff));

	for(i = 0; i < len; i++)
		sflash_put_byte(buff[i]);

	pNSS = 1;

	sflash_WRDI();

	flash_delay(3);

	return 1;	
}

// DELAY 60ms
int sflash_sector_erase(unsigned long add, int time)
{
	unsigned short i = 0;

	while(sflash_RDSR() & 0x01)
	{
		SM_DELAY();
		if(++i > WRITE_PROG_DELAY)return 0;
	}

	sflash_WREN();

	pNSS = 0;
	sflash_put_byte(SECTOR_ERASE);
	sflash_put_byte((unsigned char)((add & 0x00ff0000) >> 16));
	sflash_put_byte((unsigned char)((add & 0x0000ff00) >> 8));
	sflash_put_byte((unsigned char) (add & 0x000000ff));

	pNSS = 1;

	sflash_WRDI();

	flash_delay(time);

	return 1;	
}

// DELAY 400ms
int sflash_bulk_erase(void)
{
	int i = 0;

	while(sflash_RDSR() & 0x01)
	{
		SM_DELAY();
		if(++i > WRITE_PROG_DELAY)return 0;
	}

	sflash_WREN();
	pNSS = 0;
	sflash_put_byte(BULK_ERASE);
	pNSS = 1;

	sflash_WRDI();

	flash_delay(402);

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



////////////////////////////////////////////////////////////
// serial ram 
#define sram_put_byte(x)	sflash_put_byte(x)
#define sram_get_byte()		sflash_get_byte()

unsigned char sram_RDSR(void)
{
	unsigned char ch;

	pRAM_CS = 0; 
	sram_put_byte(RDSR);
	ch = sram_get_byte();
	pRAM_CS = 1; 

	return ch;
}

void sram_WRSR(unsigned char ch)
{
	pRAM_CS = 0; 
	sram_put_byte(WRSR);
	sram_put_byte(ch);
	pRAM_CS = 1; 
}

unsigned char sram_read_byte(unsigned short add)
{
	unsigned char ch;

	pRAM_CS = 0;
	sram_put_byte(SM_READ);
	sram_put_byte((unsigned char)((add & 0xff00) >> 8));
	sram_put_byte((unsigned char) (add & 0x00ff));
	ch = sram_get_byte();
	pRAM_CS = 1;

	return ch;
}

void sram_write_byte(unsigned short add, unsigned char ch)
{
	pRAM_CS = 0;
	sram_put_byte(SM_WRITE);
	sram_put_byte((unsigned char)((add & 0xff00) >> 8));
	sram_put_byte((unsigned char) (add & 0x00ff));
	sram_put_byte(ch);
	pRAM_CS = 1;
}

void sram_read(unsigned short add, unsigned char *buff, int len)
{
	unsigned short i;

	pRAM_CS = 0;
	sram_put_byte(SM_READ);
	sram_put_byte((unsigned char)((add & 0xff00) >> 8));
	sram_put_byte((unsigned char) (add & 0x00ff));

	for(i = 0; i < len; i++)
		buff[i] = sram_get_byte();

	pRAM_CS = 1;
}

void sram_write(unsigned short add, unsigned char *buff, int len)
{
	unsigned short i;

	pRAM_CS = 0;
	sram_put_byte(SM_WRITE);
	sram_put_byte((unsigned char)((add & 0xff00) >> 8));
	sram_put_byte((unsigned char) (add & 0x00ff));

	for(i = 0; i < len; i++)
		sram_put_byte(buff[i]);

	pRAM_CS = 1;
}

/*void sram_write2(unsigned short add, unsigned char x, int len)
{
	unsigned short i;

	pRAM_CS = 0;
	sram_put_byte(SM_WRITE);
	sram_put_byte((unsigned char)((add & 0xff00) >> 8));
	sram_put_byte((unsigned char) (add & 0x00ff));

	for(i = 0; i < len; i++)
		sram_put_byte(x);

	pRAM_CS = 1;
}*/
////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////

extern volatile CPOWERS		power;
extern volatile CHEAD_INFO	ph_info;
extern volatile CHEAD		ph;

void flash_next_sector_used_check(unsigned long add)
{
	unsigned char ch;

	// next sector
	add += 0x1000;
	add &= SECTOR_FILTER;

	if(add >= MAX_ADDRESS)
		add = DATA_BASE_ADD;

	ch = sflash_read_byte(add);
	if(ch != 0xff)
		sflash_sector_erase(add, SECTOR_ERASE_DELAY);
}

void data_flash_to_ram(unsigned long add)
{
	volatile unsigned char *p;

	p = (unsigned char *)&power;

	add &= SECTOR_FILTER;
	sram_write(DATA_SRAM_FLASH_ADD, (unsigned char *)&add, 4);

	sflash_fast_read(add, p, 1024);
	sram_write(DATA_SRAM_BASE_ADD, p, 1024);

	sflash_fast_read(add + 1024, p, 1024);
	sram_write(DATA_SRAM_BASE_ADD + 1024, p, 1024);

	sflash_fast_read(add + 2048, p, 1024);
	sram_write(DATA_SRAM_BASE_ADD + 2048, p, 1024);

	sflash_fast_read(add + 3072, p, 1024);
	sram_write(DATA_SRAM_BASE_ADD + 3072, p, 1024);
}


void data_ram_to_flash(unsigned long add)
{
	volatile unsigned char *p;

	p = (unsigned char *)&power;

	fs.write_prog = 1;

	add &= SECTOR_FILTER;

	sflash_sector_erase(add, SECTOR_ERASE_DELAY);

	sram_read(DATA_SRAM_BASE_ADD, p, 1024);
	sflash_page_program(add,       p,       PAGE_SIZE);
	sflash_page_program(add + 256, p + 256, PAGE_SIZE);
	sflash_page_program(add + 512, p + 512, PAGE_SIZE);
	sflash_page_program(add + 768, p + 768, PAGE_SIZE);

	sram_read(DATA_SRAM_BASE_ADD + 1024, p, 1024);
	sflash_page_program(add + 1024,       p,       PAGE_SIZE);
	sflash_page_program(add + 1024 + 256, p + 256, PAGE_SIZE);
	sflash_page_program(add + 1024 + 512, p + 512, PAGE_SIZE);
	sflash_page_program(add + 1024 + 768, p + 768, PAGE_SIZE);

	sram_read(DATA_SRAM_BASE_ADD + 2048, p, 1024);
	sflash_page_program(add + 2048,       p,       PAGE_SIZE);
	sflash_page_program(add + 2048 + 256, p + 256, PAGE_SIZE);
	sflash_page_program(add + 2048 + 512, p + 512, PAGE_SIZE);
	sflash_page_program(add + 2048 + 768, p + 768, PAGE_SIZE);

	sram_read(DATA_SRAM_BASE_ADD + 3072, p, 1024);
	sflash_page_program(add + 3072,       p,       PAGE_SIZE);
	sflash_page_program(add + 3072 + 256, p + 256, PAGE_SIZE);
	sflash_page_program(add + 3072 + 512, p + 512, PAGE_SIZE);
	sflash_page_program(add + 3072 + 768, p + 768, PAGE_SIZE);

	fs.write_prog = 0;
}

void DATA_FLASH_WRITE(unsigned long add)
{
	volatile unsigned long  f_add;
	volatile unsigned short sram_add;
	volatile unsigned char  *p;

	p = (unsigned char *)&power;

	sram_read(DATA_SRAM_FLASH_ADD, (unsigned char *)&f_add, 4);
	sram_add = (unsigned short)(add & 0x0fff) + DATA_SRAM_BASE_ADD;
	add &= SECTOR_FILTER;

	if(add != f_add)
	{
		sram_write(POWER_DATA_BACKUP_ADD, p, POWER_DATA_LENGTH);
		data_flash_to_ram(add);
		sram_read(POWER_DATA_BACKUP_ADD, p, POWER_DATA_LENGTH);
	}

	sram_write(sram_add, p, POWER_DATA_LENGTH);
	data_ram_to_flash(add);
}


//void DATA_READ(unsigned long add)
//{
//}
////////////////////////////////////////////////////////////

