; ------------------------------------------------------------------------
;
; Title:
;
;   PD51 -- PIC "4-pin" frequency divider (10 MHz to quadrature 50 Hz)
;
; Function:
;
;   This PIC program implements a digital frequency divider: the external
;   input clock is divided by a factor of 200 thousand (2e5). For example,
;   if the input clock is 10 MHz then the output clock will be 50 Hz.
;   Two square wave outputs are provided, 90 degrees (5 ms) apart.
;
; Diagram:
;                                ---__---
;                5V (Vdd)  +++++|1      8|=====  Ground (Vss)
;             input clock  ---->|2  pD  7|---->  output clock I
;                              o|3  51  6|---->  output clock Q
;                              o|4      5|o
;                                --------
; Notes:
;
;   Only 4 pins are required: power (2.0-5.5V), ground, input and output.
;   o Tie unused input pin3/GP4, pin4/GP3, and pin5/GP2 to Vdd or Vss.
;   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:
;
;   02-Jul-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
        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'111100'       ; set GP0,GP1 as output(0) and
        movwf   TRISIO-0x80     ;   other pins are input(1)
        bcf     STATUS,RP0      ; bank 0

; With an external 10 MHz PIC clock the (4:1) execution rate is 2.5 MIPS.
; A 12,500 instruction (400 ns each) block takes exactly 5 milliseconds.
; A 50,000 instruction (400 ns each) loop takes exactly 20 milliseconds.
; Two output pins are each toggled twice per 20 ms loop creating a pair
; of 50 Hz square waves in quadrature.
; The two GPIO bits have Gray code sequence 0 1 3 2, 0 1 3 2, etc.

phase0: movlw   0x0             ; GP1=low GP0=low
        movwf   GPIO            ; W -> output pin(s)
        movlw   d'124'          ; 12400
        call    DelayW100       ; delay W*100
        movlw   d'94'           ;
        call    DelayW1         ; delay (15 <= W <= 255)

        goto    phase1

phase1: movlw   0x1             ; GP1=low GP0=high
        movwf   GPIO            ; W -> output pin(s)
        movlw   d'124'          ; 12400
        call    DelayW100       ; delay W*100
        movlw   d'94'           ;
        call    DelayW1         ; delay (15 <= W <= 255)

        goto    phase3

phase2: movlw   0x2             ; GP1=high GP0=low
        movwf   GPIO            ; W -> output pin(s)
        movlw   d'124'          ; 12400
        call    DelayW100       ; delay W*100
        movlw   d'94'           ;
        call    DelayW1         ; delay (15 <= W <= 255)

        goto    phase0

phase3: movlw   0x3             ; GP1=high GP0=high
        movwf   GPIO            ; W -> output pin(s)
        movlw   d'124'          ; 12400
        call    DelayW100       ; delay W*100
        movlw   d'94'           ;
        call    DelayW1         ; delay (15 <= W <= 255)

        goto    phase2

        include delayw.asm      ; precise delay functions
        end
