#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#define F_CPU   4915200

//pins
#define CS      PB2                                         //chip select (eeprom)

//eeprom instructions
#define WREN    0x06
#define WRDI    0x04
#define RDSR    0x05
#define WRSR    0x01
#define READ    0x03
#define WRITE   0x02


void spi_init(void);                                        //initialize spi interface
unsigned char spi_transfer(unsigned char data);             //transmit data via spi
void spi_eeprom_write(unsigned int adress, unsigned int data);  //write data to external eeprom via spi 
unsigned int spi_eeprom_read(unsigned int adress);          //read data from external eeprom via spi 


int main(void)
{
	//init ports
	DDRB   = 0xFF;											
	PORTB  = 0xFF;
    	DDRC   = 0x00;										
	PORTC  = 0x00;											
	DDRC   = 0xFF;
 	PORTC  = 0x00;						
	
	spi_init();
   	
	spi_eeprom_write(0,1);
    
	unsigned int data = spi_eeprom_read(0);

    	for(;;);
 }


void spi_eeprom_write(unsigned int adress, unsigned int data)
{   
    adress *= 2;

    unsigned char dummy;

    if (adress < 65534)     
    {
        PORTB &= ~(1<<CS);                                      //pull chip select low

        dummy = spi_transfer(WREN);                             //transmit write enable instruction
        dummy = spi_transfer(WRITE);                            //transmit write instruction
        dummy = spi_transfer((unsigned char) adress>>8);        //transmit adress MSB
        dummy = spi_transfer((unsigned char) adress);           //transmit adress LSB
        dummy = spi_transfer((unsigned char) data>>8);          //transmit data MSB 
        dummy = spi_transfer((unsigned char) data);             //transmit data LSB
        dummy = spi_transfer(WRDI);                             //transmit write disable instruction

        PORTB |=  (1<<CS);                                      //pull chip select high
    }
}	//end of eeprom_write


unsigned int spi_eeprom_read(unsigned int adress)
{
    unsigned char dummy;
    unsigned int data = 0;        

    PORTB &= ~(1<<CS);                                      //pull chip select low

    dummy = spi_transfer(READ);                             //transmit write enable instruction
    dummy = spi_transfer((unsigned char) adress>>8);        //transmit adress MSB
    dummy = spi_transfer((unsigned char) adress);           //transmit adress LSB            
    data += (8<<spi_transfer(0x00));                        //read data LSB by dummy transmission
    data += spi_transfer(0x00);                             //read data MSB by dummy transmission
   
    PORTB |=  (1<<CS);                                      //pull chip select high

    return data;
}	//end of spi_eeprom_read


void spi_init(void)
{
    DDRB  |=  (1<<PB3) | (1<<PB5);                          //set MOSI and SCK output
    DDRB  &= ~(1<<PB4);                                     //set MISO input
    
    SPCR = (1<<SPE) | (1<<MSTR);                            //enable spi, master, clock rate f_cpu/4 
}   //end of spi_init 


unsigned char spi_transfer(unsigned char data)
{
    SPDR = (unsigned char) data;                            //transmit data
     
    while (!(SPSR & (1<<SPIF)));                            //wait for transmission complete
 
    return SPDR;                                            //return received data 