
;
; CS8416 with AVR ATtiny26L
;
; ver 1.2
; by UENO Tomohiro    2007/6/6

.include "tn26def.inc"

.def	tmp		= R16
.def	tmp2		= R17
.def	tmp3		= R18
.def	counter		= R19
.def	reg_address	= R20
.def	reg_data	= R21
.def	tmp4		= R22
.def	edit_flag	= R23
.def	ch		= R0
.def	current_btn	= R1
.def	current_freq	= R2
.def	current_ch	= R3
.def	edit_reg	= R4
.def	edit_bit	= R5
.def	edit_bit_shift	= R6
.def	dai_read_data	= R7
.def	set_1_data	= R8
.def	set_0_data	= R9
.def	emphasis	= R10

.equ	dai_reset	= 7	; portA
.equ	sel		= 6	; portA
.equ	lcd_e		= 5	; portA
.equ	lcd_rs		= 4	; portA
.equ	lcd_d7		= 3	; portA
.equ	lcd_d6		= 2	; portA
.equ	lcd_d5		= 1	; portA
.equ	lcd_d4		= 0	; portA

.equ	cdout		= 6	; portB
.equ	cclk		= 5	; portB
.equ	cdin		= 4	; portB
.equ	dai_cs		= 3	; portB
.equ	button2		= 2	; portB
.equ	button1		= 1	; portB
.equ	button0		= 0	; portB

.equ	freq_44_1	= 0
.equ	freq_48_0	= 1
.equ	freq_88_2	= 2
.equ	freq_96_0	= 3
.equ	freq_d_c	= 4
.equ	freq_32_0	= 5
.equ	freq_176_4	= 6
.equ	freq_192_0	= 7
.equ	freq_no_signal	= 0xff

.equ	ch_status_table	= 0x60

.macro LCD_STR
	ldi	ZL,low(@0)
	ldi	ZH,high(@0)
	rcall	lcd_put_str
.endmacro


	rjmp	reset	; $000 reset vector

	reti		; $001 EXT_INT0 

	reti		; $002 PIN_CHG 

	reti		; $003 TIMER1 COMPA 

	reti		; $004 TIMER1 COMPB

	reti		; $005 TIMER1 OVF1 

	reti		; $006 TIMER1 OVF0 

	reti		; $007 USI_STRT

	reti		; $008 USI_OVF

	reti		; $009 EE_RDY
	reti		; $00A ANA_COMP

	reti		; $00B ADC



reset:	
	ldi	tmp,LOW(RAMEND)

	out	SP,tmp

	rcall	wait_1ms

	; portA initialize

	ldi	tmp,0b10111111

	out	DDRA,tmp

	ldi	tmp,0b11111111	

	out	PORTA,tmp



	; portB initialize

	ldi	tmp,0b00111000

	out	DDRB,tmp

	ldi	tmp,0b11111111

	out	PORTB,tmp


	; A/D converter initialize
	ldi	tmp,0b11000111	; ADEN=1,ADSC=1,ADFR=0(not continue),ADIF=0,ADIE=0,ASPS<2-0>=111
	out	ADCSR,tmp

	rcall	lcd_init
	rcall	lcd_clear

	rcall	eeprom_read
;	rcall	eeprom_print
	ldi	YH,high(ch_status_table)
	ldi	YL,low(ch_status_table)
	ldd	tmp,Y+10*2
	cpi	tmp,0x55
	breq	PC+2
	rcall	eeprom_initialize

	rcall	lcd_clear
	ldi	tmp,0x00+0
	rcall	lcd_pos
	LCD_STR(initial_str1)
	ldi	tmp,0x40+0
	rcall	lcd_pos
	LCD_STR(initial_str2)
	
	ldi	tmp,0xfe
	mov	current_freq,tmp

