; main.asm: PF Clock Main Program ; Copyright (c) 2008 Eric Schlaepfer. ; This work is licensed under a Creative Commons ; Attribution-NonCommercial 3.0 Unported License. ; See http://creativecommons.org/licenses/by-nc/3.0/ ; ; V 0.1 ; ; Version History ; ; 0.1 ; Initial Version ; --A-- ; | | ; F B ; | | ; --G-- ; | | ; E C ; | | ; --D-- ;-----Chip pin assignments----- ; RA0 - Minute One's Digit Switch ; RA1 - Minute Ten's Digit Switch ; RA2 - Hour One's Digit Switch ; RA3 - Hour Ten's Digit Switch ; RA4 - Not used ; RA5 - PM Indicator ; RB0 - Interrupt pin from DS3231 ; RB1 - KF ; RB2 - KG ; RB3 - KE ; RB4 - KD ; RB5 - KC ; RB6 - KB ; RB7 - KA ; RC0 - External Crystal ; RC1 - External Crystal ; RC2 - Digit 1 anode ; RC3 - SCL from DS3231 ; RC4 - SDA from DS3231 ; RC5 - Digit 2 anode ; RC6 - Digit 3 anode ; RC7 - Digit 4 anode #include #define MAIN_Source DELAY_ID EQU .2 ; Inter digit blanking delay DELAY_OD EQU .200 ; Digit on time DEBOUNCE_I EQU .230 ; Initial debounce delay (255-x) DEBOUNCE_R EQU .100 ; Repeat delay (255-x) ;#define DEVELOP ; OSC=HSPLL XT config OSC = HSPLL, PWRT = ON, BOREN = ON, BORV = 3 config WDT = OFF, WDTPS = 1, LVP = OFF, MCLRE = ON config PBADEN = OFF, STVREN = ON #ifdef DEVELOP config DEBUG = ON, CP0 = OFF, CP1 = OFF, CPB = OFF, CPD = OFF #else config DEBUG = OFF, CP0 = ON, CP1 = ON, CPB = ON, CPD = ON #endif config WRT0 = OFF, WRT1 = OFF, WRTB = OFF, WRTC = OFF, WRTD = OFF config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF config LPT1OSC = OFF ; Variables udata_acs ; Storage for flags and random stuff Temp res 1 ; Temporary storage Temp2 res 1 Debounce res 1 W_Temp res 1 STATUS_Temp res 1 BSR_Temp res 1 seconds res 1 minones res 1 mintens res 1 hourones res 1 hourtens res 1 v_reset code 0x0000 ; Reset Vector goto Main v_int code 0x0008 ; Interrupt Routine movwf W_Temp movff STATUS, STATUS_Temp movff BSR, BSR_Temp bsf TMR1H, 7 ; Preload timer bcf PIR1, TMR1IF call BCDIncr ; Increment by 1 second movff BSR_Temp, BSR movf W_Temp, w movff STATUS_Temp, STATUS retfie code ; ; Increments the time ; BCDIncr incf seconds movlw .60 cpfseq seconds return clrf seconds incf minones, f movlw .10 cpfseq minones return clrf minones incf mintens, f movlw .6 cpfseq mintens return clrf mintens incf hourones, f movlw .2 cpfseq hourones bra Cont btfsc hourtens, 0 btg hourtens, 1 Cont movlw .10 btfsc hourtens, 0 movlw .3 cpfseq hourones return clrf hourones btfsc hourtens, 0 incf hourones btg hourtens, 0 return ; ; Subroutine initializes the chip ; Initialize ; Clear access RAM clrf FSR0L, 0 clrf FSR0H, 0 CMLoop clrf POSTINC0, 0 movlw H'7F' subwf FSR0L, w, 0 bnz CMLoop ; Initialize misc chip registers movlw B'00000000' movwf INTCON movlw B'00000000' movwf INTCON2 movlw B'00000000' movwf INTCON3 movlw B'00000000' movwf PIE1 movwf PIE2 movlw B'00000000' movwf IPR1 movwf IPR2 movwf RCON movlw B'00001111' movwf ADCON1 movlw B'00000111' movwf CMCON movlw B'11000001' movwf T0CON ; Initialize ports clrf PORTC clrf PORTB clrf PORTA movlw B'00001111' ; Use several analog inputs movwf TRISA movlw B'00000001' ; RB0/INT is timer int movwf TRISB movlw B'00000000' movwf TRISC ; Initialize clock interrupt movlw 80h movwf TMR1H clrf TMR1L movlw B'00001111' movwf T1CON bsf PIE1, TMR1IE bcf RCON, 7 movlw B'01000000' movwf INTCON ; Begin bsf INTCON, GIE return ; ; Where we begin ; Main call Initialize ; Initialize chip clrf seconds clrf minones clrf mintens movlw .2 movwf hourones movlw .3 movwf hourtens ; 12:00PM MainLoop ; Update display call Display btfsc hourtens, 1 bsf LATA, 5 btfss hourtens, 1 bcf LATA, 5 ; Check the buttons call CheckButtons bra MainLoop ; ; Checks the buttons and does the debounce ; CheckButtons ; Check buttons and debounce them movf PORTA, w andlw B'00001111' xorlw B'00001111' movwf Temp tstfsz Temp bra ButtonDown movlw DEBOUNCE_I ; Initial debounce is 255 - 200 movwf Debounce return ; All buttons up ButtonDown incfsz Debounce return ; Still debouncing movlw DEBOUNCE_R ; Repeat debounce is 255 - 100 movwf Debounce ; Which button was pushed? btfsc Temp, 3 bra IncHourTens btfsc Temp, 2 bra IncHourOnes btfsc Temp, 1 bra IncMinTens btfsc Temp, 0 bra IncMinOnes return ; We shouldn't get here... IncHourTens incf hourtens movlw .3 andwf hourtens ; Mask off so we go 0-4 btfsc hourtens, 0 goto IncHourTensAlt tstfsz hourones ; If hour tens is zero, ones cannot be zero return incf hourones ; If not, then set to one return IncHourTensAlt movlw .3 ; If hour tens is one, ones must be 0 to 2. cpfslt hourones clrf hourones ; If not, well, then set to zero return IncHourOnes btfsc hourtens, 0 goto IncHourOnesAlt movlw .9 ; If hourtens is 0 then range is 1 to 9 cpfslt hourones clrf hourones incf hourones return IncHourOnesAlt incf hourones movlw .3 ; If hourtens is 1 then range is 0 to 2 cpfslt hourones clrf hourones return IncMinTens incf mintens movlw .6 cpfslt mintens clrf mintens return IncMinOnes incf minones movlw .10 cpfslt minones clrf minones return ; ; Multiplex Display Routine ; Display movf hourtens, w andlw B'00000001' call NumTableZS movwf LATB bsf LATC, 2 ; Do digit 1 call Delay_DO bcf LATC, 2 clrf LATB call Delay_ID movf hourones, w call NumTable movwf LATB bsf LATC, 5 ; Do digit 2 call Delay_DO bcf LATC, 5 clrf LATB call Delay_ID movf mintens, w call NumTable movwf LATB bsf LATC, 6 ; Do digit 3 call Delay_DO bcf LATC, 6 clrf LATB call Delay_ID movf minones, w call NumTable movwf LATB bsf LATC, 7 ; Do digit 4 call Delay_DO bcf LATC, 7 clrf LATB call Delay_ID return ; ; Inter Digit Delay (1/2) ; Delay_ID movlw DELAY_ID ; 10 - 25 call Delay return ; ; Digit On Delay ; Delay_DO movlw DELAY_OD ;100 - 250 call Delay return ; ; Regular Delay. Pass in W units of 2us ; Delay movwf Temp2 DelayLoopI ; 10 cycles per loop. At 10MHz, this is 2us per loop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop decfsz Temp2, f goto DelayLoopI return ; ; 7-Segment Table Lookup ; NumTableZS btfss STATUS, Z bra NumTable retlw 0 NumTable andlw B'1111' movwf TBLPTRL rlncf TBLPTRL, w addlw LOW NumTableData movwf TBLPTRL movlw B'10000000' movwf EECON1 movlw UPPER NumTableData movwf TBLPTRU movlw HIGH NumTableData movwf TBLPTRH TBLRD*+ movf TABLAT, w return NumTableData db B'11111010' ;0 db B'01100000' ;1 db B'11011100' ;2 db B'11110100' ;3 db B'01100110' ;4 db B'10110110' ;5 db B'10111110' ;6 db B'11100000' ;7 db B'11111110' ;8 db B'11110110' ;9 db B'00000000' db B'00000000' db B'00000000' db B'00000000' db B'00000000' db B'00000000' END