.include "m16def.inc" ; ATMega16

//--------------------------------
.DSEG

.def temp=R16

.equ	LCD_PORT 	= PORTA
.equ	LCD_DDR		= DDRA
.equ    LCD_PIN		= PINA

.equ	D4 		= 0
.equ	D5 		= 1
.equ 	D6 		= 2
.equ	D7 		= 3

.equ	RS		= 4
.equ	EN		= 5

//---------------------------------
//-----------------------------------------------
.CSEG

.ORG $0000
RJMP INIT

//Инициализация МК-------------------------------
INIT:
	//Инициализация стека----------
	ldi r16,low(RAMend)
	out SPL,r16
	ldi r16,high(RAMend)
	out SPH,r16	
	//-----------------------------

	//Инициализация дисплея
	RCALL 	LCD_INIT
	RCALL	WAIT_100us

	LDI temp, 0b10000000		//Адрес DDRAM - 0x00 (первая строка)	
	RCALL 	Two

	LDI 	temp, 'M'
	RCALL WrData
	RCALL	WAIT_100us

	LDI 	temp, 'A'
	RCALL WrData
	RCALL	WAIT_100us

	

	LDI temp, 0b11000000		//Адрес DDRAM - 0x40 (вторая строка)	
	RCALL 	Two

	LDI 	temp, 0xbd
	RCALL WrData
	RCALL	WAIT_100us

	LDI 	temp, 'a'
	RCALL WrData
	RCALL	WAIT_100us

STOP:
	NOP
	RJMP STOP
	
//------------------------------------------------
//Подпрограммы------------------------------------

//---------------------------------
LCD_INIT:
	RCALL	WAIT_20ms
	sbi		LCD_DDR, D4				;Ножки порта на выход
	sbi		LCD_DDR, D5
	sbi		LCD_DDR, D6
	sbi		LCD_DDR, D7
	
	sbi		LCD_DDR, RS
	sbi		LCD_DDR, EN

	cbi		LCD_PORT, RS			;оистить значение RS, EN
	cbi		LCD_PORT, EN
	RCALL 	WAIT_100us

	
	LDI 	temp, 0b00000011
	RCALL 	One						;Начальная инициализация
	RCALL	WAIT_5ms
	LDI 	temp, 0b00000011
	RCALL 	One						;вызывается
	RCALL	WAIT_100us
	LDI 	temp, 0b00000011
	RCALL 	One						;три раза
	RCALL	WAIT_100us
	
	LDI 	temp, 0b00000010		;4x битный режим
	RCALL 	One			
	RCALL	WAIT_100us
//--------------------------	
	LDI 	temp, 0x28				;2 строки 5х7
	RCALL 	Two						
	RCALL	WAIT_100us
//--------------------------
	LDI 	temp, 0x06				;автоинкремент счетчика DDRAM
	RCALL 	Two			
	RCALL	WAIT_100us

	LDI 	temp, 0x0c				;Дисплей вкл, курсор выкл
	RCALL 	Two					
	RCALL	WAIT_100us

	LDI 	temp, 0x01				;очистить LCD
	RCALL 	Two			
	RCALL	WAIT_5ms
	
	RET
//----------------------------------
WrData:
	CLR 	R17						;Чистим R17
	SBR 	R17, 0b00010000			;Установим 5 бит в R17 (RS=1 запись данных)
	RJMP 	TwoData
	RET


Two:									;Записать в дисплей	
	CLR 	R17												
TwoData:
	PUSH 	R16							;Загрузка значения в стек
	SWAP 	R16							;поменяли полубайты местами
	ANDI 	temp, 0b00001111			;маскируем старшую часть байта
	OR 		temp, R17					;объединяем младшую часть байта и R17					
	OUT     LCD_PORT, temp				;выводим получившееся значение в порт
	NOP
	NOP
	NOP
	SBI		LCD_PORT, EN				;начало строба
	NOP
	NOP
	CBI 	LCD_PORT, EN				;конец строба
	RCALL	WAIT_100us
	NOP
	POP 	R16							;вытащили оригинал данных из стека
	ANDI 	temp, 0b00001111			;замаскировали старшие полубайты
	OR 		temp, R17					;объединили два регистра
One:
	OUT     LCD_PORT, temp				;вывели получившееся значение в порт
	NOP
	NOP
	NOP
	SBI		LCD_PORT, EN				;начало строба
	NOP
	NOP
	NOP
	CBI 	LCD_PORT, EN				;конец строба
	RCALL 	WAIT_100us					;задержка
	RET

//----------------------------------
//Подпрограммы задержки
WAIT_20ms:								;Расчет делался в программе 
	LDI R18,104							;калькуляторе AVR DELAY LOOP
	LDI R19,228
  L1:
	DEC R19
	BRNE L1
	DEC R18
	BRNE L1
	RET

//----------------------------------

WAIT_5ms:								;Расчет делался в программе 
	LDI R18,26						;калькуляторе AVR DELAY LOOP
	LDI R19,248
  L3:
	DEC R19
	BRNE L3
	DEC R18
	BRNE L3
	RET

//----------------------------------
WAIT_100us:
	LDI	R18,133
  L2:
	DEC 	R18
	BRNE	L2
	NOP
	RET