reset_loop:

	; CS8416 reset
	sbi	PORTA,dai_reset
	cbi	PORTA,dai_reset
	rcall	wait_1ms
	sbi	PORTA,dai_reset
	
	rcall	set_all_dai_reg

	ldi	reg_address,0x7f
	rcall	dai_read
	mov	tmp,reg_data

	cbr	tmp,0b00001111
	cpi	tmp,0x20
	brne	reset_loop	

	ldi	tmp,'?'
	cpi	reg_data,0x21
	brne	PC+3
	ldi	tmp,'A'
	rjmp	PC+16
	cpi	reg_data,0x22
	brne	PC+3
	ldi	tmp,'B'
	rjmp	PC+12
	cpi	reg_data,0x23
	brne	PC+3
	ldi	tmp,'C'
	rjmp	PC+8
	cpi	reg_data,0x27
	brne	PC+3
	ldi	tmp,'D'
	rjmp	PC+4
	cpi	reg_data,0x2f
	brne	PC+2
	ldi	tmp,'E'
	rcall	lcd_put


;	rcall	wait_1s
;	rcall	wait_1s
	rcall	wait_1s

	ldi	tmp,0xff
	mov	current_ch,tmp
	mov	emphasis,tmp
	mov	edit_flag,tmp

;	ldi	reg_address,0x04
;	ldi	reg_data,0x80
;	rcall	dai_write

main_loop:
	rcall	lcd_clear
	ldi	tmp,0x00+0
	rcall	lcd_pos
	LCD_STR(str_input_ch)
	ldi	tmp,0x40+0
	rcall	lcd_pos
	LCD_STR(str_receive)

mainloop_check_ch:
	in	tmp,PINB
	andi	tmp,7
	brne	PC+3
	rcall	eeprom_initialize
	rjmp	RESET

	sbis	PINB,0
	rjmp	edit_start
	
	ldi	reg_address,0x0a
	rcall	dai_read
	andi	reg_data,0x01
	cp	reg_data,emphasis
	breq	emphasis_end
	mov	emphasis,reg_data
	ldi	tmp,12
	rcall	lcd_pos
	cpi	reg_data,0
	brne	emphasis_off
	LCD_STR(emphasis_on_str)
	rjmp	emphasis_end	
emphasis_off:
	LCD_STR(emphasis_off_str)
emphasis_end:

	rcall	check_ch
	cp	tmp,current_ch
	breq	mainloop_check_ch_end
	mov	current_ch,tmp

	ldi	reg_address,0x04
	rcall	dai_read
	andi	reg_data,0xc0
	or	tmp,current_ch
	lsl	tmp
	lsl	tmp
	lsl	tmp
	or	tmp,current_ch
	ldi	reg_address,0x04
	mov	reg_data,tmp
	rcall	dai_write
	ldi	tmp,0x00+4
	rcall	lcd_pos
	mov	tmp,current_ch
	inc	tmp
	rcall	lcd_put_hex
mainloop_check_ch_end:

mainloop_check_freq:
	rcall	detect_rx_freq	
	cp	current_freq,tmp
	breq	mainloop_check_freq_end
	mov	current_freq,tmp
	ldi	tmp,0x40+8
	rcall	lcd_pos
	mov	tmp,current_freq
	rcall	put_freq
mainloop_check_freq_end:
	rcall	wait_1ms
	rjmp	mainloop_check_ch	

detect_rx_freq:
	ldi	reg_address,0x18
	rcall	dai_read

	rcall	detect_rx_freq_sub
	cpi	tmp,freq_no_signal
	breq	PC+2
	ret

	dec	reg_data
	rcall	detect_rx_freq_sub
	cpi	tmp,freq_no_signal
	breq	PC+2
	ret
	inc	reg_data
	inc	reg_data
	rcall	detect_rx_freq_sub
	ret
	
