MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 1 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00001 ;;; LEDDRVR2.ASM 00002 ;;; Copyright (c) 2002, TundraWare Inc., All Rights Reserved 00003 ;;; 00004 ;;; Program to drive homemade LED display board 00005 ;;; 00006 ;;; $Id: leddrvr2.asm,v 2.4 2002/05/02 19:25:21 tundra Exp tundra $ 00007 00008 00009 list p=16F84A 00010 include <P16F84A.INC> 00001 LIST 00002 ; P16F84A.INC Standard Header File, Version 2.00 Microchip Technology, Inc. 00134 LIST 00011 00012 errorlevel -302 ;suppress bank selection messages 2007 3FF1 00013 __config 3ff1h ;xt osc, WDT off 2000 0001 0002 0003 00014 __idlocs 1234 0004 00015 00016 ;;;;;;;;;; 00017 ;;; Device Constants 00018 ;;;;;;;;;; 00019 00000000 00020 tmr2 equ 00H ; TMR0 prescaler constants 00000001 00021 tmr4 equ 01H 00000002 00022 tmr8 equ 02H 00000003 00023 tmr16 equ 03H 00000004 00024 tmr32 equ 04H 00000005 00025 tmr64 equ 05H 00000006 00026 tmr128 equ 06H 00000007 00027 tmr256 equ 07H 00028 00029 00030 ;;;;;;;;;; 00031 ;;; Circuit Constants 00032 ;;;;;;;;;; 00033 00000008 00034 num_led equ 8 ; total number of LEDs 00000000 00035 led_clk equ 0 ; bit used to clock led selection 00000001 00036 led_dat equ 1 ; bit used for led selection data 00000002 00037 led_strobe equ 2 00000005 00038 led_ctrl equ PORTA ; intf to LED control shift registers 00039 00040 00041 ;;;;;;;;;; 00042 ;;; Program Contants 00043 ;;;;;;;;;; 00044 00045 ;;; TMR0 related stuff 00046 ;;; 00047 ;;; With a 4MHz clock, the basic cycle type is 1/4 this or 1us. 00048 ;;; The TMR0 interrupt interrupt interval is thus: 00049 ;;; MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 2 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00050 ;;; 1us * prescaler factor * tmr0_count 00051 ;;; 00052 00053 ;;; TMR0 interrupt every 1ms 00054 000000FA 00055 interval equ D'250' ; basic (TMR0 interval/4) in us 00000006 00056 tmr0_count equ D'256'-interval ; set for 250us interrupt interval 00000001 00057 tmr0_pre equ tmr4 ; prescaler factor 00058 00059 00060 ;;; wait delays: delay time = value(s) below * TMR0 interrupt rate 00061 00000005 00062 count_delay equ D'5' ; 5ms delay between counts 00063 00064 00065 ;;;;;;;;;; 00066 ;;; Register File Assignments 00067 ;;;;;;;;;; 00068 00069 CBLOCK 0cH 0000000C 00070 _fsr ; context save area 0000000D 00071 _pclath 0000000E 00072 _status 0000000F 00073 _w 00074 00000010 00075 dsply_val:(num_led/2) ; array of values to display 00076 ; 2 LEDs per byte 00077 00000014 00078 current_led ; currently displayed LED 00079 ; 0 <= current_led < num_led 00080 00000015 00081 led_seg ; segment to illuminate 00000016 00082 led_sel ; led selection pattern 00083 00000017 00084 wait_count ; time delay counter variable 00000018 00085 temp ; temp storage during calculation 00086 ENDC 00087 00088 00089 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00090 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 3 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00091 PAGE 00092 ;;;;;;;;;; 00093 ;;; Power-On Entry Point 00094 ;;;;;;;;;; 00095 0000 00096 org 00H 00097 0000 2825 00098 goto main 00099 00100 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00101 00102 ;;;;;;;;;; 00103 ;;; Interrupt Handler 00104 ;;;;;;;;;; 00105 0004 00106 org 04H 00107 0004 008F 00108 movwf _w ; save context 0005 0803 00109 movfw STATUS 0006 1303 00110 bcf STATUS,RP1 0007 1283 00111 bcf STATUS,RP0 0008 008E 00112 movwf _status 0009 0804 00113 movfw FSR 000A 008C 00114 movwf _fsr 000B 080A 00115 movfw PCLATH 000C 008D 00116 movwf _pclath 000D 018A 00117 clrf PCLATH 00118 00119 ; Figure out who interrupted and service it 00120 000E 190B 00121 btfsc INTCON,T0IF ; did we get a TMR0 interrupt? 000F 2811 00122 goto svc_tmr0 ; yup 0010 281C 00123 goto restore_context ; nope 00124 00125 ; TMR0 ISR 0011 00126 svc_tmr0: 0011 110B 00127 bcf INTCON,T0IF ; clear the interrupt condition 0012 3006 00128 movlw tmr0_count ; prime the counter 0013 0081 00129 movwf TMR0 0014 018B 00130 clrf INTCON ; Enable *just* this interrupt 0015 168B 00131 bsf INTCON,T0IE ; to maintain timing accuracy 0016 178B 00132 bsf INTCON,GIE 00133 00134 ; Update the wait timer if it is in use 00135 ; Only do this on TMR0 interrupts so timing is predictable 00136 0017 0817 00137 movfw wait_count 0018 1D03 00138 btfss STATUS,Z ; non-zero count means 'in use' 0019 0397 00139 decf wait_count,F ; decrement current count 00140 ; not in-use, fall through to next code 00141 001A 2044 00142 call display_led ; then display it 001B 281C 00143 goto restore_context ; goto here (instead of just falling MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 4 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00144 ; through) allows other ISRs 00145 ; to later be added immediately 00146 ; following 00147 001C 00148 restore_context: 001C 080D 00149 movfw _pclath ; restore entry context 001D 008A 00150 movwf PCLATH 001E 080C 00151 movfw _fsr 001F 0084 00152 movwf FSR 0020 080E 00153 movfw _status 0021 0083 00154 movwf STATUS 0022 0E8F 00155 swapf _w,F ; get W back w/o changing Z flag 0023 0E0F 00156 swapf _w,W 00157 0024 0009 00158 retfie ; all done 00159 00160 ;;; End of interrupt handler 00161 00162 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00163 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 5 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00164 PAGE 00165 ;;;;;;;;;; 00166 ;;; Main program logic 00167 ;;;;;;;;;; 00168 0025 00169 main: 0025 2083 00170 call init ; initialize the system 0026 00171 run: 0026 2076 00172 call incr_count 0027 3005 00173 movlw count_delay 0028 207E 00174 call wait ; slow down displayed count 0029 2826 00175 goto run 00176 00177 ;;; End of main logic 00178 00179 00180 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00181 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 6 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00182 PAGE 00183 ;;;;;;;;;; 00184 ;;; Data & Tables 00185 ;;;;;;;;;; 00186 00187 ;;;;;;;;;; 00188 ;;; Hex Digit-to-Segment lookup table 00189 ;;;;;;;;;; 00190 00191 002A 0782 00192 hex_7seg addwf PCL,F 002B 343F 00193 DT 03fH ; 0 002C 3406 00194 DT 006H ; 1 002D 345B 00195 DT 05bH ; 2 002E 344F 00196 DT 04fH ; 3 002F 3466 00197 DT 066H ; 4 0030 346D 00198 DT 06dH ; 5 0031 347D 00199 DT 07dH ; 6 0032 3407 00200 DT 007H ; 7 0033 347F 00201 DT 07fH ; 8 0034 3467 00202 DT 067H ; 9 0035 3477 00203 DT 077H ; A 0036 347C 00204 DT 07cH ; B 0037 3458 00205 DT 058H ; C 0038 345E 00206 DT 05eH ; D 0039 3479 00207 DT 079H ; E 003A 3471 00208 DT 071H ; F 00209 00210 00211 ;;;;;;;;;; 00212 ;;; Table used to translate LED position to equivalent led_sel 00213 ;;; bit pattern for that LED. It is assumed that any routine using 00214 ;;; this table will properly preserve higher-order bits not needed for 00215 ;;; LED selection. 00216 ;;;;;;;;;; 00217 003B 00218 led_lookup: 003B 0782 00219 addwf PCL,F 003C 3401 00220 DT 01H ; LED0 == LSD 003D 3402 00221 DT 02H ; LED1 003E 3404 00222 DT 04H ; LED2 003F 3408 00223 DT 08H ; LED3 0040 3410 00224 DT 10H ; LED4 0041 3420 00225 DT 20H ; LED5 0042 3440 00226 DT 40H ; LED6 0043 3480 00227 DT 80H ; LED7 00228 00229 00230 ;;; End of 'led_lookup' 00231 00232 00233 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 00234 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 7 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00235 PAGE 00236 ;;;;;;;;;; 00237 ;;; Supporting Subroutines 00238 ;;;;;;;;;; 00239 00240 00241 ;;;;;;;;;; 00242 ;;; Display LEDs, one per call, from MSD->LSD 00243 ;;; This effectively multiplexes across all the LEDs 00244 ;;; when called repeatedly. 00245 ;;;;;;;;;; 00246 0044 00247 display_led: 00248 ; compute and set the segments to display for this digit 00249 ; this logic only works if 'num_led' is *even* !!!! 00250 0044 0814 00251 movfw current_led ; convert current_led into an 0045 0084 00252 movwf FSR ; offset from base of display storage 0046 1003 00253 bcf STATUS,C ; don't rotate C into calc below 0047 0C84 00254 rrf FSR,F ; /2 - two digits stored in each byte 0048 3010 00255 movlw dsply_val ; base of array containing display vals 0049 0784 00256 addwf FSR,F ; point to desired value 004A 0800 00257 movfw INDF ; and get contents 004B 0098 00258 movwf temp ; store temporarily 004C 1814 00259 btfsc current_led,0 ; even or odd nibble 004D 0E98 00260 swapf temp,F ; odd==hi nibble -> low nibble 004E 0818 00261 movfw temp ; get it 004F 390F 00262 andlw 0fH ; mask off high nibble 0050 202A 00263 call hex_7seg ; convert to equivalent seg pattern 0051 0095 00264 movwf led_seg ; and save for shift out 00265 00266 ; select the corresponding LED 00267 0052 0814 00268 movfw current_led ; get the bit pattern that selects 0053 203B 00269 call led_lookup ; desired LED 0054 0096 00270 movwf led_sel ; and save for shift out 00271 00272 ; now shift the current control bits out and latch them 00273 0055 205D 00274 call led_wrt 00275 00276 ; determine next LED to display 00277 0056 0814 00278 movfw current_led ; get LED just displayed 0057 1D03 00279 btfss STATUS,Z ; was it the LSD? 0058 285B 00280 goto set_next ; nope 0059 3008 00281 movlw num_led ; yup, start again w/MSD 005A 0094 00282 movwf current_led 005B 00283 set_next: 005B 0394 00284 decf current_led,F ; pickup next digit to right 005C 0008 00285 return 00286 00287 ;;; End of 'display_led' MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 8 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00288 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 9 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00289 PAGE 00290 ;;;;;;;;;; 00291 ;;; Shift the control bits in 'led_seg' and 'led_sel' into the 00292 ;;; LED controller shift registers. 00293 ;;;;;;;;;; 00294 005D 00295 led_wrt: 00296 ; first shift out LED select pattern LSB->MSB 00297 005D 3008 00298 movlw 08H ; do this for all 8 bits 005E 00299 shift_sel: 005E 1085 00300 bcf led_ctrl,led_dat ; assume output 0 005F 1C16 00301 btfss led_sel,0 0060 2862 00302 goto clk_sel ; shift out a 0 0061 1485 00303 bsf led_ctrl,led_dat ; shift out a 1 0062 00304 clk_sel: 0062 1405 00305 bsf led_ctrl,led_clk ; clock it into the 0063 1005 00306 bcf led_ctrl,led_clk ; shift register 0064 0C96 00307 rrf led_sel,F ; pickup the next bit 0065 3EFF 00308 addlw -1 ; decrement repeat count 0066 1D03 00309 btfss STATUS,Z 0067 285E 00310 goto shift_sel 00311 00312 ; then shift out segment select pattern 'a'->'dp' 00313 0068 3008 00314 movlw 08H ; do this for all 8 bits 0069 00315 shift_seg: 0069 1085 00316 bcf led_ctrl,led_dat ; assume output 0 006A 1C15 00317 btfss led_seg,0 006B 286D 00318 goto clk_seg ; shift out a 0 006C 1485 00319 bsf led_ctrl,led_dat ; shift out a 1 006D 00320 clk_seg: 006D 1405 00321 bsf led_ctrl,led_clk ; clock it into the 006E 1005 00322 bcf led_ctrl,led_clk ; shift register 006F 0C95 00323 rrf led_seg,F ; pickup the next bit 0070 3EFF 00324 addlw -1 ; decrement repeat count 0071 1D03 00325 btfss STATUS,Z 0072 2869 00326 goto shift_seg 00327 00328 ; now strobe to output latch 00329 0073 1505 00330 bsf led_ctrl,led_strobe ; propagate changes 0074 1105 00331 bcf led_ctrl,led_strobe ; latch changes 00332 0075 0008 00333 return 00334 00335 ;;; End of 'led_wrt' 00336 00337 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 10 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00338 PAGE 00339 ;;;;;;;;;; 00340 ;;; Increment current count by 1 00341 ;;;;;;;;;; 00342 0076 00343 incr_count: 0076 0F90 00344 incfsz dsply_val,F ; count up 8 digits worth 0077 0008 00345 return 0078 0F91 00346 incfsz dsply_val+1,F 0079 0008 00347 return 007A 0F92 00348 incfsz dsply_val+2,F 007B 0008 00349 return 007C 0A93 00350 incf dsply_val+3,F 007D 0008 00351 return 00352 00353 ;;; End of 'incr_count' 00354 00355 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 11 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00356 PAGE 00357 ;;;;;;;;;; 00358 ;;; Kill time - Outer loop constant passed in W. 00359 ;;;;;;;;;; 00360 007E 00361 wait: 007E 0097 00362 movwf wait_count ; this will be decremented in ISR 007F 00363 loop: 007F 0817 00364 movfw wait_count ; get current count 0080 1D03 00365 btfss STATUS,Z ; see if we counted all the way down 0081 287F 00366 goto loop ; not done, keep waiting 0082 0008 00367 return ; all done 00368 00369 ;;; End of 'wait' 00370 00371 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 12 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00372 PAGE 00373 ;;;;;;;;;; 00374 ;;; Initialize hardware and software at startup as needed. 00375 ;;; Returns with register bank 0 selected. 00376 ;;;;;;;;;; 00377 0083 00378 init: 0083 018B 00379 clrf INTCON ; all interrupts off, flags cleared 00380 00381 ; setup control registers 00382 0084 168B 00383 bsf INTCON,T0IE ; unmask TMR0 interrupts 0085 1683 00384 bsf STATUS,RP0 ; select register bank 1 0086 0185 00385 clrf TRISA ; set PORTA to all outputs 0087 0186 00386 clrf TRISB ; set PORTB to all outputs 0088 0181 00387 clrf OPTION_REG ; TMR0 selected w/ internal clock 00388 ; don't care about RBPU, INTEDG 0089 3001 00389 movlw tmr0_pre ; set TMR0 prescaler value 008A 0481 00390 iorwf OPTION_REG,F 008B 1283 00391 bcf STATUS,RP0 ; select register bank 0 00392 00393 ; setup program variables 00394 008C 3010 00395 movlw dsply_val ; initialize count storage to 0 008D 0084 00396 movwf FSR ; this logic only works if 008E 3004 00397 movlw num_led/2 ; if 'num_led' is *even* !!! 008F 00398 zero_count: 008F 0180 00399 clrf INDF ; zero the storage location 0090 3EFF 00400 addlw -1 ; decrement loop count 0091 1903 00401 btfsc STATUS,Z ; when zero, we're done 0092 2895 00402 goto prime_counter ; we're done 0093 0A84 00403 incf FSR,F ; point to next storage location 0094 288F 00404 goto zero_count ; and do it again 00405 0095 00406 prime_counter: 0095 3006 00407 movlw tmr0_count ; prime the counter 0096 0081 00408 movwf TMR0 00409 0097 3007 00410 movlw num_led-1 ; start displaying with MSD 0098 0094 00411 movwf current_led 00412 0099 1105 00413 bcf led_ctrl,led_strobe ; initialize control bits 009A 1005 00414 bcf led_ctrl,led_clk 00415 009B 0195 00416 clrf led_seg ; all segments off 009C 0196 00417 clrf led_sel ; all LEDs off 009D 205D 00418 call led_wrt ; write out the changes 00419 009E 178B 00420 bsf INTCON,GIE ; enable unmasked interrupts 009F 0008 00421 return 00422 00423 ;;; End of 'init' 00424 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 13 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00425 MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 14 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00426 PAGE 00427 ;;;;;;;;;; 00428 ;;; EEPROM Contents 00429 ;;;;;;;;;; 00430 2100 00431 org 2100h 00432 2100 0043 006F 0070 00433 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 00434 END MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 15 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 LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 16 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 clk_seg 0000006D clk_sel 00000062 count_delay 00000005 current_led 00000014 display_led 00000044 dsply_val 00000010 hex_7seg 0000002A incr_count 00000076 init 00000083 interval 000000FA led_clk 00000000 led_ctrl 00000005 led_dat 00000001 led_lookup 0000003B led_seg 00000015 led_sel 00000016 led_strobe 00000002 led_wrt 0000005D loop 0000007F main 00000025 num_led 00000008 prime_counter 00000095 restore_context 0000001C run 00000026 set_next 0000005B shift_seg 00000069 shift_sel 0000005E svc_tmr0 00000011 temp 00000018 tmr0_count 00000006 tmr0_pre 00000001 tmr128 00000006 tmr16 00000003 tmr2 00000000 tmr256 00000007 tmr32 00000004 tmr4 00000001 tmr64 00000005 tmr8 00000002 wait 0000007E wait_count 00000017 zero_count 0000008F MPASM 03.00 Released LEDDRVR2.ASM 5-2-2002 19:27:08 PAGE 17 MEMORY USAGE MAP ('X' = Used, '-' = Unused) 0000 : X---XXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX ---------------- ---------------- 2000 : XXXX---X-------- ---------------- ---------------- ---------------- 2100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXX----------- All other memory blocks unused. Program Memory Words Used: 157 Program Memory Words Free: 867 Errors : 0 Warnings : 0 reported, 0 suppressed Messages : 0 reported, 4 suppressed