1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                                                  ;
;                        Program: Binary to 7 Segment Decoder for DTMF Applications                ;
;                        Author:  Jake Sutherland                                                  ;
;                        Date: Monday 19th April 2010                                              ;
;                                                                                                  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        list            p=pic16f628a
        include         "P16F628A.INC"
        __config _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
        errorlevel      -302    ;Eliminate bank warning

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                                                  ;
;                                   PIC16F628A Microcontroller                                     ;
;                                            ____ ____                                             ;
; Binary input Bit 2          VREF/AN2/RA2 -| 1  - 18 |- RA1/AN1                Binary input Bit 1 ;
; Binary input Bit 3    LED - CPM1/AN3/RA3 -| 2    17 |- RA0/AN0                Binary input Bit 0 ;
; Latch Enable              CMP2/T0CKI/RA4 -| 3    16 |- RA7/OSC1/CLKIN     Ripple Blanking Output ;
; Test Lamp Enable            VPP/MCLR/RA5 -| 4    15 |- RA6/OSC2/CLKOUT     Ripple Blanking Input ;
;                                      VSS -| 5    14 |- VDD                                       ;
; Common Anode/Common Cathode      INT/RB0 -| 6    13 |- RB7/T1OSC1/ICSPDAT              Segment B ;
; Segment C                      DT/RX/RB1 -| 7    12 |- RB6/T1OSCO/T1CLKI/ICSPCLK       Segment A ;
; Segment D                      CK/TX/RB2 -| 8    11 |- RB5                             Segment F ;
; Segment E                       CCP1/RB3 -|_9____10_|- RB4/PGM                         Segment G ;
;                                                                                                  ;
;                                                                                                  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

CBLOCK  H'20'
W_TEMP                                  ; GPR used for context saving
STATUS_TEMP                             ; GPRCused for context saving
BINARYNUM                               ; GPR used for storing Binary Input Digit
DISPLAY_STORE                           ; GPR used for Display Store 
ENDC


        ORG     0x000                   ; Processor reset vector location. On power up, the program jumps here
        GOTO    SETUP                   ; 

        ORG     0x004                   ; Interrupt vector location. When an Interupt occurs, the program jumps here
        MOVWF   W_TEMP                  ; Save current W register contents
        MOVF    STATUS, W               ; Move STATUS register into W register
        MOVWF   STATUS_TEMP             ; Save contents of STATUS register in temporary register

; Interrupt Service Routine goes here. If no interrupts are enabled and triggered during the program, this section can be ignored

        MOVF    STATUS_TEMP, W          ; Retrieve saved status of STATUS register
        MOVWF   STATUS                  ; Restore pre-ISR STATUS register contents
        SWAPF   W_TEMP, F               ; Restore pre-ISR W register contents
        SWAPF   W_TEMP, W               ; (a MOVF W_TEMP, W would acheive the same result but this affects the STATUS register, therefore 2 SWAPF instructions are used)
        RETFIE                          ; Return From Interrupt


BCD7SEG_COMMON_K  ; This routine assigns on/off arrangement to the 7 Segment Display depending on the number
        ADDWF   PCL, F
                               ;BAFGEDCx
        RETLW   B'10011110' ;D
        RETLW   B'10000010' ;1
        RETLW   B'11011100' ;2
        RETLW   B'11010110' ;3
        RETLW   B'10110010' ;4
        RETLW   B'01110110' ;5
        RETLW   B'01111110' ;6
        RETLW   B'11000010' ;7
        RETLW   B'11111110' ;8
        RETLW   B'11110110' ;9
        RETLW   B'11101110' ;0
        RETLW   B'11110000' ;*
        RETLW   B'00011110' ;#
        RETLW   B'11111010' ;A
        RETLW   B'00111110' ;B
        RETLW   B'01101100' ;C
        RETURN

		
BCD7SEG_COMMON_A  ; This routine assigns on/off arrangement to the 7 Segment Display depending on the number
        ADDWF   PCL, F
                               ;BAFGEDCx
        RETLW   B'01100000' ;D
        RETLW   B'01111100' ;1
        RETLW   B'00100010' ;2
        RETLW   B'00101000' ;3
        RETLW   B'01001100' ;4
        RETLW   B'10001000' ;5
        RETLW   B'10000000' ;6
        RETLW   B'00111100' ;7
        RETLW   B'00000000' ;8
        RETLW   B'00001000' ;9
        RETLW   B'00010000' ;0
        RETLW   B'00001110' ;*
        RETLW   B'11100000' ;#
        RETLW   B'00000100' ;A
        RETLW   B'11000000' ;B
        RETLW   B'10010010' ;C
        RETURN


SETUP  ; This rountine sets up the chips Inputs and Outputs
        CLRF    PORTA                   ; Initialise PORT A by setting ouput data latches
        MOVLW   H'07'                   ; Turn Comparators off and enable pins for I/O functions
        MOVWF   CMCON                   ;
        BCF     STATUS, RP1             ; Bank 1
        BSF     STATUS, RP0             ; Bank 1
        MOVLW   B'01111111'             ; RA<7> Output, RA<6:0> Inputs.
        MOVWF   TRISA                   ;

        MOVLW   B'00000001'             ; RB<7:1> Outputs, RB<0> Input.
        MOVWF   TRISB                   ;

        BCF     STATUS, RP1             ; Bank 0
        BCF     STATUS, RP0            ; Bank 0