detect_rx_freq_sub:
	ldi	tmp,freq_no_signal
	cpi	reg_data,92
	brne	PC+2
	ldi	tmp,freq_32_0
	cpi	reg_data,67
	brne	PC+2
	ldi	tmp,freq_44_1
	cpi	reg_data,61
	brne	PC+2
	ldi	tmp,freq_48_0
	cpi	reg_data,33
	brne	PC+2
	ldi	tmp,freq_88_2
	cpi	reg_data,31
	brne	PC+2
	ldi	tmp,freq_96_0
	cpi	reg_data,16
	brne	PC+2
	ldi	tmp,freq_176_4
	cpi	reg_data,14
	brne	PC+2
	ldi	tmp,freq_192_0
	ret	

check_ch:
	ldi	tmp,0b00100101 	; REFS1=0,REFS0=0(AVCC),ADLAR=1(left adjust),convert=ADC5
	out	ADMUX,tmp
	sbi	ADCSR,ADSC
	sbic	ADCSR,ADSC
	rjmp	PC-1

	in	tmp2,ADCH
	ldi	tmp,0
	cpi	tmp2,32
	brsh	PC+2
	ret
	ldi	tmp,1
	cpi	tmp2,82
	brsh	PC+2
	ret
	ldi	tmp,2
	cpi	tmp2,120
	brsh	PC+2
	ret
	ldi	tmp,3
	cpi	tmp2,152
	brsh	PC+2
	ret
	ldi	tmp,4
	cpi	tmp2,180
	brsh	PC+2
	ret
	ldi	tmp,5
	cpi	tmp2,208
	brsh	PC+2
	ret
	ldi	tmp,6
	cpi	tmp2,239
	brsh	PC+2
	ret
	ldi	tmp,7
	ret

	
put_freq:
	cpi	tmp,freq_32_0
	brne	put_freq_44_1
	LCD_STR(str_freq_32_0)
	ret
put_freq_44_1:
	cpi	tmp,freq_44_1
	brne	put_freq_48_0
	LCD_STR(str_freq_44_1)
	ret
put_freq_48_0:
	cpi	tmp,freq_48_0
	brne	put_freq_88_2
	LCD_STR(str_freq_48_0)
	ret
put_freq_88_2:
	cpi	tmp,freq_88_2
	brne	put_freq_96_0
	LCD_STR(str_freq_88_2)
	ret
put_freq_96_0:
	cpi	tmp,freq_96_0
	brne	put_freq_no_signal
	LCD_STR(str_freq_96_0)
	ret
put_freq_176_4:
	cpi	tmp,freq_176_4
	brne	put_freq_no_signal
	LCD_STR(str_freq_176_4)
	ret
put_freq_192_0:
	cpi	tmp,freq_192_0
	brne	put_freq_no_signal
	LCD_STR(str_freq_192_0)
	ret
put_freq_no_signal:
	LCD_STR(str_freq_no_signal)
	ret

edit_reg_str:
.db	"REG",0
edit_bit_str:
.db	"BIT",0

initial_str1:
.db	"Software v1.2",0
initial_str2:
.db	"CS8416 rev.",0

emphasis_on_str:
.db	"EMPH",0
emphasis_off_str:
.db	"    ",0


str_input_ch:
.db	"Ch.",0
str_receive:
.db	"Receive",0
str_freq_32_0:
.db	"32.0kHz ",0
str_freq_44_1:
.db	"44.1kHz ",0
str_freq_48_0:
.db	"48.0kHz ",0
str_freq_88_2:
.db	"88.2kHz ",0
str_freq_96_0:
.db	"96.0kHz ",0
str_freq_176_4:
.db	"176.4kHz",0
str_freq_192_0:
.db	"192.0kHz",0
str_freq_no_signal:
.db	"NoSignal",0
str_freq_d_c:
.db	"------- ",0


edit_start:
	ldi	edit_flag,1
	rcall	lcd_clear
	ldi	tmp,0
	rcall	lcd_pos
	LCD_STR(edit_reg_str)	
	ldi	tmp,0x40
	rcall	lcd_pos
	LCD_STR(edit_BIT_str)	
	ldi	tmp,0xff
	mov	edit_reg,tmp
	ldi	tmp,7
	mov	edit_bit,tmp
	ldi	tmp,0x80
	mov	edit_bit_shift,tmp
	
