#define F_CPU 1000000UL

#include <avr/io.h>
#include <util/delay.h>

#define SetBit(x,y) (x|=y)
#define ClrBit(x,y) (x&=~y)
#define TestBiy(x,y) (x&y)
#define DelayMs(x) (_delay_ms(x))

#define BIT_D 0b00000001 // бит данных
#define BIT_R 0b00000010 // бит чтения данных, иначе запись
#define BIT_E 0b00000100 // бит синхронизации
#define BIT_CS1  0b00001000 // бит отключения левой половины экрана
#define BIT_CS2  0b00010000 // бит отключения правой половины экрана
#define BIT_RST  0b00100000 // бит сброса дисплея

#define LCD_D PORTA // шина данных для дисплея
#define LCD_C PORTC // шина управления для дисплея

void WriteCom(unsigned char com, unsigned char CS){
	SetBit(LCD_C,CS); // ClrBit(LCD_C,CS);
	ClrBit(LCD_C,BIT_D);
	ClrBit(LCD_C,BIT_R);
	asm ("nop");
	asm ("nop");
	LCD_D = com;
	SetBit(LCD_C,BIT_E);
	asm ("nop");
	asm ("nop");
	ClrBit(LCD_C,BIT_E);
	DelayMs(1);
	ClrBit(LCD_C,(BIT_CS1+BIT_CS2)); // SetBit(LCD_C,(BIT_CS1+BIT_CS2));
	//SetBit(LCD_C,BIT_E);
}

void WriteData(unsigned char data, unsigned char CS){
	SetBit(LCD_C,CS); // ClrBit(LCD_C,CS);
	SetBit(LCD_C,BIT_D);
	ClrBit(LCD_C,BIT_R);
	asm ("nop");
	asm ("nop");
	LCD_D = data;
	SetBit(LCD_C,BIT_E);
	asm ("nop");
	asm ("nop");
	ClrBit(LCD_C,BIT_E);
	DelayMs(1);
	ClrBit(LCD_C,(BIT_CS1+BIT_CS2)); // SetBit(LCD_C,(BIT_CS1+BIT_CS2));
	//SetBit(LCD_C,BIT_E);
}

void WriteXY(unsigned char x, unsigned char y, const unsigned char CS){
	WriteCom(0xb8+y,CS);
	WriteCom(0x40+x,CS);
}

void clear(void){
	unsigned char x,y;
	for(x=0;x<64;x++)
		for(y=0;y<8;y++){
			WriteXY(x,y,(BIT_CS1+BIT_CS2));
			WriteData(0,(BIT_CS1+BIT_CS2));
		}
}

void initLcd(void){
	SetBit(LCD_C, BIT_RST);
	DelayMs(1);
	ClrBit(LCD_C, BIT_RST);
	DelayMs(1);
	WriteXY(0,0,(BIT_CS1+BIT_CS2));

	WriteCom(0xc0,(BIT_CS1+BIT_CS2));
	WriteCom(0x3f,(BIT_CS1+BIT_CS2));
}

void initMC(void){
	// настраиваем порты A и C на вывод данных
	DDRA=0xff;
	DDRC=0xff;
}

int main(void){
	initMC();
	initLcd();
	DelayMs(1);
	clear();
	DelayMs(1);

	WriteXY(6,2,BIT_CS1);
	DelayMs(1);
	WriteData(0b01000100,BIT_CS1);	
 	WriteData(0b01001000,BIT_CS1);	
 	WriteData(0b11110000,BIT_CS1);
	WriteData(0b00001000,BIT_CS1);	
 	WriteData(0b00000100,BIT_CS1);	
 	WriteData(0b01100010,BIT_CS1);	
 	WriteData(0b01100001,BIT_CS1);	
 	WriteData(0b00000010,BIT_CS1);	
 	WriteData(0b00000100,BIT_CS1);	
 	WriteData(0b00001000,BIT_CS1);	
 	WriteData(0b10010000,BIT_CS1);	
 	WriteData(0b01010000,BIT_CS1);	
 	WriteData(0b10010000,BIT_CS1);	
 	WriteData(0b00001000,BIT_CS1);	
 	WriteData(0b00000100,BIT_CS1);	
 	WriteData(0b01100010,BIT_CS1);	
 	WriteData(0b01100001,BIT_CS1);	
 	WriteData(0b00000010,BIT_CS1);	
 	WriteData(0b00000100,BIT_CS1);	
 	WriteData(0b00001000,BIT_CS1);	
 	WriteData(0b11110000,BIT_CS1);	
 	WriteData(0b01001000,BIT_CS1);	
 	WriteData(0b01000100,BIT_CS1);
	

	WriteXY(6,3,BIT_CS1);
	WriteData(0b00001000,BIT_CS1);	
	WriteData(0b00000100,BIT_CS1);	
	WriteData(0b00000011,BIT_CS1);	
	WriteData(0b00000100,BIT_CS1);	
	WriteData(0b00001000,BIT_CS1);
	WriteData(0b00010000,BIT_CS1);	
	WriteData(0b00100000,BIT_CS1);	
	WriteData(0b01000100,BIT_CS1);	
	WriteData(0b10001000,BIT_CS1);
	WriteData(0b10010000,BIT_CS1);
	WriteData(0b10010101,BIT_CS1);
	WriteData(0b10010010,BIT_CS1);
	WriteData(0b10010101,BIT_CS1);
	WriteData(0b10010000,BIT_CS1);
	WriteData(0b10001000,BIT_CS1);
	WriteData(0b01000100,BIT_CS1);
	WriteData(0b00100000,BIT_CS1);
	WriteData(0b00010000,BIT_CS1);
	WriteData(0b00001000,BIT_CS1);
	WriteData(0b00000100,BIT_CS1);
	WriteData(0b00000011,BIT_CS1);
	WriteData(0b00000100,BIT_CS1);
	WriteData(0b00001000,BIT_CS1); 

	while(1){}

}
