;----------------------------------------------------------------------------
; ledtest2.asm for tiny15L
; 内部発振(1.6MHz)によるLED点滅テスト(0.5秒点灯0.5秒消灯の繰り返し)
;----------------------------------------------------------------------------

.include	"c:\avrtools\appnotes\tn15def.inc"

.def	temp	=r16		;r0からr31までが汎用レジスタ
.def	cnt1	=r17		;ただしr0からr15までは、sbci, subi, cpi, andi, ori, ldi命令が使えない
.def	cnt2	=r18		;r16からr31までのレジスタはすべての命令が使える
.def	cnt3	=r19
.def	cnt4	=r20

.org	0

	rjmp	reset		;パワーオンリセット
				;rjmp(Relative Jump) (2steps)
				;rjmp k 現在のプログラムカウンタ(PC)の示す値にk+1を加えて
				;その位置に制御を渡す。kは相対バイト数を示し、通常ラベルを記述
				;PICの記述では下記のようになる
				;goto	reset
	reti			;外部割り込み未使用
				;reti(Return from Interrupt) (4steps)
	reti			;I/Oピンレベル変化未使用
	reti			;タイマー/カウンタ1比較A一致未使用
	reti			;タイマー/カウンタ1オーバーフロー未使用
	reti			;タイマー/カウンタ0オーバーフロー未使用
	reti			;EEPROM操作可未使用
	reti			;アナログコンパレータ出力遷移未使用
	reti			;A/D変換完了未使用

reset:
;---------------------------------------------------------------------------------
; tiny15Lは内部発振回路の周波数校正値がEEPROMの最終番地($3F)に記録されている
; この値を読み出してOSCCALレジスタにセットしないと正確な発振周波数にならない
;---------------------------------------------------------------------------------
	ldi	temp,$3F   	;EEPROM $3F番地を指定(周波数校正値格納場所)
				;ldi(Load Immediate) (1step)
				;指定したレジスタへ定数を格納
				;PIC命令ではwレジスタを介して下記のように記述する
				;movlw	0x3F
				;movwf 	temp
				
	out	EEAR,temp  	;EEAR(EEPROM Address Register)
				;out(Store Register to I/O Location (Out Port)) (1step)
				;指定したレジスタの内容を、指定したI/Oレジスタへ出力
				
	sbi	EECR,EERE  	;EECR(EEPROM Control Register), EERE(EEPROM Read Enable) (2steps)
				;EECRに読み出しモードを設定
				;sbi(Set Bit in I/O Register)
				;指定したレジスタの指定したビットをセット

	in	temp,EEDR  	;EEDR(EEPROM Data Register)
				;in(Load an I/O Location to Register (In Port)) (1step)
								
	out	OSCCAL,temp  	;周波数校正値を OSCCAL レジスタにセット
				;PIC12F629ではwレジスタを介して下記のように記述する
				;movf	temp,w
				;movwf	OSCCAL

;-------------------------------

	ldi	temp,$1f   	;temp=0b00011111
	out	DDRB,temp  	;PB0,PB1,PB2,PB3,PB4を出力に設定

loop:
	ldi	temp,$1f  	;temp=0b00011111
	out	PORTB,temp	;PB0,PB1,PB2,PB3,PB4 ON
	rcall	timer		;rcall(Relative Subroutine Call) (3steps) PIC命令のcallと同じ
	ldi	temp,$00   	;temp=0b00000000
	out	PORTB, temp	;PB0,PB1,PB2,PB3,PB4 OFF
	rcall	timer
	rjmp	loop		;PICでのgoto命令と同じ
	
;-------------------------------
timer:
	ldi	cnt1,222   	;PICでの下記の記述と同じ
				;movlw	d'255'
				;movwf	cnt1
tmlp1:
	ldi	cnt2,200
tmlp2:
	ldi	cnt3,5
tmlp3:
	dec	cnt3
	brne	tmlp3
	dec	cnt2		;dec(Decrement) (1step)
				;指定したレジスタの内容をマイナス1する
				;PICでの下記の記述と同じ
				;decf	cnt2,f
				
	brne	tmlp2		;brne(Branch if Not Equal) (1/2step(s))
				;brne k 直前の演算結果が等しくなければ(またはゼロ)、
				;プログラムカウンタにk+1を加えた番地へ分岐
				;kの値は-64から+63の範囲になければならない
				
	dec	cnt1
	brne	tmlp1
	ldi	cnt4,31
tmlp4:
	nop
	dec	cnt4
	brne	tmlp4
	ret			;ret(Return from Subroutine) (4steps)
				;PIC命令の return と同じ
				
				;PICではプログラムの終わりに end の記述が必要だが AVR では何も書かない