	title	"KW11L"
;++
;
; KW11L 60 Hz clock emulation for BA11-VA (etc.) case.
;
; By John Wilson, D Bit <wilson@dbit.com>.
;
; 02/26/99	JMBW	Created.
;
; This file is hereby released into the public domain.
;
; The "circuit" (it's too simple to deserve that word) is as follows:
;
; U1 = PIC16F84
; C1 = .1 uF bypass cap
; C2/C3 = 100 pF ceramic cap
; X1 = 32.768 kHz watch crystal
;
; I'll name the pins on C1/C2/C3/X1 as pins 1/2 just for clarity, but it
; doesn't matter which is which.
;
; U1 pin 14 and U1 pin 4 and C1 pin 1 go to +5
; U1 pin 5 and C1 pin 2 go to GND
; U1 pin 15 and C2 pin 1 go to X1 pin 1
; U1 pin 16 and C3 pin 1 go to X2 pin 2
; C2 pin 2 and C3 pin 2 go to GND
; U1 pin 3 goes to BEVNT L
; All others NC
;
; Here's a nasty ASCII art attempt at this:
;
;		U1 PIC16F84
;		+----------+		     +----------+
;    BEVNT L	| 1	18 |		     |		|
;	|	| 2	17 |		     | +----+	= C3
;	+--RA4--| 3	16 |--OSC1-----------+-| X1 |	|
;   +5 --/MCLR--| 4	15 |--OSC2----------+--|    |  ///
;	+--Vss--| 5	14 |--Vdd--+-- +5   |  +----+
;	|	| 6	13 |	   |	    = C2
;      ///	| 7	12 |	   = C1	    |
;		| 8	11 |	   |	   ///
;		| 9	10 |	  ///
;		+----------+
;
; Off-board connections:
;  +5		BV1
;  GND		BT1
;  BEVNT L	BR1
;
; The easiest way to handle these is by wire-wrapping them directly to the
; backplane pins, then tape/wire-tie the board in place so that it won't short
; against anything.
;
;--
	list	p=16f84
	include <p16f84.inc>
	__config _LP_OSC&_WDT_OFF ;low-power oscillator (watch xtal)
;
hz	equ	d'60'		;output frequency in Hz
clk	equ	d'32768'	;input clock frequency in Hz (watch xtal)
;
cyc	equ	clk/4		;4 clocks per cycle
div	equ	cyc/(hz*2)	;# cycles per half tick
rem	equ	cyc%(hz*2)	;remainder from above division
				;(i.e. fraction of a cycle, in units of HZ*2)
;
	cblock	h'0C'		;variable space
	 lctr			;loop counter
	 frac			;fraction of cycle to delay
	endc
;
; Entry point
;
	bcf	STATUS,RP0	;select low register space
	clrf	PORTA		;clear output latch
	bsf	STATUS,RP0	;high bank
	clrf	TRISA		;PORTA is all outputs (RA4 is all we use)
	bcf	STATUS,RP0	;back to low bank from now on
	movlw	-(hz*2)		;init fraction counter
	movwf	frac
;
; Main loop -- toggle RA4 output at 60 Hz.
;
loop	bsf	PORTA,4		;[1] set RA4
	call	delay		;[2] delay 1/2 tick
	nop			;[2] balance for GOTO at end of loop
	nop
	bcf	PORTA,4		;[1] clear RA4
	call	delay		;[2] delay 1/2 tick
	goto	loop		;[2] back to top
ovrhed	equ	5		;main loop overhead = 5 cycles per half-tick
;+
;
; Delay 1/2 tick, minus the overhead time in main loop.
;
;-
delay	; check fractional tick count to see if we should stretch this half
	; tick by one extra cycle (5 or 6 cycles)
	movlw	rem		;[1] load remainder
	addwf	frac,F		;[1] add to fractional clock counter
	btfss	STATUS,C	;[1/2] did it wrap through 0?
	 goto	delay1		;[2] no (5 cycles total)
	movlw	hz*2		;[1] divisor from computing delay
	subwf	frac,F		;[1] rewind to account for extra delay
delay1	; delay loop eats up most of what's left
delcnt	set	div-(ovrhed+5+1+2) ;find # cycles we have left to delay
				;DIV is the total half period, minus:
				; OVRHED cycles used in main loop
				; 5 cycles used with fractional stuff above
				; 1 cycle used with MOVLW coming up
	movlw	delcnt/3	;[1] (here it is)
				; 2 cycles used with RETURN at end
				;loop duration is (3N -1) cycles
	movwf	lctr		;[1] copy to counter (use up the -1)
	decfsz	lctr,F		;[1/2] count down
	 goto	$-1		;[2] loop until count exhausted
	; 0-2 NOPs to get anything not handled by loop
delcnt	set	delcnt%3
	while	delcnt
	 nop			;[1] delay 0-2 cycles more
delcnt	set	delcnt-1
	endw
	return			;[2] return
;
	end
