;;==========================================================;;
;;			hand clock with fast and stop mode				;;
;;==========================================================;;
;;															;;
;; Program:         Hclock -- Hand clock module				;;
;; Code:            Jindra Fucik							;;
;; Platform:        Microchip PIC12F629, 32768 Hz			;;
;; Date:            04.06.2013								;;
;; First release:   04.06.2013								;;
;; LastDate:        04.06.2013								;;
;;															;;
;;==========================================================;;

; Minimal external components, uses external xtall at 32768 Hz
; (re-used from clock movement :))

; This program is distributed as is but WITHOUT ANY WARRANTY
; I hope you enjoy!!
;
; Revisions:
; 04.06.2013	Start of writting code

; ----- Definitions

#define		__VERNUM	D'1'
#define		__VERDAY	0x04
#define		__VERMONTH	0x06
#define		__VERYEAR	0x13

	LIST	   p=12F629	; target processor

	; errorlevel -305 ; Using default destination of 1 (file).
	errorlevel -302 ; Register in operand not in bank 0. Ensure that bank bits are correct.

	#include p12F629.inc

	__CONFIG  _BODEN_OFF & _CP_OFF & _WDT_OFF & _MCLRE_OFF & _PWRTE_ON & _LP_OSC 

	; Make sure that internal osc. is calibrated (although not used)
	; Value has to be read before reprogramming the device.

; Hardware
;                        +-----------+
;                   +3V -|Vdd  U  Vss|- GND
; |-68-100pf+32768xtall -|OSC1    GP0|- Fast
; |-68-100pf+32768xtall -|OSC2    GP1|- Out1 -47R--+mot--|<--| 1N5819
;      o-pull-up---Stop -|GP3     GP2|- Out2 -47R--+mot--|<--| 1N5819
;                        +-----------+
; 68-100pF for LP osc (less than 37kHz)

; --- Macros

#define		DNOP		goto	$+1


; --- Constant values 

FXTAL		equ	D'32768'

GP_TRIS         equ     0x09			; GP0,GP3: inputs
GP_INI          equ     0x00			; all zero
OPTION_INI	equ	b'00001000'			; Option register: pull-up, falling GP2,no prescaler 1:1 (1:4)
WPU_INI		equ	0x01			; Weak pull-up enable for GP0. 

INTC_INI	equ	0x00			; disable interrupts
PIE1_INI	equ	0x00			; no interrupts


#define		SW_FAST	GPIO,0			; switch to fast mode
#define		OUT_A	GPIO,1			; motor out A
#define		OUT_B	GPIO,2			; motor out 2
#define		SW_STOP	GPIO,3			; switch to stop (GPIO,3 only input)

#define		ENERGISE_TIME		0x20

; --- EEPROM Section

#define		EE_INI		0x00

	cblock  EE_INI
EE_FCLK		; Fast clock divider
			; the value used when fast mode is active
	endc



; ----- Variables

; --- Internal RAM Section

#define		RAMINI0		0x020		; 64 bytes
        cblock  RAMINI0

FCLK		; Value for fast clock see description at end
CLKCNT		; counter of time ticks 
POLARITY	; used for polarity (even/odd second)
ECNT		; counter for energize of coil

		endc

; --------------- Program Section --------------------------------------


		org	0x000

PowerUp:
		clrf	STATUS			; Bank 0 default
		clrf	INTCON			; Disable all interrupts
		clrf	PCLATH			; tables on page 0
		goto	INIT

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

		org	0x004

Interrupt:		; not used...
		;movwf	INT_W			; save context registers		;1
		;swapf	STATUS,w							;2
		;movwf	INT_STAT							;3
		;clrf	STATUS			; interrupt uses bank 0			;4

EndInt:
		;swapf	INT_STAT,w		; restore context registers	;49	;34
		;movwf	STATUS							;50	;35
		;swapf	INT_W,f							;51	;36
		;swapf	INT_W,w							;52	;37
		;retfie								;53,54	;38,39



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

