Code:
	;******************************************************************
;                                                                 *
;    Project: 65C02_Clock                                         *
;       File: 16F18313_Clock.asm                                  *
;     Author: Mike McLaren, K8LH                                  *
;    (C)2016: Micro Application Consultants                       *
;           : All Rights Reserved                                 *
;       Date: 04-Apr-2016                                         *
;                                                                 *
;    16F18313 Clock-Gen + Econo-Reset for 65C02 (8-MHz crystal)   *
;    produces a 1, 2, 4, or 8 MHz CPU clock and an ACIA clock.    *
;                                                                 *
;        IDE: MPLABX v3.05                                        *
;       Lang: MPASM v5.62 (absolute addressing mode)              *
;                                                                 *
;******************************************************************
        #include <p16F18313.INC>
        errorlevel -302,-311    ; suppress bank warnings
        list st=off             ; symbol table off
        radix dec
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  config settings                                                ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 __CONFIG _CONFIG1, _FEXTOSC_HS & _FCMEN_OFF
 ;
 ; CLKOUTEN_OFF default
 ; CSWEN_ON     default
 ;
 __CONFIG _CONFIG2, _WDTE_OFF & _PPS1WAY_OFF
 ;
 ; MCLRE_ON     default
 ; PWRTE_OFF    default
 ; LPBOREN_OFF  default
 ; BOREN_ON     default
 ; BOREN_LOW    default
 ; STVREN_ON    default
 ; DEBUG_OFF    default
 ;
 __CONFIG _CONFIG3, _LVP_OFF
 ;
 ; WRT_OFF      default
 ;
 __CONFIG _CONFIG4, _CP_OFF & _CPD_OFF
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  variables                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        cblock  0x70            ; common RAM available any bank
delayhi                         ; DelayCy() subsystem variable
        endc
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  constants                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;  assign clock and reset pins (RA0..RA2 inclusive).
;
PHI0_clk equ    RA0             ; bit index for RA0 (0)
ACIA_clk equ    RA1             ; bit index for RA1 (1)
RESB_out equ    RA2             ; bit index for RA2 (2)
;
;  associate to "Peripheral Pin Select" output registers.
;
PHI0_PPS equ    RA0PPS+PHI0_clk ; equ RA0PPS
ACIA_PPS equ    RA0PPS+ACIA_clk ; equ RA1PPS
RESB_PPS equ    RA0PPS+RESB_out ; equ RA2PPS
;
;  set 'CLKR_div' constant for desired 65C02 clock frequency.
;
;               6 ->  0.5-MHz (Fosc / 64)
;               5 ->  1.0-MHz (Fosc / 32)
;               4 ->  2.0-MHz (Fosc / 16)
;               3 ->  4.0-MHz (Fosc / 8)
;               2 ->  8.0-MHz (Fosc / 4)
;               1 -> 16.0-MHz (Fosc / 2)
;
CLKR_div equ    4               ; 2.0-MHz PHI0 CPU clock
;
;  set 'NCO1_inc' constant for desired ACIA clock output.
;
;          2517 ->    38400-Hz (  2400 * 16) @ 0.01659%
;          5033 ->    76800-Hz (  4800 * 16) @ 0.00327%
;         10066 ->   153600-Hz (  9600 * 16) @ 0.00327%
;         20133 ->   307200-Hz ( 19200 * 16) @ 0.00169%
;         40265 ->   614400-Hz ( 38400 * 16) @ 0.00079%
;         60398 ->   921600-Hz ( 57600 * 16) @ 0.00004%
;        120796 ->  1843200-Hz (115200 * 16) @ 0.00004%
;        241592 ->  3686400-Hz (230400 * 16) @ 0.00004%
;
NCO1_inc equ    120796          ; 1.8432-MHz (115200 * 16)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem macro generates four instructions     ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        radix dec
clock   equ     32              ; 4, 8, 12, 16, 20 (MHz), etc.
usecs   equ     clock/4         ; cycles/microsecond multiplier
msecs   equ     usecs*1000      ; cycles/millisecond multiplier
dloop   equ     5               ; loop size, 5 to ??? cycles
;
;  -- loop --  -- delay range --  -- memory overhead ----------
;  5-cyc loop, 11..327690 cycles,  9 words (+4 each macro call)
;  6-cyc loop, 11..393226 cycles, 10 words (+4 each macro call)
;  7-cyc loop, 11..458762 cycles, 11 words (+4 each macro call)
;  8-cyc loop, 11..524298 cycles, 12 words (+4 each macro call)
;  9-cyc loop, 11..589834 cycles, 13 words (+4 each macro call)
;
DelayCy macro   cycles          ; range, see above
    if (cycles<11)|(cycles>(dloop*65536+10))
        error " DelayCy range error "
    else
        movlw   high((cycles-11)/dloop)+1
        movwf   delayhi
        movlw   low ((cycles-11)/dloop)
        call    uLoop-((cycles-11)%dloop)
    endif
        endm
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  reset vector                                                   ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        org     0x0000
v_reset
        bra     setup           ;                                 |00
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  interrupt vector                                               ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        org     0x0004
v_int
        retfie                  ;                                 |??
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  main setup                                                     ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
setup
;
;  turn off analog functions (all I/O will be digital).
;
        banksel ANSELA          ; bank 03                         |03
        clrf    ANSELA          ; analog off, digital I/O         |03
