; SLEEP period
; Puts the PIC to sleep for 1 to 65535 units of 2.3 seconds.
; The 2.3-second value is approximate. Wide variations in operating temperature
; or supply voltage can double or halve this figure. See the discussion in the
; Nap program listing.

; Device data and reset vector: Note that the watchdog timer is ON.
	device	pic16c55,xt_osc,wdt_on,protect_off
	reset	start

	org	8
hiB	ds	1
lowB	ds	1

	org	0
Sleep	NOT	hiB	; Take twos complement
	NOT	lowB	; of the 16-bit counter
	snz	; If zero, lowB overflowed,
	inc	hiB	; so carry into hiB.
	mov	w,#15	; Assign prescaler (div 128)
	mov	!option,w	; to wdt, then write to option.
	sleep	; Go to sleep.
; SLEEP (cont)

start	mov	!rb,#0	; Make RB all outputs for LEDs.
	clr	w	; At the beginning of the program,
	snb	pd	; we set up a Branch-type routine
	OR	w,#1	; to take action based on the
	snb	to	; power-down (pd) and timeout (to)
	OR	w,#2	; bits.
	jmp	pc+w	; | to | pd|
	jmp	count_dn	; | 0	| 0	| wdt wakeup: count down.
	jmp	watch_fail	; | 0	| 1	| wdt timeout: handle it.
	jmp	mclr_pin	; | 1	| 0	| mclr wakeup: handle it.
	jmp	main	; | 1	| 1	| power 1st on: goto main.

; This code executes when power is first applied to the PIC (after start).
; It consists of a loop in which the PIC sleeps for 2 hours, then inverts port RB.

main	mov	hiB,#0Ch	; Load 3125 (0C35 hex)
	mov	lowB,#35h	; into 16-bit counter.
	call	Sleep	; Hibernate for 3125 x 2.304 secs.
	XOR	rb,#255 ; Wake up after 2 hours, invert RB.
	jmp	main	; Do it again.

; When the PIC wakes up from a wdt timeout, it executes this code, which
; increments the 16-bit value in lowB and hiB, and determines whether it's
; time to wake up. If it's not, the PIC goes back to sleep. If it is, the program
; returns to resume execution at the instruction following call Sleep.

count_dn	inc	lowB	; lowB = lowB+1.
	snz	; Overflow in lowB?
	incsz	hiB	; Yes: hiB=hiB+1, overflow?.
	sleep	; No overflow: back to sleep.
	ret	; Overflow. Return to caller

; In an actual application, this code would contain instructions for dealing
; with a reset pulse waking the PIC out of sleep. Here, we have an empty
; routine that just returns to the main loop.

mclr_pin	ret

; In an actual application, this code would contain instructions for dealing
; with a watchdog-timer timeout during program execution. Here, we have an
; empty routine that just returns to the main loop.

watch_fail	ret
	end