#include <p12F675.inc>
; __CONFIG (_INTRC_OSC_NOCLKOUT & _WDT_OFF &_BODEN_OFF &_CP_OFF &_CPD_OFF & _MCLRE_OFF)
__CONFIG (_INTRC_OSC_NOCLKOUT & _WDT_OFF &_BODEN_OFF &_CP_OFF &_CPD_OFF)
;-----------------------------------------------------------------------------------------------------------------------------
; RAM allocation
;
; Register locations 20h-5Fh are General Purpose registers,
; implemented as static RAM and are mapped across both banks.
;-----------------------------------------------------------------------------------------------------------------------------
COUNT1 equ 020h ;First counter for our delay loops
COUNT2 equ 021h ;Second counter for our delay loops
spi_in1 equ 022h
spi_in2 equ 023h
spi_in3 equ 024h
spi_out1 equ 025h
spi_out2 equ 026h
spi_out3 equ 027h
spi_status equ 028h
spi_bit equ 029h ; Bit number counter
spi_count equ 02ah ; Number of bytes to read/write
spi_in equ 02bh ; Points to spi in buffer
spi_out equ 02ch ; Points to spi out buffer
;-----------------------------------------------------------------------------------------------------------------------------
; ENC28J60 Instructions and Registers
;
RCR equ 000h
RBM equ 020h
WCR equ 040h
WBM equ 060h
BFS equ 080h
BFC equ 0a0h
SRC equ 0ffh
; Bank 0
ERDPTL EQU 00h
ERDPTH EQU 01h
EWRPTL EQU 02h
EWRPTH EQU 03h
ETXSTL EQU 04h
ETXSTH EQU 05h
ETXNDL EQU 06h
ETXNDH EQU 07h
ERXSTL EQU 08h
ERXSTH EQU 09h
ERXNDL EQU 0ah
ERXNDH EQU 0bh
ERXRDPTL EQU 0ch
ERXRDPTH EQU 0dh
ERXWRPTL EQU 0eh
ERXWRPTH EQU 0fh
EDMASTL EQU 10h
EDMASTH EQU 11h
EDMANDL EQU 12h
EDMANDH EQU 13h
EDMADSTL EQU 14h
EDMADSTH EQU 15h
EDMACSL EQU 16h
EDMACSH EQU 17h
; Bank1
EHT0 EQU 00h
EHT1 EQU 01h
EHT2 EQU 02h
EHT3 EQU 03h
EHT4 EQU 04h
EHT5 EQU 05h
EHT6 EQU 06h
EHT7 EQU 07h
EPMM0 EQU 08h
EPMM1 EQU 09h
EPMM2 EQU 0ah
EPMM3 EQU 0bh
EPMM4 EQU 0ch
EPMM5 EQU 0dh
EPMM6 EQU 0eh
EPMM7 EQU 0fh
EPMCSL EQU 10h
EPMCSH EQU 11h
EPMOL EQU 14h
EPMOH EQU 15h
ERXFCON EQU 18h
EPKTCNT EQU 19h
; Bank2
MACON1 EQU 00h
MACON3 EQU 02h
MACON4 EQU 03h
MABBIPG EQU 04h
MAIPGL EQU 06h
MAIPGH EQU 07h
MACLCON1 EQU 08h
MACLCON2 EQU 09h
MAMXFLL EQU 0ah
MAMXFLH EQU 0bh
MICMD EQU 12h
MIREGADR EQU 14h
MIWRL EQU 16h
MIWRH EQU 17h
MIRDL EQU 18h
MIRDH EQU 19h
; Bank3
MAADR5 EQU 00h
MAADR6 EQU 01h
MAADR3 EQU 02h
MAADR4 EQU 03h
MAADR1 EQU 04h
MAADR2 EQU 05h
EBSTSD EQU 06h
EBSTCON EQU 07h
EBSTCSL EQU 08h
EBSTCSH EQU 09h
MISTAT EQU 0ah
EREVID EQU 12h
ECOCON EQU 15h
EFLOCON EQU 17h
EPAUSL EQU 18h
EPAUSH EQU 19h
; Registers common to all banks...
EIE EQU 1bh
EIR EQU 1ch
ESTAT EQU 1dh
ECON2 EQU 1eh
ECON1 EQU 1fh
; Physical registers
PHCON1 EQU 00h
PHSTAT1 EQU 01h
PHID1 EQU 02h
PHID2 EQU 03h
PHCON2 EQU 10h
PHSTAT2 EQU 11h
PHIE EQU 12h
PHIR EQU 13h
PHLCON EQU 14h
;-----------------------------------------------------------------------------------------------------------------------------
org 0h
; goto Init
; org 04h
; retfie
;-----------------------------------------------------------------------------------------------------------------------------
; Init inputs and outputs by setting TRISIO port
;
; TRISIO bit = 1 Input
; TRISIO bit = 0 Output
;
; Can either set my moving 8 bit value to W register then moving W to F or by using BSF (set bit 1) or BCF (set bit 0):
;
; bsf STATUS,5 ; Switch to Bank 1
; movlw b'00110101' ; Set the Port A pins
; movwf TRISIO ;
; bcf STATUS,5 ; Switch back to Bank 0
;-----------------------------------------------------------------------------------------------------------------------------
Init
; org 10h
bsf STATUS,5 ; Switch to Bank 1
movlw b'00100000' ; Set I/O 1 output (for SCK - clock)
; Set I/O 2 output (for CS - Slave Select)
movwf TRISIO ; Set I/O 4 output (for SO - to SI on ENC28J60)
; Set I/O 5 input (for SI - to SO on ENC28J60)
bcf STATUS,5 ; Switch back to Bank 0
movlw b'00000100' ; Set cs high, all other outputs low
movwf GPIO
;-----------------------------------------------------------------------------------------------------------------------------
; Setting an output high or low
;
; If it's only one output you want to update, use BSF (to set high) or BCF (to set low):
;
; bsf GPIO,0 ; Set GP IO 0 high
; Call Delay
; bcf GPIO,2 ; Set GP IO 2 low
;-----------------------------------------------------------------------------------------------------------------------------
; bsf GPIO,0
; call DelayLong
; bcf GPIO,0
call DelayLong
doagain
movlw 2
movwf spi_count ; Set the number of bytes to send/receive
movlw RCR | ERXFCON
movwf spi_out1
call spi
goto doagain
movlw 2
movwf spi_count ; Set the number of bytes to send/receive
movlw WCR | ECON1
movwf spi_out1 ; Write ECON1
movlw 2
movwf spi_out2 ; Switch to bank 2
call spi
movlw 2
movwf spi_count ; Set the number of bytes to send/receive
movlw WCR | MIREGADR
movlw PHLCON
movwf spi_out2
call spi
movlw 2
movwf spi_count
movlw WCR | MIWRL
movlw b'10000010'
call spi
movlw 2
movwf spi_count
movlw WCR | MIWRH
movlw b'00111000'
call spi
goto doagain
;-----------------------------------------------------------------------------------------------------------------------------
; SPI subroutine
; ==============
;
; Call with:
;
; spi_count set to the number of bytes to write/read
; spi_in set to the first register address of the inbound buffer
; spi_out set to the first register address of the outbound buffer
;-----------------------------------------------------------------------------------------------------------------------------
spi
movlw spi_in1
movwf spi_in ; Set the start of the inbound buffer
movlw spi_out1
movwf spi_out ; Set the start of the outbound buffer
movlw 8 ; Set bit counter
movwf spi_bit ; to 8 bits
bcf GPIO,2 ; Set CS line low
spi_looplong
nop
nop
nop
nop
nop
nop
nop
spi_loop
bcf GPIO,1 ; **** Set clock line low ****
movf spi_out,W ; Point to next spi_out byte
movwf FSR ; with File Select Register
rlf INDF,F ; Roll next data bit into Carry flag
btfss STATUS,C ; Is it high? If yes, skip...
goto BitLow
bsf GPIO,4 ; Set SO line high
goto spi_donebit ; We have done the bit, continue on...
BitLow
bcf GPIO,4 ; Set SO line low
nop ; Wait an extra cycle if BitLow to match high alternative
spi_donebit
nop
nop
nop
nop
nop
nop
nop
nop
nop
bcf STATUS,C ; Clear the Carry flag
bsf GPIO,1 ; **** Set clock line high ****
btfsc GPIO,5 ; Read bit from SI line, skip if clear (0)
bsf STATUS,C ; Set the Carry flag if bit not clear (1)
movf spi_in,W ; Point to next spi_in byte
movwf FSR ; with File Select Register
rlf INDF,F ; Roll the incoming bit into the buffer
nop ; Wait an extra cycle to match other side of clock
decfsz spi_bit,F ; Decrement bit counter, skip if zero
goto spi_looplong ; Go do next bit...
decfsz spi_count,F ; Decrement our byte counter, skip if zero
goto spi_nextbyte ; Go do next byte, otherwise...
nop ; Wait 210ns (each instruction is 1us or 1000ns)
bsf GPIO,2 ; Set CS high
return ; Return to program
spi_nextbyte
movlw 8 ; Reset bit counter
movwf spi_bit ; for next 8 bits
incf spi_out,F ; Point to next byte in outbound buffer
incf spi_in,F ; Point to next byte in inbound buffer
goto spi_loop ; Go do next byte...
;-----------------------------------------------------------------------------------------------------------------------------
; Delay subroutine
DelayLong
call Delay
call Delay
call Delay
call Delay
call Delay
call Delay
call Delay
call Delay
call Delay
return
Delay
Loop1
decfsz COUNT1,1 ; This second loop keeps the LED
goto Loop1 ; turned off long enough for us to
decfsz COUNT2,1 ; see it turned off
goto Loop1 ;
return
;-----------------------------------------------------------------------------------------------------------------------------
end
;-----------------------------------------------------------------------------------------------------------------------------