LIST p=16F876a ;tell assembler what chip we are using
include "P16F876a.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x373a ;sets the configuration settings (oscillator type etc.)
cblock 0x20 ;start of general purpose registers
OUT1 ;first byte to send out on spi
OUT2 ;second byte to send out on spi
TMP1 ;temp storage for spi
CNT ;Count for byte for spi
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
p_temp ;save register
s_temp ;save register
w_temp ;save register
;registers for display
row_pos ;position on row
zero1 ;zero storage
one1 ;one storage
two1 ;two storage
three1 ;three storage
four1 ;four storage
five1 ;five storage
six1 ;six storage
seven1 ;seven storage
zero2 ;zero storage
one2 ;one storage
two2 ;two storage
three2 ;three storage
four2 ;four storage
five2 ;five storage
six2 ;six storage
seven2 ;seven storage
zero3 ;zero storage
one3 ;one storage
two3 ;two storage
three3 ;three storage
four3 ;four storage
five3 ;five storage
six3 ;six storage
seven3 ;seven storage
zero4 ;zero storage
one4 ;one storage
two4 ;two storage
three4 ;three storage
four4 ;four storage
five4 ;five storage
six4 ;six storage
seven4 ;seven storage
zero5
one5 ;one storage
two5 ;two storage
three5 ;three storage
four5 ;four storage
five5 ;five storage
six5 ;six storage
seven5 ;seven storage
zero6
one6 ;one storage
two6 ;two storage
three6 ;three storage
four6 ;four storage
five6 ;five storage
six6 ;six storage
seven6 ;seven storage
zerol ;zero storage
onel ;one storage
twol ;two storage
threel ;three storage
fourl ;four storage
fivel ;five storage
sixl ;six storage
sevenl ;seven storage
TEN ;CONVERT CLOCK RESULT TENS TO SINGLE UNIT
UNITS ;CONVERT CLOCK RESULT UNITS TO SINGLE UNIT
TEMPCLOCK ;HOLDS TEMP CLOCK RESULT FOR TENSANDUNITS
SCRATCH ; 1 by general-purpose scratchpad
TMP ; temp register
TMP2 ; temp register
COUNT
YRS
MON
DOW
DAYS
HRS
MINS
SEC
endc
CS EQU 0 ;enable stobe
MOSI EQU 3 ;output for spi from master
SPICLK EQU 2 ;clock for spi
ROW_PORT Equ PORTB ;row port
org 0x0000
goto START
;**************************************************************************
; Interrupt routine
;**************************************************************************
; Interrupt routine handles TMR2 which generates a 1ms tick
; Interrupt vector
ORG 0x0004
INT
movwf w_temp ; Save W register
swapf STATUS,W ; Swap status to be saved into W
movwf s_temp ; Save STATUS register
movfw PCLATH
movwf p_temp ; Save PCLATH
btfss PIR1,TMR2IF ; Flag set if TMR2 interrupt
goto INTX ; Jump if not timed out
; Timer (TMR2) timeout
btfss row_pos, 0 ;check which ROW was last
goto Do_One
btfss row_pos, 1 ;check which ROW was last
goto Do_Two
btfss row_pos, 2 ;check which ROW was last
goto Do_Three
btfss row_pos, 3 ;check which ROW was last
goto Do_Four
btfss row_pos, 4 ;check which ROW was last
goto Do_Five
btfss row_pos, 5 ;check which ROW was last
goto Do_Six
btfss row_pos, 6 ;check which ROW was last
goto Do_Seven
Do_Zero movlw 0xFF
movwf row_pos
movf zero1, w
MOVWF OUT1
MOVF zero2, w
movwf OUT2
CALL xfer16
MOVF zero3, w
movwf OUT1
MOVF zero4, w
movwf OUT2
CALL xfer16
movf zero5, w
movwf OUT1
movf zero6, w
movwf OUT2
call xfer16
bcf row_pos, 0
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_One movlw 0xFF
movwf row_pos
movf one1, w
MOVWF OUT1
MOVF one2, w
movwf OUT2
CALL xfer16
MOVF one3, w
movwf OUT1
MOVF one4, w
movwf OUT2
CALL xfer16
movf one5, w
movwf OUT1
movf one6, w
movwf OUT2
call xfer16
bcf row_pos, 1
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_Two movlw 0xFF
movwf row_pos
movf two1, w
MOVWF OUT1
MOVF two2, w
movwf OUT2
CALL xfer16
MOVF two3, w
movwf OUT1
MOVF two4, w
movwf OUT2
CALL xfer16
movf two5, w
movwf OUT1
movf two6, w
movwf OUT2
call xfer16
bcf row_pos, 2
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_Three movlw 0xFF
movwf row_pos
movf three1, w
MOVWF OUT1
MOVF three2, w
movwf OUT2
CALL xfer16
MOVF three3, w
movwf OUT1
MOVF three4, w
movwf OUT2
CALL xfer16
movf three5, w
movwf OUT1
movf three6, w
movwf OUT2
call xfer16
bcf row_pos, 3
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_Four movlw 0xFF
movwf row_pos
movf four1, w
MOVWF OUT1
MOVF four2, w
movwf OUT2
CALL xfer16
MOVF four3, w
movwf OUT1
MOVF four4, w
movwf OUT2
CALL xfer16
movf four5, w
movwf OUT1
movf four6, w
movwf OUT2
call xfer16
bcf row_pos, 4
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_Five movlw 0xFF
movwf row_pos
movf five1, w
MOVWF OUT1
MOVF five2, w
movwf OUT2
CALL xfer16
MOVF five3, w
movwf OUT1
MOVF five4, w
movwf OUT2
CALL xfer16
movf five5, w
movwf OUT1
movf five6, w
movwf OUT2
call xfer16
bcf row_pos, 5
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_Six movlw 0xFF
movwf row_pos
movf six1, w
MOVWF OUT1
MOVF six2, w
movwf OUT2
CALL xfer16
MOVF six3, w
movwf OUT1
MOVF six4, w
movwf OUT2
CALL xfer16
movf six5, w
movwf OUT1
movf six6, w
movwf OUT2
call xfer16
bcf row_pos, 6
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_Seven movlw 0xFF
movwf row_pos
movf seven1, w
MOVWF OUT1
MOVF seven2, w
movwf OUT2
CALL xfer16
MOVF seven3, w
movwf OUT1
MOVF seven4, w
movwf OUT2
CALL xfer16
movf seven5, w
movwf OUT1
movf seven6, w
movwf OUT2
call xfer16
bcf row_pos, 7
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
INTX
movfw p_temp
movwf PCLATH ; Restore PCLATH
swapf s_temp,W
movwf STATUS ; Restore STATUS register - restores bank
swapf w_temp,F
swapf w_temp,W ; Restore W register
bcf PIR1,TMR2IF ; Clear the calling flag
retfie
;program initialisation
START
BANKSEL ADCON1 ;disable analogue inputs
movlw 0x06
movwf ADCON1
BANKSEL PORTA
bsf STATUS, RP0 ;select bank 1
movlw b'00000000' ;Set port data directions, data output
movwf TRISA
movwf TRISB
MOVWF TRISC
MOVLW B'00000111'
MOVWF OPTION_REG
bcf STATUS, RP0 ;select bank 0
movlw 0x01
movwf row_pos
call Clear ;clear display registers
; Set up Timer 2.
;movlw b'01111110' ; Post scale /16, pre scale /16, TMR2 ON
;uncomment previous line, and comment next line, to slow multiplexing speed
;so you can see the multiplexing happening
movlw b'00000110' ; Post scale /4, pre scale /16, TMR2 ON
movwf T2CON
bsf STATUS, RP0 ;select bank 1
movlw .249 ; Set up comparator
movwf PR2
; bsf PIE1,TMR2IE ; Enable TMR2 interrupt
; bcf STATUS, RP0 ;select bank
; bsf INTCON,PEIE ; Enable all peripheral interrupts
; bsf INTCON,GIE ; Global interrupt enable
Main
bcf INTCON,PEIE ; Enable all peripheral interrupts
bcf INTCON,GIE ; Global interrupt enable
bsf STATUS, RP0 ;select bank 1
bcf PIE1,TMR2IE ; disable TMR2 interrupt
bcf STATUS, RP0 ;select bank 0
CALL InitI2C
call RTC_brst_rd
bsf STATUS, RP0 ;select bank 1
bsf PIE1,TMR2IE ; Enable TMR2 interrupt
bcf STATUS, RP0 ;select bank
bsf INTCON,PEIE ; Enable all peripheral interrupts
bsf INTCON,GIE ; Global interrupt enable
MOVF HRS,W
CALL TENSANDUNITS
MOVF TEN,W
CALL NUMBERTABLE
CALL ScrollL8
MOVF UNITS,W
CALL NUMBERTABLE
CALL ScrollL8
CALL DOUBLEDOT
CALL ScrollL8
MOVF MINS,W
CALL TENSANDUNITS
MOVF TEN,W
CALL NUMBERTABLE
CALL ScrollL8
MOVF UNITS,W
CALL NUMBERTABLE
CALL ScrollL8
CALL DOT
CALL ScrollL8
MOVF SEC,W
CALL TENSANDUNITS
MOVF TEN,W
CALL NUMBERTABLE
CALL ScrollL8
MOVF UNITS,W
CALL NUMBERTABLE
CALL ScrollL8
CALL Delay1Sec
CALL Clear
goto Main ;endless loop
;***********************************************************
;*****************start of subroutines**********************
;***********************************************************
TENSANDUNITS
movwf TEMPCLOCK
andlw b'00001111'
movwf UNITS
swapf TEMPCLOCK,w
andlw b'00001111'
movwf TEN
RETURN
NUMBERTABLE
ADDWF PCL
goto Load_Zero
goto Load_One
goto Load_Two
goto Load_Three
goto Load_Four
goto Load_Five
goto Load_Six
goto Load_Seven
goto Load_Eight
goto Load_Nine
Clear clrf zero1
CLRF zero2
clrf zero3
CLRF zero4
clrf zero5
clrf zero6
clrf one1
clrf one2
clrf one3
clrf one4
clrf one5
clrf one6
clrf two1
clrf two2
clrf two3
clrf two4
clrf two5
clrf two6
clrf three2
clrf three1
clrf three3
clrf three4
clrf three5
clrf three6
clrf four1
clrf four2
clrf four3
clrf four4
clrf four5
clrf four6
clrf five1
clrf five2
clrf five3
clrf five4
clrf five5
clrf five6
clrf six1
clrf six2
clrf six3
clrf six4
clrf six5
clrf six6
clrf seven1
clrf seven2
clrf seven3
clrf seven4
clrf seven5
clrf seven6
RETURN
DOUBLEDOT
movlw 0x00
movwf zerol
movlw 0X18
movwf onel
movlw 0x18
movwf twol
movlw 0x00
movwf threel
movlw 0x00
movwf fourl
movlw 0x18
movwf fivel
movlw 0x18
movwf sixl
movlw 0x00
movwf sevenl
return
DOT
movlw 0x00
movwf zerol
movlw 0X18
movwf onel
movlw 0x18
movwf twol
movlw 0x00
movwf threel
movlw 0x00
movwf fourl
movlw 0x00
movwf fivel
movlw 0x00
movwf sixl
movlw 0x00
movwf sevenl
return
Load_Zero movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x4C
movwf threel
movlw 0x54
movwf fourl
movlw 0x64
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
Load_One movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x10
movwf twol
movlw 0x10
movwf threel
movlw 0x10
movwf fourl
movlw 0x10
movwf fivel
movlw 0x30
movwf sixl
movlw 0x10
movwf sevenl
return
Load_Two movlw 0x00
movwf zerol
movlw 0x7C
movwf onel
movlw 0x20
movwf twol
movlw 0x10
movwf threel
movlw 0x08
movwf fourl
movlw 0x04
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
Load_Three movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x04
movwf threel
movlw 0x08
movwf fourl
movlw 0x10
movwf fivel
movlw 0x08
movwf sixl
movlw 0x7C
movwf sevenl
return
Load_Four movlw 0x00
movwf zerol
movlw 0x08
movwf onel
movlw 0x08
movwf twol
movlw 0x7C
movwf threel
movlw 0x48
movwf fourl
movlw 0x28
movwf fivel
movlw 0x18
movwf sixl
movlw 0x08
movwf sevenl
return
Load_Five movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x04
movwf threel
movlw 0x04
movwf fourl
movlw 0x78
movwf fivel
movlw 0x40
movwf sixl
movlw 0x7C
movwf sevenl
return
Load_Six movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x44
movwf threel
movlw 0x78
movwf fourl
movlw 0x40
movwf fivel
movlw 0x20
movwf sixl
movlw 0x18
movwf sevenl
return
Load_Seven movlw 0x00
movwf zerol
movlw 0x20
movwf onel
movlw 0x20
movwf twol
movlw 0x20
movwf threel
movlw 0x10
movwf fourl
movlw 0x08
movwf fivel
movlw 0x04
movwf sixl
movlw 0x7C
movwf sevenl
return
Load_Eight movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x44
movwf threel
movlw 0x38
movwf fourl
movlw 0x44
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
Load_Nine movlw 0x00
movwf zerol
movlw 0x30
movwf onel
movlw 0x08
movwf twol
movlw 0x04
movwf threel
movlw 0x3C
movwf fourl
movlw 0x44
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
ScrollL8 call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
return
ScrollL bcf STATUS, C
rlf zerol, f
rlf zero1, f
rlf zero2, f
rlf zero3, f
rlf zero4, f
rlf zero5, f
rlf zero6, f
bcf STATUS, C
rlf onel, f
rlf one1, f
rlf one2, f
rlf one3, f
rlf one4, f
rlf one5, f
rlf one6, f
bcf STATUS, C
rlf twol, f
rlf two1, f
rlf two2, f
rlf two3, f
rlf two4, f
rlf two5, f
rlf two6, f
bcf STATUS, C
rlf threel, f
rlf three1, f
rlf three2, f
rlf three3, f
rlf three4, f
rlf three5, f
rlf three6, f
bcf STATUS, C
rlf fourl, f
rlf four1, f
rlf four2, f
rlf four3, f
rlf four4, f
rlf four5, f
rlf four6, f
bcf STATUS, C
rlf fivel, f
rlf five1, f
rlf five2, f
rlf five3, f
rlf five4, f
rlf five5, f
rlf five6, f
bcf STATUS, C
rlf sixl, f
rlf six1, f
rlf six2, f
rlf six3, f
rlf six4, f
rlf six5, f
rlf six6, f
bcf STATUS, C
rlf sevenl, f
rlf seven1, f
rlf seven2, f
rlf seven3, f
rlf seven4, f
rlf seven5, f
rlf seven6, f
return
;***********************************************************
;***************DELAY ROUTINE*******************************
;***********************************************************
Delay1Sec call Delay250
call Delay250
call Delay250
call Delay250
Return
Delay255 movlw 0xff ;delay 255mS
goto d0
Delay250 movlw d'250' ;delay 250mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay10 movlw d'10' ;delay 10mS
goto d0
Delay1 movlw d'1' ;delay 1mS
goto d0
Delay5 movlw 0x05 ;delay 5ms
d0 movwf count1
d1 movlw 0xE7
movwf counta
movlw 0x04
movwf countb
Delay_0 decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
;-----------------------------------------
;-- RTC routines --
;-----------------------------------------
RTC_brst_rd:
call I2CSTART
movlw 0D0h ; slave address + write
call I2CSEND
movlw 0X00 ; set word address to seconds register
call I2CSEND
call I2CRESTART
movlw 0D1h ; slave address + read
call I2CSEND
call I2CREAD ; read the seconds data
movwf SEC ; save it
call I2CACK
call I2CREAD ; and so on
movwf MINS
call I2CACK
call I2CREAD
movwf HRS
; call I2CACK
; call I2CREAD
; movwf DOW
; call I2CACK
; call I2CREAD
; movwf DAYS
; call I2CACK
; call I2CREAD
; movwf MON
; call I2CACK
; call I2CREAD
; movwf YRS
CALL I2CNACK
CALL I2CSTOP
return
;-----------------------------------------
;-- I2C routines --
;-----------------------------------------
InitI2C: ; The subroutine of I2C Initialization
BANKSEL TRISC
movlw B'00011000' ; Initial PortC,bit 3 & 4 as Input
movwf TRISC ; RC3 = SCL , RC4 = SDA
BANKSEL PORTC
movlw 0xff
movwf PORTC
movlw .50 ; This gives 100KHz I2C clock @ 4MHz (FOSC/CLOCKFREZ)/4 - 1 =BRG
banksel SSPADD
movwf SSPADD
movlw b'10000000' ; Disable slew rate control.
banksel SSPSTAT
movwf SSPSTAT
movlw b'00000000' ;
movwf SSPCON2 ; Setup MSSP for continuous reception.
movlw b'00101000' ; Enable MSSP and setup for I2C master
banksel SSPCON ; mode.
movwf SSPCON
banksel PIR1
movlw 0x00
movwf PIR1
return
I2CSTOP
BANKSEL SSPCON2
bsf SSPCON2, 2
CALL I2CWAIT
BANKSEL 0
RETURN
I2CWAIT
banksel PIR1
FLoop btfss PIR1,SSPIF
goto FLoop
bcf PIR1,SSPIF
return
I2CRESTART
BANKSEL SSPCON2
BSF SSPCON2,RSEN
BCF SSPCON2,ACKSTAT
CALL I2CWAIT
BANKSEL 0
RETURN
I2CSTART
BANKSEL SSPCON2
BSF SSPCON2,SEN
CALL I2CWAIT
BANKSEL 0
RETURN
I2CSEND
BANKSEL 0
MOVWF SSPBUF
CALL I2CWAIT
RETURN
I2CREAD
BANKSEL SSPCON2
BSF SSPCON2, 3
CALL I2CWAIT
MOVF SSPBUF, W
BANKSEL 0
RETURN
I2CACK
BANKSEL SSPCON2
BSF SSPCON2, ACKEN
BCF SSPCON2, ACKDT
CALL I2CWAIT
BANKSEL 0
RETURN
I2CNACK
BANKSEL 1
BSF SSPCON2, ACKEN
BSF SSPCON2, ACKDT
BANKSEL 0
RETURN
;I2CACKSTAT
; BTFSC SSPCON2, 6
; GOTO ACKSTATERROR
; RETLW 0
;*****************************************************
;*********** S.P.I ROUTINE **********************
;*****************************************************
xfer08:
movf OUT1, 0
call xfer8 ; send first byte
; wait
return
xfer16:
movf OUT1, 0
call xfer8 ; send first byte
movf OUT2, 0
call xfer8 ; send second byte
; wait
return
xfer8: movwf TMP1
movlw 0x8
movwf CNT
xfer1:
MOVLW 0X8
MOVWF CNT
RE rlf TMP1, 1 ;rotate MSB of TMP1 into C
bcf PORTA, MOSI ;clear output bit
btfsc STATUS, C ;if rotated-out bit was high,
bsf PORTA, MOSI ;output high bit
nop ;keep time constant
bsf PORTA, SPICLK ;bring clock high
nop
nop
nop
nop
nop
nop
nop
nop ;8x nop to make clock symmetric
bcf PORTA, SPICLK
; this would implement MISO, except that we don't need it.
; bcf STATUS, C ;clear C
; btfsc PORTB, MISO ;test MISO bit
; bsf STATUS, C ;set C if MISO bit set
; nop ;keep time constant
; rlf TMP2, 1 ;rotate carry into TMP2
decfsz CNT, 1
; goto xfer1
GOTO RE
return
DisplayOn
BCf PORTA,CS
BSf PORTA,CS
RETLW 0
ISR
END