;;==============================================================;;
;; 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: 10.08.2016 ;;
;; ;;
;;==============================================================;;
; Minimal external components, uses external xtall at 32768 Hz
; (reused 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
; 07.08.2016 Changed switch usage
; 10.08.2016 Reverse moving steps
; ----- Definitions
#define __VERNUM D'03'
#define __VERDAY 0x10
#define __VERMONTH 0x08
#define __VERYEAR 0x16
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|- Speed1
; |-68-100pf+32768xtall -|OSC2 GP1|- Out1 -51R--+mot--|<--| 1N5819
; o-pull-up---Speed2 -|GP3 GP2|- Out2 -51R--+mot--|<--| 1N5819
; +-----------+
; 68-100pF for LP osc (less than 37kHz)
; Speed1 & Speed2 are switches connected to ground, pull up to Vdd
; --- 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, Timer0 no prescaler 1:1
; Timer0 no prescaller mean fosc/4 = 32768 / 4 = 8192 Hz
WPU_INI equ 0x01 ; Weak pull-up enable for GP0.
INTC_INI equ 0x00 ; disable interrupts
PIE1_INI equ 0x00 ; no interrupts
#define SW_SPD1 GPIO,0 ; switch to fast mode 1
#define OUT_A GPIO,1 ; motor out A
#define OUT_B GPIO,2 ; motor out 2
#define SW_SPD2 GPIO,3 ; switch to fast mode 2 (GPIO,3 only input)
#define OUT_A_SET 0x02 ; config for out a set out b clear
#define OUT_B_SET 0x04 ; config for out b set out a clear
; Fast mode table:
; Speed1 | Speed2 | Clock rate
; Off(H) | Off(H) | 1:1 = normal clock = 8192/256 = 32 ticks
; On (L) | Off(H) | 1:4 = 4x faster than normal; defined in EEPROM 1st position 32/4 = 8
; Off(H) | On (L) | 1:5.33 = 5.33x faster than normal; defined in EEPROM 2nf position 32/5.33 = 6
; Off(H) | Off(H) | 1:6.4 = 6.4x faster than normal; defined in EEPROM 3rd position 32/6.4 = 5
; Define the amount of time that the coil should
; be energised for a 'tick'. This should be as low as
; possible but varies between clock modules...
#define ENERGISE_TIME 0x40
#define REVERT_TIME 0x06
; --- EEPROM Section
#define EE_INI 0x00
cblock EE_INI
EE_FCLK1 ; Fast clock 1st divider
EE_FCLK2 ; Fast clock 2nd divider
EE_FCLK3 ; Fast clock 3rd divider
endc
; ----- Variables
; --- Internal RAM Section
#define RAMINI0 0x020 ; 64 bytes
cblock RAMINI0
FCLK1 ; Fast clock 1st divider
FCLK2 ; Fast clock 2nd divider
FCLK3 ; Fast clock 3rd divider
CLKCNT ; Counter for clock ticks (8192/256)
POLARITY ; next pulse polarity
ECNT ; pulse length counter
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:
;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
;**********************************************************************************************************************
; Tables on first 256 bytes
;**********************************************************************************************************************
;
SpeedTable
andlw 0x03
addwf PCL,f
goto NormalTime
goto FastClk1
goto FastClk2
goto FastClk3
;
if ($ > d'255')
ERROR " Tables exceded page 0. If it works, why do you change it? "
endif
;
; ----------------------------------------------------------------------
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 ; disable all interrupts
movlw EE_FCLK1 ; read saved FCLK1 value
call EE_Read
movwf FCLK1
movlw EE_FCLK2 ; read saved FCLK2 value
call EE_Read
movwf FCLK2
movlw EE_FCLK3 ; read saved FCLK3 value
call EE_Read
movwf FCLK3
clrf TMR0
clrf CLKCNT
; ----------------------------------------------------------------------
MainLoop:
btfss INTCON,T0IF ; wait for next tick
goto MainLoop
bcf INTCON,T0IF
incf CLKCNT,f ; increment ticks
movlw 0x00 ; clear WREG
btfss SW_SPD1 ; if SW_SPD1 switch is on,
addlw 0x01 ; add bit 1 to WREG
btfss SW_SPD2 ; if SW_SPD2 switch is on,
addlw 0x02 ; add bit 2 to WREG
goto SpeedTable ; speed table will go to proper speed destination
FastClk1:
movf CLKCNT,w
subwf FCLK1,w
btfss STATUS,Z ; if FCLK1 is equal CLKCNT, send pulse
btfss STATUS,C ; if FCLK1 is Greater, do nothing
goto SendPulse ; else send pulse
goto MainLoop
FastClk2:
movf CLKCNT,w
subwf FCLK2,w
btfss STATUS,Z ; if FCLK2 is equal CLKCNT, send pulse
btfss STATUS,C ; if FCLK2 is Greater, do nothing
goto SendPulse ; else send pulse
goto MainLoop
FastClk3:
movf CLKCNT,w
subwf FCLK3,w
btfss STATUS,Z ; if FCLK3 is equal CLKCNT, send pulse
btfss STATUS,C ; if FCLK3 is Greater, do nothing
goto SendPulse ; else send pulse
goto MainLoop
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:
movlw REVERT_TIME
movwf ECNT
movlw OUT_B_SET ; start with pulse B
movwf GPIO
RevPulseLoopA: ; short time wait
decfsz ECNT,f
goto RevPulseLoopA
movlw OUT_A_SET ; then pulse A
movwf GPIO
goto SendPulseE
SendPulseB:
movlw REVERT_TIME
movwf ECNT
movlw OUT_A_SET ; start with pulse A
movwf GPIO
RevPulseLoopB: ; short time wait
decfsz ECNT,f
goto RevPulseLoopB
movlw OUT_B_SET ; then pulse B
movwf GPIO
;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 ; EE_FCLK1 fast clock counter - 5=6.4x normal clock 6=5.333x normal clock
dw 0x06 ; EE_FCLK2 fast clock counter - 5=6.4x normal clock 6=5.333x normal clock
dw 0x05 ; EE_FCLK3 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