#include <avr/io.h>
#include <util/delay.h>

// SPI settings
#define SPI_PORT 	PORTB
#define SPI_DDR  	DDRB
#define MOSI		PB5   
#define MISO		PB6
#define SCK			PB7

// Chip Select pin on AVR
#define ROM 		PB2			// 25LC320 EEPROM chip select
#define SR			PB4			// 74HC595 chip select

// INSTRUCTION SET
#define READ		0b00000011	// Read data from memory array beginning at selected address
#define WRITE		0b00000010	// Write data to memory array beginning at selected address
#define WRDI		0b00000100	// Reset the write enable latch (disable write operations)
#define WREN		0b00000110	// Set the write enable latch (enable write operations)
#define RDSR		0b00000101	// Read Status register
#define WRSR		0b00000001	// Write Status register

// Status Register Settings
unsigned char ROMSR = 0x00;		// ROM Status Register
// W/R
#define WPEN		0b10000000	// Write-Protect Enable
#define BP0			0b00000100	// Block Protection0
#define BP1			0b00001000	// Block Protection1

// Read only
#define WEL			0b00000010	// Block Protection0
#define WIP			0b00000001	// Block Protection1

// address 16bit max 2^12=4096*8bit 128*32byte

unsigned char data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

void SPIWR(unsigned char data)
{
	SPDR = data;
	while(!(SPSR & (1<<SPIF)));
	_delay_us(1);
}

unsigned char SPIRD(void)
{
	SPDR = 0x00;
	while(!(SPSR & (1<<SPIF)));
	_delay_us(1);
	return(SPDR);
}

void SPI_Init(void)
{
	SPI_DDR |= (1<<SCK)|(1<<MOSI)|(1<<ROM)|(1<<SR);
	SPCR |= (0<<SPIE)|(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
	SPCR &= ~((1<<CPOL)|(1<<CPHA)|(1<<DORD));
	SPSR |= (0<<SPI2X);
}

unsigned char ROMRDSR(void)
{
	SPI_PORT &= ~(1<<ROM);			
	SPIWR(RDSR);
	SPDR = 0x00;
	while(!(SPSR & (1<<SPIF)));
	SPI_PORT |= (1<<ROM);
	_delay_ms(1);
	return(SPDR);					
}

void ROMWRSR(unsigned char data)
{
	SPI_PORT &= ~(1<<ROM);
	SPIWR(WREN);
	SPI_PORT |= (1<<ROM);
	_delay_us(1);
	SPI_PORT &= ~(1<<ROM);
	SPIWR(WRSR);
	SPIWR(data);
	SPI_PORT |= (1<<ROM);
	_delay_ms(5);
}

void ROMBusyCheck(void)
{
	unsigned char data;
	
	data = 0x01;
	
	if(data != 0b00000000)
	{
		ROMSR = ROMRDSR();
		_delay_ms(500);
		
		PORTD ^= (1<<PIND5);
		
		data = (ROMSR & 0x01);
	}
}

void ROMWR(unsigned char addrh, unsigned char addrl, unsigned char start, unsigned char end )		// max 32byte
{
	ROMBusyCheck();
	
	SPI_PORT &= ~(1<<ROM);
	SPIWR(WREN);
	SPI_PORT |= (1<<ROM);
	_delay_ms(5);
	SPI_PORT &= ~(1<<ROM);
	SPIWR(WRITE);
	SPIWR(addrh);
	SPIWR(addrl);
	
	for(unsigned char i = start; i<end; i++)
    {
		SPIWR(data[i]);
		_delay_us(1);
		//_delay_ms(100);
		//PORTD ^= (1<<PIND5);
    }
	
	SPI_PORT |= (1<<ROM);
	_delay_ms(5);
}

void ROMRD(unsigned char addrh, unsigned char addrl, unsigned char start, unsigned char end)
{
	ROMBusyCheck();
	
	SPI_PORT &= ~(1<<ROM);
	SPIWR(READ);
	SPIWR(addrh);
	SPIWR(addrl);
	
	for(unsigned char i = start; i<end; i++)
    {
		data[i] = SPIRD();
		_delay_us(1);
		//_delay_ms(100);
		//PORTD ^= (1<<PIND5);

    }
	
	SPI_PORT |= (1<<ROM);
	_delay_ms(5);
	
}