;----------------------------------------------------------
; File VFD.asm
;
TITLE "Vacuum Fluorescent Display Driver"
;----------------------------------------------------------
;
LIST p=16C84
;
include "reg84.h"
;
;----------------------------------------------------------
; Equates
;
IntInterval equ 0x4 ; interrupt interval
; Port B pin assignments
DispData equ 0 ; Data pin is RB0
DispClk equ 1 ; Clock pin is RB1
DispStb equ 2 ; Strobe pin is RB2
;
;----------------------------------------------------------
; External hardware
;
; A 0 will shut the segment/digit off. A 1 will light up the segment
; or enable the digit. Assuming the left most digit is shifted out
; first, the bits are
; [Dig 4] [Dig 3] [Dig Mid] [Dig 2] [Dig 1] followed by
; [Auto] [Seg g] [Seg f] [Seg e] [Seg d] [Seg c] [Seg b] [Seg a]
; The shift registers are 10 bit - so the segment bits are preceded
; by two dummy bits
;
;----------------------------------------------------------
RtccCount equ 07ah
; This was a count used for some other application with a 10 MHz crystal.
; This app has a 3.58 MHZ crystal. Let us see what we get...
; With an overhead, the count is 0x6f. No of cycles = 0 - 0x6f = 145
; The rate = 145 * 3.58 / 4 = 129.774 us = 130 us(approx)
;
;----------------------------------------------------------
; Data
ORG 0CH ; Data Origin
;
SaveWReg res 1
SaveStat res 1
;
Digit12 res 1 ; Least significant two bytes
Digit34 res 1 ; Most significant two bytes
DigitMid res 1 ; Centre symbol bit pattern
;
SegSr res 1 ; Segment shift register
;
SegInx res 1 ; Segment index(uses 3 bits)
IntCount res 1 ; Interrupt counter(uses 4 bits)
SegBitCnt res 1 ; Segment bit count(uses 3 bits)
;
Counter1 res 1 ; General purpose slow counter
Counter2 res 1
;
;----------------------------------------------------------
; Program
;
ORG 0 ; Reset vector
;
goto main
;
;
ORG 4 ; Interrupt vector
;
goto DispISR
;
;
ORG 8 ; Program starts here
;
;----------------------------------------------------------
main call InitIsr
movlw 0x21
movwf Digit12
movlw 0x43
movwf Digit34
movlw 55
movwf DigitMid
Loop movlw 0x4
xorwf Counter2,0
JMPNZ Loop
clrf Counter2
movlw 0x11
addwf Digit12,1
addwf Digit34,1
decf Counter1,1
goto Loop
;
;----------------------------------------------------------
InitIsr
bsf RegStatus,BitRp0
bcf RegTrisb,DispData ; Set Data pin to output
bcf RegTrisb,DispClk ; Set Clock pin to output
bcf RegTrisb,DispStb ; Set Strobe pin to output
bcf RegOption,BitRts ; Enable RTCC timer
bcf RegStatus,BitRp0
movlw 0
movwf RegRtcc
movwf SegInx
movlw 1
movwf IntCount
bsf RegIntcon,BitGie ; Enable Global interrupt
bsf RegIntcon,BitRtie ; Enable RTCC interrupt
return
;
;----------------------------------------------------------
; Interrupt service routine to manage display
DispISR btfss RegIntcon,BitRtif
retfie
movwf SaveWReg ; Save W and status
swapf RegStatus,w
movwf SaveStat
bcf RegStatus,BitRp0
movlw RtccCount ; Reload RTCC
movwf RegRtcc
;
decfsz IntCount,1 ; if --IntCount != 0
goto SkipIsr ; return
IncCnt incf Counter1,1
JMPNZ DoDisp
incf Counter2,1
DoDisp movlw IntInterval ; IntCount = IntInterval
movwf IntCount
movlw 8
movwf SegSr ; SegSr = 8
movf SegInx,0 ; W = SegInx
Loop1 btfsc RegStatus,BitZero ; while W != 0
goto DigDone
bcf RegStatus,BitCarry
rlf SegSr,1 ; SegSr <<= 1
addlw 0xff ; --W
goto Loop1
;
DigDone movlw 0xff
movlw 5 ; SegBitCnt = 5
movwf SegBitCnt
call DispDigit ; Display digit in SegSr
;
movf SegInx,0 ; W = SegInx
btfss RegStatus,BitZero ; if SegInx == 0
goto NotDig1
movf Digit12,0 ; W(3,0) = Digit12(3,0)
goto GetSeg
;
NotDig1 xorlw 1 ; else if SegInx == 1
btfss RegStatus,BitZero
goto NotDig2
swapf Digit12,0 ; W(3,0) = Digit12(7,4)
goto GetSeg
;
NotDig2 xorlw 1^3 ; else if SegInx == 3
btfss RegStatus,BitZero
goto NotDig3
movf Digit34,0 ; W(3,0) = Digit34(3,0)
goto GetSeg
;
NotDig3 xorlw 3^4 ; else if SegInx == 4
btfss RegStatus,BitZero
goto NotDig4
swapf Digit34,0 ; W(3,0) = Digit34(7,4)
goto GetSeg
;
NotDig4 movf DigitMid,0
movwf SegSr
goto Disp
;
GetSeg andlw 0xf ; if digit
call DigToSeg ; W &= 0xf
movwf SegSr
Disp movlw 8 ; SegBitCnt = 8
movwf SegBitCnt
bcf RegPortb,DispClk ; Two dummy clocks
bsf RegPortb,DispClk ;
bcf RegPortb,DispClk ;
bsf RegPortb,DispClk ;
call DispDigit ; Display digit in SegSr
bsf RegPortb,DispStb ; Set strobe to high
bcf RegPortb,DispStb ; Set strobe to low
;
movf SegInx,0 ; if --SegInx < 0
addlw 0xff
btfss RegStatus,BitCarry
movlw 4 ; SegInx = 4
movwf SegInx
;
SkipIsr swapf SaveStat,w
movwf RegStatus
swapf SaveWReg,w
bcf RegIntcon,BitRtif
retfie
;
DispDigit ; do
rlf SegSr,1 ; SegSr <<= 1
btfsc RegStatus,BitCarry ; Output carry
bsf RegPortb,DispData
btfss RegStatus,BitCarry
bcf RegPortb,DispData
bcf RegPortb,DispClk ; Set clock to low
bsf RegPortb,DispClk ; Set clock to high
decfsz SegBitCnt,1 ; while --SegBitCnt != 0
goto DispDigit
SegEnd return
;
;----------------------------------------------------------
; Subroutine to convert 4 bit digit in W to a 7 segment pattern. The bits
; correspond to auto, segment g to a from MSB to LSB. Due to the inversion
; in the hardware, the bits have to be complemented.
DigToSeg
addwf RegPcl,1
retlw 0x3f ; 00111111B ; 0
retlw 0x06 ; 00000110B ; 1
retlw 0x5b ; 01011011B ; 2
retlw 0x4f ; 01001111B ; 3
retlw 0x66 ; 01100110B ; 4
retlw 0x6d ; 01101101B ; 5
retlw 0x7d ; 01111101B ; 6
retlw 0x07 ; 00000111B ; 7
retlw 0x7f ; 01111111B ; 8
retlw 0x6f ; 01101111B ; 9
retlw 0x77 ; 01110111B ; A
retlw 0x7c ; 01111100B ; b
retlw 0x39 ; 00111001B ; C
retlw 0x5e ; 01011110B ; d
retlw 0x79 ; 01111001B ; E
retlw 0x71 ; 01110001B ; F
return
;
END
;----------------------------------------------------------
External Labels :