
#include <avr/io.h>         //подключаем библиотеки
#include <util/delay.h>

#define SPI_DDR     DDRB    //назначаем имя для изменеия направления на порту B
#define SPI_PORT    PORTB   //назначаем имя для используемого порта
#define SPI_SS      PB4     //назначаем имя выхода SS
#define SPI_MOSI    PB5     //назначаем имя выхода MOSI
#define SPI_MISO    PB6     //назначаем имя выхода MISO
#define SPI_SCK     PB7     //назначаем имя выхода SCK


// 25LC512 EEPROM instructions
#define WREN    	0x06    // write enable
#define WRDI    	0x04    // write disable
#define WRITE   	0x02    // initialize start of write sequence
#define READ    	0x03    // initialize start of read sequence
#define CE      	0xc7    // erase all sectors of memory
#define RDSR    	0x05    // read STATUS register


unsigned char array[]={1,2,3,4,5,6,7,8,9};


void spi_w(unsigned char data){			//забивает 8 бит в шину
	unsigned char i=0;
	
	_delay_us(10);
	for (i=0; i<8; i++)
       {
		if( (data>>(7-i))&0x01 ) SPI_PORT |= (1<<SPI_MOSI); else SPI_PORT &= ~(1<<SPI_MOSI);		//SPI_MOSI = (addr>>(7-i))&0x01
        _delay_us(10);        
		SPI_PORT |= (1<<SPI_SCK);					//SPI_SCK=1;
        _delay_us(30);
        SPI_PORT &= ~(1<<SPI_SCK);					//SPI_SCK=0;
        _delay_us(20);
       }
	_delay_us(20);	
}


unsigned char spi_r(void){				//забиваем 8 dummy бит в шину - чтение
	unsigned char i=0; 
	unsigned char data=0; 

	_delay_us(10);
	for (i=0; i<8; i++)
       {
        SPI_PORT |= (1<<SPI_SCK);					//SPI_SCK=1;
        _delay_us(30); 
        data = data<<1;
        data |= (1<<SPI_MISO);		
        SPI_PORT &= ~(1<<SPI_SCK);					//SPI_SCK=0;
        _delay_us(20); 
       }
	_delay_us(20);
       
	return data;
}




//-----------------------------------------------------------------
void waitBusy(void){						// checks if EEPROM is ready to be modified and waits if not ready
    char status = 0;
	
	do{
		SPI_PORT &= ~(1<<SPI_SS);          // Select EEPROM
		spi_w(RDSR);						// Read EEPROM status register          
		status = spi_r();     				// send dummy byte to receive incoming data
		SPI_PORT |= (1<<SPI_SS);           // Release EEPROM    
	}while(status & 0x01);             		// write-in-progress while status<0> set to '1'
}


//-------------------------------------------------------------------
void mem_r(char addr){
	unsigned int i = 0, size = 9;
	unsigned char array[10];
	
	waitBusy();
	
	SPI_PORT &= ~(1<<SPI_SS);               	// Select EEPROM		
    spi_w(READ);								// initiate read
	spi_w(addr>>8);								// address must be 16-bits but we're transferring it in two 8-bit sessions
	spi_w(addr);
    
    for( i=0 ; i<size ; i++)					// Request and store loadArray_size number of bytes into loadArray
        array[i] = spi_r();   					// send dummy byte to read 1 byte
 	
	SPI_PORT |= (1<<SPI_SS);                	// Release EEPROM	
}


//-------------------------------------------------------------------
void mem_w(unsigned short addr, char* array){
	unsigned int i = 0, size = 9;
    
	waitBusy();
 
    SPI_PORT &= ~(1<<SPI_SS);               	// Select EEPROM
    spi_w( WREN );   							// Send WRITE_ENABLE command
    SPI_PORT |= (1<<SPI_SS);                	// Release EEPROM
	
    SPI_PORT &= ~(1<<SPI_SS);               	// Select EEPROM again after WREN cmd
    spi_w( WRITE );  							// initiate write
    spi_w( addr >> 8 );
    spi_w( addr );    
 	SPI_PORT |= (1<<SPI_SS);           		// Release EEPROM
	
	for( i=0 ; i < size; i++ ){
		waitBusy();
	
		SPI_PORT &= ~(1<<SPI_SS);          		// Select EEPROM
		spi_w( WREN );   							// Send WRITE_ENABLE command
		SPI_PORT |= (1<<SPI_SS);           		// Release EEPROM
	
		SPI_PORT &= ~(1<<SPI_SS);          		// Select EEPROM again after WREN cmd
		spi_w( WRITE );  							// initiate write
		spi_w( (addr+i) >> 8 );
		spi_w( addr+i );
		spi_w( array[i] );	
		SPI_PORT |= (1<<SPI_SS);					// Release EEPROM
	}
}



int main(void){
	//unsigned char data = 0;
	//unsigned int data = 0;

    SPI_DDR = (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS);    //настраиваем MOSI, SCK, SS как выходы
    SPI_PORT |= (1<<SPI_SS);                              //устанавливаем SS в 1

    while(1){ 

		//waitBusy();
		mem_r(180);


        _delay_ms(1000);   

    }
    return 0;
}