edit_loop:
	rcall	wait_1ms
	sbis	PINB,0
	rjmp	edit_loop_btn_reg
	sbis	PINB,1
	rjmp	edit_loop_btn_bit
	sbis	PINB,2
	rjmp	edit_loop_btn_change
	rjmp	edit_loop_end

edit_loop_btn_reg:
	inc	edit_reg
	ldi	tmp,10
	cp	edit_reg,tmp
	brne	PC+3
	ldi	tmp,0
	mov	edit_reg,tmp
	rcall	edit_print

	sbis	PINB,0
	rjmp	PC-1
	rjmp	edit_loop_end


edit_loop_btn_bit:
	dec	edit_bit
	ldi	tmp,7
	and	edit_bit,tmp
	mov	tmp,edit_bit_shift
	ror	tmp
	ror	edit_bit_shift
	rcall	edit_print

	sbis	PINB,1
	rjmp	PC-1
	rjmp	edit_loop_end

edit_loop_btn_change:
	rcall	get_reg_table

	mov	tmp,set_1_data			;check '1'
	and	tmp,edit_bit_shift
	breq	PC+6
	mov	tmp,edit_bit_shift
	com	tmp
	and	set_1_data,tmp
	or	set_0_data,edit_bit_shift
	rjmp	edit_loop_btn_change_end

	mov	tmp,set_0_data			;check '0'
	and	tmp,edit_bit_shift
	breq	PC+5
	mov	tmp,edit_bit_shift
	com	tmp
	and	set_0_data,tmp
	rjmp	edit_loop_btn_change_end

	or	set_1_data,edit_bit_shift	; do none

edit_loop_btn_change_end:
	rcall	set_reg_table
	rcall	set_all_dai_reg
	rcall	edit_print
	rcall	eeprom_write

	sbis	PINB,2
	rjmp	PC-1
	rjmp	edit_loop_end

edit_loop_end:
	rjmp	edit_loop
                                                                                                                                                                                                                                                                                                                                                         
edit_print:
	ldi	tmp,0x04
	rcall	lcd_pos
	mov	tmp,edit_reg
	rcall	lcd_put_hex
	ldi	tmp,0x44
	rcall	lcd_pos
	mov	tmp,edit_bit
	rcall	lcd_put_hex
	
	mov	reg_address,edit_reg
	rcall	dai_read
	mov	dai_read_data,reg_data
	rcall	get_reg_table
	
	ldi	tmp,8
	rcall	lcd_pos
	ldi	tmp3,0x80

	ldi	tmp4,0
	ldi	tmp,'0'
	lsl	dai_read_data
	adc	tmp,tmp4
	mov	tmp2,set_1_data
	and	tmp2,tmp3
	breq	PC+2
	ldi	tmp,1
	mov	tmp2,set_0_data
	and	tmp2,tmp3
	breq	PC+2
	ldi	tmp,0
	rcall	lcd_put
	lsr	tmp3
	brne	PC-14

	ldi	tmp,0x48
	rcall	lcd_pos
	ldi	counter,8
	ldi	tmp,' '
	rcall	lcd_put
	dec	counter
	brne	PC-3

	ldi	tmp,0x4f
	sub	tmp,edit_bit
	rcall	lcd_pos
	ldi	tmp,2
	rcall	lcd_put

	ret

set_dai_reg:
	push	edit_reg
	mov	reg_address,tmp
	mov	edit_reg,tmp
	rcall	get_reg_table
	rcall	dai_read
	or	reg_data,set_1_data
	mov	tmp,set_0_data
	com	tmp
	and	reg_data,tmp
	rcall	dai_write
	pop	edit_reg
	ret

