;************************************************************************** ; LA001.ASM ; ; PROGRAM: Simple Pic Based Logic Analyser and Frequency Meter. ; ; DESCRIPTION: A simple logic analyser that samples port A ; and a frequency meter that uses TMR0 clocked externally. ; ; ; AUTHOR: Douglas Rice ; Copyright 2000 ; ; Crystal: 4MHz ; ; I/O used:- ; PORTA:0 Input, trigger ; PORTA:1 Input ; PORTA:2 Input ; PORTA:3 Input ; PORTA:4 Input, TMRO clk input ; ; ; Port B is used for the LCD ; ; 12/02/2000 Chaged Button Names ; INCLUDE "p16F84.inc" ; ;************************************************************************** LIST P=16F84, R=DEC __idlocs 0x1234 __config _XT_OSC&_PWRTE_ON & _WDT_OFF cblock 0x0c endc ;-------------------------------------------------------------------------- ; Sec 1. Equates and Constants ;-------------------------------------------------------------------------- ; The General Purpose Registers start at the end of the ; Special Purpose Registers. ; IPMentState values ; in normal running or in time setting modes ; ;;SET_NORM EQU 0 ;;SET_SET EQU 2 ; STstate flag to indicate if beep is enabled. ; STstate is a variable of flag bits ;;STrelay EQU 0 ;;STbeep EQU 1 ; DoTimeSlice bits ; these bits are set to schedule a timer chain event DTsS4event EQU 0 ; DTsSevent EQU 1 DTsMevent EQU 2 DTSTriggered EQU 3 ; a capture should take place DTsTurnOff EQU 4 DTsMeasFreq EQU 5 DTsDispFreq EQU 6 DTsDispCount EQU 7 ; IPtrigMenu DTSWaitForEdge EQU 0 ; if set, then wait for 0 to 1 edge on PA0 DTSSingle EQU 1 ; IPtrigMenu DTSFast EQU 0 ;-------------------------------------------------------------------------- ; Sec 1.1 Button and LED ;-------------------------------------------------------------------------- BUTTON_RATE EQU 5 ; RATE - Top Button BUTTON_EDG EQU 6 ; EDG - Bottom Buttom BUTTON_TRIG EQU 7 ; TRIG - Middle Button LCDnumSamples EQU 40 ; PORTA binary values ;-------------------------------------------------------------------------- ; Sec 1.2 Button and LED ;-------------------------------------------------------------------------- ; PORTB bits ;;RELAY EQU 0 ;;RS232OUT EQU 1 ;;SPEAKER EQU 2 ;;KEYFLASH EQU 3 ;-------------------------------------------------------------------------- ; Sec 2.0 Variables ;-------------------------------------------------------------------------- ; Variables start 0x0C ; ; Variables for FlashLED ( FL ) process ; ; DoTimeSlice Bits, to schedule, set bit LCDanalBuff EQU 0x4F - LCDnumSamples cblock DoTimeSlice CLtmr4sec ; counts quarter seconds CLnbcdS ; stores current time IPlast ; Input variables IPnew IPbuttonEvent IPsetState DispState ; Display State IPmenu IPtrigMenu LCDcnt3 LCDAnalSpeed ENDC cblock ; variables used in BCD.INC BCDip3 BCDip2 BCDip1 BCDip0 BCDop0 ;equ 13 ; RAM Assignments BCDop1 ;equ 14 BCDop2 ;equ 15 BCDop3 ;equ 16 BCDop4 ;equ 17 BCDcount ;equ 18 BCDtemp ;equ 19 endc TEST_STRADDLE MACRO START if high( $ ) != high( START ) Error "Table straddles Page Boundary " endif endm ;-------------------------------------------------------------------------- ; Sec 3. Program Code ;-------------------------------------------------------------------------- ORG 0 GOTO Start ORG 4 RETFIE GOTO Intrtn ;-------------------------------------------------------------------------- ; Sec 3.1 Main Program Init Code ;-------------------------------------------------------------------------- Start ; Enable Interupts MOVLW H'00' MOVWF INTCON ; Set up PortB:7 as output. BSF STATUS, RP0 MOVLW 0XF0 MOVWF TRISB MOVLW 0xFF ; Make PORTA 3:0 INPUTS. MOVWF TRISA BCF STATUS, RP0 CLRF DoTimeSlice CLRF IPmenu CLRF IPtrigMenu CLRF IPsetState CLRF DispState CALL IPmenuSetSpeed MOVWF LCDAnalSpeed ; Change Prescaler CLRWDT ; Configure Tmr 0 BSF STATUS,RP0 ; Set up prescaller for 8192 / 16 = 512 ticks perseconds. MOVLW 0x0 + 2 ; For Tmr0 0=/2, 1=/4, 2=/8,3=/16 MOVWF OPTION_REG BCF STATUS,RP0 ; Set up prescaller for 8192 / 16 = 512 ticks perseconds. MOVLW 4 MOVWF CLtmr4sec CALL LCDstart CALL IPnextDisplay BSF DoTimeSlice,DTSTriggered ; Run the logig analyser GOTO MainLoop MLinitLoop BTFSS INTCON,T0IF GOTO MLinitLoop ; TMR0 timeout BCF INTCON,T0IF DECFSZ LCDcnt,f GOTO MLinitLoop ;-------------------------------------------------------------------------- ; Sec 3.2 Main Program ;-------------------------------------------------------------------------- MainLoop ; Enable Interupts ; Disable Interupts MLdisableInt CALL CLtimeslice ; Any events that exist BTFSC DoTimeSlice,DTsS4event ; On 1/4 Second Tick CALL SS4tick ; Any events that exist BTFSC DoTimeSlice,DTsSevent ; On Second Tick CALL SStick BTFSC DoTimeSlice,DTSTriggered ; Run the logig analyser CALL LCDanal BTFSC DoTimeSlice,DTsTurnOff ; CALL IPpowerDown BTFSC DoTimeSlice,DTsMeasFreq ; Run the logig analyser CALL FRfreqMeter BTFSC DoTimeSlice,DTsDispFreq ; Run the logig analyser CALL FRdisplayResult BTFSC DoTimeSlice,DTsDispCount ; Run the logig analyser CALL CNdispCount BTFSS IPbuttonEvent,BUTTON_RATE ; On BUTTON_RATE Press CALL IPRATEPressed BTFSS IPbuttonEvent,BUTTON_EDG ; On BUTTON_EDG Press CALL IPedgePressed BTFSS IPbuttonEvent,BUTTON_TRIG ; On BUTTON_TRIG Press CALL IPtrigPressed GOTO MainLoop ;-------------------------------------------------------------------------- ; Sec 3.3 LCD Logic Analyser. ;-------------------------------------------------------------------------- ; ; If triggered, then Continous/single on button ; wait for trigger ; LCDanal ; INIT for the next capture MOVFW PORTB BCF INTCON, RBIF CLRF LCDcnt3 MOVLW LCDanalBuff MOVWF FSR MOVLW LCDnumSamples MOVWF LCDcnt2 BTFSS IPtrigMenu,DTSWaitForEdge ; Trigger a Logic Capture GOTO LCDanalCapture ; Trigger on rising edge of PortA LCDanalWtrig1 BTFSC INTCON, RBIF RETURN BTFSC PORTA,0 GOTO LCDanalWtrig1 LCDanalWtrig2 BTFSC INTCON, RBIF RETURN BTFSS PORTA,0 GOTO LCDanalWtrig2 ; Now capture a trace LCDanalCapture BTFSS IPmenu,0 ; Trigger a Logic Capture GOTO LCDanalLoop BTFSS IPmenu,1 ; Trigger a Logic Capture GOTO LCDanalLoop BTFSS IPmenu,2 ; Trigger a Logic Capture GOTO LCDanalLoop ; GOTO LCDanalLoopF GOTO LCDanalLoopDelta LCDanalLoop MOVFW PORTA ANDLW 0x1F MOVWF INDF INCFSZ FSR,F NOP MOVFW LCDAnalSpeed MOVWF LCDcnt3 LCDanalLoop2 DECFSZ LCDcnt3,f GOTO LCDanalLoop2 BTFSC INTCON, RBIF GOTO LCDanalDisp DECFSZ LCDcnt2,f GOTO LCDanalLoop GOTO LCDanalDisp ; Now capture a trace LCDanalLoopF MOVFW PORTA ANDLW 0x1F MOVWF INDF INCFSZ FSR,F DECFSZ LCDcnt2,f GOTO LCDanalLoopF GOTO LCDanalDisp LCDanalLoopDelta MOVFW PORTA ANDLW 0x1F xorwf INDF,W bz LCDanalLoopDelta1 xorwf INDF,W ; increment buffer pointer and store new sample INCFSZ FSR,F NOP MOVWF INDF ; have we got to the end of memory DECFSZ LCDcnt2,f LCDanalLoopDelta1 BTFSC INTCON, RBIF GOTO LCDanalDisp GOTO LCDanalLoopDelta GOTO LCDanalDisp LCDanalDisp ; clear RB change of button pressed flag MOVFW PORTB BCF INTCON, RBIF CALL LCDclearRightTop MOVLW LDPI + 5*NUM_OF_CHARS -1 CALL LCDwrtCmd MOVLW SWM+DEC CALL LCDwrtCmd MOVLW LCDanalBuff MOVWF FSR MOVLW LCDnumSamples MOVWF LCDcnt2 LCDanalDispLoop MOVFW INDF ANDLW 0x1F CALL LCDwrtData INCFSZ FSR,F NOP DECFSZ LCDcnt2,f GOTO LCDanalDispLoop GOTO IPnextMeasurement ;-------------------------------------------------------------------------- ; Sec 3.3 Jump Table for running or time setting mode ;-------------------------------------------------------------------------- LCDInit ; We run this from the toggle state and ; Prevent update of time display on second ticks. RETURN include "lcd_nec.inc" ; the code below must be kept together. LCDgetByte ; we should have set up PCLATH ; and reset LCDgetCharFlag BCF LCDPortB,LCDgetCharFlag MOVLW high $ MOVWF PCLATH MOVFW LCDstrPtr; INCF LCDstrPtr,f ADDWF PCL,f LCDstrs LCDstrLFast equ $ - LCDstrs DT "del" GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast1 equ $ - LCDstrs DT "x1 " GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast2 equ $ - LCDstrs DT "x2 " GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast3 equ $ - LCDstrs DT "x4 " GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast4 equ $ - LCDstrs DT "x8 " GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast5 equ $ - LCDstrs DT "x16" GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast6 equ $ - LCDstrs DT "x32" GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast7 equ $ - LCDstrs DT "x64" GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLFast8 equ $ - LCDstrs DT "del" GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLCont equ $ - LCDstrs DT "C " GOTO LCDgetByteEnd1 LCDstrLContEdge equ $ - LCDstrs DT "C_- " GOTO LCDgetByteEnd1 LCDstrLSingle equ $ - LCDstrs DT "S " GOTO LCDgetByteEnd1 LCDstrLSingleEdge equ $ - LCDstrs DT "S_- " GOTO LCDgetByteEnd1 LCDstrLFreq equ $ - LCDstrs DT "Freq" GOTO LCDgetByteEnd1 LCDstrLBlank equ $ - LCDstrs DT " " GOTO LCDgetByteEnd1 LCDstrLCount equ $ - LCDstrs DT "Count " GOTO LCDgetByteEnd1 LCDstrLTime equ $ - LCDstrs DT "Time " GOTO LCDgetByteEnd1 LCDstrLBye equ $ - LCDstrs DT "Goodbye!" GOTO LCDgetByteEnd1 LCDLastStr TEST_STRADDLE LCDgetByte ; Jump into these to select how many spaces printed ; at the end, so that 9 chars are printed. LCDgetByteEnd0 DECF LCDeraseCnt,f LCDgetByteEnd1 DECF LCDeraseCnt,f LCDgetByteEnd2 DECF LCDeraseCnt,f LCDgetByteEnd3 DECF LCDeraseCnt,f LCDgetByteEnd4 DECF LCDeraseCnt,f LCDgetByteEnd5 DECF LCDeraseCnt,f LCDgetByteEnd6 BSF LCDPortB,LCDgetCharFlag RETURN ;-------------------------------------------------------------------------- ; Sec 4. Subroutines, procedures and functions ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; Sec 4.1 Button Poll Routine ;-------------------------------------------------------------------------- IPtimeslice ; ----___ ; --_____ ; ; This reads all Port B inputs and looks for Press MOVFW IPnew MOVWF IPlast MOVFW PORTB MOVWF IPnew ; IP last contains new setting, IPlast contains previous COMF IPlast,W IORWF IPnew,W ; now force IPbuttonEvent bits to low for new pressed button ; the service routine should set the bit to clear the event. ANDWF IPbuttonEvent,F RETURN ;-------------------------------------------------------------------------- ; Sec 4.2 ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; Sec 4.3 Clock Chain Routine ;-------------------------------------------------------------------------- CLtimeslice ; Assuming: ; Crystal = 32.768 kHz ; Prescaller ticks at Crystal / 4 or 8192 ticks per second. ; Prescaller set to divide by 8, so ; Tmr0 ticks at 128 ticks per second ; Tmr0 times out once per 2 seconds. ; BTFSS INTCON,T0IF RETURN ; TMR0 timeout BCF INTCON,T0IF BSF DoTimeSlice,DTsS4event ; This ticks 1 per second, ; DECFSZ CLtmr4sec,f RETURN ; divide by 4 MOVLW 4 MOVWF CLtmr4sec GOTO CLbcdS ;-------------------------------------------------------------------------- ; Sec 4.4 BDC Clock Chain Routine ;-------------------------------------------------------------------------- ; BCD Counter - Seconds CLbcdS BSF DoTimeSlice,DTsSevent RETURN ;-------------------------------------------------------------------------- ; Sec 4.5 Event Handler Routines - Timer ;-------------------------------------------------------------------------- SS4tick ; do this 4 times a second BCF DoTimeSlice,DTsS4event CALL IPtimeslice RETURN SStick BCF DoTimeSlice,DTsSevent RETURN ;-------------------------------------------------------------------------- ; Sec 4.6 Event Handler Routine - Buttons ;-------------------------------------------------------------------------- ; come here and combine the current state and the current event to index into ; the state jump table. ; IPRATEPressed ; Top Button BSF IPbuttonEvent,BUTTON_RATE ; Check for Turn off, Look at IPlast to see if the other button is already pressed BTFSS IPlast,BUTTON_EDG GOTO IPpowerDown1 ; set the speed INCFSZ IPmenu,f NOP CALL IPmenuSetSpeed MOVWF LCDAnalSpeed GOTO IPnextDisplay IPedgePressed ; Bottom Buttom BSF IPbuttonEvent,BUTTON_EDG ; Check for Turn off, Look at IPlast to see if the other button is already pressed BTFSS IPlast,BUTTON_RATE GOTO IPpowerDown1 INCFSZ IPtrigMenu,f NOP GOTO IPnextDisplay IPtrigPressed ; middle Button BSF IPbuttonEvent,BUTTON_TRIG ; BTFSS IPtrigMenu,2 MOVLW high $ MOVWF PCLATH MOVFW IPtrigMenu ANDLW 0x07 ADDWF PCL,F goto IPtrigPressed1 ; anal goto IPtrigPressed1 ; anal goto IPtrigPressed1 ; anal goto IPtrigPressed1 ; anal goto IPtrigPressed2 ; freq gOTO IPtrigPressed2 ; blank goto IPtrigPressed3 ; inc count goto IPtrigPressed2 ; freq TEST_STRADDLE IPtrigPressed IPtrigPressed1 BSF DoTimeSlice,DTSTriggered RETURN IPtrigPressed2 RETURN IPtrigPressed3 CALL IPincCount ; inc count GOTO CNdispCount ; blank IPincCount ; These are the ah,am,al INCFSZ BCDop0,F NOP MOVLW 0x06 ADDWF BCDop0,w SKPDC RETURN MOVLW 0x10 -.10 ; increment digit ADDWF BCDop0,f MOVFW BCDop0 ADDLW 0x60 ; look for 10 digit. SKPC RETURN CLRF BCDop0 ; increment digt INCFSZ BCDop1,F NOP MOVLW 0x06 ADDWF BCDop1,w SKPDC RETURN MOVLW 0x10 -.10 ADDWF BCDop1,f MOVFW BCDop1 ADDLW 0x60 ; look for 10 digit. SKPC RETURN CLRF BCDip1 ; increment digt INCFSZ BCDop2,F NOP MOVLW 0x06 ADDWF BCDop2,w SKPDC RETURN MOVLW 0x10 -.10 ADDWF BCDop2,f MOVFW BCDop2 ADDLW 0x60 ; look for 10 digit. SKPC RETURN CLRF BCDop2 RETURN ; IPnextDisplay ; Display current settings in the bottom Right of the display MOVLW LCDstrLBlank CALL LCDwrtStrBL ; Continuous or once CALL IPtrigMenuJT CALL LCDwrtStrBR ; Speed CALL IPmenuJT CALL LCDaddStr ; if the trig menu is 4 to 7 then display frequency MOVLW high $ MOVWF PCLATH MOVFW IPtrigMenu ANDLW 7 ADDWF PCL,f goto LCDanalDisp goto LCDanalDisp goto LCDanalDisp goto LCDanalDisp goto FRdisplayResult1 goto FRdisplayResult1 goto CNdispCount0 goto CNdispCount TEST_STRADDLE IPnextDisplay CNdispCount0 BCF DoTimeSlice,DTSTriggered BCF DoTimeSlice,DTsMeasFreq BCF DoTimeSlice,DTsDispFreq ; Run the logig analyser CLRF BCDop3 CLRF BCDop2 CLRF BCDop1 CLRF BCDop0 RETURN IPmenuJT MOVLW high $ MOVWF PCLATH MOVFW IPmenu ANDLW 0x07 ADDWF PCL,f RETLW LCDstrLFast1 RETLW LCDstrLFast2 RETLW LCDstrLFast3 RETLW LCDstrLFast4 RETLW LCDstrLFast5 RETLW LCDstrLFast6 RETLW LCDstrLFast7 RETLW LCDstrLFast8 TEST_STRADDLE IPmenuJT IPmenuSetSpeed MOVLW high $ MOVWF PCLATH MOVFW IPmenu ANDLW 0x07 ADDWF PCL,f ; set choice State Table - limited to 2 states and two events RETLW 0x1 RETLW 0x2 RETLW 0x4 RETLW 0x8 RETLW 0x10 RETLW 0x20 RETLW 0x40 RETLW 0x80 TEST_STRADDLE IPmenuSetSpeed IPtrigMenuJT MOVLW high $ MOVWF PCLATH MOVFW IPtrigMenu ANDLW 0x07 ADDWF PCL,f ; set choice State Table - limited to 2 states and two events RETLW LCDstrLCont RETLW LCDstrLContEdge RETLW LCDstrLSingle RETLW LCDstrLSingleEdge RETLW LCDstrLFreq RETLW LCDstrLBlank RETLW LCDstrLCount RETLW LCDstrLTime TEST_STRADDLE IPtrigMenuJT IPpowerDown1 ; Display the Goodbye and then wait for the buttons to be released. MOVLW LCDstrLBye CALL LCDwrtStrBL BSF DoTimeSlice,DTsTurnOff ; Run the logig analyser RETURN IPpowerDown ; The buttons are still pressed BTFSS IPlast,BUTTON_EDG RETURN BTFSS IPlast,BUTTON_RATE RETURN ; No buttons are pressed so now you can turn off ; now read the Keyboard Inputs so that pin change Change can work MOVLW 0xFF MOVWF PORTB ; read port B MOVFW PORTB MOVLW 0 ; Power down if BUTTON_EDG is pressed when BUTTON_RATE is pressed ; read Port B, enable RB change but not GIE ; Set up PortB:7 as output. BSF STATUS, RP0 MOVLW 0XF0 MOVWF TRISB MOVLW 0x00 ; Make PORTA OUTPUTS. MOVWF TRISA BCF STATUS, RP0 CLRF PORTA BSF PORTB,LCDbitRESETline ; now read the Keyboard Inputs so that pin change Change can work MOVFW PORTB MOVLW 0 MOVWF INTCON ; clear all interrupts BSF INTCON,RBIE MOVFW PORTB SLEEP ; ; ; wake up here, as GIE is not enabled. NT ; this code is horrible but is a get it to work bodge ; crash out GOTO Start RETURN IPnextMeasurement ; this routine works out what to do after the display has been updated MOVLW ~( 1<< DTsMeasFreq | 1 << DTSTriggered | 1 << DTsTurnOff ) ANDWF DoTimeSlice,f CALL IPnextMeasJT IORWF DoTimeSlice,f RETURN ;DTsS4event EQU 0 ; ;DTsSevent EQU 1 ;DTsMevent EQU 2 DTSTriggered EQU 3 ; a capture should take place DTsTurnOff EQU 4 DTsMeasFreq EQU 5 DTsDispFreq EQU 6 DTsDispCount EQU 7 IPnextMeasJT ; if the trig menu is 4 to 7 then display frequency MOVLW high $ MOVWF PCLATH MOVFW IPtrigMenu ANDLW 7 ADDWF PCL,f RETLW 1 << DTSTriggered ; C RETLW 1 << DTSTriggered ; C _- RETLW 0 ; S RETLW 0 ; S_- RETLW 1 << DTsMeasFreq ; freq RETLW 0 ; blank RETLW 0 ; count RETLW 0 ; time TEST_STRADDLE IPnextMeasJT ;-------------------------------------------------------------------------- ; Sec 4.8 EEprom Routines ;-------------------------------------------------------------------------- EEread ; w contains address BCF STATUS,RP0 MOVWF EEADR BSF STATUS,RP0 BSF EECON1,RD BCF STATUS,RP0 MOVFW EEDATA RETURN EEwrt ; blocking, EEADR and EEDATA set up. BCF STATUS,RP0 MOVWF EEDATA BSF STATUS,RP0 BCF INTCON,GIE BCF EECON1,EEIF BSF EECON1,WREN MOVLW 0x55 MOVWF EECON2 MOVLW 0xAA MOVWF EECON2 BSF EECON1,WR ; Now wait for EEwrt to finish write EEwaitForWrt ; block until EEPROM write has finished. BCF EECON1,WREN ; disable EROM BTFSS EECON1,EEIF GOTO EEwaitForWrt BCF EECON1,EEIF ; EEPROM finished BCF STATUS,RP0 RETURN ;-------------------------------------------------------------------------- ; Sec 4.11 Frequency Counter Code ;------------------------------------------------------------------------- cblock current lasttmr0 ;BCDip0,BCDip1,BCDip2,BCDip3 tc0,tc1,tc2,tc3,tc4 endc incCnt ; get current count movfw current movwf lasttmr0 movfw TMR0 movwf current subwf lasttmr0,w ; we don't need to worry about the carry. sublw 0 addwf BCDip0,f ; t skpc ; t+0 retlw -24 ; t+1 these values are used to adjust the main timing loop. incfsz BCDip1,f ; t+2 retlw -26 ; t+3 incfsz BCDip2,f ; t+4 retlw -28 ; t+5 incfsz BCDip3,f ; t+6 retlw -30 ; t+7 FRfreqMeter1 ; we arm to display first of all BSF DoTimeSlice,DTsDispFreq ; we arm to measure BCF DoTimeSlice,DTsMeasFreq BCF DoTimeSlice,DTSTriggered CLRF IPtrigMenu DECFSZ IPtrigMenu,f NOP return FRfreqMeter ; Change Prescaler and connect TMR0 ip to external CLRWDT ; Configure Tmr 0 BSF STATUS,RP0 ; Set up prescaller for 8192 / 16 = 512 ticks perseconds. MOVLW 0x0 + 0x20 + 0 ; T0CS + For Tmr0 0=/2, 1=/4, 2=/8,3=/16 MOVWF OPTION_REG BCF STATUS,RP0 ; clear Pin Change interrupt MOVFW PORTB BCF INTCON, RBIF clrf BCDip0 clrf BCDip1 clrf BCDip2 clrf BCDip3 ; 2,000,000 = 1E8480 ; using prescale of div 2 ; These seem to work, ; but still underead a litte bit movlw 0x81 movwf tc0 movlw 0x85 movwf tc1 movlw 0x1F movwf tc2 movfw TMR0 movwf current freqMeter0 BSF PORTA,0 ; 21 cycles call incCnt BCF PORTA,0 FreqDelay ; w contains a fiddle factor to adjust this delay ; get current count ; we don't need to worry about the carry. addwf tc0,f ;t ;t= 0 skpnc goto fd1 ;t+1 these values are used to adjust the main timing loop. ; decfsz tc1,f ;t+2 goto fd2 ;t+3 decfsz tc2,f ;t+4 goto fd3 ;t+5 goto fd4 fd1 ; replace NOP instructions with a test to see if buttons have been pressed ; note that theses also take 2 clock cycles btfsc INTCON,RBIF ;t+3 goto fdEscape ;t+4 fd2 btfsc INTCON,RBIF ;t+5 goto fdEscape ;t+6 ; nop ;t+5 ; nop ;t+6 fd3 goto freqMeter0 ;t+7 fd4 ; we have a reading so arm to display it. BCF DoTimeSlice,DTsMeasFreq BSF DoTimeSlice,DTsDispFreq fdEscape ; come here if escaped out offrequency measurement. ; The half measured frequency should not be displayed. ; Change Prescaler back to TMR0 clocked by Internal. CLRWDT ; Configure Tmr 0 BSF STATUS,RP0 ; Set up prescaller for 8192 / 16 = 512 ticks perseconds. MOVLW 0x0 + 2 ; For Tmr0 0=/2, 1=/4, 2=/8,3=/16 MOVWF OPTION_REG BCF STATUS,RP0 ; Set up prescaller for 8192 / 16 = 512 ticks perseconds. MOVLW 4 MOVWF CLtmr4sec return ; now run into the convert and display routine ; display current count FRdisplayResult1 ; we arm to display first of all clrf BCDip0 clrf BCDip1 clrf BCDip2 clrf BCDip3 FRdisplayResult #DEFINE buildbcdBinDec24 BCF PORTA,0 ; call bcdBinDec24 call B2_BCD ; After conversion the Decimal Number CNdispCount ; now set up the display for the display. CALL LCDclearRightTop MOVLW LDPI + 5*NUM_OF_CHARS -1 CALL LCDwrtCmd SWAPF BCDop3,w andlw 0x0F ADDLW 0x30 CALL LCDwrtChar MOVFW BCDop3 andlw 0x0F ADDLW 0x30 CALL LCDwrtChar SWAPF BCDop2,w andlw 0x0F ADDLW 0x30 CALL LCDwrtChar MOVFW BCDop2 andlw 0x0F ADDLW 0x30 CALL LCDwrtChar SWAPF BCDop1,w andlw 0x0F ADDLW 0x30 CALL LCDwrtChar MOVFW BCDop1 andlw 0x0F ADDLW 0x30 CALL LCDwrtChar SWAPF BCDop0,w andlw 0x0F ADDLW 0x30 CALL LCDwrtChar MOVFW BCDop0 andlw 0x0F ADDLW 0x30 CALL LCDwrtChar ; we have displayed it so prevent another display GOTO IPnextMeasurement ;-------------------------------------------------------------------------- ; Sec 4.10 Binary to BCD -Procedure ;------------------------------------------------------------------------- include "bcd.inc" ;-------------------------------------------------------------------------- ; Sec 5.0 Interrupt Routines ;-------------------------------------------------------------------------- Intrtn ; Which Interupt ? ; No Context Save in these routines. ; BTFSC INTCON,2 ; GOTO IntTmr0 ; BTFSC INTCON,1 ; GOTO Intfint ; BTFSC INTCON,0 ; GOTO IntRbport IntTmr0 ; BCF INTCON,2 RETFIE Intfint ; BCF INTCON,1 ; RETFIE IntRbport ; BCF INTCON,0 RETFIE ;-------------------------------------------------------------------------- ; Program End ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; EEPROM data ;-------------------------------------------------------------------------- ORG 0x2100 ; first 2 on and off are general ones DE 0x24,0x00 ; 4 cblock LastVar endc END