INIT:
		clrf	GPIO
		movlw	0x07
		movwf	CMCON			; set GP2:0 to digital I/O

		bsf	STATUS,RP0		; bank 1
		movlw	GP_TRIS
		movwf	TRISIO
		;call	0x3FF			; get OSCCAL value
		;movwf	OSCCAL
		movlw	WPU_INI			; pull-ups
		movwf	WPU
		clrf	IOC			; interrupt on change
		clrf	VRCON			; voltage reference off
		movlw	OPTION_INI		; Option register: no pull-up, falling GP2, no prescaler, wdt 1:1
		movwf	OPTION_REG
		movlw	PIE1_INI
		movwf	PIE1
		bcf	STATUS,RP0		; bank 0
		clrf	PIR1
		movlw	0x00			; Timer 1 off, 1:1
		movwf	T1CON

		movlw	0x20			; clear RAM
		movwf	FSR
ClearRAM:
		clrf	INDF
		incf	FSR,f
		movlw	0x60
		xorwf	FSR,w
		btfss	STATUS,Z
		goto	ClearRAM

		movlw	INTC_INI
		movwf	INTCON

		movlw	EE_FCLK			; read saved FCLK value
		call	EE_Read
		movwf	FCLK			
		clrf	TMR0
		bcf		INTCON,T0IF
		clrf	CLKCNT

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

MainLoop:
	btfss	INTCON,T0IF
	goto	MainLoop

	bcf		INTCON,T0IF
	incf	CLKCNT,f

	btfss	SW_STOP				; if STOP switch is active,
	clrf	CLKCNT				; clear counter every time
	
	btfsc	SW_FAST				; if fast button is not pressed
	goto	NormalTime			; calculate only normal time
	
	movf	FCLK,w
	xorwf	CLKCNT,w

	btfsc	STATUS,Z			; if FCLK and CLKCNT are the same
	goto	SendPulse

NormalTime:
	movf	CLKCNT,w
	andlw	0xE0 				; bits 7,6,5
	btfsc	STATUS,Z			; if CLKCNT>=32
	goto	MainLoop

SendPulse:
	incf	POLARITY,f
	clrf	CLKCNT

	btfss	POLARITY,0
	goto	SendPulseB

SendPulseA:
	bsf		OUT_A
	goto	SendPulseE

SendPulseB:
	bsf		OUT_B
	;goto	SendPulseE

SendPulseE:
	movlw	ENERGISE_TIME
	movwf	ECNT
SendPulseLoop:
	decfsz	ECNT,f
	goto	SendPulseLoop
	bcf		OUT_A
	bcf		OUT_B
	goto	MainLoop

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

EE_Read:
		bsf	STATUS,RP0		; w=ADR
		movwf	EEADR
		bsf	EECON1,RD
		movf	EEDATA,w
		bcf	STATUS,RP0
		return



; ----- EEPROM default values


		org	0x2100

; TMR0 = clock / 4 = 32768 / 4 = 8192
; TMR0 over = 256 ~ 8192 / 256 = 32
; 32 times TMR0 over = 1 sec
; 8 times TMR0 = 4x faster
; 6 times TMR0 =5.333x normal clock
; 5 times TMR0 =6.4x normal clock
		dw	0x08			; fast clock counter - 5=6.4x normal clock 6=5.333x normal clock
		;dw	0x06			; fast clock counter - 5=6.4x normal clock 6=5.333x normal clock
		;dw	0x05			; fast clock counter - 5=6.4x normal clock 6=5.333x normal clock

		org	0x2120

		dt	"FastClck"
		dt	" ver. ",(__VERNUM   & 0x0F)+0x30," "
		dt	"J.Fucik "
		dt	(__VERDAY   >> 4)  +0x30
		dt	(__VERDAY   & 0x0F)+0x30,"/"
		dt	(__VERMONTH >> 4)  +0x30
		dt	(__VERMONTH & 0x0F)+0x30,"/"
		dt	(__VERYEAR  >> 4)  +0x30
		dt	(__VERYEAR  & 0x0F)+0x30

	end