set_all_dai_reg:
	ldi	tmp,0
	rcall	set_dai_reg
	ldi	tmp,1
	rcall	set_dai_reg
	ldi	tmp,2
	rcall	set_dai_reg
	ldi	tmp,3
	rcall	set_dai_reg
	ldi	tmp,4
	rcall	set_dai_reg
	ldi	tmp,5
	rcall	set_dai_reg
	ldi	tmp,6
	rcall	set_dai_reg
	ldi	tmp,7
	rcall	set_dai_reg
	ldi	tmp,8
	rcall	set_dai_reg
	ldi	tmp,9
	rcall	set_dai_reg
	ret


;;;;;;;;;;;;;;;;;;;;;;;;;;
; edit table

get_reg_table:
	mov	tmp,edit_reg
	inc	tmp
	ldi	YH,high(ch_status_table)
	ldi	YL,low(ch_status_table)
	ldi	tmp2,0
	inc	tmp2
	ld	set_1_data,Y+
	ld	set_0_data,Y+
	cp	tmp,tmp2
	brne	PC-4
	ret

set_reg_table:
	ldi	tmp,0
	ldi	YH,high(ch_status_table)
	ldi	YL,low(ch_status_table)
	cp	tmp,edit_reg
	breq	PC+5
	ld	tmp2,Y+
	ld	tmp2,Y+
	inc	tmp
	rjmp	PC-5
	st	Y+,set_1_data
	st	Y+,set_0_data
	ret

;
; dai register write
;
;   reg_address  : address (bit7-0)
;   reg_data	 : data    (bit7-0)
;
dai_write:
	cbi	PORTB,dai_cs
	ldi	tmp,0b00100000
	rcall	write_sub
	mov	tmp,reg_address
	rcall	write_sub
	mov	tmp,reg_data
	rcall	write_sub
	sbi	PORTB,dai_cs
	ret

;
; dai register read
;
;   reg_address  : address (bit7-0)
;   reg_data	 : data    (bit7-0)
;
dai_read:
	cbi	PORTB,dai_cs
	ldi	tmp,0b00100000
	rcall	write_sub
	mov	tmp,reg_address
	rcall	write_sub
	sbi	PORTB,dai_cs
	nop
	nop
	cbi	PORTB,dai_cs
	ldi	tmp,0b00100001
	rcall	write_sub
	ldi	tmp2,8
dai_read_loop:
	lsl	reg_data		
	cbr	reg_data,0x01
	sbic	PINB,cdout
	sbr	reg_data,0x01
	sbi	PORTB,cclk
	cbi	PORTB,cclk
	dec	tmp2
	brne	dai_read_loop
	sbi	PORTB,dai_cs
	rcall	wait_1ms
	ret

write_sub:
	ldi	tmp2,8
write_sub_loop:	
	sbi	PORTB,cdin	
	rol	tmp
	brcs	PC+2
	cbi	PORTB,cdin
	sbi	PORTB,cclk
	cbi	PORTB,cclk
	dec	tmp2
	brne	write_sub_loop
	ret

;;;;;;;;;;;;
;; eeprom

eeprom_write:
	ldi	tmp2,0
	ldi	YH,high(ch_status_table)
	ldi	YL,low(ch_status_table)
eeprom_write_loop:	
	sbic	EECR,EEWE
	rjmp	PC-1
	out	EEAR,tmp2
	ld	tmp,Y+
	out	EEDR,tmp
	sbi	EECR,EEMWE
	sbi	EECR,EEWE
	rcall	wait_1ms
	inc	tmp2
	cpi	tmp2,16*2
	brne	eeprom_write_loop
	ret

eeprom_read:
	ldi	tmp2,0
	ldi	YH,high(ch_status_table)
	ldi	YL,low(ch_status_table)
eeprom_read_loop:	
	sbic	EECR,EEWE
	rjmp	PC-1
	out	EEAR,tmp2
	sbi	EECR,EERE
	in	tmp,EEDR
	st	Y+,tmp
	rcall	wait_1ms
	inc	tmp2
	cpi	tmp2,16*2
	brne	eeprom_read_loop
	ret

