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