;time-stamp: <03/02/05 11:29:36 kawasan>
;Time-stamp: <03/02/08 19:49:00 kawasan>
;
;商品名:ポンさん
;赤ん坊寝かしつけ装置
;ぬいぐるみの外観に、内部は電池とPICと振動モータとSWのみのシンプル構成です。
;SWを入れると一定のリズムで振動モータが動作。また10分程で自動停止をする。
;リズムは工場出荷時はポン、ポン、ポーンと3回の構成です。
;SW長押しでリズム学習が可能にしたいなぁ。
;
;Device	PIC16F84
;File	pon3.asm
;OSC	RC ( R = 4.7K, C = 100p : About 1MHz)
;WDT	Off
;PuT	On
;CP	Off
;Code	001B ( FreeのPiceeにて書き込む時に使うコンフィギュレーション・ヒューズの値 )
;	今は、Configurationの所でコード化してます。
;
;Pin-Layout
; 1 RA2       nc
; 2 RA3       nc
; 3 RA4/T0CKI nc
; 4 /MCLR     VDD
; 5 Vss       GND
; 6 RB0/INT   nc
; 7 RB1       nc
; 8 RB2       nc
; 9 RB3       nc
;10 RB4       P-SW ( Push時にGND接続, マイコン側で弱PullUp指定 )
;11 RB5       nc
;12 RB6       nc
;13 RB7       nc
;14 VDD       VDD ( 2.0V～6.0V : 電池1.5 x 2 = 3V )
;15 OSC2/CKO  nc
;16 OSC1/CKI  CR接続
;17 RA0       Motor ( 0/1 = Off/on )
;18 RA1       nc
;
;ASM	Debianのpicasmパッケージにてアセンブルしてる。(Unix汎用？)
;
;******************************************************
;	Include
;******************************************************
	include "pic16c84.inc"
;
;
;******************************************************
;	Configuration
;******************************************************
	config CP=off, PWRT=on, WDT=off, OSC=RC
;
;
;******************************************************
;       Define
;******************************************************
O_MOTOR		equ	PORTA		;
OB_MOTOR	equ	( 0 )		; Motor ( 0/1 = Off/on )
I_PSW		equ	PORTB		;
IB_PSW		equ	( 4 )		; Push-SW ( 0/1 = On/Off )
;
; X = 1MHz, プリスケーラなし, TMR0 = 256
; ( X / 4 ) / 256 = About 1000Hz → 1ms周期で割り込み発生
TIME_INT_BASE	equ	( 10 * 1000 / 1000 )
TIME_10MS	equ	( 10 * 10 / TIME_INT_BASE )
TIME_500MS	equ	( 500 / 10 )	; TimeBase 10ms
TIME_1MIN	equ	( 60000 / 500 )	; TimeBase 500ms
;
TIME_MIN	equ	( 14 )		; TimeBase 1s
TIME_PSW_START	equ	( 6 )		; TimeBase 100ms
TIME_PSW_STOP	equ	( 10 )		; TimeBase 100ms
;
TIME_MS10_100	equ	( 100 / 10 )	; TimeBase 10ms
;
;******************************************************
;	Ram
;******************************************************
		org	0x0c
R_SAVE_W	ds	1		; Stack W
R_SAVE_STATUS	ds	1		; Stack STATUS
R_FLAGS00	ds	1		; 各種フラグ状態
F_EVENT		equ	( 0 )		; 動作中flag
F_PSW		equ	( 1 )		; P-SW変化flag
R_TIME_10MS	ds	1		; 10ms event-cnt (Base 1ms割込)
R_TIME_500MS	ds	1		; 500ms event-cnt (Base 10msカウンタ)
R_TIME_1MIN	ds	1		; 1min event-cnt (Base 500msカウンタ)
R_TIME_MIN	ds	1		; min-cnt (Base 1minカウンタ)
R_TIME_MS10	ds	1		; Wait-cnt (Base 10msカウンタ)
R_EEADR		ds	1		; EEPROM-index
R_LOOP_CNT	ds	1		; loop-cnt
;
;
;******************************************************
;	Power On Reset
;******************************************************
	org	PIC84_RES
	goto	start			;
;
;
;******************************************************
;	Interrupt
;******************************************************
	org	PIC84_INT
	goto	int			;
;
;
;******************************************************
;	Start program
;******************************************************
start
	call	init_hard		;
	call	init_soft		;
