
;------------------------------------------------------------------------------
; Title       : eu.asm
; Description : Emotion Unit
; Author      : KAWAMOTO "nanashino" Yasuhisa
; Email       : nanashi@yk.rim.or.jp
; Date        : 08/18/2000
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; History     : 08/18/2000  EEPROM化け対策の為にLEDデータをProgram Memoryに移行
;               04/20/2000  割り込みルーチン内でのSREG復元抜けの修正
;               04/17/2000  AKI-AVR Programmer Ver1.26以降への対応
;                           旧バージョンにはEEPROMデータの奇数/偶数アドレスが
;                           逆になるバグがあったようです。
;               04/06/2000  初期バージョン
;------------------------------------------------------------------------------

.include "1200def.inc"

;-- Defined constant --
.equ	N=69			; 139us@4.0MHz and R=2
.equ	R=2			; 1/8
.equ	W=8			; x8

;-- Global register --
.def	t_tmp2		=r15	; Scratch register2(in tim0_ovf)
.def	t_tmp		=r16	; Scratch register(in tim0_ovf)
.def	t_sr		=r17	; SREG storage(in tim0_ovf)
.def	t_reload	=r18	; Reload register(in tim0_ovf)
.def	led_wc		=r19	; LED wait counter
.def	led_col		=r20	; LED column number
.def	sadr_l		=r21	; Left data start address
.def	sadr_r		=r22	; Right data start address
.def	dadr		=r23	; Data address
.def	rsv_wc		=r24	; IR receive wait counter
.def	rsv_bc		=r25	; IR receive bit counter
.def	rsv_1c		=r26	; IR receive one counter
.def	rsv_st		=r27	; IR receive status register
.def	rsv_bf		=r28	; IR receive buffer
.def	rsv_dt		=r29	; IR receive data
.def	tmp		=r31	; Scratch register

;-- Bit position in Status register --
.equ	RDBF		= 7	; IR receive data buffer full

	.cseg
;-- Reset and interrupt vector --
	.org $0000
	rjmp	main		; Reset handler
	.org INT0addr
	reti			; External interrupt handler (Not Used)
	.org OVF0addr
	rjmp	tim0_ovf	; Timer0 overflow handler
	.org ACIaddr
	reti			; Analog comparator handler (Not Used)

;-- Timer0 overflow handler --
tim0_ovf:
	in	t_sr,SREG		; Store SREG
	out	TCNT0,t_reload		; Set reload timer
	dec	rsv_wc
	brne	rsv_skip
;-- IR receive --
rsv:
	cpi	rsv_bc,0		; Check signal
	brne	rsv_0
	sbis	PIND,2
	inc	rsv_bc
	ldi	rsv_wc,1
	rjmp	rsv_exit
rsv_0:
	cpi	rsv_bc,1		; Start bit
	brne	rsv_1
	sbic	PIND,2
	rjmp	rsv_err
	inc	rsv_bc
	ldi	rsv_wc,3
	rjmp	rsv_exit
rsv_1:
	cpi	rsv_bc,10		; Check parity bit
	brne	rsv_10
	sbic	PIND,2
	inc	rsv_1c
	sbrs	rsv_1c,0
	rjmp	rsv_err
	inc	rsv_bc
	ldi	rsv_wc,3
	rjmp	rsv_exit
rsv_10:
	cpi	rsv_bc,11		; Check stop bit
	brne	rsv_11
	sbis	PIND,2
	rjmp	rsv_err
	sbr	rsv_st,(1 << RDBF)
	ldi	rsv_1c,0
	ldi	rsv_bc,0
	ldi	rsv_wc,1
	rjmp	rsv_exit
rsv_11:
	sec				; Data bit
	sbis	PIND,2
	clc
	ror	rsv_bf
	sbrc	rsv_bf,7
	inc	rsv_1c
	inc	rsv_bc
	ldi	rsv_wc,3
	rjmp	rsv_exit
rsv_err:
	ldi	rsv_1c,0
	ldi	rsv_bc,0
	ldi	rsv_wc,1
rsv_exit:
rsv_skip:
	dec	led_wc
	breq	disp
	rjmp	disp_skip
;-- Display 5x7dot-matrix LED --
disp:
	cpi	led_col,0
	brne	disp_r0
	sbi	PORTD,1			; AB = H
	mov	dadr,sadr_r
disp_r0:
	cpi	led_col,5
	brne	disp_l0
	mov	dadr,sadr_l
disp_l0:
	cbi	PORTD,0			; CLK = L
	sbi	PORTD,0			; CLK = H
	cbi	PORTD,1			; AB = L

;; 08/18/2000
;;;	out	EEAR,dadr
;;;	sbi	EECR,0			; Set EERE
;;;wait_eep:
;;;	sbic	EECR,0			; Wait clear EERE
;;;	rjmp	wait_eep
;;;	in	t_tmp,EEDR
;;;	mov	t_tmp2,t_tmp

