MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 1 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00001 ;;; LEDDRVR.ASM 00002 ;;; Copyright (c) 2002, TundraWare Inc., All Rights Reserved 00003 ;;; 00004 ;;; Program to drive homemade 4-digit LED display board 00005 ;;; 00006 ;;; $Id: leddrvr.asm,v 1.13 2002/03/25 16:55:26 tundra Exp tundra $ 00007 00008 list p=16F84A 00009 include <P16F84A.INC> 00001 LIST 00002 ; P16F84A.INC Standard Header File, Version 2.00 Microchip Technology, Inc. 00134 LIST 00010 00011 errorlevel -302 ;suppress bank selection messages 2007 3FF1 00012 __config 3ff1h ;xt osc, WDT off 2000 0001 0002 0003 00013 __idlocs 1234 0004 00014 00015 ;;;;;;;;;; 00016 ;;; Device Constants 00017 ;;;;;;;;;; 00018 00000000 00019 tmr2 equ 00H ; TMR0 prescaler constants 00000001 00020 tmr4 equ 01H 00000002 00021 tmr8 equ 02H 00000003 00022 tmr16 equ 03H 00000004 00023 tmr32 equ 04H 00000005 00024 tmr64 equ 05H 00000006 00025 tmr128 equ 06H 00000007 00026 tmr256 equ 07H 00027 00028 00029 ;;;;;;;;;; 00030 ;;; Circuit Constants 00031 ;;;;;;;;;; 00032 00000004 00033 num_led equ 4 ; total number of LEDs 000000F0 00034 led_sel_mask equ 0f0H ; bits not used for LED == 1 00000005 00035 led_sel equ PORTA 00000006 00036 seg_sel equ PORTB 00037 00038 ;;;;;;;;;; 00039 ;;; Program Contants 00040 ;;;;;;;;;; 00041 00042 ;;; TMR0 related stuff 00043 ;;; 00044 ;;; With a 4MHz clock, the basic cycle type is 1/4 this or 1us. 00045 ;;; The TMR0 interrupt interrupt interval is thus: 00046 ;;; 00047 ;;; 1us * prescaler factor * tmr0_count 00048 ;;; 00049 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 2 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00050 ;;; TMR0 interrupt every 1ms 00051 00000006 00052 tmr0_count equ D'256'-D'250' ; set for 1ms interrupt interval 00000001 00053 tmr0_pre equ tmr4 ; prescaler factor 00054 00055 00056 ;;; wait delays: delay time = value(s) below * TMR0 interrupt rate 00057 00000064 00058 count_delay equ D'100' ; 100ms delay between counts 00059 00060 00061 ;;;;;;;;;; 00062 ;;; Register File Assignments 00063 ;;;;;;;;;; 00064 00065 CBLOCK 0cH 0000000C 00066 _fsr ; context save area 0000000D 00067 _pclath 0000000E 00068 _status 0000000F 00069 _w 00070 00000010 00071 dsply_val:2 ; array of values to display 00072 ; 2 LEDs per byte 00073 00000012 00074 current_led ; currently displayed LED 00075 ; 0 <= current_led < num_led 00076 00000013 00077 wait_count ; time delay counter variable 00078 00000014 00079 temp ; temp storage during calculation 00080 ENDC 00081 00082 00083 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00084 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 3 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00085 PAGE 00086 ;;;;;;;;;; 00087 ;;; Power-On Entry Point 00088 ;;;;;;;;;; 00089 0000 00090 org 00H 00091 0000 2825 00092 goto main 00093 00094 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00095 00096 ;;;;;;;;;; 00097 ;;; Interrupt Handler 00098 ;;;;;;;;;; 00099 0004 00100 org 04H 00101 0004 008F 00102 movwf _w ; save context 0005 0803 00103 movfw STATUS 0006 1303 00104 bcf STATUS,RP1 0007 1283 00105 bcf STATUS,RP0 0008 008E 00106 movwf _status 0009 0804 00107 movfw FSR 000A 008C 00108 movwf _fsr 000B 080A 00109 movfw PCLATH 000C 008D 00110 movwf _pclath 000D 018A 00111 clrf PCLATH 00112 00113 ; Figure out who interrupted and service it 00114 000E 190B 00115 btfsc INTCON,T0IF ; did we get a TMR0 interrupt? 000F 2811 00116 goto svc_tmr0 ; yup 0010 281C 00117 goto restore_context ; nope 00118 00119 ; TMR0 ISR 0011 00120 svc_tmr0: 0011 110B 00121 bcf INTCON,T0IF ; clear the interrupt condition 0012 3006 00122 movlw tmr0_count ; prime the counter 0013 0081 00123 movwf TMR0 0014 018B 00124 clrf INTCON ; Enable *just* this interrupt 0015 168B 00125 bsf INTCON,T0IE ; to maintain timing accuracy 0016 178B 00126 bsf INTCON,GIE 00127 00128 ; Update the wait timer if it is in use 00129 ; Only do this on TMR0 interrupts so timing is predictable 00130 0017 0813 00131 movfw wait_count 0018 1D03 00132 btfss STATUS,Z ; non-zero count means 'in use' 0019 0393 00133 decf wait_count,F ; decrement current count 00134 ; not in-use, fall through to next code 00135 001A 2040 00136 call display_led ; then display it 001B 281C 00137 goto restore_context ; goto here (instead of just falling MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 4 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00138 ; through) allows other ISRs 00139 ; to later be added immediately 00140 ; following 00141 001C 00142 restore_context: 001C 080D 00143 movfw _pclath ; restore entry context 001D 008A 00144 movwf PCLATH 001E 080C 00145 movfw _fsr 001F 0084 00146 movwf FSR 0020 080E 00147 movfw _status 0021 0083 00148 movwf STATUS 0022 0E8F 00149 swapf _w,F ; get W back w/o changing Z flag 0023 0E0F 00150 swapf _w,W 00151 0024 0009 00152 retfie ; all done 00153 00154 ; End of interrupt handler 00155 00156 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00157 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 5 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00158 PAGE 00159 ;;;;;;;;;; 00160 ;;; Main program logic 00161 ;;;;;;;;;; 00162 0025 00163 main: 0025 205F 00164 call init ; initialize the system 0026 00165 run: 0026 205B 00166 call incr_count 0027 3064 00167 movlw count_delay 0028 2073 00168 call wait ; slow down displayed count 0029 2826 00169 goto run 00170 00171 ;;; End of main logic 00172 00173 00174 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00175 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 6 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00176 PAGE 00177 ;;;;;;;;;; 00178 ;;; Data & Tables 00179 ;;;;;;;;;; 00180 00181 ;;;;;;;;;; 00182 ;;; Hex Digit-to-Segment lookup table 00183 ;;;;;;;;;; 00184 00185 002A 0782 00186 hex_7seg addwf PCL,F 002B 343F 00187 DT 03fH ; 0 002C 3406 00188 DT 006H ; 1 002D 345B 00189 DT 05bH ; 2 002E 344F 00190 DT 04fH ; 3 002F 3466 00191 DT 066H ; 4 0030 346D 00192 DT 06dH ; 5 0031 347D 00193 DT 07dH ; 6 0032 3407 00194 DT 007H ; 7 0033 347F 00195 DT 07fH ; 8 0034 3467 00196 DT 067H ; 9 0035 3477 00197 DT 077H ; A 0036 347C 00198 DT 07cH ; B 0037 3458 00199 DT 058H ; C 0038 345E 00200 DT 05eH ; D 0039 3479 00201 DT 079H ; E 003A 3471 00202 DT 071H ; F 00203 00204 00205 ;;;;;;;;;; 00206 ;;; Table used to translate LED position to equivalent led_sel 00207 ;;; bit pattern for that LED. It is assumed that any routine using 00208 ;;; this table will properly preserve higher-order bits not needed for 00209 ;;; LED selection. 00210 ;;;;;;;;;; 00211 003B 00212 led_lookup: 003B 0782 00213 addwf PCL,F 003C 3401 00214 DT 01H ; LED0 == LSD 003D 3402 00215 DT 02H ; LED1 003E 3404 00216 DT 04H ; LED2 003F 3408 00217 DT 08H ; LED3 00218 00219 ;;; End of 'led_lookup' 00220 00221 00222 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00223 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 7 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00224 PAGE 00225 ;;;;;;;;;; 00226 ;;; Supporting Subroutines 00227 ;;;;;;;;;; 00228 00229 00230 ;;;;;;;;;; 00231 ;;; Display LEDs, one per call, from MSD->LSD 00232 ;;; This effectively multiplexes across all the LEDs 00233 ;;; when called repeatedly. 00234 ;;;;;;;;;; 00235 0040 00236 display_led: 00237 ; clear last displayed digit 00238 0040 30F0 00239 movlw led_sel_mask ; clear out LED selection bits only 0041 0585 00240 andwf led_sel,F 0042 0186 00241 clrf seg_sel ; all segments off 00242 00243 ; compute and set the segments to display for this digit 00244 0043 0812 00245 movfw current_led ; convert current_led into an 0044 0084 00246 movwf FSR ; offset from base of display storage 0045 1003 00247 bcf STATUS,C ; don't rotate C into calc below 0046 0C84 00248 rrf FSR,F ; /2 - two digits stored in each byte 0047 3010 00249 movlw dsply_val ; base of array containing display vals 0048 0784 00250 addwf FSR,F ; point to desired value 0049 0800 00251 movfw INDF ; and get contents 004A 0094 00252 movwf temp ; store temporarily 004B 1812 00253 btfsc current_led,0 ; even or odd nibble 004C 0E94 00254 swapf temp,F ; odd==hi nibble -> low nibble 004D 0814 00255 movfw temp ; get it 004E 390F 00256 andlw 0fH ; mask off high nibble 004F 202A 00257 call hex_7seg ; convert to equivalent seg pattern 0050 0086 00258 movwf seg_sel ; and turn 'em on 00259 00260 ; select the corresponding LED 00261 0051 0812 00262 movfw current_led ; offset into lookup table 0052 203B 00263 call led_lookup 0053 0485 00264 iorwf led_sel,F ; turn on these LED selection bits 00265 00266 ; determine next LED to display 00267 0054 0812 00268 movfw current_led ; get LED just displayed 0055 1D03 00269 btfss STATUS,Z ; was it the LSD? 0056 2859 00270 goto set_next ; nope 0057 3004 00271 movlw num_led ; yup, start again w/MSD 0058 0092 00272 movwf current_led 0059 00273 set_next: 0059 0392 00274 decf current_led,F ; pickup next digit to right 005A 0008 00275 return 00276 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 8 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00277 ; End of 'display_led' 00278 00279 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 9 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00280 PAGE 00281 ;;;;;;;;;; 00282 ;;; Increment current count by 1 00283 ;;;;;;;;;; 00284 005B 00285 incr_count: 005B 0F90 00286 incfsz dsply_val,F ; count up 005C 0008 00287 return 005D 0A91 00288 incf dsply_val+1,F 005E 0008 00289 return 00290 00291 ;;; End of 'incr_count' 00292 00293 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 10 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00294 PAGE 00295 ;;;;;;;;;; 00296 ;;; Initialize hardware and software at startup as needed. 00297 ;;; Returns with register bank 0 selected. 00298 ;;;;;;;;;; 00299 005F 00300 init: 005F 018B 00301 clrf INTCON ; all interrupts off, flags cleared 00302 00303 ; setup control registers 00304 0060 168B 00305 bsf INTCON,T0IE ; unmask TMR0 interrupts 0061 1683 00306 bsf STATUS,RP0 ; select register bank 1 0062 0185 00307 clrf TRISA ; set PORTA to all outputs 0063 0186 00308 clrf TRISB ; set PORTB to all outputs 0064 0181 00309 clrf OPTION_REG ; TMR0 selected w/ internal clock 00310 ; don't care about RBPU, INTEDG 0065 3001 00311 movlw tmr0_pre ; set TMR0 prescaler value 0066 0481 00312 iorwf OPTION_REG,F 0067 1283 00313 bcf STATUS,RP0 ; select register bank 0 00314 00315 ; setup program variables 00316 0068 0190 00317 clrf dsply_val ; start count at 0 0069 0191 00318 clrf dsply_val+1 00319 006A 3006 00320 movlw tmr0_count ; prime the counter 006B 0081 00321 movwf TMR0 00322 006C 3003 00323 movlw num_led-1 ; start displaying with MSD 006D 0092 00324 movwf current_led 00325 006E 30F0 00326 movlw led_sel_mask ; clear out LED selection bits only 006F 0585 00327 andwf led_sel,F 0070 0186 00328 clrf seg_sel ; no segments to display yet 00329 0071 178B 00330 bsf INTCON,GIE ; enable unmasked interrupts 0072 0008 00331 return 00332 00333 ;;; End of 'init' 00334 00335 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 11 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00336 PAGE 00337 ;;;;;;;;;; 00338 ;;; Kill time - Outter loop constant passed in W. 00339 ;;;;;;;;;; 00340 0073 00341 wait: 0073 0093 00342 movwf wait_count ; this will be decremented in ISR 0074 00343 loop: 0074 0813 00344 movfw wait_count ; get current count 0075 1D03 00345 btfss STATUS,Z ; see if we counted all the way down 0076 2874 00346 goto loop ; not done, keep waiting 0077 0008 00347 return ; all done 00348 00349 ;;; End of 'wait' 00350 00351 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 12 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00352 PAGE 00353 ;;;;;;;;;; 00354 ;;; EEPROM Contents 00355 ;;;;;;;;;; 00356 2100 00357 org 2100h 00358 2100 0043 006F 0070 00359 DE "Copyright 2002, TundraWare Inc. All Rights Reserved." 0079 0072 0069 0067 0068 0074 0020 0032 0030 0030 0032 002C 0020 0054 0075 006E 0064 0072 0061 0057 0061 0072 0065 0020 0049 006E 0063 002E 0020 0020 0041 006C 006C 0020 0052 0069 0067 0068 0074 0073 0020 0052 0065 0073 0065 0072 007 00360 END MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 13 SYMBOL TABLE LABEL VALUE C 00000000 DC 00000001 EEADR 00000009 EECON1 00000088 EECON2 00000089 EEDATA 00000008 EEIE 00000006 EEIF 00000004 F 00000001 FSR 00000004 GIE 00000007 INCFILES ../include INDF 00000000 INTCON 0000000B INTE 00000004 INTEDG 00000006 INTF 00000001 IRP 00000007 NOT_PD 00000003 NOT_RBPU 00000007 NOT_TO 00000004 OPTION_REG 00000081 PCL 00000002 PCLATH 0000000A PORTA 00000005 PORTB 00000006 PS0 00000000 PS1 00000001 PS2 00000002 PSA 00000003 RBIE 00000003 RBIF 00000000 RD 00000000 RP0 00000005 RP1 00000006 STATUS 00000003 T0CS 00000005 T0IE 00000005 T0IF 00000002 T0SE 00000004 TMR0 00000001 TRISA 00000085 TRISB 00000086 W 00000000 WR 00000001 WREN 00000002 WRERR 00000003 Z 00000002 _CP_OFF 00003FFF _CP_ON 0000000F _HS_OSC 00003FFE _LP_OSC 00003FFC _PWRTE_OFF 00003FFF MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 14 SYMBOL TABLE LABEL VALUE _PWRTE_ON 00003FF7 _RC_OSC 00003FFF _WDT_OFF 00003FFB _WDT_ON 00003FFF _XT_OSC 00003FFD __16F84A 00000001 _fsr 0000000C _pclath 0000000D _status 0000000E _w 0000000F count_delay 00000064 current_led 00000012 display_led 00000040 dsply_val 00000010 hex_7seg 0000002A incr_count 0000005B init 0000005F led_lookup 0000003B led_sel 00000005 led_sel_mask 000000F0 loop 00000074 main 00000025 num_led 00000004 restore_context 0000001C run 00000026 seg_sel 00000006 set_next 00000059 svc_tmr0 00000011 temp 00000014 tmr0_count 00000006 tmr0_pre 00000001 tmr128 00000006 tmr16 00000003 tmr2 00000000 tmr256 00000007 tmr32 00000004 tmr4 00000001 tmr64 00000005 tmr8 00000002 wait 00000073 wait_count 00000013 MPASM 03.00 Released LEDDRVR.ASM 3-25-2002 17:31:23 PAGE 15 MEMORY USAGE MAP ('X' = Used, '-' = Unused) 0000 : X---XXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXX-------- 2000 : XXXX---X-------- ---------------- ---------------- ---------------- 2100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXX----------- All other memory blocks unused. Program Memory Words Used: 117 Program Memory Words Free: 907 Errors : 0 Warnings : 0 reported, 0 suppressed Messages : 0 reported, 4 suppressed