eeprom_initialize:
	rcall	lcd_clear
	ldi	tmp,0
	rcall	lcd_pos
	LCD_STR(eeprom_init_str)
	
	ldi	YH,high(ch_status_table)
	ldi	YL,low(ch_status_table)
	ldi	ZH,high(eeprom_init_data)
	ldi	ZL,low(eeprom_init_data)
	lsl	ZL
	rol	ZH	
	ldi	tmp2,0

	lpm	tmp,Z
	adiw	ZL,1
	st	Y+,tmp	
	lpm	tmp,Z
	adiw	ZL,1
	st	Y+,tmp	
	inc	tmp2	
	cpi	tmp2,11
	brne	PC-8

	rcall	wait_1s
	rcall	wait_1s
	rcall	wait_1s
	rcall	wait_1s
	rcall	wait_1s
	rcall	eeprom_write
	ret
			
eeprom_init_str:
.db	"Setting Init...",0

eeprom_init_data:
.db	0x00,0x00	;reg 00	: '1'set,'0'set
.db	0x00,0x00	;reg 01
.db	0x40,0x30	;reg 02
.db	0x00,0x00	;reg 03
.db	0x80,0x40	;reg 04
.db	0x88,0x77	;reg 05
.db	0x00,0x00	;reg 06
.db	0x00,0x00	;reg 07
.db	0x00,0x00	;reg 08
.db	0x00,0x00	;reg 09
.db	0x55,0xaa	;reg 10 (eeprom sanity check, not CS8416 reg)



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; LCD (SUNLIKE SC1602BS-B) initialize
;
lcd_init:
	ldi	counter,10
	rcall	wait_1ms
	dec	counter
	brne	PC-2
	ldi	tmp,0x03
	rcall	lcd_control_out
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	ldi	tmp,0x03
	rcall	lcd_control_out
	rcall	wait_1ms
	ldi	tmp,0x03
	rcall	lcd_control_out
	rcall	wait_1ms
	ldi	tmp,0x02
	rcall	lcd_control_out
	ldi	tmp,0x28
	rcall	lcd_control
	ldi	tmp,0x0c
	rcall	lcd_control
	ldi	tmp,0x06
	rcall	lcd_control
	ldi	tmp,0x01

	rcall	lcd_char_set
	ret

;
; LCD screen clear and move position (0,0)
;
lcd_clear:
	ldi	tmp,0x01
	rcall	lcd_control
	ret
	
;
; LCD move position  :  (0,0)=0x00, (0,1)=0x01, (1,0)=0x40
;
lcd_pos:
	sbr	tmp,0x80
	rcall	lcd_control
	ret

;
; LCD put character
;
lcd_put:
	push	tmp
	swap	tmp	
	rcall	lcd_data_out
	pop	tmp
	rcall	lcd_data_out
	ret

;
; LCD put number in hex
;
lcd_put_hex:
	ldi	tmp2,7
	push	tmp
	swap	tmp
	cbr	tmp,0xf0
	sbr	tmp,0x30
	cpi	tmp,0x3a
	brcs	PC+2
	add	tmp,tmp2
	rcall	lcd_put
	pop	tmp
	cbr	tmp,0xf0
	sbr	tmp,0x30
	cpi	tmp,0x3a
	brcs	PC+2
	add	tmp,tmp2
	rcall	lcd_put
	ret

;
; LCD put number in decimal
;
lcd_put_decimal:
	mov	tmp2,tmp
	ldi	tmp,0
lcd_put_decimal_loop:
	cpi	tmp2,10
	brlo	lcd_put_decimal_skip
	subi	tmp2,10
	inc	tmp
	rjmp	lcd_put_decimal_loop
lcd_put_decimal_skip:
	sbr	tmp,0x30
	rcall	lcd_put
	mov	tmp,tmp2
	sbr	tmp,0x30
	rcall	lcd_put
	ret

