;-----------------------------
;	LCDテスト
;    AT90S2313	at    4MHz
;-----------------------------

.include "2313def.inc"

.equ	NULL=	0

.equ	LCD_E=	4		;制御ﾋﾞｯﾄ	ENABLE
.equ	LCD_RS=	6		;制御ﾋﾞｯﾄ	REGISTER SELECT

.cseg
.org	0x00
		rjmp	main

;subluchine

;---------------------------------
;_delay_ms(int ms)    at    4MHz
;    引数:R26,R27	int(msec)
;---------------------------------
_delay_ms:
		ldi	r16,249
_delay1:
		rjmp	PC+1
		rjmp	PC+1
		rjmp	PC+1
		rjmp	PC+1
		rjmp	PC+1
		rjmp	PC+1
		nop
		dec	r16
		brbc	1,_delay1
		rjmp	PC+1
		rjmp	PC+1
		sbiw	r27:r26,1
		brbc	1,_delay_ms
		ret

;-----------------------------
;		LCD初期化
;-----------------------------
;void lcd_init(void){
lcd_init:
;	lcd_wait(15L*MSECCNT);
		ldi	r26,low(15)
		ldi	r27,high(15)
		rcall	_delay_ms
;	LCD_PORTO = LCD_E | LCD_DATMASK;
		ldi	r16,0x1f
		out	DDRB,r16
		ldi	r16,0x10		;E=H
		out	PORTB,r16
;	DDRD = 0b111111;			/* RS 出力設定 */
		ldi	r16,0b11111011		; IR入力
		out	DDRD,r16
;	PORTD &= ~LCD_RS;			/* RS = L */
		cbi	PORTD,LCD_RS
;	lcd_put_4bit( 0x3 );			/* Function Set Mode */
		ldi	r16,0x3
		rcall	lcd_put_4bit
;	lcd_wait(4L*MSECCNT);
		ldi	r26,low(5)
		ldi	r27,high(5)
		rcall	_delay_ms
;	lcd_put_4bit( 0x3 );
		ldi	r16,0x3
		rcall	lcd_put_4bit
;	lcd_wait(1L*MSECCNT);
		ldi	r26,low(2)
		ldi	r27,high(2)
		rcall	_delay_ms
;	lcd_put_4bit( 0x3 );
		ldi	r16,0x3
		rcall	lcd_put_4bit
;	lcd_put_4bit( 0x2 );			/* Function Set Mode-4bit */
		ldi	r16,0x2
		rcall	lcd_put_4bit
;	lcd_put_ch( 0x28 );			/* Mode-4bit / Line = 2 / Font = 5x7dot */
		ldi	r16,0x28
		rcall	lcd_put_ch
;	lcd_put_ch( 0x0e );			/* Display = ON / Cursor = ON / Blink = ON */
		ldi	r16,0x0e
		rcall	lcd_put_ch
;	lcd_put_ch( 0x06 );			/* Cursor = Increment / Display_sift = OFF */
		ldi	r16,0x06
		rcall	lcd_put_ch
;	lcd_put_ch( 0x01 );			/* Display Clear */
		ldi	r16,0x01
		rcall	lcd_put_ch
;	lcd_wait(2L*MSECCNT);
		ldi	r26,low(3)
		ldi	r27,high(3)
		rcall	_delay_ms
;	PORTD |= LCD_RS;			/* RS = H */
		sbi	PORTD,LCD_RS
;	}
		ret

;-----------------------------------------------------------*/
;	LCD表示位置の設定				    */
;	引数 :R16		:x座標			    */
;	引数 :R17		:y座標			    */
;	戻り値 : なし					    */
;		tx					    */
;	    0123456789ABCDEF				    */
;	ty 0################				    */
;	   1################				    */
;-----------------------------------------------------------*/

;void lcd_position(char tx , char ty) {
lcd_position:
;	PORTD &= ~LCD_RS;			/* RS = L */
		cbi	PORTD,LCD_RS
;	lcd_put_ch(0x80 | tx | (0x40 * ty));	/* Address = 0 */
		bst	r17,0			;ty->t bit
		ldi	r17,0x80
		bld	r17,6			;t bit-> 0x40
		add	r16,r17			;+tx
		rcall	lcd_put_ch
;	PORTD |= LCD_RS;			/* RS = H */
		sbi	PORTD,LCD_RS
;	}
		ret

;-----------------------------------------------------------*/
;	LCD 4ﾋﾞｯﾄ送信					    */
;	引数 :R16	 : DB7-4に与えるデータ		    */
;-----------------------------------------------------------*/

;void	lcd_put_4bit(char bitdata) {
lcd_put_4bit:
		andi	r16,0xf
		push	r17
;	LCD_PORT &= ~LCD_DATMASK;
		in	r17,PORTB
		andi	r17,0xf0
;	LCD_PORT |= (LCD_DATMASK & bitdata);	/*データを格納 */
		or	r17,r16
		out	PORTB,r17
;	LCD_PORT &= ~LCD_E;			/* ENABLE = L */
		cbi	PORTB,LCD_E
;	lcd_wait(MSECCNT/50);
		ldi	r26,low(1)
		ldi	r27,high(1)
		rcall	_delay_ms
;	LCD_PORT |= LCD_E;			/* ENABLE = H */
		sbi	PORTB,LCD_E
;	lcd_wait(MSECCNT/50);
		ldi	r26,low(1)
		ldi	r27,high(1)
		rcall	_delay_ms
;	}
		pop	r17
		ret