;
;  setup data direction for 'output' pins (default 'input').
;
        banksel TRISA           ; bank 01                         |01
        bcf     TRISA,PHI0_clk  ; set phi0 clock pin as output    |01
        bcf     TRISA,ACIA_clk  ; set acia clock pin as output    |01
        bcf     TRISA,RESB_out  ; set resb reset pin as output    |01
;
;  clear RESB pin output latch (hold the 65C02 in reset).
;
        banksel LATA            ; bank 02                         |02
        bcf     LATA,RESB_out   ; RESB_out = '0'                  |02
;
;  setup Fosc for 32-MHz (external 8-MHz crystal and 4xPLL).
;
        banksel OSCCON1         ; bank 18                         |18
        movlw   b'00010000'     ; -001---- NOSC[2:0], Ext 4xPLL   |18
                                ; ----0000 NDIV[3:0], Clk Div 1   |18
        movwf   OSCCON1         ; 8-MHz Xtal & 4xPLL -> 32-MHz    |18
stable
        btfss   OSCCON3,ORDY    ; OSC stable? yes, skip, else     |18
        bra     stable          ; loop (wait until OSC stable)    |18
;
;  assign PHI0_clk pin (RA0) and ACIA_clk pin (RA1) resources
;  via 'Peripheral Pin Select'.
;
        banksel PPSLOCK         ; bank 28                         |28
        movlw   0x55            ; PPS unlock sequence             |28
        movwf   PPSLOCK         ;  "                              |28
        movlw   0xAA            ;  "                              |28
        movwf   PPSLOCK         ;  "                              |28
        bcf   PPSLOCK,PPSLOCKED ;  "                              |28
        banksel PHI0_PPS        ; bank 29                         |29
        movlw   b'00011110'     ; assign CLKR (Ref Clock) output  |29
        movwf   PHI0_PPS        ; to the PHI0 clock pin (RA0)     |29
        movlw   b'00011101'     ; assign NCO module output to     |29
        movwf   ACIA_PPS        ; the ACIA clock pin (RA1)        |29
        banksel PPSLOCK         ; bank 28                         |28
        bsf   PPSLOCK,PPSLOCKED ; all done, lock it up            |28
;
;  setup CLKR (Reference Clock) module for PHI0 CPU Clock.
;
        banksel CLKRCON         ; bank 07                         |07
        movlw   0x10|CLKR_div   ; 50% duty cycle & divider bits   |07
        movwf   CLKRCON         ; prep 1, 2, 4, or 8-MHz output   |07
        bsf     CLKRCON,CLKREN  ; enable Reference Clock output   |07
;
;  setup NCO to generate the ACIA clock.
;
        banksel NCO1CON         ; bank 08                         |08
;       bcf     NCO1CON,N1PFM   ; fixed duty cycle mode (default) |08
        movlw   b'00000001'     ; N1CKS<1:0> = '01' = Fosc        |08
        movwf   NCO1CLK         ; set NCO clock source            |08
        clrf    NCO1ACCL        ; clear 20-bit phase accumulator  |08
        clrf    NCO1ACCH        ;  "                              |08
        clrf    NCO1ACCU        ;  "                              |08
        movlw   upper(NCO1_inc) ;  "                              |08
        movwf   NCO1INCU        ;  "                              |08
        movlw   high(NCO1_inc)  ;  "                              |08
        movwf   NCO1INCH        ;  "                              |08
        movlw   low(NCO1_inc)   ; setup 20-bit phase increment    |08
        movwf   NCO1INCL        ;  "                              |08
        bsf     NCO1CON,N1EN    ; enable NCO module output        |08
;
;  complete the 65C02 reset cycle.
;
        DelayCy(20*msecs)       ; wait ~20-msecs                  |08
        banksel LATA            ; bank 02                         |02
        bsf     LATA,RESB_out   ; release 65C02 from reset        |02
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  main loop                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
loop
        bra     loop            ; loop forever (until reset)      |02
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem 16-bit 'uLoop' timing subroutine      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a = dloop-1
    while a > 0
        nop                     ; (cycles-11)%dloop entry points  |??
a -= 1
    endw
uLoop   addlw   -1              ; subtract 'dloop' loop time      |??
        skpc                    ; borrow? no, skip, else          |??
        decfsz  delayhi,F       ; done?  yes, skip, else          |??
        bra     uLoop-dloop+5   ; do another loop                 |??
        return                  ;                                 |??
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        end
 
				
Bookmarks