lcd_put_str:
;	ldi	ZL,LOW(vol_data_2)
;	ldi	ZH,HIGH(vol_data_2)
	lsl	ZL
	rol	ZH	
lcd_put_str_loop:
	lpm	tmp,Z
	cpi	tmp,0
	brne	PC+2
	ret
	rcall	lcd_put
	adiw	ZL,1
	rjmp	lcd_put_str_loop

lcd_char_set:
	ldi	tmp,0x40+8*0
	rcall	lcd_control
	ldi	tmp,0x1f
	rcall	lcd_put
	ldi	tmp,0x1b
	rcall	lcd_put
	ldi	tmp,0x15
	rcall	lcd_put
	ldi	tmp,0x15
	rcall	lcd_put
	ldi	tmp,0x15
	rcall	lcd_put
	ldi	tmp,0x15
	rcall	lcd_put
	ldi	tmp,0x1b
	rcall	lcd_put
	ldi	tmp,0x1f
	rcall	lcd_put

	ldi	tmp,0x40+8*1
	rcall	lcd_control
	ldi	tmp,0x1f
	rcall	lcd_put
	ldi	tmp,0x1b
	rcall	lcd_put
	ldi	tmp,0x13
	rcall	lcd_put
	ldi	tmp,0x1b
	rcall	lcd_put
	ldi	tmp,0x1b
	rcall	lcd_put
	ldi	tmp,0x1b
	rcall	lcd_put
	ldi	tmp,0x11
	rcall	lcd_put
	ldi	tmp,0x1f
	rcall	lcd_put

	ldi	tmp,0x40+8*2
	rcall	lcd_control
	ldi	tmp,0x04
	rcall	lcd_put
	ldi	tmp,0x0e
	rcall	lcd_put
	ldi	tmp,0x15
	rcall	lcd_put
	ldi	tmp,0x04
	rcall	lcd_put
	ldi	tmp,0x04
	rcall	lcd_put
	ldi	tmp,0x04
	rcall	lcd_put
	ldi	tmp,0x04
	rcall	lcd_put
	ldi	tmp,0x04
	rcall	lcd_put

	ret

lcd_control:
	push	tmp
	swap	tmp	
	rcall	lcd_control_out
	pop	tmp
	rcall	lcd_control_out
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	ret

lcd_control_out:
	cbr	tmp,0x10	;rs
	sbr	tmp,0xe0	;e
	out	PORTA,tmp
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	cbi	PORTA,lcd_e
	sbi	PORTA,lcd_e
	rcall	wait_1ms
	ret

lcd_data_out:
	sbr	tmp,0xf0	;rs,e
	out	PORTA,tmp
	rcall	wait_1ms
	cbi	PORTA,lcd_e
	sbi	PORTA,lcd_e
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;
; wait 1 second
;
wait_1s:
	push	tmp

	ldi	tmp,250
wait_1s_a:
	rcall	wait_1ms
	dec	tmp
	brne	wait_1s_a

	ldi	tmp,250
wait_1s_b:
	rcall	wait_1ms
	dec	tmp
	brne	wait_1s_b

	ldi	tmp,250
wait_1s_c:
	rcall	wait_1ms
	dec	tmp
	brne	wait_1s_c

	ldi	tmp,250
wait_1s_d:
	rcall	wait_1ms
	dec	tmp
	brne	wait_1s_d

	pop	tmp	
	ret
	
;
; wait 1 ms
;
wait_1ms:
	push	tmp
	ldi	tmp,255
wait_1ms_loop:
	nop
	nop
	dec	tmp
	brne	wait_1ms_loop
	pop	tmp
	ret
	

;
; wait 10 us
;
wait_10us:
	push	tmp
	ldi	tmp,10
	nop
	dec	tmp
	brne	PC-2
	pop	tmp
	ret
	
;
; wait 10 ms
;
wait_10ms:
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	rcall	wait_1ms
	ret

1
