TITLE "auto-ranging frequency meter @4.000MHz" LIST p=16F84 ERRORLEVEL 0, -302 ; File: fmeter.asm; Created: Feb-1999, P. Strebel ; Measures 0.900Hz to 30.00MHz with a PIC16F84 and 50% duty cycle. ; The frequency display is rounded to four decimal digits to get a ; maximum tolerance of 1 last digit without oscillator adjustement. ; ********** ********** ; * *** * ; NC A2 ** 1 18 ** A1 NC ; * * ; NC A3 ** 2 17 ** A0 NC ; * * ; input A4 ** 3 16 ** Xin X1 ; * * ; reset MCLR ** 4 15 ** Xout X0 ; * * ; GND ** 5 14 ** VCC ; * * ; NC B0 ** 6 13 ** B7 D7 ; * * ; ENA B1 ** 7 12 ** B6 D6 ; * * ; R/W B2 ** 8 11 ** B5 D5 ; * * ; D/C B3 ** 9 10 ** B4 D4 ; * PIC16F84 * ; *********************** ; VCC = 5V (2-6V for controller, 4.5-5.5V for display) ; input: cmos schmitt-trigger (pulled up with 10k) ; reset: pulled up with 10k to VCC ; --------------------------------- 1 = GND ; | | 2 = VCC ; | | 3 = V0 ; | LM054 8-Char LCD-Module | 4 = D/C ; | | 5 = R/W ; | 14............1 | 6 = ENA ; --------------------------------- 7-14 = D0-D7 ; V0: VCC-4.5V, D0..D3 not used in 4-bit mode ; Alternative small display: DL1414T 4-Char LED ; soldered piggyback on the PIC: ; GND (Pin 7) GND | | VCC (Pin 6) VCC ; D0 (Pin 8) B0 | PIC | B7 (Pin 5) A0 ; D1 (Pin 9) B1 | | B6 (Pin 4) A1 ; D2 (Pin 10) B2 | | B5 (Pin 3) WR ; D3 (Pin 11) B3 |_________| B4 (Pin 2) D4 ; D6 (Pin 12) A3 -- -- A0 (Pin 1) D5 ; display LM054 DL1414T update interval ; 0.900 Hz .. 9.999Hz 0.90 .. 9.99 ca. 250ms .. 1.2s ; 10.00 Hz .. 99.99Hz 10.0 .. 99.9 ca. 250ms ; 100.0 Hz .. 999.9Hz 100. .. 999. ca. 250ms ; 1.000kHz .. 9.999kHz 1K00 .. 9.99 ca. 250ms ; 10.00kHz .. 99.99kHz 10K0 .. 99K9 ca. 250ms ; 100.0kHz .. 999.0kHz 100K .. 999K ca. 250ms ; 1.000MHz .. 9.999MHz 1M00 .. 9M99 ca. 250ms ; 10.00MHz .. 99.99MHz 10M0 .. 99M9 ca. 250ms ; Higher frequencies use the prescaler and measuring time is 200ms ; Lower frequencies use no prescaler, measuring time is 200ms..1.1s ; Determination of prescaler: TMR0 input frequency should be below ; 1/4 of oscillator clock. We set the prescaler to get a maximum ; frequency of 1/8 of the oscillator speed (4Mhz/8 = 500 kHz). ; A test is done for 512us with a prescaler of 256 and then TMR0 ; is read to see what prescaler is needed. ; prescaler input frequency TMR0 (after test) prsc ; 1 (off) < 500kHz 0 off ; 2 > 500kHz >1 0 ; 4 > 1MHz >2 1 ; 8 > 2MHz >4 2 ; 16 > 4MHz >8 3 ; 32 > 8MHz >16 4 ; 64 > 16MHz >32 5 ; 128 > 32MHz >64 6 ; 256 > 64MHz >128 7 __IDLOCS H'FFFF' __CONFIG H'3FF1' ; WDT off, XT osc TMR0 EQU 1 PC EQU 2 STATUS EQU 3 FSR EQU 4 PORTA EQU 5 PORTB EQU 6 PCLATH EQU H'0A' INTCON EQU H'0B' _OPTION EQU H'81' ; OPTION register in page 1 _TRISA EQU H'85' ; TRISA in page 1 _TRISB EQU H'86' ; TRISB in page 1 C EQU 0 DC EQU 1 Z EQU 2 P EQU 5 DSPLY EQU 1 ; 1=LM054, 2=DL1414T ORG H'00C' ; start of RAM tmp0 RES 1 ; temporary storage tmp1 RES 1 tmp2 RES 1 tmp3 RES 1 tim0 RES 1 ; software timer tim1 RES 1 tim2 RES 1 tim3 RES 1 cnt0 RES 1 ; wave counters cnt1 RES 1 cnt2 RES 1 cnt3 RES 1 prsc RES 1 ; prescaler setting quot RES 1 ; quotient (division) dign RES 1 ; number of decimal digits digo RES 1 ; digits out to display digs RES D'12' ; decimal digits MMkkk111mmmu ORG H'000' ; reset GOTO main ORG H'004' ; interrupt intserv BCF INTCON,2 ; [3] reset int flag INCFSZ cnt1,F ; [4] no status or W change GOTO intend ; [6] always same nr of cycles INCF cnt2,F ; [6] intend RETFIE ; [8] ORG H'010' ; main program main CLRF PORTA ; port A low CLRF PORTB ; port B low BSF STATUS,P ; bank 1 MOVLW B'00010000' ; A4 input, A3..A0 outputs MOVWF _TRISA MOVLW B'00000000' ; B7..B0 outputs MOVWF _TRISB MOVLW B'11111111' ; no pu, risi, A4, hilo, presc to WDT MOVWF _OPTION ; BCF STATUS,P ; bank 0 GOTO $+DSPLY ; skip for DL1414T: CALL initlcd GOTO $+DSPLY ; skip for DL1414T: CALL loadcgr GOTO $+DSPLY ; skip for DL1414T: CALL ckcali ; calibration timer if B0 low at reset timeout MOVLW H'0C' ; begin reset vars MOVWF FSR initvar CLRF 0 INCF FSR,F MOVLW H'30' XORWF FSR,W BTFSS STATUS,Z GOTO initvar ; end reset vars display CALL round GOTO $+DSPLY ; skip for DL1414T: CALL home MOVLW D'11' ; point to first (10MHz) digit MOVWF dign CLRF digo displ MOVF dign,W ; digit out ADDLW digs MOVWF FSR CALL dispdig DECF dign,F BTFSS dign,7 GOTO displ newm MOVLW 7 ; prescaler to 256 MOVWF prsc CALL setprsc MOVLW D'171' ; test timer (*3 cycles) MOVWF tmp0 CLRF TMR0 ; clear timer and prescaler tstp DECFSZ tmp0,F ; wait while TMR0 counts up GOTO tstp MOVF TMR0,W ; read timer MOVWF tmp0 MOVLW 8 MOVWF prsc BSF STATUS,C ; see what prescaler to use chkp DECF prsc,F RLF tmp0,F ; shift out leftmost bit BTFSS STATUS,C GOTO chkp donp CALL setprsc ; no prescaler needed: prsc=255 CLRF tim0 ; reset software timer CLRF tim1 CLRF tim2 CLRF tim3 CLRF TMR0 ; clear timer and prescaler CALL phase ; synchronize with signal edge CLRF TMR0 ; clear timer and prescaler BTFSC tim2,7 ; [1] timeout? GOTO timeout ; [2] CLRF cnt0 ; [3] reset counters CLRF cnt1 ; [4] CLRF cnt2 ; [5] CLRF cnt3 ; [6] MOVLW B'10100000' ; [7] enable timer interrupt MOVWF INTCON ; [8] MOVLW D'250' ; [9] wait for 200000 cycles (200ms) MOVWF tmp1 ; | tmp1 * (tmp0+1) * 4 cycles wait1 MOVLW D'199' ; | MOVWF tmp0 ; | | tpm0 * 4 cycles wait0 NOP ; | | DECFSZ tmp0,F ; | | GOTO wait0 ; | | DECFSZ tmp1,F ; | GOTO wait1 ; | CLRF tim3 ; [10] preset software timer CLRF tim2 ; [11] MOVLW H'30' ; [12] 200016/16 MOVWF tim1 ; [13] MOVLW H'D5' ; [14] MOVWF tim0 ; [15] CALL phase ; synchronize with signal edge XORWF TMR0,F ; (W=0) stop timer for 2 cycles MOVF TMR0,W ; read timer CLRF INTCON ; stop interrupt MOVWF cnt0 ; waves/presc now in cnt3:cnt2:cnt1:cnt0 BTFSC tim2,7 ; timeout? GOTO timeout BCF tim2,6 ; clear flag (maybe set) MOVF cnt1,W ; interrupt time = int count/2 MOVWF tmp0 MOVF cnt2,W MOVWF tmp1 CLRF tmp2 CLRF tmp3 BCF STATUS,C RRF tmp3,F RRF tmp2,F RRF tmp1,F RRF tmp0,F MOVLW tim0 ; tim += interrupt time MOVWF FSR CALL add32 BCF STATUS,C ; tim *= 16 to get [us] RLF tim0,F RLF tim1,F RLF tim2,F RLF tim3,F BCF STATUS,C RLF tim0,F RLF tim1,F RLF tim2,F RLF tim3,F BCF STATUS,C RLF tim0,F RLF tim1,F RLF tim2,F RLF tim3,F BCF STATUS,C RLF tim0,F RLF tim1,F RLF tim2,F RLF tim3,F ; time [us] now in tim3:tim2:tim1:tim0 BTFSC prsc,3 ; prescaler off? GOTO mulx INCF prsc,F mulp BCF STATUS,C ; multiply with prescaler RLF cnt0,F RLF cnt1,F RLF cnt2,F RLF cnt3,F DECFSZ prsc,F GOTO mulp mulx NOP ; waves in cnt3:cnt2:cnt1:cnt0 ; cnt range is from 0x00 00 01 to 0xFF FF FF (at ca.75MHz) ; tim range is about 0x03 0D 00 to about 0x10 F0 00 us ; frequency (MHz)=cnt/tim; following digit=reminder*10/tim MOVLW tim0 ; to get 10MHz digit MOVWF FSR ; multiply tim by 10 CALL mul10 MOVLW D'11' ; point to 10MHz digit MOVWF dign calc MOVF tim0,W ; tim to tmp (divisor) MOVWF tmp0 MOVF tim1,W MOVWF tmp1 MOVF tim2,W MOVWF tmp2 MOVF tim3,W MOVWF tmp3 ; division is looped sub: expected result < 10 (ca. 50-300 cycles) CLRF quot ; count loops divil INCF quot,F MOVLW cnt0 ; dividend MOVWF FSR CALL sub32 BTFSC STATUS,C GOTO divil divix MOVLW cnt0 ; point to cnt MOVWF FSR CALL add32 ; rebuild reminder DECF quot,F ; result MOVF dign,W ; store result (0..9) ADDLW digs MOVWF FSR MOVF quot,W MOVWF 0 DECF dign,F BTFSC dign,7 ; all digits ready? GOTO display MOVLW cnt0 ; reminder * 10 MOVWF FSR CALL mul10 GOTO calc ; next digit mul10 BCF STATUS,C ; [FSR] *= 10 RLF 0,F ; * 2; copy to tmp3:tmp2:tmp1:tmp0 MOVF 0,W MOVWF tmp0 INCF FSR,F RLF 0,F MOVF 0,W MOVWF tmp1 INCF FSR,F RLF 0,F MOVF 0,W MOVWF tmp2 INCF FSR,F RLF 0,F MOVF 0,W MOVWF tmp3 DECF FSR,F DECF FSR,F DECF FSR,F BCF STATUS,C ; * 4 RLF tmp0,F RLF tmp1,F RLF tmp2,F RLF tmp3,F BCF STATUS,C ; * 8 RLF tmp0,F RLF tmp1,F RLF tmp2,F RLF tmp3,F add32 MOVF tmp0,W ; [FSR] += tmp3:tmp2:tmp1:tmp0 ADDWF 0,F INCF FSR,F MOVF tmp1,W BTFSC STATUS,C INCFSZ tmp1,W ADDWF 0,F INCF FSR,F MOVF tmp2,W BTFSC STATUS,C INCFSZ tmp2,W ADDWF 0,F INCF FSR,F MOVF tmp3,W BTFSC STATUS,C INCFSZ tmp3,W ADDWF 0,F RETLW 0 ; carry set at overflow sub32 MOVF tmp0,W ; [FSR] -= tmp3:tmp2:tmp1:tmp0 SUBWF 0,F INCF FSR,F MOVF tmp1,W BTFSS STATUS,C INCFSZ tmp1,W SUBWF 0,F INCF FSR,F MOVF tmp2,W BTFSS STATUS,C INCFSZ tmp2,W SUBWF 0,F INCF FSR,F MOVF tmp3,W BTFSS STATUS,C INCFSZ tmp3,W SUBWF 0,F RETLW 0 ; carry cleared at overflow round MOVLW digs+D'11' ; point to first (10MHz) digit MOVWF FSR roun0 MOVF 0,W ; search for digit > 0 BTFSS STATUS,Z GOTO roun1 MOVF FSR,W XORLW digs+4 ; at digit 4 BTFSC STATUS,Z GOTO roun1 DECF FSR,F GOTO roun0 roun1 MOVLW 3 GOTO $+DSPLY ; skip for DL1414T: MOVLW 4 SUBWF FSR,F ; point to last digit - 1 MOVLW 5 ; add 1/2 last digit roun2 ADDWF 0,W MOVLW D'10' ; decimal carry? SUBWF 0,W BTFSS STATUS,C RETLW 0 ; no: done MOVLW D'10' SUBWF 0,F MOVLW 1 ; carry INCF FSR,F GOTO roun2 ;;; wait for signal edge or timeout (loops*16 + 3 cycles) phase MOVF TMR0,W ; [3] wait for signal edge MOVWF tmp0 ; [4] phas0 INCFSZ tim0,F ; [1] inc software timer GOTO phas1 ; [3] always same nr of cycles INCFSZ tim1,F ; [3] GOTO phas2 ; [5] always same nr of cycles INCF tim2,F ; [5] MOVLW H'01' ; [6] if tim2 matches timeout XORWF tim2,W ; [7] BTFSC STATUS,Z ; [8] BSF tim2,6 ; [9] flag this with bit6 NOP ; [10] phas4 MOVF TMR0,W ; [11] TMR0 changed? XORWF tmp0,W ; [12] BTFSS STATUS,Z ; [13] RETLW 0 ; [15] edge detected GOTO phas0 ; [16] next loop phas1 BTFSS tim2,6 ; [4] if tim2 timeout GOTO phas3 ; [6] MOVLW H'0F' ; [6] check tim1 (01 0F 01 = ca 1.11s) XORWF tim1,W ; [7] BTFSS STATUS,Z ; [8] GOTO phas4 ; [10] BSF tim2,7 ; flag timeout with bit 7 RETLW 0 ; no edge detected phas2 NOP ; [6] phas3 NOP ; [7] NOP ; [8] GOTO phas4 ; [10] ;;; prescaler in _OPTION to prsc (prescaler to WDT if bit3 is set) setprsc MOVF prsc,W ; prepare new option in W ANDLW B'00001111' IORLW B'11110000' ; no pu, risi, A4, hilo CLRF TMR0 ; clear timer and prescaler CLRWDT ; clear WDT and prescaler BSF STATUS,P ; bank 1 MOVWF _OPTION BCF STATUS,P ; bank 0 RETLW 0 initlcd MOVLW B'00110000' ; bit3..0,dat/cmd,rd/wr,ena,0 MOVWF PORTB ; command, write, ena low BSF STATUS,P ; set page 1 MOVLW B'00000000' ; 7..1 outputs, 0 output MOVWF _TRISB BCF STATUS,P ; set page 0 MOVLW D'20' CALL delayw CALL latch MOVLW D'5' CALL delayw CALL latch MOVLW D'1' CALL delayw CALL latch CALL pollbsy MOVLW B'00100000' ; 4-Bit interface MOVWF PORTB CALL latch MOVLW H'20' ; 4 bit, 1 line, 5x7 matrix CALL outcmd MOVLW H'08' ; display off CALL outcmd MOVLW H'01' ; display on CALL outcmd MOVLW H'06' ; increment, no shift CALL outcmd MOVLW H'0C' ; display on, cursor off CALL outcmd MOVLW H'01' ; clear display, cursor home CALL outcmd RETLW 0 delayw MOVWF tmp1 ; delay ca. w * 1000 cycles dlyw1 MOVLW D'149' MOVWF tmp0 dlyw0 NOP DECFSZ tmp0,F GOTO dlyw0 DECFSZ tmp1,F GOTO dlyw1 RETLW 1 latch BSF PORTB,1 ; ena high BCF PORTB,1 ; ena low RETLW 0 pollbsy BSF STATUS,P ; set page 1 MOVLW B'11110000' MOVWF _TRISB ; data inputs BCF STATUS,P ; set page 0 MOVLW B'00000100' ; command, read, ena low MOVWF PORTB pollbs0 BSF PORTB,1 ; ena high (higher nibble) MOVF PORTB,W MOVWF tmp0 BCF PORTB,1 ; ena low BSF PORTB,1 ; latch lower nibble BCF PORTB,1 ; ena low BTFSC tmp0,7 GOTO pollbs0 CLRF PORTB ; ena low, write, command BSF STATUS,P ; set page 1 MOVLW B'00000000' MOVWF _TRISB ; data outputs BCF STATUS,P ; set page 0 RETLW 0 ;;; binary 0..63 to bcd 00..99 binbcd CLRF tmp0 DECF tmp0,F binbc0 INCF tmp0,F ADDLW D'246' ; subtract 10 BTFSC STATUS,C GOTO binbc0 ADDLW D'10' ; done: undo subtract SWAPF tmp0,F ; upper digit ADDWF tmp0,W ; plus lower digit RETURN hexchr ANDLW H'0F' ; 0..15 to '0'..'F' MOVWF tmp0 ; store SUBLW D'09' ; check if >= 10 (carry clr) MOVLW D'48' BTFSS STATUS,C ; add 7 if carry clr ADDLW D'07' ADDWF tmp0,W RETURN disphex MOVWF tmp2 ; display as two hex chars, save SWAPF tmp2,W CALL hexchr CALL dispch MOVF tmp2,W CALL hexchr CALL dispch MOVF tmp2,W ; restore RETURN home MOVLW H'80' ; cursor to line 0 ; fall through to outcmd outcmd MOVWF tmp1 ; tmp0 is used by pollbsy CALL pollbsy ; command, write, ena low GOTO outbyte dispch MOVWF tmp1 ; tmp0 is used by pollbsy CALL pollbsy MOVLW B'00001000' ; data, write, ena low outbyte MOVWF PORTB MOVF tmp1,W ; high nibble first ANDLW H'F0' IORWF PORTB,F BSF PORTB,1 ; ena high BCF PORTB,1 ; ena low MOVLW H'0F' ANDWF PORTB,F SWAPF tmp1,W ; low nibble ANDLW H'F0' IORWF PORTB,F BSF PORTB,1 ; ena high BCF PORTB,1 ; ena low MOVF tmp1,W ; restore W RETURN dispdig GOTO $+DSPLY ; skip for DL1414T: GOTO dispdi1 ; LM054 GOTO dispdi2 ; DL1414T dispdi1 MOVLW H'0F' ; digit at FSR ANDWF 0,F BTFSC digo,2 ; 4 digits out? RETLW 0 MOVF digo,F ; 0 digits out? BTFSS STATUS,Z GOTO dispd0 MOVF dign,W ; digit nr 4? XORLW 4 BTFSC STATUS,Z GOTO dispd0 MOVF 0,F ; digit > 0? BTFSC STATUS,Z RETLW 0 dispd0 MOVF 0,W ; write digit ADDLW '0' CALL dispch INCF digo,F BTFSC digo,2 ; 4 digits out? GOTO dispd4 CALL getdot ; decimal point XORLW 0 BTFSS STATUS,Z CALL dispch RETLW 0 dispd4 CALL getun0 ; unit (Hz, kHz, MHz) CALL dispch CALL getun1 CALL dispch CALL getun2 CALL dispch RETLW 0 dispdi2 MOVLW H'0F' ; digit at FSR ANDWF 0,F BTFSC digo,2 ; 4 digits (3+unit) out? RETLW 0 MOVF digo,F ; 0 digits out? BTFSS STATUS,Z GOTO dspd0 MOVF dign,W ; digit nr 4? XORLW 4 BTFSC STATUS,Z GOTO dspd0 MOVF 0,F ; digit > 0? BTFSC STATUS,Z RETLW 0 dspd0 MOVF 0,W ; write digit ADDLW '0' CALL dspch CALL getdp ; decimal point / unit XORLW 0 BTFSS STATUS,Z CALL dspch RETLW 0 dspch MOVWF tmp0 ; to DL1414T at digo MOVF PORTA,W ANDLW H'F6' BTFSC tmp0,5 IORLW H'01' BTFSC tmp0,6 IORLW H'08' MOVWF PORTA MOVF tmp0,W ANDLW H'1F' BTFSS digo,0 IORLW H'80' BTFSS digo,1 IORLW H'40' IORLW H'20' ; wr high MOVWF PORTB ANDLW H'DF' ; wr low MOVWF PORTB IORLW H'20' ; wr high MOVWF PORTB INCF digo,F RETLW 0 ;;; clock display for xtal adjustment ckcali BCF PORTB,0 ; should be low when driven BSF STATUS,P ; bank 1 BCF _OPTION,7 ; Port B pullups BSF _TRISB,0 ; B0 input BCF STATUS,P ; bank 0 MOVLW 1 ; wait for stable input CALL delayw BTFSS PORTB,0 ; if pin pulled to gnd: GOTO cali ; clock for xtal adjustment BSF STATUS,P ; bank 1 BSF _OPTION,7 ; Port B no pullups BCF _TRISB,0 ; B0 output BCF STATUS,P ; bank 0 RETLW 0 cali BSF STATUS,P ; bank 1 MOVLW B'11011111' ; no pu, risi, mclk, hilo, presc to WDT MOVWF _OPTION BCF _TRISB,0 ; B0 output BCF STATUS,P ; bank 0 CLRF tim1 ; seconds CLRF tim2 ; minutes CLRF tim3 ; hours CLRF TMR0 ; reset timer and prescaler MOVLW B'10100000' ; enable timer interrupt MOVWF INTCON cali0 MOVLW H'BE' ; load -3906 (-1s) to cnt MOVWF cnt1 MOVF tim0,W ; -3907 every 4th second ANDLW H'03' BTFSC STATUS,Z DECF cnt1,F MOVLW H'F0' MOVWF cnt2 CALL home ; clock display MOVF tim3,W ; display hours CALL binbcd CALL disphex MOVLW ':' CALL dispch MOVF tim2,W ; display minutes CALL binbcd CALL disphex MOVLW ':' CALL dispch MOVF tim1,W ; display seconds CALL binbcd CALL disphex INCF tim1,F ; inc seconds MOVLW D'60' XORWF tim1,W BTFSS STATUS,Z GOTO cali1 CLRF tim1 INCF tim2,F ; inc minutes MOVLW D'60' XORWF tim2,W BTFSS STATUS,Z GOTO cali1 CLRF tim2 INCF tim3,F ; inc hours MOVLW D'24' XORWF tim3,W BTFSC STATUS,Z CLRF tim3 cali1 MOVF cnt1,W ; wait for a new second BTFSS STATUS,Z GOTO cali1 MOVF cnt2,W BTFSS STATUS,Z GOTO cali1 GOTO cali0 ORG H'300' ; rom tables getdp MOVLW B'00011' ; PCLATH to this segment MOVWF PCLATH MOVF dign,W ; digit count ANDLW H'0F' ; 0..15 ADDWF PC,F ; jump to table RETLW 0 ; 0 RETLW 'm' ; 1 RETLW 0 ; 2 RETLW 0 ; 3 RETLW '.' ; 4 RETLW 0 ; 5 RETLW 0 ; 6 RETLW 'K' ; 7 RETLW 0 ; 8 RETLW 0 ; 9 RETLW 'M' ; 10 RETLW 0 ; 11 RETLW 0 ; 12 RETLW 'G' ; 13 RETLW 0 ; 14 RETLW 0 ; 15 getdot MOVLW B'00011' ; PCLATH to this segment MOVWF PCLATH MOVF dign,W ; digit count ANDLW H'0F' ; 0..15 ADDWF PC,F ; jump to table RETLW 0 ; 0 RETLW '.' ; 1 RETLW 0 ; 2 RETLW 0 ; 3 RETLW '.' ; 4 RETLW 0 ; 5 RETLW 0 ; 6 RETLW '.' ; 7 RETLW 0 ; 8 RETLW 0 ; 9 RETLW '.' ; 10 RETLW 0 ; 11 RETLW 0 ; 12 RETLW '.' ; 13 RETLW 0 ; 14 RETLW 0 ; 15 getun0 MOVLW B'00011' ; PCLATH to this segment MOVWF PCLATH DECF dign,W ; digit count ANDLW H'07' ; 0..15 ADDWF PC,F ; jump to table RETLW 0 ; 0 (Hz) RETLW 0 ; 1 (Hz) RETLW 0 ; 2 (Hz) RETLW 2 ; 3 (kHz) RETLW 2 ; 4 (kHz) RETLW 2 ; 5 (kHz) RETLW 5 ; 6 (MHz) RETLW 5 ; 7 (MHz) getun1 MOVLW B'00011' ; PCLATH to this segment MOVWF PCLATH DECF dign,W ; digit count ANDLW H'07' ; 0..15 ADDWF PC,F ; jump to table RETLW 1 ; 0 (Hz) RETLW 1 ; 1 (Hz) RETLW 1 ; 2 (Hz) RETLW 3 ; 3 (kHz) RETLW 3 ; 4 (kHz) RETLW 3 ; 5 (kHz) RETLW 6 ; 6 (MHz) RETLW 6 ; 7 (MHz) getun2 MOVLW B'00011' ; PCLATH to this segment MOVWF PCLATH DECF dign,W ; digit count ANDLW H'07' ; 0..15 ADDWF PC,F ; jump to table RETLW ' ' ; 0 (Hz) RETLW ' ' ; 1 (Hz) RETLW ' ' ; 2 (Hz) RETLW 4 ; 3 (kHz) RETLW 4 ; 4 (kHz) RETLW 4 ; 5 (kHz) RETLW 7 ; 6 (MHz) RETLW 7 ; 7 (MHz) loadcgr MOVLW B'00011' ; PCLATH to pattern MOVWF PCLATH MOVLW H'40' ; character generator rom CALL outcmd CLRF tmp2 ; byte counter loadcg0 MOVF tmp2,W XORLW D'64' ; test if all 64 bytes out BTFSC STATUS,Z RETLW 0 ; return if so MOVF tmp2,W CALL pattern ; get byte from table, write to cgr CALL dispch INCF tmp2,F ; point to next byte GOTO loadcg0 pattern ADDWF PC,F ; return char from table below cgrtb0 RETLW B'01001' ; Hz RETLW B'01001' RETLW B'01001' RETLW B'01111' RETLW B'01001' RETLW B'01001' RETLW B'01001' RETLW B'00000' cgrtb1 RETLW B'00000' ; RETLW B'00000' RETLW B'01111' RETLW B'00010' RETLW B'00100' RETLW B'01000' RETLW B'01111' RETLW B'00000' cgrtb2 RETLW B'01000' ; kHz RETLW B'01000' RETLW B'01001' RETLW B'01010' RETLW B'01100' RETLW B'01010' RETLW B'01001' RETLW B'00000' cgrtb3 RETLW B'01001' ; RETLW B'01001' RETLW B'01001' RETLW B'01111' RETLW B'01001' RETLW B'01001' RETLW B'01001' RETLW B'00000' cgrtb4 RETLW B'00000' ; RETLW B'00000' RETLW B'01111' RETLW B'00010' RETLW B'00100' RETLW B'01000' RETLW B'01111' RETLW B'00000' cgrtb5 RETLW B'01000' ; MHz RETLW B'01101' RETLW B'01010' RETLW B'01010' RETLW B'01000' RETLW B'01000' RETLW B'01000' RETLW B'00000' cgrtb6 RETLW B'10100' ; RETLW B'10100' RETLW B'10100' RETLW B'10111' RETLW B'10100' RETLW B'10100' RETLW B'10100' RETLW B'00000' cgrtb7 RETLW B'10000' ; RETLW B'10000' RETLW B'10111' RETLW B'10001' RETLW B'10010' RETLW B'10100' RETLW B'10111' RETLW B'00000' END;