; ------------------------------------------------------------------------
;
; Title:
;
;   PD72 -- PIC "4-pin" frequency divider and pulse width generator
;
; Function:
;
;   This PIC program implements a digital frequency divider:
;
;   - base crystal = 1.686MHz
;   - target signal = 1.686Hz with a pulse width of 139ms
;
;   This is a simple 1,000,000x digital frequency divider,
;   except the duty cycle of the low frequency output is unusual.
;
; Diagram:
;                                ---__---
;                5V (Vdd)  +++++|1      8|=====  Ground (Vss)
;          X MHz clock in  ---->|2  pD  7|---->  Y Hz output
;                              *|3  72  6|*
;                              o|4      5|o
;                                --------
; Notes:
;
;   Only 4 pins are required: power (2.0-5.5V), ground, input and output.
;   * For added drive power, pin3/GP4 and pin6/GP1 are also outputs.
;   o Tie input 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:
;
;   03-Jan-2019  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'101100'       ; set GP0,GP1,GP4 as output(0) and
        movwf   TRISIO-0x80     ;   other pins are input(1)
        bcf     STATUS,RP0      ; bank 0

; Instruction cycle math:
;
; - External clock input rate is 1.686 MHz,
;   so PIC (4:1) execution rate is 421,500 instructions per second,
;   which is ~2372.479 ns per instruction.
;
; - 1.686 Hz output has a period of ~593.119810 ms,
;   which is 250,000 instructions.
;
; - Pulse width must be approx 139 ms,
;   which is close to 58589 instructions,
;   which is ~139.001186 ms.
;
; - Therefore make the output high for 58589 instructions,
;   and low for (250000 - 58589) = 191411 instructions.
;

        ; Set output high for 58589 instructions.

rise:   movlw   0xFF            ; (      1) high output
        movwf   GPIO            ; (      1) W -> output pin(s)
        movlw   d'5'            ; (      1) delay W*10000
        call    DelayW10k       ; (  50000)
        movlw   d'85'           ; (      1)
        call    DelayW100       ; (   8500) delay W*100
        movlw   d'82'           ; (      1)
        call    DelayW1         ; (     82) delay (15 <= W <= 255)
        goto    fall            ; (      2)

        ; Set output low for 191411 instructions.

fall:   movlw   0x00            ; (      1) low output
        movwf   GPIO            ; (      1) W -> output pin(s)
        movlw   d'19'           ; (      1) delay W*10000
        call    DelayW10k       ; ( 190000)
        movlw   d'13'           ; (      1)
        call    DelayW100       ; (   1300) delay W*100
        movlw   d'104'          ; (      1)
        call    DelayW1         ; (    104) delay (15 <= W <= 255)
        goto    rise            ; (      2)

        include delayw.asm      ; precise delay functions
        end
