;---------------------------------------------------------- ; 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 ;----------------------------------------------------------