LIST p=16F876 ;tell assembler what chip we are using
include "P16F876a.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3939 ;sets the configuration settings (oscillator type etc.)
#define SCL PORTA,1 ; bus clock line I2C
#define SDA PORTA,4 ; bus data line I2C
#define ENABLE PORTA,2 ;ENABLE LED 74HC595N
cblock 0x20 ;start of general purpose registers
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
zero ;zero storage
one ;one storage
two ;two storage
three ;three storage
four ;four storage
five ;five storage
six ;six storage
seven ;seven storage
zero1 ;zero storage
one1 ;one storage
two1 ;two storage
three1 ;three storage
four1 ;four storage
five1 ;five storage
six1 ;six storage
seven1 ;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
ROW_PORT Equ PORTB ;row port
ROW_TRIS Equ TRISB
COL_PORT Equ PORTC ;column port
COL_TRIS Equ TRISC
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
movf PCLATH,w
movwf p_temp ; Save PCLATH
btfss PIR1,TMR2IF ; Flag set if TMR2 interrupt
goto INTX ; Jump if not timed out
; Timer (TMR2) timeout
bcf PIR1,TMR2IF ; Clear the calling flag
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 zero, w
CALL SEND_OUT
bcf row_pos, 0
MOVLW b'11111110'
CALL SEND_OUT
call DISPLAYON
goto INTX
Do_One
movlw 0xFF
movwf row_pos
movf one, w
CALL SEND_OUT
bcf row_pos, 1
MOVLW b'11111101'
CALL SEND_OUT
call DISPLAYON
goto INTX
Do_Two
movlw 0xFF
movwf row_pos
movf two, w
CALL SEND_OUT
bcf row_pos, 2
MOVLW b'11111011'
CALL SEND_OUT
call DISPLAYON
goto INTX
Do_Three
movlw 0xFF
movwf row_pos
movf three, w
CALL SEND_OUT
bcf row_pos, 3
MOVLW b'11110111'
CALL SEND_OUT
call DISPLAYON
goto INTX
Do_Four
movlw 0xFF
movwf row_pos
movf four, w
CALL SEND_OUT
bcf row_pos, 4
MOVLW b'11101111'
CALL SEND_OUT
call DISPLAYON
goto INTX
Do_Five
movlw 0xFF
movwf row_pos
movf five, w
CALL SEND_OUT
bcf row_pos, 4
MOVLW b'11011111'
CALL SEND_OUT
call DISPLAYON
goto INTX
Do_Six
movlw 0xFF
movwf row_pos
movf six, w
CALL SEND_OUT
bcf row_pos, 4
MOVLW b'10111111'
CALL SEND_OUT
call DISPLAYON
goto INTX
Do_Seven
movlw 0xFF
movwf row_pos
movf seven, w
CALL SEND_OUT
bcf row_pos, 4
MOVLW b'01111111'
CALL SEND_OUT
call DISPLAYON
goto INTX
INTX
movf p_temp,W
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
retfie
;program initialisation
START
BANKSEL ADCON1 ;disable analogue inputs
movlw 0x06 ;turn off a/d
movwf ADCON1
BANKSEL PORTA
bsf STATUS, RP0 ;select bank 1
movlw b'00000000' ;Set port data directions, data output
movwf ROW_TRIS
movwf COL_TRIS
MOVLW 0XC0
MOVWF SSPSTAT
MOVLW B'00000111'
MOVWF OPTION_REG
bcf STATUS, RP0 ;select bank 0
clrf COL_PORT ;turn OFF all LED's
movlw 0xFF
movwf ROW_PORT
MOVLW 0X20
MOVWF SSPCON
movlw 0x01
movwf row_pos
call Clear ;clear display registers
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 0
;main program loop
Main
bcf INTCON,PEIE ; disable all peripheral interrupts
bcf INTCON,GIE ; Global interrupt disable
bsf STATUS, RP0 ;select bank 1
bcf PIE1,TMR2IE ; disable TMR2 interrupt
bcf STATUS, RP0 ;select bank 0
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
clrf TEN
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 Delay255
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 zero ;clear display storage
clrf one
clrf two
clrf three
clrf four
clrf five
clrf six
clrf seven
return
DOUBLEDOT
movlw 0x00
movwf zero1
movlw 0X18
movwf one1
movlw 0x18
movwf two1
movlw 0x00
movwf three1
movlw 0x00
movwf four1
movlw 0x18
movwf five1
movlw 0x18
movwf six1
movlw 0x00
movwf seven1
return
DOT
movlw 0x00
movwf zero1
movlw 0X18
movwf one1
movlw 0x18
movwf two1
movlw 0x00
movwf three1
movlw 0x00
movwf four1
movlw 0x00
movwf five1
movlw 0x00
movwf six1
movlw 0x00
movwf seven1
return
Load_Zero movlw 0x00
movwf zero1
movlw 0x38
movwf one1
movlw 0x44
movwf two1
movlw 0x4C
movwf three1
movlw 0x54
movwf four1
movlw 0x64
movwf five1
movlw 0x44
movwf six1
movlw 0x38
movwf seven1
return
Load_One movlw 0x00
movwf zero1
movlw 0x38
movwf one1
movlw 0x10
movwf two1
movlw 0x10
movwf three1
movlw 0x10
movwf four1
movlw 0x10
movwf five1
movlw 0x30
movwf six1
movlw 0x10
movwf seven1
return
Load_Two movlw 0x00
movwf zero1
movlw 0x7C
movwf one1
movlw 0x20
movwf two1
movlw 0x10
movwf three1
movlw 0x08
movwf four1
movlw 0x04
movwf five1
movlw 0x44
movwf six1
movlw 0x38
movwf seven1
return
Load_Three movlw 0x00
movwf zero1
movlw 0x38
movwf one1
movlw 0x44
movwf two1
movlw 0x04
movwf three1
movlw 0x08
movwf four1
movlw 0x10
movwf five1
movlw 0x08
movwf six1
movlw 0x7C
movwf seven1
return
Load_Four movlw 0x00
movwf zero1
movlw 0x08
movwf one1
movlw 0x08
movwf two1
movlw 0x7C
movwf three1
movlw 0x48
movwf four1
movlw 0x28
movwf five1
movlw 0x18
movwf six1
movlw 0x08
movwf seven1
return
Load_Five movlw 0x00
movwf zero1
movlw 0x38
movwf one1
movlw 0x44
movwf two1
movlw 0x04
movwf three1
movlw 0x04
movwf four1
movlw 0x78
movwf five1
movlw 0x40
movwf six1
movlw 0x7C
movwf seven1
return
Load_Six movlw 0x00
movwf zero1
movlw 0x38
movwf one1
movlw 0x44
movwf two1
movlw 0x44
movwf three1
movlw 0x78
movwf four1
movlw 0x40
movwf five1
movlw 0x20
movwf six1
movlw 0x18
movwf seven1
return
Load_Seven movlw 0x00
movwf zero1
movlw 0x20
movwf one1
movlw 0x20
movwf two1
movlw 0x20
movwf three1
movlw 0x10
movwf four1
movlw 0x08
movwf five1
movlw 0x04
movwf six1
movlw 0x7C
movwf seven1
return
Load_Eight movlw 0x00
movwf zero1
movlw 0x38
movwf one1
movlw 0x44
movwf two1
movlw 0x44
movwf three1
movlw 0x38
movwf four1
movlw 0x44
movwf five1
movlw 0x44
movwf six1
movlw 0x38
movwf seven1
return
Load_Nine movlw 0x00
movwf zero1
movlw 0x30
movwf one1
movlw 0x08
movwf two1
movlw 0x04
movwf three1
movlw 0x3C
movwf four1
movlw 0x44
movwf five1
movlw 0x44
movwf six1
movlw 0x38
movwf seven1
return
ScrollL8 call ScrollL
call Delay20
call ScrollL
call Delay20
call ScrollL
call Delay20
call ScrollL
call Delay20
call ScrollL
call Delay20
call ScrollL
call Delay20
call ScrollL
call Delay20
call ScrollL
call Delay20
return
ScrollL bcf STATUS, C
rlf zero1, f
rlf zero, f
bcf STATUS, C
rlf one1, f
rlf one, f
bcf STATUS, C
rlf two1, f
rlf two, f
bcf STATUS, C
rlf three1, f
rlf three, f
bcf STATUS, C
rlf four1, f
rlf four, f
bcf STATUS, C
rlf five1, f
rlf five, f
bcf STATUS, C
rlf six1, f
rlf six, f
bcf STATUS, C
rlf seven1, f
rlf seven, f
return
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_wr:
call I2CSTART
movlw 0D0h ; slave address + write
call write_RTC
movlw 0 ; set word address to seconds register
call write_RTC
movf SEC, W
call write_RTC
movf MINS, W
call write_RTC
movf HRS, W
call write_RTC
movf DOW, W
call write_RTC
movf DAYS, W
call write_RTC
movf MON, W
call write_RTC
movf YRS, W
call write_RTC
call I2CSTOP
return
RTC_brst_rd:
call I2CSTART
movlw 0D0h ; slave address + write
call write_RTC
movlw 0X00 ; set word address to seconds register
call write_RTC
call I2CSTART
movlw 0D1h ; slave address + read
call write_RTC
call read_RTC ; read the seconds data
movwf SEC ; save it
call ack;
call read_RTC ; and so on
movwf MINS
call ack;
call read_RTC
movwf HRS
call ack;
call read_RTC
movwf DOW
call ack;
call read_RTC
movwf DAYS
call ack;
call read_RTC
movwf MON
call ack;
call read_RTC
movwf YRS
call nack;
call I2CSTOP
return
;---- Read RTC into W ----
read_RTC:
call SET_BANK1
bsf TRISA,4 ; set SDA for input
call SET_BANK0
movlw 08h ; send 8 bits
movwf COUNT
bcf SCL ; clock data out
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
clrf TMP ; clear var
rlf TMP, 1 ; rotate carry in
clrf TMP ; clear var again
I2C_read_loop:
rlf TMP, 1
call SET_BANK1
bsf TRISA, 1 ; SCL high (input)
call SET_BANK0
btfsc SDA
bsf TMP, 0 ; if data out = 1, set bit
bcf SCL
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
decfsz COUNT, 1
goto I2C_read_loop
movf TMP, W
return
;---- ACK read (assumes SCL=0 on entry) ----
ack:
bcf SDA
call SET_BANK1
bcf TRISA,4 ; set SDA for output
call SET_BANK0
call SET_BANK1
bsf TRISA, 1 ; SCL high (input)
call SET_BANK0
nop
bcf SCL
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
return
;---- NACK read (assumes SCL = 0 on entry) ----
nack:
bsf SDA
call SET_BANK1
bcf TRISA,4 ; set SDA for output
call SET_BANK0
call SET_BANK1
bsf TRISA, 1 ; SCL high (input)
call SET_BANK0
bcf SCL
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
return
;--- Write the byte in W to RTC ---
;---- assumes CE is asserted ----
write_RTC:
movwf TMP ;Save the data
;
;--- Do a I2C bus write of byte in 'TMP' ---
;
I2C_write:
call SET_BANK1
bcf TRISA, 4 ; set SDA for output
call SET_BANK0
movlw 08h ; send 8 bits
movwf COUNT
bcf SCL
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
I2C_w_loop:
bcf SDA ; assume data out is low
btfsc TMP, 7
bsf SDA ; if data out = 1, set bit
; nop
call SET_BANK1
bsf TRISA, 1 ; SCL high (input)
call SET_BANK0
rlf TMP, 1
bcf SCL ; clock it in
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
decfsz COUNT, 1
goto I2C_w_loop
call SET_BANK1
bsf TRISA,4 ; set SDA for input
call SET_BANK0
bcf SCL
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
; nop
call SET_BANK1
bsf TRISA, 1 ; SCL high (input)
call SET_BANK0
; if(sda) printf("Ack bit missing %02X\n",(unsigned int)d);
bcf SCL
call SET_BANK1
bcf TRISA, 1 ; SCL low (output)
call SET_BANK0
return
I2CSTART
bsf SDA ; SDA high
nop
call SET_BANK1
bsf TRISA, 1 ; SCL high (input)
call SET_BANK0
bcf SDA ; SDA low (start)
return
I2CSTOP ; assumes SCL is high on entry
bcf SDA ; SDA low
nop
nop
call SET_BANK1
bsf TRISA, 1 ; SCL high (input)
call SET_BANK0
bsf SDA ; SDA high
return
SET_BANK0
bcf STATUS, RP0
bcf STATUS, RP1
return
SET_BANK1
bsf STATUS, RP0
bcf STATUS, RP1
return
;******************************************************
;****************SPI ROUTE*****************************
;******************************************************
SEND_OUT
BCF PIR1,SSPIF
MOVWF SSPBUF
TEST_BF
BTFSS PIR1,SSPIF
GOTO TEST_BF
RETLW 0
DISPLAYON
BCf ENABLE
BSf ENABLE
RETURN
END