;SUPER PROBE MkII.asm v42
;(V43 is latest see "files" for latest .asm)
;****************************************************
;Super Probe - Maximum Functions from Minimum Parts
;
; Current Functions
; -----------------
; Logic Probe
; Voltmeter
; Frequency Counter
; Event Counter
; Capacitor Test
; Signal Generator
; Diode Tester
; Logic Pulser
; Serial Generator (4 rates)
; Midi Generator
; r/c servo pulse
; Square Wave
; 20kHz digital noise
; 38KHz burst
; Stopwatch
;
; 29 added r/c square noise burst baudrates
; 29 added menu forward/back
; 30 added pwm function
; 31 reworked square wave for interrupt operation
; 32 fix logic probe function
; 33 (compatibility with new assembler)
; 34 fix dpcap syntax for hex values - last 2
; 35 add inductance measure
; 36 recalibrate inductance
; 37 inverted display anodes
; Versions above 37 by Heli Tejedor, helitp@arrakis.es, http_//heli.xbot.es
; 38 added 4 new baud rates and #define INVERT_A for new hardware
; 39 NEW mode hivolt scaled to 25.00 (multiply by 2500 and divide by 1023)
; mode volt scaled to 5.00 (multiply by 500 and divide by 1023)
; by Heli Tejedor, http_//heli.xbot.es, helitp@arrakis.es
; 40 New mode Servo R/C measure (pulse width) R/C.i Servo output is now R/C.o
; tested from 990us to 100ms (theoretically work from 10us to >16seg)
; 41 R/C.i measure pulse-width high and low, 10us resolution (=200kHz pulse)
; 42 Increase scan-rate to reduce flikering 22-6-2011 - Colin Mitchell
; Added STOP WATCH function 22-6-2011 - Colin Mitchell
; 43 Added LEDs feature - measures the voltage across a LED @20mA refer to "files"
;#define INVERT_A ; New hardware with transistor output for anodes
list p=16f870A ; list directive to define processor
#include ; processor specific variable definitions
errorlevel -302 ; Register not in bank 0 warning
radix dec
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF
& _PWRTE_ON & _HS_OSC & _LVP_OFF & _DEBUG_OFF & _CPD_OFF
#define VERS 042 ;Version to display
#define LPTIME 42990 ;calibration time for counter
#define MAXMODE 20 ;total operational modes - added stopwatch 23-6-2011
#define MAXBAUD 8 ;Serial generator baud rates
#define CLAMP PORTA,5 ;clamp input to T0
#define R20 PORTA,0 ;22 ohm direct feed
#define R100 PORTA,1 ;100 ohms
#define R470 PORTA,4 ;470 ohms
#define R150 PORTA,2 ;150
#define R10K PORTC,7 ;10k
#define R10KA PORTC,6 ;10k
#define R100K PORTA,3 ;100k feed to input
#define BLACK R150
#define WHITE R100
#define SOUT R20
#define BUT1 PORTC,4 ;button 1
#define BUT2 PORTC,5 ;button 2
; Data storange
org 20h
wsave equ 20H
ssave equ 21H
;icount equ 22H ; not used
bitcnt equ 22H ;
flag equ 23H
count equ 24H
scount equ 25H
csave equ 26H
ddata equ 27H ; was data
sdata equ 28H
temp equ 29H ;TE added - see line 576
ontime equ 2BH
oftime equ 2CH
isrvec equ 2DH
qtime equ 2EH ;comm timer for serial
timer equ 30H
freq equ 33H ;
pwmp equ 35H
mode equ 36H
rate equ 37H
baud equ 38H
midic equ 39H ;midi channel
pmode equ 3AH
hi equ 3BH
lo equ 3CH ; was low
rand equ 3DH
acc equ 40H ;32 bit register acc+0(40H)_MSB acc+3(43H)_LSB
xacc equ 44H ;aux 32 bit value
digits equ 48H ;segment data for LED
dignr equ 4CH
dp equ 4DH
ftimer equ 4EH
segmask equ 50H
dela equ 51H
bcd equ 54H ;10 digit packed bcd buffer (5 bytes)
;pto equ 59H ; not used
;pti equ 5AH ; not used
cnt equ 59H ;
ii equ 5AH
frame equ 5BH
place equ 5Ch
port_temp equ 5Dh
#define HOLD flag,0
#define DIR flag,1
#define SAVE flag,2
#define RUN flag,3
#define SWIT flag,4
#define HIV flag,5
#define MED_L flag,6
; Program Start
org 0
goto start
; Interrupt service routines ==========================================
org 4
isr
movwf wsave
swapf STATUS,w
movwf ssave
clrf STATUS
movf isrvec,w
addwf PCL,f
goto pwmi ; PWM interrupt
goto sqri ; square wave generator interrupt
; goto here for exit from interrupt
isrx
swapf ssave,w
movwf STATUS
swapf wsave,f
swapf wsave,w
retfie
; Table for number to seven segment conversion ========================
digseg
addwf PCL,f
retlw 3fh ;0
retlw 6h ;1
retlw 5bh ;2
retlw 4fh ;3
retlw 66h ;4
retlw 6dh ;5
retlw 7dh ;6
retlw 7h ;7
retlw 7fh ;8
retlw 67h ;9
; Get anode value for PORT C output
getano
addwf PCL,f
#ifdef INVERT_A
retlw 0FEh ; 1 inverted
retlw 0FDh ; 2 inverted
retlw 0FBh ; 4 inverted
retlw 0F7h ; 8 inverted
#else ; Original not inverted
retlw 1
retlw 2
retlw 4
retlw 8
#endif
; bit 7 decimal point
; bit 6 flash decimal
; bit 5,4 dp location
; bit 3-0 starting digit from bcd buffer
getdp
addwf PCL,f
retlw 03h
retlw 03h
retlw 03h
retlw 03h
retlw 94h
retlw 0A5h
retlw 0C6h
retlw 0D7h
retlw 0E8h
retlw 0F9h
dpcap
addwf PCL,f
retlw 01h
retlw 01h
retlw 84h
retlw 84h
retlw 84h
retlw 95h
retlw 0A6h
retlw 0B7h
retlw 0C8h
retlw 0D9h
; Logic pulser table
dpuls
addwf PCL,f
retlw 170 ; 5 Hz
retlw 55 ; 50 Hz
retlw 17 ; 500 Hz
retlw 5 ; 5000 Hz
srq
movf temp,w
incf temp,f
addwf PCL,f
; 9 bits/byte Approx_ (us_byte-50)/5,4
retlw low 1380 ; 1200 7500 us/byte
retlw high 1380 ; 1200
retlw low 685 ; 2400 3750 us/byte
retlw high 685 ; 2400
retlw low 338 ; 4800 1875 us/byte
retlw high 338 ; 4800
retlw low 161 ; 9600 940 us/byte
retlw high 161 ; 9600
retlw low 78 ; 19200 470 us/byte
retlw high 78 ; 19200
retlw low 33 ; 38400 230 us/byte
retlw high 33 ; 38400
retlw low 20 ; 57600 156 us/byte
retlw high 20 ; 57600
retlw low 5 ; 115200 78 us/byte
retlw high 5 ; 115200
modes
movf temp,w
incf temp,f
addwf PCL,f
vbase
retlw 73h ;Prob
retlw 50h ;
retlw 5ch ;
retlw 7ch ;
retlw 73h ;PULS
retlw 3eh ;
retlw 38h ;
retlw 6dh ;
retlw 3eh ;VOLL
retlw 5ch ;
retlw 38h ;
retlw 38h ;
retlw 3eh ;VOLH
retlw 5ch ;
retlw 38h ;
retlw 76h ;
retlw 05eh ;diod
retlw 4 ;
retlw 5ch ;
retlw 05eh ;
retlw 71h ;FrEq
retlw 50h ;
retlw 79h ;
retlw 6fh ;
retlw 0 ; Cnt
retlw 39h ;
retlw 54h ;
retlw 78h ;
retlw 0 ; CAP
retlw 39h ;
retlw 77h ;
retlw 73h ;
retlw 39h ;CoiL
retlw 5ch ;
retlw 4 ;
retlw 38h ;
retlw 0 ; SIG
retlw 6dh ;
retlw 6 ;
retlw 3dh ;
retlw 54h ;ntSC
retlw 78h ;
retlw 6dh ;
retlw 39h ;
retlw 00h ; SEr
retlw 6dh ;
retlw 79h ;
retlw 50h ;
retlw 15h ;Midi
retlw 4 ;
retlw 5eh ;
retlw 4 ;
retlw 50h ;r/c.o
retlw 52h ;
retlw 0D8h ;
retlw 5ch ;
retlw 50h ;r/c.i
retlw 52h ;
retlw 0D8h ;
retlw 4 ;
retlw 08h ;_| |_
retlw 37h ;
retlw 08h ;
retlw 37h ;
retlw 54h ;Nois
retlw 5ch ;
retlw 4 ;
retlw 6dh ;
retlw 04h ;ir38
retlw 50h ;
retlw 4fh ;
retlw 7fh ;
retlw 73h ;PWm
retlw 2ah ;
retlw 15h ;
retlw 0 ;
retlw 6dh ;STOP
retlw 78h
retlw 3fh
retlw 73h
vpuls
retlw 0 ; 5
retlw 0 ;
retlw 0 ;
retlw 6dh ;
retlw 0 ; 50
retlw 0 ;
retlw 6dh ;
retlw 3fh ;
retlw 0 ; 500
retlw 6dh ;
retlw 3fh ;
retlw 3fh ;
retlw 0 ; 5.0
retlw 0 ;
retlw 0edh ;
retlw 3fh ;
vbaud
retlw 06h ;1200
retlw 5bh ;
retlw 3fh ;
retlw 3fh ;
retlw 5bh ;2400
retlw 66h ;
retlw 3fh ;
retlw 3fh ;
retlw 66h ;4800
retlw 7fh ;
retlw 3fh ;
retlw 3fh ;
retlw 67h ;9600
retlw 7dh ;
retlw 3fh ;
retlw 3fh ;
retlw 00h ; 19.2 (19200)
retlw 06h ;
retlw 0E7h ;
retlw 5bh ;
retlw 00h ; 38.4 (38400)
retlw 4Fh ;
retlw 0FFh ;
retlw 66h ;
retlw 00h ; 57.6 (57600)
retlw 6dh ;
retlw 087h ;
retlw 7Dh ;
retlw 06h ;115.2 (115200)
retlw 06h ;
retlw 0Edh ;
retlw 5bh ;
; execute routine as selected from menu =============================
exec
movf mode,w
addwf PCL,f
goto lp1 ;logic probe
goto pulse ;logic pulser
goto volt ;voltmeter 0 - 5.00V
goto hivolt ;voltmeter 0 - 25.00V
goto diode ;diode voltage
goto fcount ;frequency count
goto dcount ;event count
goto cap ;cap meter
goto induct ;inductance meter
goto sig ;signal generator
goto vgen ;video generator
goto serial ;serial out
goto midi ;midi out
goto radcon ;servo pulse generator
goto servoi ;servo pulse measure
goto square ;square wave
goto noise ;digital noise
goto ir38 ;38 kHz test signal
goto pwm ;variable pulse width
goto stop ;stop watch function
start
bsf STATUS,5
movlw b'00111111'
movwf TRISA
movlw 0
movwf TRISB
movlw b'10110000'
movwf TRISC
movlw b'10001000'
movwf OPTION_REG
bcf STATUS,5
movlw 4
movwf T2CON
clrf segmask
bsf segmask,0
clrf dignr
call getset ;restore current mode
call signon
movlw low 1000
movwf freq
movlw high 1000
movwf freq+1
movlw 48
movwf pwmp
; menu selection of operational modes ================================
cycmode
call putset ;save all parameters
cycle
bcf INTCON,GIE
movf mode,w
call setmode ;load segment menu data
c2
call segout ;run display
movlw 5
call delay
btfsc BUT1 ;still held down?
goto c4 ;no
btfss BUT2
goto c2
c5
call segout
movlw 5
call delay
btfsc BUT1
goto doexec
btfsc BUT2
goto c5
decf mode,f
movlw MAXMODE-1
btfsc mode,7 ;underflow?
movwf mode
goto cycle
c4
call segout
movlw 5
call delay
btfsc BUT2
goto doexec ;both buttons up - execute
btfsc BUT1
goto c4
incf mode,f
movf mode,w
xorlw MAXMODE
btfsc STATUS,Z
clrf mode
goto cycle
doexec
call putset ;first, save op mode
call clreg
goto exec
clreg
bsf STATUS,RP0 ;Select BANK1 for TRIS registers
bsf R20 then clear all lines
bsf R100
bsf R470
bsf R150
bsf R10K
bsf R10KA
bsf R100K
bsf CLAMP
movlw 6
movwf ADCON1
bcf STATUS,RP0 ;select BANK0
retlw 00
; save current setup in eeprom =======================================
putopt
btfss SAVE ;flagged for save?
retlw 00 ;no.
bcf SAVE ;yes.
putset
clrf hi
clrf lo
movf mode,w
call eewrite ;save current mode in eeprom
incf lo,f
movf pmode,w
call eewrite
incf lo,f
movf midic,w
call eewrite
incf lo,f
movf baud,w
call eewrite
retlw 00
; get op mode from eeprom ==============
getset ;from line 415
clrf hi
clrf lo
call eeread
movwf mode
movf mode,w
addlw -MAXMODE
btfsc STATUS,C
clrf mode ;restore
incf lo,f ;next location
call eeread
movwf pmode ;pulse mode
movf pmode,w
addlw -4
btfsc STATUS,C
clrf pmode
incf lo,f
call eeread
movwf midic
addlw -15
btfsc STATUS,C
clrf midic
incf lo,f ;next location
call eeread
movwf baud ;pulse mode
movf baud,w
addlw -4
btfsc STATUS,C
clrf baud
retlw 00
; put mode text on 4 char display ====================================
setmode
movwf temp
bcf STATUS,C
rlf temp,f
rlf temp,f
call modes
movwf digits
call modes
movwf digits+1
call modes
movwf digits+2
call modes
movwf digits+3
retlw 00
; show version nr and op mode at startup =============================
signon ;from line 416
movlw VERS
call wtod ;put version nr ;to line 1397
movlw 0 ;blank.
movwf digits
call sign
movf mode,w
call setmode
call sign
retlw 00
sign
movlw .30 ;added 23-6-2011
movwf temp
x1
call segout
movlw 5 ;Changed V36 was .12
call delay ;line 1702
decfsz count,f
goto x1
decfsz temp,f
goto x1
retlw 00
; PWM interrupt handler ==================
pwmi
bcf INTCON,T0IF
btfss SWIT
goto on
bcf SWIT
off
bcf R20
movf oftime,w
movwf TMR0
goto isrx
on
bsf SWIT
bsf R20
movf ontime,w
movwf TMR0
goto isrx
; PWM control routine =====================
pwm
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R20 ;Set R20 = output
movlw b'10000010' ;/32 TMR0
movwf OPTION_REG
bcf STATUS,RP0 ;Select BANK0
movlw 0
movwf isrvec ;set interrupt re-vector
bsf INTCON,T0IE
bsf INTCON,GIE
p2
movf pwmp,w
addlw 2
call wtod
movf pwmp,w
sublw 0
movwf ontime
movf pwmp,w
sublw 96
sublw 0
movwf oftime
p4
movlw 5
call delay
call segout
movlw 5
call delay
call segout
decfsz timer,f
goto p4
movlw 25
movwf timer
p3
movlw 5
call delay
call segout
btfss BUT1
goto dn
btfss BUT2
goto up
clrf timer
goto p3
dn
btfss BUT2
goto cycle
decfsz pwmp,f
decf pwmp,f
incf pwmp,f
goto p2
up
btfss BUT1
goto cycle
incf pwmp,f
movf pwmp,w
xorlw 96
btfsc STATUS,Z
decf pwmp,f
goto p2
; IR38 Routine ========================
ir38
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R20 ;Set R20 = output
bcf STATUS,RP0 ;Select BANK0
ir2
call brst
movlw 5
movwf count
ir4
call segout
movlw 5
call delay ;line 1702
decfsz count,f
goto ir4
call segoff
btfsc BUT1
goto ir2
btfsc BUT2
goto ir2
goto cycle
brst
movlw 38
movwf count
b2
bsf R20
movlw 20
movwf dela
b3
decfsz dela,f
goto b3
nop
nop
nop
bcf R20
movlw 20
movwf dela
b5
decfsz dela,f
goto b5
nop
decfsz count,f
goto b2
retlw 00
; 20 kHz digital noise @20MHz =====
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R20 ;Set R20 = output
bcf STATUS,RP0 ;Select BANK0
movlw 55h
movwf rand
n2
call pseudo
btfsc rand,0
bsf R20
btfss rand,0
bcf R20
call segout
movlw 65
movwf dela
n4
decfsz dela,f
goto n4
btfsc BUT2
goto n2
btfsc BUT1
goto n2
goto cycle
pseudo
movf rand,w
addwf rand+1,w
movwf rand+1
addwf rand+2,w
movwf rand+2
bcf STATUS,C ;do 8 bit rotate
rrf rand,f
btfsc STATUS,C
bsf rand,7
addwf rand,f
retlw 00
; pulse width generation @20MHz ======================================
radcon
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R20 ;Set R20 = output
bcf STATUS,RP0 ;Select BANK0
movlw low 1500
movwf timer
movlw high 1500
movwf timer+1
rc1
movf timer,w
movwf acc
movf timer+1,w
movwf acc+1
clrf acc+2
clrf acc+3
call b2bcd
call format
rc2
movlw 50
movwf count
rc3
call segout
movlw 10
call delay
decfsz count,f
goto rc3
movf timer,w
movwf lo
movf timer+1,w
movwf hi
call segoff
call rcpls
btfss BUT1
goto rcdn
btfss BUT2
goto rcup
goto rc2
rcup
btfss BUT1
goto cycle
rcup2
movlw 10
addwf timer,f
btfsc STATUS,C
incf timer+1,f
movf timer+1,w
xorlw 9
btfsc STATUS,Z
goto rcdn2
goto rc1
rcdn
btfss BUT2
goto cycle
rcdn2
movlw -10
addwf timer,f
btfss STATUS,C
decf timer+1,f
movf timer+1,w
xorlw 2
btfsc STATUS,Z
goto rcup2
goto rc1
rcpls
incf hi,f
incf lo,f
bsf R20
rc4
nop
nop
rc5
decfsz lo,f
goto rc4
decfsz hi,f
goto rc5
bcf R20
retlw 00
; servo input (pulse width measure) precise machine cycle count used !!
servoi
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bsf CLAMP ;CLAMP = input
bsf R10K ;no extra voltage = input
bsf R150 ;disconnect other 10k = input
bcf R100K ;use 100k pulldown = output
bsf R20 ;Pulse input
movlw 6
movwf ADCON1 ;all ra is digital
bcf STATUS,RP0 ;Select BANK0
bcf R100K ;pull down lightly
servo1
call show2 ;short delay and run display
btfsc R20 ;check direct input
goto servo4 ;wait R20 low
servo2 not display data in this loop!!
call segout
btfss BUT1
goto servo4 ;button anti freeze
btfss BUT2
goto servo4 ;button anti freeze
btfss R20 ;check direct input
goto servo2 ;wait R20 high
clrf acc ;clear count at start
clrf acc+1
clrf acc+2
clrf acc+3
nop
nop
nop
goto servo6
servoHa
nop
servoHb
nop
servoHc ; loop 3+(3*13) processor cycles
nop
; movlw 13 ;if not call segout
movlw 3
movwf bitcnt ; used in math!!
call segout ;run display_ 30 machine cycles
servo_dh
decfsz bitcnt,f
goto servo_dh
servo6
btfss R20 ;check direct input
goto r20low
movlw 10 ;inc acc in 10 units (10us)
addwf acc,f
btfss STATUS,C
goto servoHa
incfsz acc+1,f ; 24 bit count = 16,7seg
goto servoHb
incfsz acc+2,f
goto servoHc ; total 10us constant
r20low
clrf xacc ;clear count at start
clrf xacc+1
clrf xacc+2
clrf xacc+3
nop
movlw 11
movwf bitcnt ; used in math!!
goto servo_dl
servoLa
nop
servoLb
nop
servoLc
nop ; loop 3+(3*13) processor cycles
; movlw 13 ;if not call segout
movlw 3
movwf bitcnt ; used in math!!
call segout ;run display_ 30 machine cycles
servo_dl
decfsz bitcnt,f
goto servo_dl
btfsc R20 ;check direct input
goto r20high
movlw 10 ;inc acc in 10 units (10us)
addwf xacc,f
btfss STATUS,C
goto servoLa
incfsz xacc+1,f
goto servoLb
incfsz xacc+2,f
goto servoLc ; total 10us constant
r20high
btfss MED_L ;show high or low
goto ser_sh ;show high
call xfer ;show low
call b2bcd
call format ;show 4 digits
call flash ;add decimal point
call segout ;run display_ 30 machine cycles
; call show2
goto servo4
ser_sh
call b2bcd
call format ;show 4 digits
call flash ;add decimal point
call segout ;run display_ 30 machine cycles
; call show2
servo4
btfsc BUT1
goto servo5 ;But1
bcf MED_L ;set show high
clrf digits
clrf digits+1
clrf digits+2
movlw 76h ;'H'
movwf digits+3
call segout
btfss BUT2
goto cycle
servo5
btfsc BUT2
goto servo1
bsf MED_L ;set show low
clrf digits
clrf digits+1
clrf digits+2
movlw 38h ;'L'
movwf digits+3
call segout
btfss BUT1
goto cycle
goto servo1
retlw 00
; Square wave interrupt handler ======================================
sqri
bcf INTCON,T0IF
movf freq,w
addwf timer,f
movf freq+1,w
btfsc STATUS,C
incfsz freq+1,w
addwf timer+1,f
btfss timer+1,7
bcf R20
btfsc timer+1,7
bsf R20
movlw -73
addwf TMR0,f
goto isrx
; linear squarewave generation @20MHz ================================
square
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R20 ;set R20 = output
movlw b'10001000'
movwf OPTION_REG ;/32 clock
bcf STATUS,RP0 ;Select BANK0
movlw 1
movwf isrvec
bsf INTCON,GIE
bsf INTCON,T0IE ;timer-0 interrupt on
sqhl
movf freq,w
movwf acc
movf freq+1,w
movwf acc+1
clrf acc+2
clrf acc+3
call b2bcd
call format
sq2
movf rate,w
movwf count
sqs1
call segout
movlw 5
call delay ;line 1702
decfsz count,f
goto sqs1
movlw -5
addwf rate,f
movf rate,w
addlw -5
btfsc STATUS,C
goto sq4
movlw 6
movwf rate
sq4
btfss BUT1
goto sqdn
btfss BUT2
goto squp
clrf rate
goto sq2
squp
btfss BUT1
goto cycle
incf freq,f
btfsc STATUS,Z
incf freq+1,f
goto sqhl
sqdn
btfss BUT2
goto cycle
movlw -1
addwf freq,f
btfss STATUS,C
decf freq+1,f
btfss freq+1,7
goto sqhl
clrf freq
clrf freq+1
goto sqhl
; logic pulser =======================================================
pulse
bsf STATUS,RP0 ;Select BANK1 for ADCON1 register
movlw 6
movwf ADCON1 ;all digital on ra
bcf STATUS,RP0 ;Select BANK0
ppp2
movf pmode,w ;get pulse mode
addlw (vpuls-vbase)/4 ;NOTE_ = (vpuls-vbase)/4 in this assembler
call setmode
movf pmode,w ;now, get delay factor
call dpuls
movwf timer
goto ppp3
ppp5
bsf STATUS,RP0
bcf R20 ;activate pulse
nop
bsf R20 ;end of pulse
bcf STATUS,RP0
bsf digits,6 ;show pulse is active
goto ppp8
ppp3
bsf R20 ;set latch to low.
btfsc R470 ;which way to pulse?
bcf R20 ;then set latch to high.
movlw 8 ;low level detected?
btfsc R20
movlw 1 ;no - show high
movwf digits ;in 1st display
ppp8
movf timer,w
call delsq ;delay w/display
movlw 2
call delsq ;adjust for hi end error
btfsc BUT1
goto ppp4 ;no button 1.
btfsc BUT2
goto ppp5 ;but 1 only - do pulses
goto cycmode ;exit to menu.
ppp4
btfsc BUT2 ;only button 2 ?
goto ppp3 ;no - set pulse direction
ppp4x
movlw 5
call delay ;line 1702
call blank
call segout
btfss BUT1 ;exit?
goto cycmode ;yes - and save params
btfss BUT2
goto ppp4x
incf pmode,f
movf pmode,w
sublw 3
btfss STATUS,C
clrf pmode
goto ppp2
; signal generator (0.5 v square wave) ==============================
sig
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R10K ;engage 10k resistor = output
bcf R100K ;engage 100k resistor = output
movlw 6
movwf ADCON1 ;all digital on ra
bcf STATUS,RP0 ;Select BANK0
bcf R10K ;10k pull to ground
bcf R100K ;100k for signal gen
clrf digits
movlw 5
call digseg
movwf digits+1
movlw 0
call digseg
movwf digits+2
movwf digits+3
sis3
btfss timer,6
bsf digits,6
bsf R100K
call sis8
sis4
incf timer,f
btfsc timer,6
bcf digits,6
bcf R100K
call sis8
btfsc BUT1
goto sis4
btfsc BUT2
goto sis3
goto cycle
sis8
movlw 32
movwf count
sis9
call segout ;run display
movlw 14
call short
decfsz count,f
goto sis9
retlw 00
; do short delays
short
movwf dela
shs2
nop
nop
nop
nop
nop
decfsz dela,f
goto shs2
retlw 00
; measure capacitor from tip to ground lead ===========================
cap
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R100K ;enable 100k resistor = output
bcf STATUS,RP0 ;Select BANK0
bsf R100K ;pull up resistor
bcf R20 ;pull down for clamp
bsf HOLD ;default hold condition
cac2
call segoff
clrf acc ;clear accum
clrf acc+1
clrf acc+2
clrf acc+3
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bsf R20 ;release clamp R20 = input
bcf STATUS,RP0 ;Select BANK0
nop
nop ;compensate
nop ;for stray
nop ;capacitance
nop
nop
cac7
nop ;tune loop with nop's
nop
nop
nop
nop
nop
nop
nop
nop
btfsc R20 ;check direct (a/d) input
goto cahit
incfsz acc,f
goto cac7
incfsz acc+1,f
goto cac7
incfsz acc+2,f
goto cac7
incfsz acc+3,f
goto cac7
cahit
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R20 ;discharge cap R20 = output
bcf STATUS,RP0 ;Select BANK0
call b2bcd
call cform ;format for caps
cac6
call show2
btfsc BUT1
goto cac6 ;no button - hold reading
btfsc BUT2
goto cac2 ;but1 only - do reading
goto cycle
; measure inductor from tip to gound lead ============================
induct
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R100 ;enable 470 ohm resistor = output
bcf STATUS,RP0 ;Select BANK0
bcf R100 ;pull up resistor
bsf HOLD ;default hold condition
inc2
call segoff
movlw 80
call delay
clrf acc ;clear accum
clrf acc+1
clrf acc+2
clrf acc+3
bsf R100 ;start voltage
inc7
nop ;Changed V36
btfss R20 ;check direct (a/d) input
goto inhit
incfsz acc,f
goto inc7
incfsz acc+1,f
goto inc7
incfsz acc+2,f
goto inc7
incfsz acc+3,f
goto inc7
inhit
bcf R100
call b2bcd
movlw 3
call xform
bsf digits+2,7
inc6
call show2
btfsc BUT1
goto inc6 ;no button - hold reading
btfsc BUT2
goto inc2 ;but1 only - do reading
goto cycle
; turn off all digits
segoff
#ifdef INVERT_A
bsf PORTC,0 ; inverted anodes
bsf PORTC,1
bsf PORTC,2
bsf PORTC,3
#else
bcf PORTC,0
bcf PORTC,1
bcf PORTC,2
bcf PORTC,3
#endif
retlw 00
; Logic probe function ===============================================
; show Low, High, and Float w/ Pulse detection
lp1
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R10K ;turn on voltage feed = output
bcf R10KA ;turn on other feed = output
movlw b'10101000' ;no prescale on TMR0
movwf OPTION_REG
movlw 0Eh ;ana0 on, left justify
movwf ADCON1
bcf STATUS,RP0 ;Select BANK0
bsf R10K ;10k pull up
bcf R10KA ;10k pull down
movlw 81h ;read a/d on RA.0
movwf ADCON0
clrf dp ;no decimal
movlw 0ffh
movwf TMR0 ;set for single count overflow
lpx1
btfsc BUT1
goto lpx2
btfsc BUT2
goto lpx2
goto cycle
lpx2
call atod ;read the input
movf hi,w ;8 bit value
sublw 40 ;low enough for low?
btfsc STATUS,C
goto lplow
movf hi,w
sublw 180
btfss STATUS,C
goto lphi
lpflo
movlw 40h ;'-'
goto lphl
lphi
movlw 76h ;'H'
goto lphl
lplow
movlw 38h ;'L'
lphl
call letter
btfss INTCON,T0IF ;counter overflow?
goto lpno
bcf INTCON,T0IF
movlw 0ffh
movwf TMR0 ;set for next time
clrf timer
movlw 73h ;'P'
movwf digits+1 ;show pulse detected
lpno
call show1
incf timer,f
movf timer,f
btfsc STATUS,Z
clrf digits+1 ;always flash off
goto lpx1
; run display for a short time
show2
clrf count
goto shos2
show1
clrf count
bsf count,7
goto shos2
show
clrf count
bsf count,6
shos2
call segout ;show digits
call flash ;add dp
movlw 5 ;10
call delay ;line 1702
decfsz count,f
goto shos2
retlw 00
; show one character and blank other 3
letter
movwf digits
goto blnk2
blank
clrf digits
blnk2
clrf digits+1
clrf digits+2
clrf digits+3
retlw 00
; show 8 bit value on display
wtod ;from 563
movwf acc
clrf acc+1
clrf acc+2
clrf acc+3
call b2bcd
call format
retlw 00
; measure diode drops =====
; same as voltmeter but with 5v feed to probe
diode
bcf HIV ;scale flag 5V
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf R10K ;enable feed resistor = output
goto vdx ;otherwise, like voltmeter
; voltmeter function, 0-25 volts ======================================
hivolt
bsf HIV ;scale flag 25V
goto vdx
; voltmeter function, 0-5 volts =======================================
volt
bcf HIV ;scale flag 5V
vdx
bsf STATUS,RP0 ;Select BANK1 for ADCON1 register
movlw 8Eh ;enable ra.0 analog right justify
movwf ADCON1
bcf STATUS,RP0 ;Select BANK0
bsf R10K ;only used for 'diode' mode.
movlw 81h ;select ana0 and enable a/d
movwf ADCON0
vov2
call atod ;get 10 bits
; bcf STATUS,C
; rrf hi,f
; rrf lo,f ;scale to 9 bits 0-5.11 V
call Scale ;scale to 0-5.00 V or 0-25V
movf lo,w
movwf acc
movf hi,w
movwf acc+1
clrf acc+2
clrf acc+3
call b2bcd
call format
bsf digits+1,7
movlw 200
movwf count
vov4
call segout
movlw 5 ;10
call delay ;line 1702
decfsz count,f
goto vov4
btfsc BUT1
goto vov2
btfsc BUT2
goto vov2
goto cycle
; read 16 bit a/d value in hi/low
atod
bsf ADCON0,2
nop
nop
adchk
btfsc ADCON0,2 ;check for conversion complete
goto adchk
bsf STATUS,RP0
movf ADRESL,w
bcf STATUS,RP0
movwf lo
movf ADRESH,w
movwf hi
retlw 00
; count events using TMR0 directly ====================================
dcount
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bsf CLAMP ;disable clamp = input
bcf R10K ;use 10k only = output
bsf R150 ;disconnect other 10k = input
bsf R100K ;no 100k feed = input
bsf R20 ;float direct resistor = input
movlw b'10101000' ;no prescale on TMR0
movwf OPTION_REG
movlw 6
movwf ADCON1 ;all ra is digital
bcf STATUS,RP0 ;;Select BANK0
bsf R10K ;use 10k pullup
dcic2
clrf TMR0 ;clear hardware timer
clrf xacc ;clear 32bit count
clrf xacc+1
clrf xacc+2
clrf xacc+3
dcic3
call xfer
call b2bcd
movlw 3
dcic5
call xform ;show low 4 digits
call segout ;run display
call icup ;update counter
btfss BUT1 ;button 1 ?
goto dcic9 ;no - continue
btfss BUT2
goto dcic2 ;reset counting.
goto dcic3 ;continue count.
dcic9
btfss BUT2 ;both buttons?
goto cycle ;yes - exit.
call xfer
call b2bcd
movlw 7
goto dcic5
; update 32bit count from hardware timer
icup
movf TMR0,w ;hardware counter to accum
movwf xacc
btfss INTCON,T0IF ;overflow
retlw 00 ;not yet.
bcf INTCON,T0IF
incfsz xacc+1,f
retlw 00
incfsz xacc+2,f
retlw 00
incf xacc+3,f
retlw 00
; move aux count to accum
xfer
movf xacc,w
movwf acc
movf xacc+1,w
movwf acc+1
movf xacc+2,w
movwf acc+2
movf xacc+3,w
movwf acc+3
retlw 00
; measure frequency using TMR0 with 8-bit prescale ===================
fcount
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bsf CLAMP ;CLAMP = input
bsf R10K ;no extra voltage = input
bsf R150 ;disconnect other 10k = input
bcf R100K ;use 100k pulldown = output
bsf R20 ;float direct resistor = input
movlw b'10100111' ;256 count prescaler
movwf OPTION_REG
movlw 6
movwf ADCON1 ;all ra is digital
bcf STATUS,RP0 ;Select BANK0
bcf R150 ;pull down lightly
clrf acc
clrf acc+1
clrf acc+2
clrf acc+3
fcf2
call b2bcd
call format
btfsc BUT1
goto fcf4
fcf7
btfss BUT2 ;both buttons?
goto cycle
fcfx
movlw 3
call xform
fcf4
call cnton
call onesec
call cntoff
goto fcf2
; clear 32bit count and turn on TMR0
cnton
bcf CLAMP
clrf TMR0 ;clear timer and prescale
clrf acc
clrf acc+1
clrf acc+2
clrf acc+3
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bsf CLAMP ;tristate the clamp = input
bcf STATUS,RP0 ;Select BANK0
retlw 00
; turn off counter and pulse input to read out prescale
cntoff
bcf CLAMP
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf CLAMP ;CLAMP = output
bcf STATUS,RP0 ;Select BANK0
movf TMR0,w
movwf acc+1
clrf acc
cnc2
decf acc,f
bsf CLAMP
bcf CLAMP
movf TMR0,w
xorwf acc+1,w
btfsc STATUS,Z
goto cnc2
retlw 00
;---------------------------------------------------------
; add decimal point to display
flash
swapf dp,w
andlw 3 ;bits 5,4 = digit nr.
addlw digits
movwf FSR
btfsc dp,7 ;decimal used?
bsf 0,7 ;light decimal point
incf ftimer,f
btfsc STATUS,Z
incf ftimer+1,f
btfss ftimer+1,5
goto fno
btfsc dp,6 ;flash mode?
bcf 0,7 ;flash back off
retlw 00
fno
nop
retlw 00
; open count gate for exactly 1.000000 second
onesec
movlw low LPTIME
movwf timer
movlw high LPTIME
movwf timer+1
osx1
nop ;100 cycle loop count
nop
osx2
call ffill ;time filler
call segout ;show last data
call flash ;include decimal
call dotime ;check for TMR0 overflow
decfsz timer,f
goto osx1
decfsz timer+1,f
goto osx2
movlw 8
movwf timer
osx5
call dotime
decfsz timer,f
goto osx5
retlw 00
; just kill some time
ffill
movlw 16
movwf temp
fif2
decfsz temp,f
goto fif2
nop
nop
retlw 00
; check for TMR0 rollover
; (constant execution times)
dotime
btfss INTCON,T0IF ;overflow?
goto dno
bcf INTCON,T0IF ;clear the flag
incf acc+2,f ;increment next byte
btfsc STATUS,Z
incf acc+3,f ;and next on rollover
retlw 00
dno
nop
nop
nop
retlw 00
; squared delay function
delsq
movwf dela+1
movwf dela+2
dlsd1
movf dela+2,w
movwf dela
dlsd0
call segout
decfsz dela,f
goto dlsd0
decfsz dela+1,f
goto dlsd1
retlw 00
; qubic delay function
delay
movwf dela+2
dld2
movwf dela+1
dld1
movwf dela
dld0
decfsz dela,f
goto dld0
decfsz dela+1,f
goto dld1
decfsz dela+2,f
goto dld2
retlw 00
; format used for capacitor measurements
; each count = 100pf
cform
call first
movf count,w ;1st non zero
call dpcap
movwf dp
andlw 0fh ;where to start
movwf count
goto ff5
; ***** video pattern generation ***** ===============================
vgen
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf BLACK ;BLACK = output
bcf WHITE ;WHITE = output
bcf R100 ;R100 = output
bcf STATUS,RP0 ;Select BANK0
bcf R100
#ifdef INVERT_A
bsf PORTC,2 ; inverted anodes
bsf PORTC,3
#else
bcf PORTC,2
bcf PORTC,3
#endif
movlw 0BFh
movwf PORTB
vgv2
call vsync
movlw 40
movwf count
vc1
nop
call bline
decfsz count,f
goto vc1
movlw 15
movwf count
vc2
call dline
call dline4
call dline4
call bline4
call bline4
call bline4
call bline4
call bline4
call bline4
call bline4
call bline4
call bline4
call bline4
nop
decfsz count,f
goto vc2
movlw 17
movwf count
vc3
call bline
nop
decfsz count,f
goto vc3
call zline4
btfsc BUT2
goto vgv2
goto cycle
vsync
movlw 6
movwf count
vv2
bcf BLACK
call dla10
bsf BLACK
movlw 46
call vdela
decfsz count,f
goto vv2
movlw 6
movwf count
vv3
bcf BLACK
movlw 46
call vdela
bsf BLACK
call dla8
decfsz count,f
goto vv3
movlw 6
movwf count
vv4
bcf BLACK
call dla10
bsf BLACK
movlw 46
call vdela
decfsz count,f
goto vv4
retlw 00
zline4
call dla4
zline
bcf BLACK ;start h-sync
call dla16
call dla7
bsf BLACK
call vseg
movlw 89
call vdela
nop
retlw 00
bline4
call dla4
bline
bcf BLACK ;start h-sync
call dla16
call dla7
bsf BLACK
movlw 93
call vdela
nop
retlw 00
dline4
call dla4
dline
bcf BLACK ;start h-sync
call dla16
call dla7
bsf BLACK
call dla18
call dla18
movlw 19
movwf temp
bd2
nop
nop
nop
nop
nop
nop
bsf WHITE
nop
bcf WHITE
decfsz temp,f
goto bd2
movlw 5
call vdela
retlw 00
; delay in processor cycles (includes call/retlw 00)
dla18 nop
dla17 nop
dla16 nop
dla15 nop
dla14 nop
dla13 nop
dla12 nop
dla11 nop
dla10 nop
dla9 nop
dla8 nop
dla7 nop
dla6 nop
dla5 nop
dla4 retlw 00
vdela
movwf temp
vd2
decfsz temp,f
goto vd2
retlw 00
; light alternate digits (12 ct)
vseg
incf frame,f ;count frames
#ifdef INVERT_A
bsf PORTC,0 ; inverted anodes
bsf PORTC,1
btfss frame,0
bcf PORTC,0
btfsc frame,0
bcf PORTC,1
#else
bcf PORTC,0
bcf PORTC,1
btfss frame,0
bsf PORTC,0
btfsc frame,0
bsf PORTC,1
#endif
nop
retlw 00
; **** end video gen ***** =======
; turn off displays
clear
#ifdef INVERT_A
movlw 0Fh ; inverted anodes
iorwf PORTC,f
#else
movlw 0F0h
andwf PORTC,f
#endif
retlw 00
; cycle thru individual segment drives on 4 digits
; (constant execution time_ 30 instructions)
; ************** Do Not Modify *******************
segout
#ifdef INVERT_A
movlw 00Fh
iorwf PORTC,f ;inverted anodes set low 4 bits
#else
movlw 0F0h
andwf PORTC,f ;clear low 4 bits
#endif
movf dignr,w ;get digit nr
addlw digits ;base of segment list
movwf FSR
movf 0,w ;get the data
andwf segmask,w ;mask the bit
xorlw 0ffh ;invert
movwf PORTB ;one possible segment line low
movf dignr,w
call getano
#ifdef INVERT_A
andwf PORTC,f ; inverted anodes set one high inverted
#else
iorwf PORTC,f ; set one high.
#endif
bcf STATUS,C
rlf segmask,f
btfsc STATUS,C
goto nseg
nop
nop
nop
nop
nop
retlw 00
nseg
bsf segmask,0 ;rotate
incf dignr,f
btfsc dignr,2 ;overflow?
clrf dignr
bak
retlw 00
; display digits from specified position
xform
movwf count
goto ff5
; format first 4 signifcant digits on display
format
call first ;find 1st non-zero digit
ffx
movf count,w
call getdp ;get formatting info
movwf dp
andlw 0fh
movwf count
ff5
call ff9 ;get segment pattern
movwf digits
call ff9
movwf digits+1
call ff9
movwf digits+2
call ff9
movwf digits+3
retlw 00
ff9
movf count,w
decf count,f
call getbd ;get bcd value
call digseg
retlw 00
; set count to 1st non zero digit
first
movlw 9 ;start w/last digit
movwf count
ff2
movf count,w ;get next digit
call getbd
xorlw 0 ;set z flag
btfss STATUS,Z
retlw 00 ;hit non zero
decfsz count,f
goto ff2
retlw 00
; get bcd digit specified by 'w'
getbd
movwf temp ;save digit nr
clrw
btfsc temp,7 ;negative value?
retlw 00 ;zero if negative.
bcf STATUS,C
rrf temp,f ;find buffer offset
movf temp,w
rlf temp,f ;restore all bits
addlw bcd ;add start of bcd buff
movwf FSR ;set pointer
movf 0,w ;get the byte
movwf ddata ;and store it.
btfsc temp,0 ;low or hi nibble?
swapf ddata,f ;hi.
movf ddata,w
andlw 0fh
retlw 00
; Convert 32-bit binary number at into a bcd number
; at . Uses Mike Keitz's procedure for handling bcd
; adjust; Modified Microchip AN526 for 32-bits.
b2bcd
movlw 32 ; 32-bits
movwf ii ; make cycle counter
clrf bcd ; clear result area
clrf bcd+1
clrf bcd+2
clrf bcd+3
clrf bcd+4
b2bcd2
movlw bcd ; make pointer
movwf FSR
movlw 5
movwf cnt
; Mike's routine_
b2bcd3
movlw 33h
addwf 0,f ; add to both nybbles
btfsc 0,3 ; test if low result > 7
andlw 0f0h ; low result >7 so take the 3 out
btfsc 0,7 ; test if high result > 7
andlw 0fh ; high result > 7 so ok
subwf 0,f ; any results <= 7, subtract back
incf FSR,f ; point to next
decfsz cnt,f
goto b2bcd3
rlf acc+0,f ; get another bit
rlf acc+1,f
rlf acc+2,f
rlf acc+3,f
rlf bcd+0,f ; put it into bcd
rlf bcd+1,f
rlf bcd+2,f
rlf bcd+3,f
rlf bcd+4,f
decfsz ii,f ; all done?
goto b2bcd2 ; no, loop
retlw 00
; read data 'w' at address hi/low
eeread
bcf STATUS,RP0
bsf STATUS,RP1 ;bank-2
movf lo,w
movwf EEADR
movf hi,w
movwf EEADRH
bsf STATUS,RP0 ;bank-3
bcf EECON1,EEPGD ;access data memory
bsf EECON1,RD ;start the read
bcf STATUS,RP0 ;bank-2
movf EEDATA,w
bcf STATUS,RP1
bcf STATUS,RP0
retlw 00
; write data 'w' at address hi/low
eewrite
bcf STATUS,RP0
bsf STATUS,RP1 ;bank-2
movwf EEDATA ;set data
movf lo,w
movwf EEADR ;set address
movf hi,w
movwf EEADRH
bsf STATUS,RP0 ;bank-3
bcf EECON1,EEPGD ;access data memory
bsf EECON1,WREN ;start write operation
movlw 55h
movwf EECON2
movlw 0AAh
movwf EECON2
bsf EECON1,WR
nop
nop
ee2
btfsc EECON1,WR ;wait for complete
goto ee2
bcf STATUS,RP0
bcf STATUS,RP1
retlw 00
; Serial signal generator ================================================
serial
call clear
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bsf SOUT ;set to input
bcf STATUS,RP0 ;Select BANK0
movf baud,w
movwf temp
bcf STATUS,C
rlf temp,f
call srq ;get low byte
movwf qtime
call srq
movwf qtime+1
movlw (vbaud-vbase)/4
addwf baud,w
call setmode
ss5
call segout
btfss BUT2
goto ss8
btfsc BUT1
goto ss5
btfss BUT2
goto cycle
call setdir
movlw 'A' ; 55h TEST
movwf sdata
movlw 26
movwf scount
ss2
movf sdata,w
call serout
incf sdata,f ; TEST
movlw 43
call delsq
decfsz scount,f
goto ss2
movlw 13
call serout
movlw 100
call delsq
movlw 10
call serout
movlw 220
call delsq
btfss BUT1 ;still held down?
goto ss5 ;repeat operation.
goto serial
ss8
call clear ;blank display
movlw 20
call delay
btfss BUT1
goto cycle
btfss BUT2
goto ss8
incf baud,f
; bcf baud,2 ;limit 0-3
movf baud,w
xorlw MAXBAUD ; limit 0-MAXBAUD (8)
btfsc STATUS,Z
clrf baud
bsf SAVE
goto serial
; Midi note generator =====================
midi
movf midic,w
addlw 1 ;convert to midi number
call wtod
movlw 39h ;'C'
movwf digits
movlw 76h ;'H'
movwf digits+1
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bsf SOUT ;set to input
bcf STATUS,RP0 ;Select BANK0
ms5
call segout
btfss BUT2
goto madj
btfsc BUT1
goto ms5
call setdir
movlw 45 ;31250 baud, may be 44
movwf qtime
clrf qtime+1
movf midic,w ;get midi chan nr.
iorlw 90h ;add note on command.
call serout ;note on
movlw 60
call serout ;middle C
movlw 40
call serout ;velocity
ms6
movlw 20
call delsq
btfss BUT1 ;wait for button release
goto ms6
movf midic,w
iorlw 90h
call serout
movlw 60
call serout
movlw 0
call serout ;send note off
call putopt ;maybe save channel
movlw 250
call delsq
goto midi
madj
movlw 100
call delsq
btfss BUT1
goto cycle
btfss BUT2
goto madj
bsf SAVE ;flag for saving new channel
incf midic,f ;next midi channel
movlw 0fh
andwf midic,f ;roll over at 15
goto midi
; check for current state
setdir
bcf DIR ;check for resting state
btfss SOUT
bsf DIR
bsf STATUS,RP0 ;Select BANK1 for TRIS register
bcf SOUT ;set to output
bcf STATUS,RP0 ;Select BANK0
retlw 00
; send serial data from outdat
serout
clrf count ;bit count
bsf count,3 ;count=8
movwf ddata
call zero ;start bit
sers2
call full
btfsc ddata,0
call one
btfss ddata,0
call zero
rrf ddata,f
decfsz count,f
goto sers2
call full
call one
call full
call full
call full
retlw 00
zero
btfss DIR ;which way is up?
bcf SOUT
btfsc DIR
bsf SOUT
retlw 00
one
btfss DIR ;which way is up?
bsf SOUT
btfsc DIR
bcf SOUT
retlw 00
full
movf qtime+1,w
movwf temp+1
movf qtime,w
movwf temp
incf temp+1,f
incf temp,f
ff3
decfsz temp,f
goto ff3
decfsz temp+1,f
goto ff3
retlw 00
; Stopwatch funcion
; Button 1_ start/stop; probe change_ start/stop
; Button 2_ reset
stop bsf STATUS,5
bcf R10K ;select 10k
bcf STATUS,5
bcf R10k ;10k to ground
movlw 1
movwf T1CON
; Wait for a start condition
_clr call clear
call clrxac ;clear accum
call disp ;set up for display
call flip ;init the probe tip
_wait call segdel
call flip ;change on tip?
btfss status,z
goto _run ;yes.
btfsc BUT1 ;button 1 ?
goto _two ;no - wait
btfsc BUT2 ;but 2 ?
goto _start ;no - begin count
goto cycle ;yes - exit.
_two btfsc BUT2 ;only button 2 ?
goto _wait
goto _clr ;reset on 2 only.
; Run until stop condition
_start call _next ;count time
call _next
call _next ;debounce but 1
call _next
_s3 call _next
btfss BUT1 ;hit but 1?
goto _s3 ;but 1 still down?
_run call _next ;count time
call flip ;probe tip changed?
btfss status,z
goto _done ;yes.
btfsc BUT1 ;hit but 1 ?
goto _run ;keep running
_done call segdel
btfsc BUT2 ;reset?
goto _done ;no.
goto _clr ;yes
_next call segdel
btfss PIR1,0 ;TMR1IF,0 ;overflow?
goto _next ;not yet.
call clear ;all segs off
bcf PIR1,0 ;TMR1IF ;clear the flag.
movlw 0 ;-50000> ;reset the timer
movwf TMR1L
movlw 0 ;-50000<
movwf TMR1H ;set timer 1 to -50000
call disp
call incxac ;count
movf place,w
addlw -4
btfss status,c
bsf digits+1,7
btfsc status,z
bsf digits+2,7
retlw 0
; look for state change on probe tip
flip
movf port_temp,w ;last port data
movwf temp ;save it
movf porta,w ;read port a
movwf port_temp ;for next time.
xorwf temp,w ;compare to last value
andlw 1 ;ra0 only
btfsc status,z
retlw 00 ;retlw 00 nz = change.
disp call xfer
call b2bcd
call format
retlw 00
segdel call segout
movlw 5
goto delay
; increment the 32bit accumulator
incxac incf xacc,1
btfss status,z
retlw 00
incf xacc+1,1
btfss status,z
retlw 00
incf xacc+2,1
btfss status,z
retlw 00
incf xacc+3,1
btfss status,z
retlw 00
; clear the 32bit accumulator
clrxac clrf xacc ;clear 32bit count
clrf xacc+1
clrf xacc+2
clrf xacc+3
retlw 00
;=========================
; SCALE multiply by 500 and divide by 1023 if HIV is reset
; multiply by 100 and divide by 1023 if HIV is set
; input= hi_lo output hi_lo
;==========================
Scale
btfsc HIV ;flag clear scale=5V?
goto scal25 ;yes scale = 25V
; multiply by 500
movlw high 500
movwf acc+0
movlw low 500
movwf acc+1
goto scal1
scal25
; multiply by 2500
movlw high 2500
movwf acc+0
movlw low 2500
movwf acc+1
scal1
call mul16_16 ;call multiply, acc0_2*hi_lo=acc0_3
; now divide by 1023
movlw high 1023
movwf hi
movlw low 1023
movwf lo
call div32_16 ;call divide, acc0_3/hi_lo=acc2_3
movf acc+2,w
movwf hi
movf acc+3,w
movwf lo
retlw 00
;*****************************************************************************************
; PIC16 fast unsigned multiply routines by Jim Bixby, bix@san.rr.com
;
; Unsigned multiply routine
; Multiplies of any size can easily be made from the macros - for this code,
; only MUL16X16 is made
;
; The approach here is linear code for speed at the expense of RAM and registers
; Adapted from _ http_//www.piclist.org/techref/microchip/math/mul/8x8u.htm
;*****************************************************************************************
; Add16AB macro - add AH_AL to BH_BL, result goes to BH_BL
Add16AB MACRO AH,AL,BH,BL
movf AL,w
addwf BL,f
movf AH,w
btfsc STATUS,C
incfsz AH,w
addwf BH,f
ENDM
;*****************************************************************************************
; Macro for adding & right shifting - used once per bit by mulmac
mult MACRO bit,A,H,L ;A=multiplier,H_L=result, other arg in W
btfsc A,bit
addwf H,f
rrf H,f
rrf L,f
ENDM ; End of macro
;*****************************************************************************************
; 8x8-->16 multiply macro A * B --> H_L
; Invokes mult macro above
mulmac MACRO A,B,H,L ; H_L = A*B
clrf H
clrf L
movf B,W ; move the multiplicand to W reg.
bcf STATUS,C ; Clear the carry bit in the status Reg.
mult 0,A,H,L
mult 1,A,H,L
mult 2,A,H,L
mult 3,A,H,L
mult 4,A,H,L
mult 5,A,H,L
mult 6,A,H,L
mult 7,A,H,L
ENDM
;
NOEXPAND
;*****************************************************************************************
; mul16_16
; acc+0_1 * hi_1 --> acc+0_3
; ARG0=Msb, ARG3=Lsb
; Invokes the three macros above
; 164 prog words, 168 inst cycles, 10 registers (6 for call/retlw 00 arguments + 4)
; Uses xacc+0_3 also. hi_1 unchanged on retlw 00
;*****************************************************************************************
mul16_16
; 32 bit result is first calculated into T0_T1_A2_A3
; When done, T0_1 is moved to A0_1 so the final result is in A0_3
; Register names can be changed at will, and any register can be located
; anywhere - order is not important.
mulmac acc+0, hi, xacc+0, xacc+1 ;T0_1 <--A0*B0
mulmac acc+1, lo, acc+2, acc+3 ;A2_3 <--A1*B1
mulmac acc+1, hi, xacc+2, xacc+3 ;T2_3 <--A1*B0
Add16AB xacc+2, xacc+3, xacc+1, acc+2 ; Add T2_3 to T1_A2, carry into T0
btfsc STATUS,C ; nb_ this relies on the _C bit being
incf xacc+0,f ; correct after the Add16AB macro
mulmac acc+0, lo, xacc+2, xacc+3 ;T2_3 <--A0*B1
Add16AB xacc+2, xacc+3, xacc+1, acc+2 ; Add T2_3 to T1_A2, carry into T0
btfsc STATUS,C
incf xacc+0,f
movf xacc+1,w ;Move T0_1 to A0_1
movwf acc+1 ;to finish
movf xacc+0,w
movwf acc+0
retlw 00
EXPAND
;**********************************************************************************************
; PIC16 unsigned 32 by 16 divide routines by Peter Hemsley
; acc+0_3 / hi_1 --> acc+2_3
; acc+0=Msb, acc+3=Lsb
; xacc+0_1 quotient
; hi_1 unchanged on retlw 00
;**********************************************************************************************
div32_16
movlw 32 ; 32-bit divide by 16-bit
movwf bitcnt
clrf xacc+0 ; Clear remainder (high)
clrf xacc+1 ; (low)
dvloop
clrc ; Set quotient bit to 0
; Shift left dividend and quotient
rlf acc+3,f ; lsb
rlf acc+2,f
rlf acc+1,f
rlf acc+0,f ; lsb into carry
rlf xacc+1,f ; and then into partial remainder
rlf xacc+0,f
skpnc ; Check for overflow
goto subd
movf hi,w ; Compare partial remainder and divisor (high)
subwf xacc+0,w
skpz
goto testgt ; Not equal so test if remdrH is greater
movf lo,w ; High bytes are equal, compare low bytes (low)
subwf xacc+1,w
testgt
skpc ;Carry set if remdr >= divis
goto remrlt
subd
movf lo,w ; Subtract divisor from partial remainder
subwf xacc+1,f
skpc ; Test for borrow
decf xacc+0,f ; Subtract borrow
movf hi,w
subwf xacc+0,f
bsf acc+3,0 ; Set quotient bit to 1
; Quotient replaces dividend which is lost
remrlt
decfsz bitcnt,f
goto dvloop
retlw 00
END |