; ------------------------------------------------------------------------
;
; Title:
;
;   PD41 -- PIC "4-pin" 7.68 MHz to 1 Hz frequency divider (1x, 2x, 4x)
;
; Function:
;
;   This PIC program implements a digital frequency divider: the external
;   input clock is divided by three factors: 7,680,000 and 15,360,000 and
;   30,720,000. For example, given a 7.68 MHz input clock GP0 outputs 1 Hz.
;   Given a 15.36 MHz input clock, GP0 outputs 2 Hz and GP1 outputs 1 Hz.
;   If your PIC allows a 30.72 MHz input clock, then GP0 outputs 4 Hz, GP1
;   outputs 2 Hz, and GP2 outputs 1 Hz. And so on.
;
; Diagram:
;                                ---__---
;                5V (Vdd)  +++++|1      8|=====  Ground (Vss)
;             7.68 MHz in  ---->|2  pD  7|---->  1 s (1 Hz) out
;                     n/c      -|3  41  6|---->  2 s (1/2 Hz) out
;                          o--->|4      5|---->  4 s (1/4 Hz) out
;                                --------
; Notes:
;
;   Only 4 pins are required: power (2.0-5.5V), ground, input and output.
;   o Tie input pin4/GP3 to Vdd or Vss.
;   - Microchip says do not leave this pin floating.
;   Output frequency accuracy is the same as clock input accuracy.
;   Output drive current is 25 mA maximum per pin.
;   Coded for Microchip 12F675 but any '609 '615 '629 '635 '675 '683 works.
;
; Version:
;
;   23-Aug-2021  Tom Van Baak (tvb)  www.LeapSecond.com/pic
;
; ------------------------------------------------------------------------


; Microchip MPLAB IDE assembler code (mpasm).

        list        p=pic12f675
        include     p12f675.inc
        __config    _EC_OSC & _MCLRE_OFF & _WDT_OFF

; Register definitions.

        cblock  0x20            ; define register base
            gpcopy              ; shadow of output pins
        endc

; One-time PIC 12F675 initialization.

        org     0               ; power-on entry here
        bcf     STATUS,RP0      ; bank 0
        clrf    GPIO            ; set all pins low
        movlw   07h             ; set mode to turn
        movwf   CMCON           ;   comparator off
        bsf     STATUS,RP0      ; bank 1
        clrf    ANSEL-0x80      ; set digital IO (no analog A/D)
        movlw   b'101000'       ; set GP0,GP1,GP2,GP4 as output(0) and
        movwf   TRISIO-0x80     ;   other pins are input(1)
        bcf     STATUS,RP0      ; bank 0
        clrf    gpcopy          ; initialize shadow output

; With an external 7.68 MHz clock (and 4:1 PIC execution ratio), a
; total of 960,000 instructions takes exactly 0.5 second per loop.
; The 3 low order output pins are binary incremented once per loop
; creating 3 square waves with 4s 2s 1s periods.

Loop    incf    gpcopy,F        ; (      1) increment lower 3-bits
        movf    gpcopy,W        ; (      1) gpcopy -> W
        movwf   GPIO            ; (      1) W -> output pin(s)

        movlw   d'95'           ; (      1)
        call    DelayW10k       ; ( 950000) delay W*10000
        movlw   d'99'           ; (      1)
        call    DelayW100       ; (   9900) delay W*100
        movlw   d'92'           ; (      1)
        call    DelayW1         ; (     91) delay (15 <= W <= 255)
        goto    Loop            ; (      2)

        include delayw.asm      ; precise delay functions
        end
