// www.artem.ru
// (C)2008 Artem Kuchin
//
// THIS IS NOT A COMPLETE CODE!!! 
// YOU MUST ADD YOU OWN LCD LIB AND REWRITE ALL CALLS TO LCD FUNCTIONS


// ****************************************
// ***        SET FREQUENCY CORRECTLY    **

#define F_CPU 1000000UL

// ****************************************


#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <stdlib.h>


#define X_XTAL1 1
#define X_OE 2
#define X_WR 3
#define X_BS1 4
#define X_XA0 5
#define X_XA1 6
#define X_BS2 7 

int main() {
	char i;
	unsigned char data[3];
	char buf[32];
	my44780 disp1;

	DDRD|=0b11111110;

	my44780_init(&disp1,MY44780_INIT_CHARSET1|MY44780_INIT_DISPLAY_ON);
	// display ON, blinking bottom line cursor
	my44780_send_command(&disp1,0b00001111);
	my44780_command_clear(&disp1);
	my44780_send_string(&disp1,"rst->gnd");
	_delay_ms(5000);

	// toggle xtal1 at lease 6 times
	for(i=0;i<8;i++){	
		PORTD|=_BV(X_XTAL1);
		_delay_ms(10);
		PORTD&=~_BV(X_XTAL1);
		_delay_ms(10);
	}
	// set prog enable pins (pagel is gnd, xa0, xa1, bs1 - zero)
	// PD4,PD5,PD6
	PORTD&=~(_BV(X_XA0)|_BV(X_XA1)|_BV(X_BS1));
	PORTD|=_BV(X_WR); // write disables
	
	my44780_command_clear(&disp1);
	my44780_send_string(&disp1,"rst->12");
	_delay_ms(5000);

	// read signature bytes

	// SET OE HIGH
	PORTD|=_BV(X_OE);

	DDRB=0xff;

	for(i=0;i<3;i++){
		// load command
		//Set XA1 to 1, XA0 to 0. This enables command loading.
		PORTD|=_BV(X_XA1);
		PORTD&=~_BV(X_XA0);
		// Set BS1 to “0”, BS1 - PD4
		PORTD&=~_BV(X_BS1);
		// Set DATA to command
		PORTB=0b00001000; // A: Load Command “0000 1000”.
		//Give XTAL1 a positive pulse. This loads the command., XTAL1 - PD1
		PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);
	
		//load address
		//Set XA1 to 0, XA0 to 0. This enables address loading.
		// XA1 - PD6, XA0 - PD5
		PORTD&=~_BV(X_XA1);
		PORTD&=~_BV(X_XA0);
		// Set BS1 to “0”, BS1 - PD4
		PORTD&=~_BV(X_BS1);
		// Set DATA to command
		PORTB=i; //  addr 0
		//Give XTAL1 a positive pulse. This loads the address low byte , pd1
		PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);

		// XA0=XA1=1
		//PORTD|=_BV(X_XA0)|_BV(X_XA1);
	
		DDRB=0;
		//Set OE to “0”  - OE - PD2
		//the selected Signature byte can now be read at DATA.
		PORTD&=~_BV(X_OE);
		_delay_ms(10);
	
		// read data
		data[(int)i]=PINB;

		//Set OE to “1”.
		PORTD|=_BV(X_OE);

		DDRB=0xff;
	}


	my44780_command_clear(&disp1);
	itoa(data[0],buf,16);
	my44780_send_string(&disp1,buf);
	my44780_send_string(&disp1," ");
	itoa(data[1],buf,16);
	my44780_send_string(&disp1,buf);
	my44780_send_string(&disp1," ");
	itoa(data[2],buf,16);
	my44780_send_string(&disp1,buf);


	_delay_ms(5000);

	// read fuses and lock bits
	// load command
	//Set XA1 to 1, XA0 to 0. This enables command loading.
	PORTD|=_BV(X_XA1);
	PORTD&=~_BV(X_XA0);
	// Set BS1 to “0”, BS1 - PD4
	PORTD&=~_BV(X_BS1);
	// Set DATA to command
	PORTB=0b00000100; // A: Load Command “0000 1000”.
	//Give XTAL1 a positive pulse. This loads the command., XTAL1 - PD1
	PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);
	

	i=0;

	DDRB=0;

	PORTD&=~_BV(X_OE);

	// fuse low byte
	PORTD&=~_BV(X_BS1);
	PORTD&=~_BV(X_BS2);
	_delay_ms(10);
	// read data
	data[(int)i]=PINB;
	i++;

	// fuse high byte
	PORTD|=_BV(X_BS1);
	PORTD|=_BV(X_BS2);
	_delay_ms(10);
	// read data
	data[(int)i]=PINB;
	i++;

	// lock bits
	PORTD|=_BV(X_BS1);
	PORTD&=~_BV(X_BS2);
	_delay_ms(10);
	// read data
	data[(int)i]=PINB;

	// disable output
	PORTD|=_BV(X_OE);
	DDRB=0xff;
	
	my44780_command_clear(&disp1);
	itoa(data[0],buf,16);
	my44780_send_string(&disp1,buf);
	my44780_send_string(&disp1," ");
	itoa(data[1],buf,16);
	my44780_send_string(&disp1,buf);
	my44780_send_string(&disp1," ");
	itoa(data[2],buf,16);
	my44780_send_string(&disp1,buf);
	
	_delay_ms(5000);
	for(i=10;i>0;i--){
		my44780_command_clear(&disp1);
		my44780_send_string(&disp1,"prog ");
		itoa(i,buf,10);
		my44780_send_string(&disp1,buf);
		_delay_ms(1000);
	}
	
	DDRD|=0b11111110;

	// chip erase
	//Set XA1 to 1, XA0 to 0. This enables command loading.
	PORTD|=_BV(X_XA1);
	PORTD&=~_BV(X_XA0);
	// Set BS1 to “0”, BS1 - PD4
	PORTD&=~_BV(X_BS1);
	// Set DATA to command
	PORTB=0b10000000;
	//Give XTAL1 a positive pulse. This loads the command., XTAL1 - PD1
	PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);
	// Give WR a negative pulse. This starts the Chip Erase. RDY/BSY goes low.
	PORTD&=~_BV(X_WR);_delay_ms(10);PORTD|=_BV(X_WR);_delay_ms(10);
	// Wait until RDY/BSY goes high before loading a new command.



	// load default data for FUSE low byte		
	//Set XA1 to 1, XA0 to 0. This enables command loading.
	PORTD|=_BV(X_XA1);
	PORTD&=~_BV(X_XA0);
	// Set BS1 to “0”, BS1 - PD4
	PORTD&=~_BV(X_BS1);
	// Set DATA to command
	PORTB=0b01000000;
	//Give XTAL1 a positive pulse. This loads the command., XTAL1 - PD1
	PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);
	// load data
	PORTD&=~_BV(X_XA1);
	PORTD|=_BV(X_XA0);
	PORTB=0b11100001; // DEFAULT VALUE FOR LOW FUSE BYTE
	PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);
	// Set BS1 to “0” and BS2 to “0”.
	PORTD&=~_BV(X_BS1);
	PORTD&=~_BV(X_BS2);
	// Give WR a negative pulse. This starts the Chip Erase. RDY/BSY goes low.
	PORTD&=~_BV(X_WR);_delay_ms(10);PORTD|=_BV(X_WR);_delay_ms(10);


	// load default data for HIGH low byte
	//Set XA1 to 1, XA0 to 0. This enables command loading.
	PORTD|=_BV(X_XA1);
	PORTD&=~_BV(X_XA0);
	// Set BS1 to “0”, BS1 - PD4
	PORTD&=~_BV(X_BS1);
	// Set DATA to command
	PORTB=0b01000000;
	//Give XTAL1 a positive pulse. This loads the command., XTAL1 - PD1
	PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);
	// load data
	PORTD&=~_BV(X_XA1);
	PORTD|=_BV(X_XA0);
	PORTB=0b10011001; // DEFAULT VALUE FOR HIGH FUSE BYTE
	PORTD|=_BV(X_XTAL1);_delay_ms(10);PORTD&=~_BV(X_XTAL1);_delay_ms(10);
	// Set BS1 to “0” and BS2 to “0”.
	PORTD|=_BV(X_BS1);
	PORTD&=~_BV(X_BS2);
	// Give WR a negative pulse. This starts the Chip Erase. RDY/BSY goes low.
	PORTD&=~_BV(X_WR);_delay_ms(10);PORTD|=_BV(X_WR);_delay_ms(10);

	my44780_command_clear(&disp1);
	my44780_send_string(&disp1,"done");

	while(1);


}