;-- LED data --
; + - - - - - - -
; + - - - - - - -
; + * * * * * * *
; + - - - - - - -
; + - - - - - - -
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$ff,$ff,$80,$ff,$ff,$ff,$ff,$ff
	cpi	dadr,$00
	brne	rom00
	ldi	t_tmp,$ff
rom00:
	cpi	dadr,$01
	brne	rom01
	ldi	t_tmp,$ff
rom01:
	cpi	dadr,$02
	brne	rom02
	ldi	t_tmp,$80
rom02:
	cpi	dadr,$03
	brne	rom03
	ldi	t_tmp,$ff
rom03:
	cpi	dadr,$04
	brne	rom04
	ldi	t_tmp,$ff
rom04:
; + - - * * * - -
; + - * * * * * -
; + - * * * * * -
; + - * * * * * -
; + - - * * * - -
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$e3,$c1,$c1,$c1,$e3,$ff,$ff,$ff
	cpi	dadr,$08
	brne	rom08
	ldi	t_tmp,$e3
rom08:
	cpi	dadr,$09
	brne	rom09
	ldi	t_tmp,$c1
rom09:
	cpi	dadr,$0a
	brne	rom0a
	ldi	t_tmp,$c1
rom0a:
	cpi	dadr,$0b
	brne	rom0b
	ldi	t_tmp,$c1
rom0b:
	cpi	dadr,$0c
	brne	rom0c
	ldi	t_tmp,$e3
rom0c:
; + - - * * * - -
; + - * - - - * -
; + - * - - - * -
; + - * - - - * -
; + - * - - - * -
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$e3,$dd,$dd,$dd,$dd,$ff,$ff,$ff
	cpi	dadr,$10
	brne	rom10
	ldi	t_tmp,$e3
rom10:
	cpi	dadr,$11
	brne	rom11
	ldi	t_tmp,$dd
rom11:
	cpi	dadr,$12
	brne	rom12
	ldi	t_tmp,$dd
rom12:
	cpi	dadr,$13
	brne	rom13
	ldi	t_tmp,$dd
rom13:
	cpi	dadr,$14
	brne	rom14
	ldi	t_tmp,$dd
rom14:
; + - - - * - - -
; + - - - - * - -
; + - * * * * * *
; + - - - - * - -
; + - - - * - - -
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$f7,$fb,$c0,$fb,$f7,$ff,$ff,$ff
	cpi	dadr,$18
	brne	rom18
	ldi	t_tmp,$f7
rom18:
	cpi	dadr,$19
	brne	rom19
	ldi	t_tmp,$fb
rom19:
	cpi	dadr,$1a
	brne	rom1a
	ldi	t_tmp,$c0
rom1a:
	cpi	dadr,$1b
	brne	rom1b
	ldi	t_tmp,$fb
rom1b:
	cpi	dadr,$1c
	brne	rom1c
	ldi	t_tmp,$f7
rom1c:
; + - - - - - * *
; + - - - - * - -
; + - - - * - - -
; + - - * - - - -
; + - * - - - - -
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$fc,$fb,$f7,$ef,$df,$ff,$ff,$ff
	cpi	dadr,$20
	brne	rom20
	ldi	t_tmp,$fc
rom20:
	cpi	dadr,$21
	brne	rom21
	ldi	t_tmp,$fb
rom21:
	cpi	dadr,$22
	brne	rom22
	ldi	t_tmp,$f7
rom22:
	cpi	dadr,$23
	brne	rom23
	ldi	t_tmp,$ef
rom23:
	cpi	dadr,$24
	brne	rom24
	ldi	t_tmp,$df
rom24:
; + - * - - - - -
; + - - * - - - -
; + - - - * - - -
; + - - - - * - -
; + - - - - - * *
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$df,$ef,$f7,$fb,$fc,$ff,$ff,$ff
	cpi	dadr,$28
	brne	rom28
	ldi	t_tmp,$df
rom28:
	cpi	dadr,$29
	brne	rom29
	ldi	t_tmp,$ef
rom29:
	cpi	dadr,$2a
	brne	rom2a
	ldi	t_tmp,$f7
rom2a:
	cpi	dadr,$2b
	brne	rom2b
	ldi	t_tmp,$fb
rom2b:
	cpi	dadr,$2c
	brne	rom2c
	ldi	t_tmp,$fc
rom2c:
; + - - - - - - -
; + - - - - - - -
; + - - - - - - -
; + - - - - - - -
; + - - - - - - -
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
	cpi	dadr,$30
	brne	rom30
	ldi	t_tmp,$ff
rom30:
	cpi	dadr,$31
	brne	rom31
	ldi	t_tmp,$ff