;-----------------------------------------------------------*/
;	LCD 1ﾊﾞｲﾄ送信					    */
;	引数 : R16	 : LCDﾓｼﾞｭｰﾙへの送信データ	    */
;-----------------------------------------------------------*/

;void	lcd_put_ch(char ch) {
lcd_put_ch:
		push	r16
;	lcd_put_4bit(ch >> 4);			   /* 上位4ﾋﾞｯﾄ送信 */
		swap	r16
		rcall	lcd_put_4bit
;	lcd_put_4bit(LCD_DATMASK & ch);		   /* 下位4ﾋﾞｯﾄ送信 */
		pop	r16
		rcall	lcd_put_4bit
;	lcd_wait(MSECCNT);
		ldi	r26,low(1)
		ldi	r27,high(1)
		rcall	_delay_ms
;	}
		ret

;-----------------------------------------------------------*/
;	LCD 10進表示ﾙｰﾁﾝ				    */
;	引数 : R16	 : 表示データ0～255		    */
;	     : R17	 : 表示桁数1～3			    */
;-----------------------------------------------------------*/
lcd_putui:
		push	r19
		push	r18
		mov	r18,r17
		rcall	btod			;bin to bcd
		cpi	r18,3
		brcs	lcd_pui1
		push	r16			;百の桁表示
		mov	r16,r17
		rcall	lcd_pui_s
		pop	r16
lcd_pui1:
		cpi	r18,2
		brcs	lcd_pui2
		push	r16			;十の桁表示
		swap	r16
		rcall	lcd_pui_s
		pop	r16
lcd_pui2:
		rcall	lcd_pui_s		;一の桁表示
		pop	r18
		pop	r19
		ret

lcd_pui_s:
		ldi	r19,'0'
		andi	r16,0xf
		add	r16,r19
		rcall	lcd_put_ch
		ret

;-----------------------------
;	bin to bcd
;	入力:R16	bin(0～255)
;	出力:R17,R16
;-----------------------------
btod:
		push	r19
		push	r18
		clr	r17			;百の桁
btod1:
		cpi	r16,100
		brcs	btod2
		inc	r17
		subi	r16,100
		rjmp	btod1
btod2:
		mov	r18,r16
		swap	r18
		andi	r18,0xf			;上位4bit
		inc	r18			;ｶｳﾝﾀ設定
btod3:
		mov	r19,r16
		andi	r19,0xf			;下位4bit
		cpi	r19,0xa			;10以上なら+6
		brcs	btod4
		subi	r16,0xfa		;addi	r16,6
btod4:
		dec	r18			;ｶｳﾝﾀ回数+6
		breq	btod5
		subi	r16,0xfa
		rjmp	btod3
btod5:
		pop	r18
		pop	r19
		ret

;-----------------------------------------------------------*/
;		LCD ﾗｲﾝｸﾘｱ				    */
;	引数 : R16	: 0 1行目 1 2行目		    */
;-----------------------------------------------------------*/

;void	lcd_lclr(unsigned char l)
.def	l	=	r17
;unsigned char i;
.def	ii	=	r18

lcd_lclr:
		push	r16
;	lcd_locate(0,l);			/* ｶｰｿﾙ位置の設定 */
		ldi	r16,0
		rcall	lcd_position
;	for(i = 0; i < 40; i++)
		clr	ii
lcd_lc1:
;		lcd_putchr(' ');
		ldi	r16,' '
		rcall	lcd_put_ch

		cpi	ii,40			;for文第2項
		brcc	lcd_lc2

		inc	ii			;for文第3項
		rjmp	lcd_lc1
lcd_lc2:
;	lcd_locate(0,l);
		ldi	r16,0
		rcall	lcd_position
;}
		pop	r16
		ret

;-----------------------------------------------------------*/
;	lcd 文字列表示					    */
;	引数 :Z(R30,R31) : 文字列の先頭ポインタ		    */
;-----------------------------------------------------------*/

;void	lcd_put_str(char *str) {
lcd_put_str:
		pop	r31			;Z = 戻り番地
		pop	r30
		lsl	r30			;Z = Z * 2
		rol	r31
lcd_put_0:
;	while (*str != 0) {
		lpm				;r0 = (Z)
;	str++;
		adiw	r31:r30,1		;ﾎﾟｲﾝﾀZ inc
		tst	r0
		breq	lcd_put_1
;		lcd_put_ch( *str );
		mov	r16,r0
		rcall	lcd_put_ch
		rjmp	lcd_put_0
;		}
lcd_put_1:
;	}
		lsr	r31			;Z = Z / 2
		ror	r30
		ijmp				;jmp Z

;-----------------------------------------------------------*/
;	メインプログラム				    */
;-----------------------------------------------------------*/

;void main(void) {
main:
		ldi	r16,low(RAMEND)
		out	SPL,r16

;	lcd_init();				/* LCD初期化 */
		rcall	lcd_init

;	lcd_locate(0,0);			/* ｶｰｿﾙ位置の設定 */
		ldi	r16,0
		ldi	r17,0
		rcall	lcd_position

;	lcd_puts("IR analyzer");		/* 文字列の表示 */
		rcall	lcd_put_str
.db		"IR analyzer",NULL

main1:
		rjmp	main1

