.include "1200def.inc"

.def	stack		= r16
.def	tp_main		= r17				; メインワーク
.def	tp_sub		= r18				; メインワーク
.def	tp_txrx		= r19
.def	tx_byte		= r20
.def	rx_byte		= r21
.def	bit_count	= r22
.def	tp_tim0		= r23
;.def	sw_count	= r24
.def	scan_key	= r25
.def	tp_scan		= r26
.def	tp_key		= r27
.def	delay		= r28

.equ	TxD		= 0				; 送信(PD0)
.equ	RxD		= 1				; 受信(PD1)

.equ	JUMPER		= 2
.equ	LED		= 6

.equ	ROW1		= 3
.equ	ROW2		= 2
.equ	ROW3		= 1
.equ	ROW4		= 0
.equ	COL1		= 7
.equ	COL2		= 6
.equ	COL3		= 5
.equ	COL4		= 4

.equ	TIM_VAL		= 39

.CSEG
.ORG	$0
		rjmp	RESET
		rjmp	DUMMY
		rjmp	TIM0_OVF
		rjmp	DUMMY

DUMMY:
		reti

;---------------------------------------
;	初期化
;---------------------------------------
RESET:
		ldi	tp_main,0b11110000		; PB7～4はH出力、PB3～0はプルアップ無し
		out	PORTB,tp_main
		ldi	tp_main,0b11110000		; PB7～4を出力、PB3～0を入力に設定
		out	DDRB,tp_main

		ldi	tp_main,0b00111110		; PD6、0はL出力、PD5～1はプルアップ有り
		out	PORTD,tp_main
		ldi	tp_main,0b01000001		; PD6、0を出力、PD5～1を入力に設定
		out	DDRD,tp_main

		ldi	tp_main,(1<<TOIE0)		; チャタリング防止のDelayにタイマ割り込みを使用
		out	TIMSK,tp_main

		ldi	tp_main,(1<<CS02)		; 内部クロック1/256
		out	TCCR0,tp_main			; 4000000Hz/256/256≒61Hz

		clr	tp_main
		out	TCNT0,tp_main

		ldi	delay,66			; 9600bps
		sbis	PIND,JUMPER			; ジャンパOpen(H)-9600bps/Close(L)-34800bps
		ldi	delay,14			; 34800bps	

;---------------------------------------
;	LED点滅
;---------------------------------------
		clr	tp_main
		clr	tp_sub
		sbi	PORTD,LED			; PD6点灯
LED_0:
		dec	tp_sub
		brne	LED_0
LED_1:
		dec	tp_sub
		brne	LED_1
LED_2:
		dec	tp_sub
		brne	LED_2
LED_3:
		dec	tp_sub
		brne	LED_3
		dec	tp_main
		brne	LED_0
		cbi	PORTD,LED			; PD6消灯

;---------------------------------------
;	メインループ
;---------------------------------------
MAIN:
		in	tp_main,PINB			; キーが押されるまで待つ
		andi	tp_main,0x0F
		breq	MAIN
		rcall	SCAN				; キースキャン
		tst	scan_key
		breq	MAIN
		mov	tp_key,scan_key
		rcall	TIMEUP
		rcall	SCAN				; キースキャン(チャタリング防止)
		cp	scan_key,tp_key
		brne	MAIN		
		rcall	TIMEUP
		rcall	SCAN				; キースキャン(チャタリング防止)
		cp	scan_key,tp_key
		brne	MAIN		
		mov	tx_byte,scan_key
		dec	tx_byte				; 1～16->0～15
		ori	tx_byte,0xB0
		rcall	SEND_BYTE			; 送信 

MAIN_2:
		in	tp_main,PINB			; キーが離されるまで待つ
		andi	tp_main,0x0F
		brne	MAIN_2
		rcall	TIMEUP
		rcall	SCAN				; キースキャン(チャタリング防止)
		tst	scan_key
		brne	MAIN_2
		rcall	TIMEUP
		rcall	SCAN				; キースキャン(チャタリング防止)
		tst	scan_key
		brne	MAIN_2
		rjmp	MAIN

;---------------------------------------
;	タイムアップまで待つ
;---------------------------------------
TIMEUP:
		clr	tp_tim0
		sei
TIMEUP_0:
		tst	tp_tim0
		breq	TIMEUP_0
		cli

;---------------------------------------
;	タイマオーバーフロー割り込み
;---------------------------------------
TIM0_OVF:
		in	stack,SREG
		inc	tp_tim0
		out	SREG,stack
		reti

;---------------------------------------
;	キースキャン
;---------------------------------------
SCAN:
		ldi	tp_main,4
		ldi	tp_sub,0b10000000
		clr	scan_key
SCAN_0:
		out	PORTB,tp_sub
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		in	tp_scan,PINB
		andi	tp_scan,0x0F
		brne	SCAN_1
		lsr	tp_sub
		inc	scan_key
		dec	tp_main
		brne	SCAN_0
		clr	scan_key
		rjmp	SCAN_4
SCAN_1:
		ldi	tp_main,4
		lsl	tp_scan
		lsl	tp_scan
		lsl	tp_scan
		lsl	tp_scan
SCAN_2:
		lsl	tp_scan
		brcs	SCAN_3
		subi	scan_key,-4			; +4
		dec	tp_main
		brne	SCAN_2		
SCAN_3:
		inc	scan_key
SCAN_4:
		ldi	tp_main,0b11110000
		out	PORTB,tp_main
		ret		

.equ		STOPBIT	= 1

SEND_BYTE:	
		ldi	bit_count,9+STOPBIT	; 送信ビット長
		com	tx_byte			; ビット反転
		sec				; スタートビット
SEND_BYTE_0:
		brcc	SEND_BYTE_1
		sbi	PORTD,TxD		; キャリーが立っていたら'1'を送信(負論理)
		rjmp	SEND_BYTE_2
SEND_BYTE_1:
		cbi	PORTD,TxD		; キャリーが立っていなかったら'0'を送信(負論理)	;    send a '1'
		nop
SEND_BYTE_2:
		rcall	UART_DELAY		; 1ビット分待つ
		rcall	UART_DELAY

		lsr	tx_byte
		dec	bit_count
		brne	SEND_BYTE_0
		ret

RECV_BYTE:
		ldi 	bit_count,9		; 受信ビット長
		rcall	UART_DELAY
RECV_BYTE_0:
		rcall	UART_DELAY
		rcall	UART_DELAY
		clc
		sbis 	PIND,RxD		; ビットが立っていたら'0'、立っていなかったら'1'を格納
		sec
		dec 	bit_count
		breq 	RECV_BYTE_1
		ror 	rx_byte
		rjmp 	RECV_BYTE_0
RECV_BYTE_1:
		ret

UART_DELAY:	
		mov	tp_txrx,delay
UART_DELAY_0:	
		dec	tp_txrx
		brne	UART_DELAY_0
		ret