;
;
;******************************************************
;	Main program
;******************************************************
main
;	( SW変化待ち )
	movwf	I_PSW			; 空読み
	bcf	INTCON,GIE		; 全体の割り込み禁止
	bcf	INTCON,RBIF		; Clear RBポート変化割込状態flag
	bsf	INTCON,RBIE		; Enable RBポート変化割込
	sleep				; 低消費modeへ (復帰はRB変化割込)
	nop				; dummy-op-code (一応入れとく)
	bcf	INTCON,RBIE		; Disable RBポート変化割込
	bsf	INTCON,GIE		; 全体の割り込み許可
;
;	( リズム起動準備 )
	movlw	TIME_1MIN		;
	movwf	R_TIME_1MIN		;
	movlw	TIME_MIN		;
	movwf	R_TIME_MIN		; Set 起動期間
	bsf	R_FLAGS00,F_EVENT	; Set Event=start
;
;	( P-SWを話すまでのwait )
	movlw	TIME_PSW_START		;
	movwf	R_LOOP_CNT		; Set loop-cnt
;
main_03
	call	wait100ms		;
	decfsz	R_LOOP_CNT,F		; skip, ( -- cnt ) == 0
	goto	main_03			;
;
;	( 停止P-SW準備 )
	bcf	R_FLAGS00,F_PSW		; Reset P-SW押下イベント
	bcf	INTCON,RBIF		; clear RB変化割込
	bsf	INTCON,RBIE		; enable RB変化割込
;
main_05
	btfss	R_FLAGS00,F_EVENT	; skip, Event != end
	goto	main_ext		;
;
	clrf	R_EEADR			; Reset EEPROM-index
;
main_10
;	=== On ===
	call	get_eeprom		;
	btfsc	STATUS,Z		; skip, !Zero-Flag
	goto	main_05			;
;
	movwf	R_LOOP_CNT		; Set loop-cnt
	call	motor_on		; On Motor
;
main_20
	call	wait100ms		;
	decfsz	R_LOOP_CNT,F		; skip, ( --  cnt ) == 0
	goto	main_20			;
;
;	=== Off ===
	call	get_eeprom		;
	movwf	R_LOOP_CNT		; Set loop-cnt
	call	motor_off		; Off Motor
;
main_30
	call	wait100ms		;
	decfsz	R_LOOP_CNT,F		; skip, ( -- cnt ) == 0
	goto	main_30			;
;
;	( 停止P-SWの判定 )
	btfss	R_FLAGS00,F_PSW		; skip, P-SW押下イベント
	goto	main_10			;
;
;	( P-SWを話すまでのwait )
	movlw	TIME_PSW_STOP		;
	movwf	R_LOOP_CNT		; Set loop-cnt
;
main_95
	call	wait100ms		;
	decfsz	R_LOOP_CNT,F		; skip, ( -- cnt ) == 0
	goto	main_95			;
;
main_ext
	goto	main			;
;
;
;******************************************************
;	Interrupt routine
;
;     ［注意］
;	Push's & Pop'sの処理はBank0での
;	割込発生を前提としています
;******************************************************
int
; --- < レジスタ退避 > ---
	movwf	R_SAVE_W		;
	swapf	STATUS,W		;
	movwf	R_SAVE_STATUS		; Push's
;
; --- [ ここより、RB変化割込処理 ] ---
	btfss	INTCON,RBIE		; skip, RB変化割込 enable
	goto	int_time		;
;
	btfss	INTCON,RBIF		; skip, RB変化割込あり
	goto	int_time		;
;
	btfss	I_PSW,IB_PSW		; skip, P-SW != on
	bsf	R_FLAGS00,F_PSW		; set P-SW押下イベント
	bcf	INTCON,RBIF		; clear RB変化割込
	goto	int_exit		;
;
int_time
; --- [ ここより、タイマ割込処理 ] ---
; --- < タイマ割込再起動処理 > ---
;	movlw	TMR0_CNT		;
;	movwf	TMR0			; Set TMR0 cnt
	bcf	INTCON,T0IF		; Reset T0IF flag
;
;	< 1msタイマ処理 >
;	No Process
;
;	< 10msタイマ処理 >
	decfsz	R_TIME_10MS,F		;
	goto	int_exit		;
;
	movlw	TIME_10MS		;
	movwf	R_TIME_10MS		;
;
	movf	R_TIME_MS10,F		;
	btfss	STATUS,Z		; skip, Zero-Flag
	decf	R_TIME_MS10,F		; Waitカウンタ --
;
;       < 500msタイマー処理 >
	decfsz	R_TIME_500MS,F		;
	goto	int_exit		;
;
	movlw	TIME_500MS		;
	movwf	R_TIME_500MS		;