GETNUM  ; This rountine is to obtain the binary number from PORTA  and store it in a general purpose register (temporary register)
        MOVF    PORTA, W                ; Move PORTA to W
        ANDLW   H'0F'                   ; Mask the upper nibble. This ensures upper nibble is always 0
        MOVWF   BINARYNUM               ; Move the value to a general purpose register (temporary register)
		

TEST_DISP_SELECT  ; This routine tests the Display Type Input pin (Common Cathode or Common Anode)
        BTFSC   PORTB, 0                ; Test 'Display Type Input'
        GOTO    COMMON_K                ; If set, we are using a Common Cathode Display, therefore we CALL 'BCD7SEG_COMMON_K' to load appropiate segments of the display according to the value of PORT A
        CALL    BCD7SEG_COMMON_A        ; If clear, we are using a Common Anode Display, therefore we CALL 'BCD7SEG_COMMON_A' to load appropiate segments of the display according to the value of PORT A
        MOVWF   DISPLAY_STORE           ; This instruction loads appropiate segments as determined by the tables above to a general purpose register (temporary register) for use later
        GOTO    TEST_FOR_0              ; Then we go to the TEST_FOR_0 routine
		

COMMON_K  ; This routine is called if the 'Display Type Input' pin is set. If it is clear, this routine is skipped
        CALL    BCD7SEG_COMMON_K        ; Call rountine to load appropiate segments of the display according to the value of PORT A
        MOVWF   DISPLAY_STORE           ; This instruction loads appropiate segments as determined by the tables above to a general purpose register (temporary register) for use later
        GOTO    TEST_FOR_0              ; Then we go to the TEST_FOR_0 routine
		

TEST_FOR_0  ; This routine is to determine if a zero is displayed
        MOVF    BINARYNUM, W            ; Move the Binary Number to the working register
        XORLW   B'00000000'             ; Binary 00000000 is the number for '0'. By XOR'ing '00000000' with 'BINARYNUM', we can determine if 'BINARYNUM' is equal to zero by testing the 'zero' bit of the STATUS register
        BTFSC   STATUS, Z               ; Test 'zero' bit of STATUS register
        GOTO    CHECK_BLANKING          ; Binary number in BINARYNUM is '0', so we GOTO 'CHECK_BLANKING' to determine whether the Ripple Blanking Input (PORTA,6) is high or low, which will determine whether we display '0' or not
        GOTO    NOT_ZERO                ; Binary number in BINARYNUM is NOT '0', so we GOTO 'NOT_ZERO' and display the number, as well as setting the Ripple Blanking Output (PORTA,7)
		

NOT_ZERO  ; If the inputs are found to NOT = '0', this routine displays the number. This routine is skipped if it IS '0'
        MOVF    DISPLAY_STORE, W        ; Move the segment arragement to the working register
        MOVWF   PORTB                   ; Move the W register to PORTB
        BSF     PORTA, 7                ; Set the 'Ripple Blanking Output'
        GOTO    LATCH                   ; Test if Latch enabled
		

CHECK_BLANKING  ; If the input IS found to = '0', this routine checks the Ripple Blanking Input to determine whether to display the '0' or not (if not, it will clear the display)
        BTFSC   PORTA, 6                ; Test the 'Ripple Blanking Input'. Skip GOTO if clear
        GOTO    NO_BLANK                ; Ripple Blanking Input set so dont blank the number '0'
        BTFSC   PORTB, 0                ; Test 'Display Type Input'. If CC, execute next instruction. If CA skip next instruction
        MOVLW   H'00'                   ; 0x00 is to clear the display if a CC display is used
        BTFSS   PORTB, 0                ; ( Two 'BTFSC PORTB,0' statements prevents having to create another subroutine just to load 1 value with 1 instruction. It can be done like this)
        MOVLW   H'FF'                   ; 0xFF is to clear the display if a CA display is used
        MOVWF   PORTB                   ; 7 Segment display is connected to PORTB
        BCF     PORTA, 7                ; Clear Ripple Blanking Output
        GOTO    LATCH                   ; Test if Latch enabled
		

NO_BLANK  ; This rountine is exectuced if the RBI is HIGH, therefore '0' is displayed
        MOVF    DISPLAY_STORE, W        ; Move the segment arragement to the working register
        MOVWF   PORTB                   ; Move the W register to PORTB
        BSF     PORTA, 7                ; Set the Ripple Blanking Output
        GOTO    LATCH                   ; Test if Latch enabled
		

LATCH  ; This routine checks the LATCH. Active Low
        BTFSS   PORTA, 4                ; Test LATCH
        BSF     PORTA, 7                ; If LATCH enabled, set the Ripple Blanking Output. If LATCH disabled, skip
        BTFSS   PORTA, 4                ; Test LATCH
        GOTO    LATCH                   ; If LATCH enabled, GOTO LATCH and test again. If LATCH disabled, skip 
		

TEST_LAMP  ; This routine checks the TEST LAMP input
        BTFSC   PORTA, 5                ; Test input pin
        GOTO    GETNUM                  ; If set, Start again, test for Binary Number on PORTA
        MOVLW   H'08'                   ; If input clear, set all segments on LED display
        MOVWF   BINARYNUM               ; Move 11111111 to PORTB
        GOTO    TEST_DISP_SELECT        ; GOTO TEST_LAMP to check if pin state changed
		

END