rom31:
	cpi	dadr,$32
	brne	rom32
	ldi	t_tmp,$ff
rom32:
	cpi	dadr,$33
	brne	rom33
	ldi	t_tmp,$ff
rom33:
	cpi	dadr,$34
	brne	rom34
	ldi	t_tmp,$ff
rom34:
; + * * * * * * *
; + * * * * * * *
; + * * * * * * *
; + * * * * * * *
; + * * * * * * *
; + + + + + + + +
; + + + + + + + +
; + + + + + + + +
;;;	.db	$80,$80,$80,$80,$80,$ff,$ff,$ff
	cpi	dadr,$38
	brne	rom38
	ldi	t_tmp,$80
rom38:
	cpi	dadr,$39
	brne	rom39
	ldi	t_tmp,$80
rom39:
	cpi	dadr,$3a
	brne	rom3a
	ldi	t_tmp,$80
rom3a:
	cpi	dadr,$3b
	brne	rom3b
	ldi	t_tmp,$80
rom3b:
	cpi	dadr,$3c
	brne	rom3c
	ldi	t_tmp,$80
rom3c:

	mov	t_tmp2,t_tmp

	cpi	led_col,5
	brlo	disp_r1
	ror	t_tmp
	rol	t_tmp2
	ror	t_tmp
	rol	t_tmp2
	ror	t_tmp
	rol	t_tmp2
	ror	t_tmp
	rol	t_tmp2
	ror	t_tmp
	rol	t_tmp2
	ror	t_tmp
	rol	t_tmp2
	ror	t_tmp
	rol	t_tmp2
disp_r1:
	out	PORTB,t_tmp2

	inc	dadr
	inc	led_col
	cpi	led_col,10
	brne	disp_exit
	ldi	led_col,0
disp_exit:
	ldi	led_wc,W
;; 04/20/2000	reti
disp_skip:
	out	SREG,t_sr		; Restore SREG
	reti

;-- Init hardware --
init_hw:
	ldi	t_reload,(256-N)	; Set reload value

	ldi	led_wc,W
	ldi	led_col,0
	ldi	sadr_l,0
	ldi	sadr_r,0

	ldi	rsv_wc,1
	ldi	rsv_bc,0
	ldi	rsv_1c,0
	ldi	rsv_st,0

	ldi	tmp,0b11111111
	out	DDRB,tmp
	ldi	tmp,0b11111111
	out	PORTB,tmp
	ldi	tmp,0b01111011
	out	DDRD,tmp
	ldi	tmp,0b01111011
	out	PORTD,tmp
	cbi	PORTD,3			; /CLR = L
	sbi	PORTD,3			; /CLR = H
	ldi	tmp,R
	out	TCCR0,tmp		; Start timer and set clock source
	out	TCNT0,t_reload
	ldi	tmp,(1 << TOV0)		; Clear T/C0 overflow flag
	out	TIFR,tmp
	ldi	tmp,(1 << TOIE0)	; Enable T/C0 overflow interrupt
	out	TIMSK,tmp
	ret

;-- Main --
main:
	rcall	init_hw			; Init hardware
	sei				; Enable interrupt
loop1:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop1
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	cpi	rsv_dt,$55		; Check header == $55
	brne	loop1
loop2:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop2
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	cpi	rsv_dt,$ff		; Check header == $ff
	brne	loop1
loop3:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop3
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	cpi	rsv_dt,~$ff		; Check header == ~$ff
	brne	loop1
loop4:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop4
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	cpi	rsv_dt,$f7		; Check Command == $f7(Set message)
	brne	loop1
loop5:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop5
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	cpi	rsv_dt,~$f7		; Check Command == ~$f7(Set message)
	brne	loop1
loop6:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop6
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	mov	tmp,rsv_dt		; Store message value
loop7:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop7
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	com	rsv_dt			; Check ~message value
	cp	tmp,rsv_dt
	brne	loop1
loop8:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop8
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	subi	rsv_dt,$f7		; Check check-sum
	cp	tmp,rsv_dt
	brne	loop1
loop9:
	sbrs	rsv_st,RDBF		; Check set RDBF
	rjmp	loop9
	mov	rsv_dt,rsv_bf
	cbr	rsv_st,(1 << RDBF)	; Clear RDBF
	com	rsv_dt			; Check ~check-sum
	subi	rsv_dt,$f7
	cp	tmp,rsv_dt
	brne	loop1
	mov	rsv_dt,tmp
	andi	tmp,$c0			; Check message bit7 and bit6
	cpi	tmp,$c0
	brne	loop1
	mov	sadr_l,rsv_dt		; Set left data start address
	andi	sadr_l,$07
	lsl	sadr_l
	lsl	sadr_l
	lsl	sadr_l
	mov	sadr_r,rsv_dt		; Set right data start address
	andi	sadr_r,$38
	rjmp	loop1