;
;	< 1minタイマー処理 (500ms毎に起動) >
	decfsz	R_TIME_1MIN,F		;
	goto	int_exit		;
;
	movlw	TIME_1MIN		;
	movwf	R_TIME_1MIN		;
;
;	< minタイマー処理 (1min毎に起動) >
	btfss	R_FLAGS00,F_EVENT	; skip, Event=start
	goto	int_exit		;
;
	decfsz	R_TIME_MIN,F		;
	goto	int_exit		;
;
	bcf	R_FLAGS00,F_EVENT	; Set Event=end
;
; --- < レジスタ復旧と割込の終了 > ---
int_exit
	swapf	R_SAVE_STATUS,W		;
	movwf	STATUS			;
	swapf	R_SAVE_W,F		;
	swapf	R_SAVE_W,W		; Pop's
	retfie				;
;
;
;******************************************************
;	Initial routine ( Hard )
;******************************************************
init_hard
; --- < ポート設定 > ---
;	< ポート出力値設定 >
	bcf	STATUS,RP0		; Sel Bank0
	movlw	B'00000000'		;
	movwf	PORTA			; PortA Data = 0x00
	movlw	B'00000000'		;
	movwf	PORTB			; PortB Data = 0x00
;
;	< ポートI/O設定 >
	bsf	STATUS,RP0		; Sel Bank1
	movlw	B'00000000'		;
	TRIS	PORTA			; RA[5-0] is "---o_oooo"
	movlw	B'00010000'		;
	TRIS	PORTB			; RB[7-0] is "oooi_oooo"
;
	movlw	B'00001111'		; /RBPU INTEDG RTS RTE PSA PS2 PS1 PS0
	OPTION				; 0     0      0   0   1   1   1   1
					; /RBPU :PortB pull-up = enable
					; INTEDG:Interrupt edge RB0/INT ~|_
					; T0CS  :TMR0 clock source CLOCKOUT
					; T0SE  :TMR0 clock edge RA4/T0CKI _|~ (dummy)
					; PSA   :Prescaler assignment bit = WDT
					; PS    :PRESCALER VALUE TMR0 RATE 1:128 (dummy)
;
;	< 割り込み設定 >
	bcf	STATUS,RP0		; Sel Bank0
	clrf	TMR0			; Set TMR0 cnt
	bsf	INTCON,T0IE		; Enable TMR0 Int
	bcf	INTCON,T0IF		; Clear TMR0 OverFlow IntFlag
;
;	< ポート出力値設定-2 >
	bcf	O_MOTOR,OB_MOTOR	; Off Motor
;
	return				;
;
;
;******************************************************
;	Initial routine ( Soft )
;******************************************************
init_soft
;	< 10ms-eventタイマ処理 >
	movlw	TIME_10MS		;
	movwf	R_TIME_10MS		;
;
;	< 500ms-eventタイマ処理 >
	movlw	TIME_500MS		;
	movwf	R_TIME_500MS		;
;
;	< 1min-eventタイマ処理 >
	movlw	TIME_1MIN		;
	movwf	R_TIME_1MIN		;
;
;	< その他変数の処理 >
	bcf	R_FLAGS00,F_EVENT	; Set Event=end
;
	return				;
;
;
;******************************************************
;	Wait ( 100ms )
;******************************************************
wait100ms
	movlw	TIME_MS10_100		;
	movwf	R_TIME_MS10		; Set timer
;
wait100ms_50
	movf	R_TIME_MS10,F		;
	btfss	STATUS,Z		; skip, Zero-Flag
	goto	wait100ms_50		;

	return				;
;
;
;******************************************************
;	Motor Off
;******************************************************
motor_off
	bcf	O_MOTOR,OB_MOTOR	;
	return				;
;
;
;******************************************************
;	Motor On
;******************************************************
motor_on
	bsf	O_MOTOR,OB_MOTOR	;
	return				;
;
;
;******************************************************
;	get EEPROM-DATA
;******************************************************
get_eeprom
	movf	R_EEADR,W		;
	movwf	EEADR			; Set address
	incf	R_EEADR,F		; address ++
;
	bcf	INTCON,GIE		; DI
	bsf	STATUS,RP0		; Bank 1
	bsf	EECON1,RD		; EE Read
	bcf	STATUS,RP0		; Bank 0
	bsf	INTCON,GIE		; EI
;
	movf	EEDATA,W		; W = EEDATA
	return				;
;
;
;******************************************************
;	EEPROM
;******************************************************
	org	0
pattern
	edata	2, 3			;
	edata	3, 3			;
	edata	9, ( 3 + 9 )		;
	edata	0			; end-code
;
;
	END
