Před několika léty vyhrála konkurs časopisu Praktická elektronika velmi, ale opravdu velmi podobná konstrukce. Momentálně má podobný LCmetr v nabídce Hadex (nebo Tipa, nikdy si nevzpomenu kdo je kdo). Tak proč si něco podobného nepostavit, nebo se alespoň nepodívat jak že to ten autor vlastně napsal. Kompletní schéma a zdroják najdete v Download centru.



include LCM.H
;**********************************************************************************************
; Initialize the CPU
INIT     CLRF      PORTB
         MOVLW     H'E1'
         TRIS      PORTB
         CLRF      PORTA
         MOVLW     H'10'
         TRIS      PORTA
         MOVLW     H'38'
         OPTION
         CLRF      INTCON
;**********************************************************************************************
;initialize display
;
;LCD display routines
;
; The LCD operates in nibble mode
;   PORT A is the data bus
;   PORT B contains the control lines
INITLCD  CALL      DLY15     ;delay 15ms
         MOVLW     03        ;output function set
         MOVWF     PORTA
         BSF       _ENB      ;send first function set
         CALL      DLY5      ;delay 5ms
         BCF       _ENB
         BSF       _ENB      ;send second function set
         CALL      DLY5      ;delay 5ms
         BCF       _ENB
         BSF       _ENB      ;send third function set
         CALL      DLY5      ;delay 5ms
         BCF       _ENB
         MOVLW     02
         MOVWF     PORTA     ;set 4 bit mode
         CALL      SEND
         MOVLW     28        ;send 4bits, 2 line, 5X7 dots
         CALL      CMDLCD    ;send command to LCD
         MOVLW     0C        ;send DISPLAY ON
         CALL      CMDLCD
         MOVLW     06        ;send ENTRY MODE SET
         CALL      CMDLCD
         CALL      CLRDSP    ;clear the display
;**********************************************************************************************
;Test switches to ensure Lx, Cx and Zero are off
TESTSW   BTFSC     _LX       ;IF /LX (assumes sw inputs are active high)
         GOTO      ERRORL
         BTFSC     _CX       ;   AND /CX
         GOTO      ERRORL
         GOTO      WAIT     ;      WAIT
ERRORL   CALL      DISPSW    ;ELSE   ERROR LOOP display "SWITCH ERROR"
         GOTO      TESTSW    ;ENDIF loop until operator clears switches
WAIT     CALL      CLRDSP    ;send DISPLAY CLEAR
         MOVLW     'W'       ;display "WAIT"
         CALL      CHARLCD
         MOVLW     'A'
         CALL      CHARLCD
         MOVLW     'I'
         CALL      CHARLCD
         MOVLW     'T'
         CALL      CHARLCD
         MOVLW     H'19'     ;delay 5 seconds
         MOVWF     T2
TD2      MOVLW     H'FF'
         CALL      DELAY
         DECFSZ    T2
         GOTO      TD2
;**********************************************************************************************
;
;  Calibrate
;
;       (F is actually COUNT = F*TIME where TIME=.20 seconds)
;Calibration:
;Cs=(f2^2 * 1000/(F1^2-F2^2) pf's
;Ls=1/(4*pi^2*F1^2/TIME^2*Cs) = 1.013212E15/F1^2/Cs uhy's
;
CALIB    CALL      CLRDSP    ;clear the display
         MOVLW     'C'       ;display "CALIBRATING"
         CALL      CHARLCD
         MOVLW     'A'
         CALL      CHARLCD
         MOVLW     'L'
         CALL      CHARLCD
         MOVLW     'I'
         CALL      CHARLCD
         MOVLW     'B'
         CALL      CHARLCD
         MOVLW     'R'
         CALL      CHARLCD
         MOVLW     'A'
         CALL      CHARLCD
         CALL      CHAR8
         MOVLW     'T'
         CALL      CHARLCD
         MOVLW     'I'
         CALL      CHARLCD
         MOVLW     'N'
         CALL      CHARLCD
         MOVLW     'G'
         CALL      CHARLCD
         MOVLW     H'0C'
         MOVWF     FSR
RAMLOOP  CLRF      INDF      'clear RAM from 0C thru 1F
         INCF      FSR
         BTFSS     FSR,5
         GOTO      RAMLOOP
         CALL      MEASURE   ;measure F1^2
         CALL      FEQUA     ;F=F1^2
         BSF       _CAL      ;switch in calibration capacitor
         MOVLW     H'
09'     ;delay 2 seconds
         MOVWF     T2
TD1      MOVLW     H'
FF'
         CALL      DELAY
         DECFSZ    T2
         GOTO      TD1
         CALL      MEASURE   ;measure F2^2
         CALL      CEQUA     ;C=F2^2 (H'
87.08 00 03 = 68)
         CALL      BEQUA     ;B=F2^2
         BCF       _CAL      ;switch out calibration capacitor
         CALL      AEQUF     ;A= F1^2
         CALL      SUB       ;A=F1^2 - F2^2
         CALL      BEQUA     ;B=F1^2 - F2^2
         MOVF      CX,W      ;A=F2^2
         MOVWF     AX
         MOVF      C0,W
         MOVWF     A0
         MOVF      C1,W
         MOVWF     A1
         MOVF      C2,W
         MOVWF     A2
         CALL      DIV       ;A=F2^2/(F1^2 - F2^2)
         MOVLW     8A        ;B=1000pf (H'8A.7A 00 00)
         MOVWF     BX
         MOVLW     7A
         MOVWF     B0
         CLRF      B1
         CLRF      B2
         CALL      MPY       ;A=F2^2*1000pf/(F1^2 - F2^2)=C
         CALL      CEQUA     ;C=A
         CALL      BEQUA     ;B=C
         CALL      AEQUF     ;A=F1^2
         CALL      MPY       ;A=F1^2*C
         CALL      BEQUA     ;B=F1^2*C
         MOVLW     H'B2'     ;A=1.013212E15 (H'B2.66 60 B3)
         MOVWF     AX
         MOVLW     H'66'
         MOVWF     A0
         MOVLW     H'60'
         MOVWF     A1
         MOVLW     H'B3'
         MOVWF     A2
         CALL      DIV       ;A=1.013212E15/(F1^2*Cs)=L
         MOVF      AX,W      ;L=A
         MOVWF     LX
         MOVF      A0,W
         MOVWF     L0
         MOVF      A1,W
         MOVWF     L1
         MOVF      A2,W
         MOVWF     L2
;**********************************************************************************************
;
;MAIN LOOP
;
DO1A     MOVLW     H'81'     ;DO
         CALL      CMDLCD    ;   set DD RAM address=0
IF1A     BTFSC     _LX       ;   IF /LX and /CX
         GOTO      ELSEIF1A
         BTFSC     _CX
         GOTO      ELSEIF1A
IF6A     BTFSC     _ZERO     ;      IF ZERO
         GOTO      CALIB     ;         CALIBRATE
ELSE6A   CALL      MEASURE   ;      A=F1^2
ENDIF6A EQU       $
IF2A     MOVF      T0,W      ;      IF VALID (W=0)
         BTFSS     _Z
         GOTO      ENDIF2A
         CALL      FEQUA     ;         F=F1^2
         CALL      CLRDSP    ;         CLEAR DISPLAY
         MOVLW     'R'       ;         "READY"
         CALL      CHARLCD
         MOVLW     'E'
         CALL      CHARLCD
         MOVLW     'A'
         CALL      CHARLCD
         MOVLW     'D'
         CALL      CHARLCD
         MOVLW     'Y'
         CALL      CHARLCD
ENDIF2A  GOTO      ENDIF1A   ;      ENDIF
ELSEIF1A BTFSS     _LX       ;   ELSEIF LX and CX
         GOTO      ELSE1A
         BTFSS     _CX
         GOTO      ELSE1A
         CALL      DISPSW    ;      "SWITCH ERROR"
         GOTO      ENDIF1A
ELSE1A   EQU       $         ;   ELSE (LX or CX)
         CALL      MEASURE   ;      A=F2^2
IF3A     MOVF      T0,W      ;      IF VALID (W=0)
         BTFSS     _Z
         GOTO      ELSE3A
         CALL      BEQUA     ;         B=F2^2
         CALL      AEQUF     ;         A=F1^2
         CALL      DIV       ;         A=F1^2/F2^2
         MOVLW     H'81'
         MOVWF     BX
         CLRF      B0
         CLRF      B1
         CLRF      B2        ;         B=1
         CALL      SUB       ;         A=F1^2/F2^2-1
         MOVF      AX,W
         BTFSS     _Z
         GOTO      IF4A      ;         IF A<0 THEN A=0
         CLRF      AX
         CLRF      A0
         CLRF      A1
         CLRF      A2
IF4A     BTFSS     _LX       ;         IF LX
         GOTO      ELSE4A
         CALL      BEQUL     ;            B=L
         CALL      MPY       ;            A=(F1^2/F2^2-1)*L
         MOVF      AX,W      ;               LS=A
         MOVWF     LSX
         MOVF      A0,W
         MOVWF     LS0
         MOVF      A1,W
         MOVWF     LS1
         MOVF      A2,W
         MOVWF     LS2
         CALL      BEQUA     ;               B=LS
         MOVLW     H'8E'     ;               A=10^4
         MOVWF     AX
         MOVLW     H'1C'
         MOVWF     A0
         MOVLW     H'40'
         MOVWF     A1
         CLRF      A2
         CALL      SUB       ;               A=10^4 - LS
IF13A    BTFSC     A0,7      ;               IF RESULT POSITIVE
         GOTO      ELSE13A
         MOVLW     H'6F'     ;                  B = .000007
         MOVWF     BX
         MOVLW     H'6A'
         MOVWF     B0
         MOVLW     H'E1'
         MOVWF     B1
         MOVLW     H'8B'
         MOVWF     B2
         CALL      MPY       ;                  A = (10^4 - LS)*.000007
         MOVLW     H'81'     ;                  B =1
         MOVWF     BX
         CLRF      B0
         CLRF      B1
         CLRF      B2
         CALL      ADD       ;                 A=((10^4 - LS)*.000007)+1
         MOVF      LSX,W     ;                 B = LS
         MOVWF     BX
         MOVF      LS0,W
         MOVWF     B0
         MOVF      LS1,W
         MOVWF     B1
         MOVF      LS2,W
         MOVWF     B2
         CALL      MPY       ;                 A=(((10^4-LS)*.000007)+1)LS
         GOTO      ENDIF13A
ELSE13A  MOVF      LSX,W
         MOVWF     AX        ;                 B = LS
         MOVF      LS0,W
         MOVWF     A0
         MOVF      LS1,W
         MOVWF     A1
         MOVF      LS2,W
         MOVWF     A2
ENDIF13A EQU       $
IF5A     BTFSS     _ZERO     ;            IF ZERO
         GOTO      ELSE5A
         CALL      MEASURE   ;               remeasure f1^2
         CALL      FEQUA
         CALL      DISP00
         GOTO      ENDIF5A
ELSE5A   EQU       $         ;            ELSE
         CALL      DISPLX    ;               "Lx= "
         CALL      DISPVAL   ;               DISPLAY VALUE
ENDIF5A  GOTO      ENDIF4A   ;            ENDIF
ELSE4A   CALL      BEQUC     ;         ELSE (CX)
         CALL      MPY       ;            A=(F1^2/F2^2-1)*C
IF8A     BTFSS     _ZERO     ;            IF ZERO
         GOTO      ELSE8A
         CALL      MEASURE
         CALL      FEQUA
         CALL      DISP00
         GOTO      ENDIF8A
ELSE8A   EQU       $         ;            ELSE
         CALL      DISPCX    ;               "Cx= "
         CALL      DISPVAL   ;               DISPLAY VALUE
ENDIF8A EQU       $         ;            ENDIF
ENDIF4A  GOTO      ENDIF3A   ;         ENDIF
ELSE3A   EQU       $         ;      ELSE (invalid)
IF11A    BTFSS     T0,1      ;         IF stalled oscillator (W=2)
         GOTO      ENDIF11A
         CALL      CLRDSP
         MOVLW     'N'       ;            "NOT A"
         CALL      CHARLCD
         MOVLW     'O'
         CALL      CHARLCD
         MOVLW     'T'
         CALL      CHARLCD
         CALL      DISPSP
         MOVLW     'A'
         CALL      CHARLCD
IF12A    BTFSS     _LX       ;            IF LX
         GOTO      ELSE12A
         MOVLW     'N'       ;               "N L"
         CALL      CHARLCD
         MOVLW     ' '
         CALL      CHARLCD
         CALL      CHAR8
         MOVLW     'L'
         CALL      CHARLCD
         GOTO      ENDIF12A
ELSE12A EQU       $         ;            ELSE (CX)
         MOVLW     ' '       ;               " C"
         CALL      CHARLCD
         MOVLW     'C'
         CALL      CHARLCD
ENDIF12A EQU       $         ;            ENDIF
ENDIF11A EQU       $         ;         ENDIF
ENDIF3A EQU       $         ;      ENDIF
ENDIF1A EQU       $         ;   ENDIF
         GOTO      DO1A      ;LOOP
         PAGE
;**********************************************************************************************
DISPVAL
;Compute value:
;Input: A=floating point Lx or Cx
;Output: A=BCD value of Lx or Cx
;
;
DISPVAL CLRF    T2              ;T2 = 0
WHILE1B MOVF    AX,W            ;WHILE A >=  1
        SUBLW   H'80'
        BTFSC   _C
        GOTO    WEND1B+1
        MOVLW   H'84'           ;   A = A / 10
        MOVWF   BX
        MOVLW   H'20'
        MOVWF   B0
        CLRF    B1
        CLRF    B2
        CALL    DIV
        INCF    T2              ;   T2 = T2 + 1
WEND1B  GOTO    WHILE1B         ;WEND
        MOVLW   H'8E'           ;A = INT(A * 10000)
        MOVWF   BX
        MOVLW   H'1C'
        MOVWF   B0
        MOVLW   H'40'
        MOVWF   B1
        CLRF    B2
        CALL    MPY
        CALL    INT
        CALL    BCD             ;A = STR$(A)
        MOVF    T2,W
        MOVWF   AX              ;AX = T2
        MOVLW   H'E4'
        MOVWF   LP              ;default L prefix is micro
        MOVLW   "p"
        MOVWF   CP              ;default C prefix is pico
AX0     MOVF    AX,W            ;IF AX = 0 THEN
        BTFSS   _Z
        GOTO    AX1
        CALL    DISP0           ;   PRINT 0.12
        CALL    DISPDOT
        CALL    DIGIT1
        CALL    DIGIT2
        CALL    CHAR8
        BTFSS   _LX             ;   IF NOT LX THEN
        GOTO    SP              ;      PRINT " " AND ENG UNITS
        CALL    DIGIT3          ;   ELSE PRINT 3
        GOTO    UNITS           ;      PRINT ENG UNITS
AX1     DECFSZ  AX              ;ELSEIF AX - 1 = 0 THEN
        GOTO    AX2
AX1LX   CALL    DIGIT1          ;   PRINT 1.23
        CALL    DISPDOT
        CALL    DIGIT2
        CALL    DIGIT3
        CALL    CHAR8
        BTFSS   _LX             ;   IF NOT LX THEN
        GOTO    SP              ;      PRINT " " AND ENG UNITS
        CALL    DIGIT4          ;   ELSE  PRINT 4
        GOTO    UNITS           ;      PRINT ENG UNITS
AX2     DECFSZ  AX              ;ELSEIF AX - 2 = 0 THEN
        GOTO    AX3
AX2LX   CALL    DIGIT1          ;   PRINT 12.34
        CALL    DIGIT2
        CALL    DISPDOT
        CALL    DIGIT3
        CALL    CHAR8
        CALL    DIGIT4
        GOTO    UNITS           ;     AND ENG UNITS
AX3     DECFSZ  AX              ;ELSEIF AX - 3 = 0 THEN
        GOTO    AX4
AX3LX   CALL    DIGIT1          ;   PRINT 123.4
        CALL    DIGIT2
        CALL    DIGIT3
        CALL    DISPDOT
        CALL    CHAR8
        CALL    DIGIT4
        GOTO    UNITS           ;      AND ENG UNITS
AX4     MOVLW   "m"
        MOVWF   LP              ;L PREFIX="m"
        MOVLW   "n"
        BTFSS  _JUMPER          ;IF JUMPER SHORT THEN CP="n"
        MOVWF   CP
        DECFSZ  AX              ;ELSEIF AX - 4 = 0 THEN
        GOTO    AX5
        BTFSC   _LX             ;   IF LX THEN PRINT 1.234
        GOTO    AX4LX           ;              AND ENG UNITS
        BTFSC   _JUMPER         ;   ELSEIF JUMPER
        GOTO    AX4CX
AX4LX   CALL    DIGIT1          ;      PRINT 1.234
        CALL    DISPDOT
        CALL    DIGIT2
        CALL    DIGIT3
        CALL    CHAR8
        CALL    DIGIT4
        GOTO    UNITS           ;      AND ENG UNITS
AX4CX   CALL    DIGIT1          ;   ELSE PRINT DIGITS 1234
        CALL    DIGIT2
        CALL    DIGIT3
        CALL    DIGIT4
        CALL    CHAR8
        GOTO    SP              ;        PRINT " " AND ENG UNITS
AX5     MOVLW   H'E4'
        BTFSC   _JUMPER         ;IF NOT JUMPER THEN CP="u"
        MOVWF   CP
        DECFSZ  AX              ;ELSEIF AX - 5 = 0 THEN
        GOTO    AX6
        BTFSC   _LX             ;   IF LX THEN PRINT 12.34 AND ENG UNITS
        GOTO    AX2LX
        BTFSS   _JUMPER         ;   IF JUMPER PRINT 12.34 AND ENG UNITS
        GOTO    AX2LX
        CALL    DISPDOT         ;   ELSE PRINT .0123
        CALL    DISP0
        CALL    DIGIT1
        CALL    DIGIT2
        CALL    CHAR8
        CALL    DIGIT3
        GOTO    UNITS
AX6     DECFSZ  AX              ;ELSEIF AX - 6 = 0 THEN
        GOTO    AX7
        BTFSC   _LX             ;   IF LX THEN
        GOTO    AX3LX           ;      PRINT 123.4 AND ENG UNITS
        BTFSS   _JUMPER         ;   IF JUMPER
        GOTO    AX3LX           ;      PRINT 123.4 AND ENG UNITS
        CALL    DISPDOT         ;   ELSE PRINT .1234
        CALL    DIGIT1
        CALL    DIGIT2
        CALL    DIGIT3
        CALL    CHAR8
        CALL    DIGIT4
        GOTO    UNITS
AX7     MOVLW   " "
        MOVWF   LP              ;LP = " "
        MOVLW   H'E4'
        MOVWF   CP              ;CP = "u"
        GOTO    AX4LX           ;PRINT 1.234
SP      CALL    DISPSP
UNITS   CALL    DISPSP
        BTFSS   _LX             ;IF LX THEN
        GOTO    CXP
        MOVF    LP,W
        CALL    CHARLCD
        MOVLW   "H"             ;   PRINT "Hy's"
        CALL    CHARLCD
        MOVLW   "y"
        GOTO    PX
CXP     MOVF    CP,W
        CALL    CHARLCD
        MOVLW   "F"             ;ELSE PRINT "F's"
PX      CALL   CHARLCD          ;END IF
        MOVLW   "'"
        CALL    CHARLCD
        MOVLW   "s"
        CALL    CHARLCD
        GOTO    DISPSP          ;exit displaying a space
;
;
DIGIT1  SWAPF   A1              ;PRINT DIGIT 1
        MOVF    A1,W
        CALL    NUMLCD
        RETLW   0
DIGIT2 EQU     DIGIT1          ;PRINT DIGIT 2
DIGIT3  SWAPF   A2              ;PRINT DIGIT 3
        MOVF    A2,W
        CALL    NUMLCD
        RETLW   0
DIGIT4 EQU     DIGIT3          ;PRINT DIGIT 4
;**********************************************************************************************
;  Delay timer.  Delay = 771*MSD microseconds (.197 sec max)
;  entry CALL DELAY, W = MSD
;  CALL DLY200 implements a 200 us delay
DLY15    CALL      DLY5
         CALL      DLY5
DLY5     MOVLW     07
         GOTO      DELAY
DLY200   MOVLW     40        ;delay 200us
         MOVWF     T1
         MOVLW     01
         GOTO      DELAY2
DELAY    CLRF      T1
DELAY2   MOVWF     T0
DELAYL   DECFSZ    T1        ;decrement LSB until zero
         GOTO      DELAYL
         DECFSZ    T0        ;decrement MSB until zero
         GOTO      DELAYL
         RETLW     0         ;exit
;**********************************************************************************************
;  Send one byte to LCD
;  CALL CMDLCD  sends command in W to LCD
;  CALL NUMLCD  sends BCD digit in low nibble in W as ASCII char
;  CALL CHARLCD sends ASCII character in W to LCD
;There is a 200 us delay built into the end of the routine.
;
CHAR8    MOVLW     H'C0'     ;SET TO SECOND 8 CHARS
CMDLCD   MOVWF     B0        ;save byte
         CLRF      PORTB     ;SET /RW, /ENB, /RS
         GOTO      SENDLCD
NUMLCD   ANDLW     0F        ;mask LS nibble
         IORLW     30        ;make ASCII number
CHARLCD  MOVWF     B0        ;save byte
         MOVLW     08
         MOVWF     PORTB     ;set /RW, /ENB, RS
SENDLCD  SWAPF     B0        ;send high nibble first
         MOVF      B0,W
         MOVWF     PORTA
         BSF       _ENB      ;toggle ENB on
         BCF       _ENB      ;toggle ENB off
         SWAPF     B0        ;swap nibbles
         MOVF      B0,W
         MOVWF     PORTA     ;send low nibble
SEND     BSF       _ENB      ;toggle ENB on
         BCF       _ENB      ;toggle ENB off
         CALL      DLY200    ;delay 200us
         RETLW     0         ;exit
;**********************************************************************************************
CLRDSP   MOVLW     01
CLR6     CALL      CMDLCD    ;clear display
         CALL      DLY5      ;delay 5ms
         MOVLW     H'28'     ;set 4 bit 2 line
         CALL      CMDLCD
         GOTO      DISPSP
;**********************************************************************************************
DISPDOT  MOVLW     "."
         GOTO      CHARLCD
DISP0    MOVLW     "0"
         GOTO      CHARLCD
;**********************************************************************************************
DISPSW   MOVLW     'S'       ;DISPLAY SWITCH ERROR
         CALL      CHARLCD
         MOVLW     'W'
         CALL      CHARLCD
         MOVLW     'I'
         CALL      CHARLCD
         MOVLW     'T'
         CALL      CHARLCD
         MOVLW     'C'
         CALL      CHARLCD
         MOVLW     'H'
         CALL      CHARLCD
         CALL      DISPSP
         CALL      CHAR8
         MOVLW     'E'
         CALL      CHARLCD
         MOVLW     'R'
         CALL      CHARLCD
         MOVLW     'R'
         CALL      CHARLCD
         MOVLW     'O'
         CALL      CHARLCD
         MOVLW     'R'
         CALL      CHARLCD
         CALL      DISPSP
         CALL      DISPSP
         GOTO      DISPSP
;**********************************************************************************************
DISP00   CALL      CLRDSP
         CALL      DISP0
         CALL      DISPDOT
         CALL      DISP0
         CALL      DISP0
         CALL      DISP0
         GOTO      DISPSP
;**********************************************************************************************
DISPLX   MOVLW     "L"
         CALL      CHARLCD
         GOTO      DISPX
DISPCX   MOVLW     "C"
         CALL      CHARLCD
DISPX    MOVLW     "x"
         CALL      CHARLCD
         MOVLW     "="
         CALL      CHARLCD
         RETLW     0
;**********************************************************************************************
DISPSP   MOVLW     " "
         CALL      CHARLCD
         RETLW     0
;**********************************************************************************************
;**********************************************************************************************
;**********************************************************************************************
;**********************************************************************************************
;**********************************************************************************************
;MEASURE Measure frequency on RTCC pin
;        returns A=count squared=(freq*time)squared
;        time = .2 seconds
;DISPVAL Display value of Lx or Cx
;        Input: A=floating point value
;        Output: A=5 digit BCD value in A0, A1, A2
;        AX=decimel exponent
;        value is output to the LCD as:
;           X.XXX, XX.XX, XXX.X or XXXX as a function of AX
;BEQUA    B=A
;AEQUF    A=F
;BEQUC    B=C
;BEQUL    B=L
;FEQUA    F=A
;CEQUA    C=A
;BCD     16 bit number in A1,A2 converted to 5 BCD
;        digits in A0, A1 and A2 with MS digit in A0
;FLOAT   24 bit unsigned integer to 32 bit floating point
;        Input: integer right justified in A0, A1, A2
;        Output: 32 bit floating point number in AX, A0, A1, A2
;INT     32 bit floating point to 16 bit integer
;        Input: 32 bit floating point number in AX, A0, A1, A2
;  Output:24 bit 2's compl' integer right justified in A0, A1, A2
;ADD     32 bit floating point add
;  Input: 32 bit floating point number in AX, A0, A1, A2
;         32 bit floating point number in BX, B0, B1, B2
;  Output:  32 bit floating point sum in AX, A0, A1, A2
;SUB     32 bit floating point subtract
;  Input: 32 bit floating point number in AX, A0, A1, A2
;         32 bit floating point number in BX, B0, B1, B2
;  Output:  32 bit floating point difference in AX, A0, A1, A2
;MPY     32 bit floating point multiply
;  Input: 32 bit floating point number in AX, A0, A1, A2
;         32 bit floating point number in BX, B0, B1, B2
;  Output:  32 bit floating point product in AX, A0, A1, A2
;DIV     32 bit floating point divide
;  Input: 32 bit floating point dividend in AX, A0, A1, A2
;         32 bit floating point divisor in BX, B0, B1, B2
;  Output:  32 bit floating point quotient in AX, A0, A1, A2
         PAGE
;**********************************************************************************************
;  Routine to measure frequency
;       returns floating point number = count squared in A
;       IF switch settings on exit match those on entry
;          return T0=0  (valid measurement)
;       ELSEIF switches have changed
;          return T0=1 (invalid measurement)
;       ELSEIF oscillator stalled
;          return T0=2 (open circuit inductor or short circuit capacitor)
;          (invalid measurement)
;       ENDIF
;
MEASURE     MOVF    PORTB,W       ;save switch settings
            ANDLW   H'60'
            MOVWF   T2
            CLRF    A0            ;clear count
            CLRF    A1
            CLRF    A2
            MOVLW   H'38'         ;initialize delay = 200,000us (.2 sec)
            MOVWF   T0            ;loop is 14us
            MOVLW   H'CD'         ;so initialize counter to 14285+256(H'38CD)
            MOVWF   T1            ;actual period is 200006 us
            CLRF    CNTR          ;initialize CNTR
MEAS1       GOTO    MEAS2         ;2 cycle delay
MEAS2       MOVF    CNTR,W        ;W=CNTR
            SUBWF   A2,W          ;W=A2-CNTR
            BTFSS   _C            ;Did A2 overflow? (CARRY)
            GOTO    MEAS5         ;   NO, do not increment A1
            BTFSS  _Z             ;Does A2=0, NO do not increment A1
            INCFSZ  A1            ;   YES, inc A1, overlow? (ZERO)
            GOTO    MEAS3         ;        NO
            INCF    A0            ;        YES, increment A0
MEAS3       SUBWF   A2            ;A2=W=A2-(A2-CNTR)=CNTR
            DECFSZ  T1            ;decrement delay
            GOTO    MEAS1
            DECFSZ  T0
            GOTO    MEAS2
            CLRF    T0            ;initialize return code=0
            MOVF    A0,W          ;measurement complete, 17 bits in A0,A1,A2
            BTFSS   _Z            ;  IF A0
            GOTO    MEAS4
            MOVF    A1,W          ;     and A1 both zero
            BTFSS   _Z
            GOTO    MEAS4
            BSF     T0,1
            RETLW   0             ;     return T0=2 (stalled oscillator)
MEAS4       MOVF    PORTB,W       ;  IF switch settings changed
            ANDLW   H'60'         ;     (MASK SWITCHES)
            SUBWF   T2,W
            BTFSC   _Z
            GOTO    MEAS6
            BSF     T0,0          ;     switches have changed
            RETLW   0             ;     return with T0=1 (invalid measurement)
MEAS6       CALL    FLOAT         ;convert to floating point
            CALL    BEQUA         ;B=A
            CALL    MPY           ;A=A*A
            CLRF    T0
            RETLW   0             ;return with T0=0 (valid measurement)
MEAS5       NOP
            GOTO    MEAS3
;**********************************************************************************************
BEQUA       MOVF    AX,W
            MOVWF   BX
            MOVF    A0,W
            MOVWF   B0
            MOVF    A1,W
            MOVWF   B1
            MOVF    A2,W
            MOVWF   B2
            RETLW   0
;**************************************************************
AEQUF       MOVF    FX,W
            MOVWF   AX
            MOVF    F0,W
            MOVWF   A0
            MOVF    F1,W
            MOVWF   A1
            MOVF    F2,W
            MOVWF   A2
            RETLW   0
;**********************************************************
BEQUC       MOVF    CX,W
            MOVWF   BX
            MOVF    C0,W
            MOVWF   B0
            MOVF    C1,W
            MOVWF   B1
            MOVF    C2,W
            MOVWF   B2
            RETLW   0
;************************************************************
BEQUL       MOVF      LX,W      ;           B=L
            MOVWF     BX
            MOVF      L0,W
            MOVWF     B0
            MOVF      L1,W
            MOVWF     B1
            MOVF      L2,W
            MOVWF     B2
            RETLW     0
;*************************************************************
FEQUA       MOVF      AX,W      ;save A in F
            MOVWF     FX
            MOVF      A0,W
            MOVWF     F0
            MOVF      A1,W
            MOVWF     F1
            MOVF      A2,W
            MOVWF     F2
            RETLW     0
;*************************************************************
CEQUA       MOVF      AX,W      ;save A in C
            MOVWF     CX
            MOVF      A0,W
            MOVWF     C0
            MOVF      A1,W
            MOVWF     C1
            MOVF      A2,W
            MOVWF     C2
            RETLW     0
;**********************************************************************************************
;                  Binary To BCD Conversion Routine
;      This routine converts a 16 Bit binary Number to a 5 Digit
; BCD Number.
;       The 16 bit binary number is input in locations A1 and
;A2 with the high byte in A1.
;       The 5 digit BCD number is returned in A0, A1 and A2 with A0
; containing the MSD in its right most nibble.
;
;   Performance :
;               Program Memory  :       35
;               Clock Cycles    :       885
;
;**********************************************************************************************
BCD     MOVF    A1,W
        MOVWF   B0
        MOVF    A2,W
        MOVWF   B1
        bcf     _C                ; clear the carry bit
        movlw   .16
        movwf   T1
        clrf    A0
        clrf    A1
        clrf    A2
loop16  rlf     B1
        rlf     B0
        rlf     A2
        rlf     A1
        rlf     A0
        decfsz  T1
        goto    adjDEC
        RETLW   0
adjDEC  movlw   A2
        movwf   FSR
        call    adjBCD
        movlw   A1
        movwf   FSR
        call    adjBCD
        movlw   A0
        movwf   FSR
        call    adjBCD
        goto    loop16
adjBCD  movlw   3
        addwf   0,W
        movwf   T0
        btfsc   T0,3          ; test if result > 7
        movwf   0
        movlw   30
        addwf   0,W
        movwf   T0
        btfsc   T0,7         ; test if result > 7
        movwf   0            ; save as MSD
        RETLW   0
;**********************************************************************************************
;**********************************************************************************************
; PIC16 32 BIT FLOATING POINT LIBRARY
; Unary operations: both input and output are in AX,A
; Binary operations: input in AX,A and BX,B with output in AX,A
;**********************************************************************************************
;**********************************************************************************************
; 32 bit floating point representation
; EXPONENT  8 bit biased exponent
;     It is important to note that the use of biased exponents produces
;     a unique representation of a floating point 0, given by
;     EXP = HIGHBYTE = MIDBYTE = LOWBYTE = 0x00, with 0 being
;     the only number with AX = 0.
; HIGHBYTE  8 bit most significant byte of sign-magnitude representation, with
;     SIGN = MSB, and implicit mantissa MSB = 1 and radix point to the
;     left of MSB
; MIDBYTE 8 bit middle significant byte of sign-magnitude matissa
; LOWBYTE 8 bit least significant byte of sign-magnitude matissa
;     RADIX
; EXPONENT  POINT   HIGHBYTE  MIDBYTE LOWBYTE
; xxxxxxxx           .  Sxxxxxxx  xxxxxxxx  xxxxxxxx
EXPBIAS equ H'80'
;**********************************************************************************************
; Integer to float conversion
; Input:  24 bit unsigned integer right justified in A0, A1, A2
; Use:  CALL  FLOAT
; Output: 32 bit floating point number in AX, A0, A1, A2
; Result: A  <--  FLOAT( A )
FLOAT   MOVLW   H'18'+EXPBIAS   ; initialize exponent and add bias
        MOVWF   AX
        CLRF    SIGN                    ; fall thru to normalize
;-------------------------------------------------------------------
; Normalization routine
; Input:  32 bit unnormalized floating point number in AX, A0, A1, A2
;               with sign in SIGN,MSB
; Use:  CALL  NRM32
; Output: 32 bit normalized floating point number in AX, A0, A1,
;   A2
; Result: A  <--  NORMALIZE( A )
NRM32   CLRF    T0    ; clear exponent decrement
        MOVF    A0,W    ; test if highbyte=0
        BTFSS   _Z
        GOTO    NORM32
        MOVF    A1,W    ; if so, shift 8 bits by move
        MOVWF   A0
        MOVF    A2,W
        MOVWF   A1
        CLRF    A2
        BSF     T0,3    ; increase decrement by 8
        MOVF    A0,W    ; test if highbyte=0
        BTFSS   _Z
        GOTO    NORM32
        MOVF    A1,W    ; if so, shift 8 bits by move
        MOVWF   A0
        CLRF    A1
        BCF     T0,3    ; increase decrement by 8
        BSF     T0,4
        MOVF    A0,W    ; if highbyte=0, result=0
        BTFSC   _Z
        GOTO    RES032
NORM32  MOVF    T0,W
        SUBWF   AX
        BCF     _C
NORM32A BTFSC   A0,MSB    ; if MSB=1, normalization done
        GOTO    FIXSIGN32
        RLF     A2    ; otherwise, shift left and
        RLF     A1    ; decrement AX
        RLF     A0
        DECF    AX
        GOTO    NORM32A

FIXSIGN32 BTFSS SIGN,MSB
        BCF     A0,MSB    ; clear explicit MSB if positive
        RETLW   0
;**********************************************************************************************
; Float to integer conversion
; Input:  32 bit floating point number in AX, A0, A1, A2
; Use:  CALL  INT
; Output: 24 bit unsigned integer right justified in A0, A1, A2
; Result: A  <--  INT( A )
INT     BSF     A0,MSB    ; make MSB explicit
        MOVLW   EXPBIAS   ; remove bias from AX
        SUBWF   AX
        BTFSS   AX,MSB    ; if <= 0, result=0
        BTFSC   _Z
        GOTO    RES032
        MOVF    AX,W
        SUBLW   18
        MOVWF   AX
SHIFT32 BCF     _C
        RRF     A0    ; right shift by AX
        RRF     A1
        RRF     A2
        DECFSZ  AX
        GOTO    SHIFT32
        RETLW   0
RES032  CLRF    A0    ; integer result equals zero
        CLRF    A1
        CLRF    A2
        CLRF    AX    ; clear AX for other routines
INT32OK RETLW   0
;**********************************************************************************************
; Floating Point Multiply
; Input:  32 bit floating point number in AX, A0, A1, A2
;   32 bit floating point number in BX, B0, B1, B2
; Use:  CALL  MPY
; Output: 32 bit floating point product in AX, A0, A1, A2
; Result: A  <--  A * B
MPY     MOVF    AX,W    ; test for zero arguments
        BTFSS   _Z
        MOVF    BX,W
        BTFSC   _Z
        GOTO    RES032
M32BNE0 MOVF    A0,W
        XORWF   B0,W
        MOVWF   SIGN    ; save sign in SIGN
        MOVF    BX,W
        ADDWF   AX
        MOVLW   EXPBIAS
        BTFSS   _C
        GOTO    MTUN32
        ADDWF   AX
        GOTO    MOK32
MTUN32  ADDWF   AX
MOK32   BSF     A0,MSB    ; make argument MSB's explicit
        BSF     B0,MSB
        BCF     _C
        CLRF    A3    ; clear initial partial product
        CLRF    A4
        CLRF    A5
        MOVLW   18
        MOVWF   T0    ; initialize counter
MLOOP32 BTFSS   A2,LSB    ; test high byte
        GOTO    MNOADD32
MADD32  MOVF    B2,W
        ADDWF   A5
        MOVF    B1,W
        BTFSC   _C
        INCFSZ  B1,W
        ADDWF   A4
        MOVF    B0,W
        BTFSC   _C
        INCFSZ  B0,W
        ADDWF   A3
MNOADD32  RRF   A3
        RRF     A4
        RRF     A5
        RRF     A0
        RRF     A1
        RRF     A2
        BCF     _C
        DECFSZ  T0
        GOTO    MLOOP32
        BTFSC   A3,MSB    ; check for postnormalization
        GOTO    MUL32OK
        RLF     A0
        RLF     A5
        RLF     A4
        RLF     A3
        DECF    AX
MUL32OK BTFSS   SIGN,MSB
        BCF     A3,MSB    ; clear explicit MSB if positive
        MOVF    A3,W
        MOVWF   A0    ; move result to A
        MOVF    A4,W
        MOVWF   A1
        MOVF    A5,W
        MOVWF   A2
        RETLW   0
;**********************************************************************************************
; Floating Point Divide
; Input:  32 bit floating point dividend in AX, A0, A1, A2
;   32 bit floating point divisor in BX, B0, B1, B2
; Use:  CALL  DIV
; Output: 32 bit floating point quotient in AX, A0, A1, A2
; Result: A  <--  A / B
; PM: 152         DM: 14
DIV   MOVF    A0,W
      XORWF   B0,W
      MOVWF   SIGN    ; save sign in SIGN
      BSF     A0,MSB    ; make argument MSB's explicit
      BSF     B0,MSB
TALIGN32  CLRF    T0    ; clear align increment
      MOVF    A0,W
      MOVWF   A3    ; test for alignment
      MOVF    A1,W
      MOVWF   A4
      MOVF    A2,W
      MOVWF   A5
      MOVF    B2,W
      SUBWF   A5
      MOVF    B1,W
      BTFSS   _C
      INCFSZ  B1,W
TS1ALIGN32    SUBWF A4
      MOVF    B0,W
      BTFSS   _C
      INCFSZ          B0,W
TS2ALIGN32    SUBWF A3
      CLRF    A3
      CLRF    A4
      CLRF    A5
      BTFSS   _C
      GOTO    DALIGN32OK
      BCF     _C    ; align if necessary
      RRF     A0
      RRF     A1
      RRF     A2
      RRF     A3
      MOVLW   0x01
      MOVWF   T0    ; save align increment
DALIGN32OK    MOVF BX,W    ; compare AX and BX
      SUBWF   AX
      BTFSS   _C
      GOTO    ALTB32
AGEB32 MOVLW   EXPBIAS
      ADDWF   T0,W
      ADDWF   AX
      GOTO    DARGOK32
ALTB32 MOVLW   EXPBIAS
      ADDWF   T0,W
      ADDWF   AX
DARGOK32 MOVLW   18    ; initialize counter
      MOVWF   T1
DLOOP32 RLF   A5    ; left shift
      RLF     A4
      RLF     A3
      RLF     A2
      RLF     A1
      RLF     A0
      RLF     T0
      MOVF    B2,W    ; subtract
      SUBWF   A2
      MOVF    B1,W
      BTFSS   _C
      INCFSZ          B1,W
DS132 SUBWF   A1
      MOVF    B0,W
      BTFSS   _C
      INCFSZ          B0,W
DS232 SUBWF   A0
      RLF     B0,W
      IORWF   T0
      BTFSS   T0,LSB    ; test for restore
      GOTO    DREST32
      BSF     A5,LSB
      GOTO    DOK32
DREST32 MOVF    B2,W    ; restore if necessary
      ADDWF   A2
      MOVF    B1,W
      BTFSC   _C
      INCFSZ  B1,W
DAREST32  ADDWF   A1
      MOVF    B0,W
      BTFSC   _C
      INCF    B0,W
      ADDWF   A0
      BCF     A5,LSB
DOK32 DECFSZ  T1
      GOTO    DLOOP32
DDIV32OK  BTFSS   SIGN,MSB
      BCF     A3,MSB    ; clear explicit MSB if positive
      MOVF    A3,W
      MOVWF   A0    ; move result to A
      MOVF    A4,W
      MOVWF   A1
      MOVF    A5,W
      MOVWF   A2
      RETLW   0
;**********************************************************************************************
; Floating Point Subtract
; Input:  32 bit floating point number in AX, A0, A1, A2
;   32 bit floating point number in BX, B0, B1, B2
; Use:  CALL SUB
; Output: 32 bit floating point sum in AX, A0, A1, A2
; Result: A  <--  A - B
SUB   MOVF    BX,W
      BTFSS   _Z
      GOTO    SUB1
      MOVF    B0,W
      BTFSC   _Z
      RETLW   0
SUB1  MOVLW   0x80
      XORWF   B0
;-------------------------------------------------------------------
; Floating Point Add
; Input:  32 bit floating point number in AX, A0, A1, A2
;   32 bit floating point number in BX, B0, B1, B2
; Use:  CALL ADD
; Output: 32 bit floating point sum in AX, A0, A1, A2
; Result: A  <--  A - B
ADD   MOVF    A0,W    ; exclusive or of signs in TEMP
      XORWF   B0,W
      MOVWF   T0
      MOVF    AX,W    ; use A if AX >= BX
      SUBWF   BX,W
      BTFSS   _C
      GOTO    USEA32
      MOVF    BX,W
      MOVWF   A5    ; otherwise, swap A and B
      MOVF    AX,W
      MOVWF   BX
      MOVF    A5,W
      MOVWF   AX
      MOVF    B0,W
      MOVWF   A5
      MOVF    A0,W
      MOVWF   B0
      MOVF    A5,W
      MOVWF   A0
      MOVF    B1,W
      MOVWF   A5
      MOVF    A1,W
      MOVWF   B1
      MOVF    A5,W
      MOVWF   A1
      MOVF    B2,W
      MOVWF   A5
      MOVF    A2,W
      MOVWF   B2
      MOVF    A5,W
      MOVWF   A2
USEA32 MOVF    A0,W
      MOVWF   SIGN    ; save sign in SIGN
      BSF     A0,MSB    ; make MSB's explicit
      BSF     B0,MSB
      MOVF    B0,W
      MOVWF   A3
      MOVF    B1,W
      MOVWF   A4
      MOVF    B2,W
      MOVWF   A5
      MOVF    BX,W    ; compute shift count in BX
      SUBWF   AX,W
      MOVWF   BX
      BTFSC   _Z
      GOTO    ALIGNED32
      MOVLW   8
      SUBWF   BX,W
      BTFSS   _C    ; if BX >= 8, do byte shift
      GOTO    ALIGNB32
      MOVWF   BX
      RLF     A5    ; rotate next bit for rounding
      MOVF    A4,W
      MOVWF   A5
      MOVF    A3,W
      MOVWF   A4
      CLRF    A3
      MOVLW   8
      SUBWF   BX,W
      BTFSS   _C    ; if BX >= 8, do byte shift
      GOTO    ALIGNB32
      MOVWF   BX
      RLF     A5    ; rotate next bit for rounding
      MOVF    A4,W
      MOVWF   A5
      CLRF    A4

ALIGNB32  MOVF    BX,W    ; already aligned if BX = 0
      BTFSC   _Z
      GOTO    ALIGNED32
ALOOPB32  BCF   _C    ; right shift by BX
      RRF     A3
      RRF     A4
      RRF     A5
      DECFSZ  BX
      GOTO    ALOOPB32
ALIGNED32 BTFSS T0,MSB    ; negate if signs opposite
      GOTO    AOK32
      COMF    A3
      COMF    A4
      COMF    A5
      INCF    A5
      BTFSC   _Z
      INCF    A4
      BTFSC   _Z
      INCF    A3
AOK32 MOVF    A5,W    ; add
      ADDWF   A2
      MOVF    A4,W
      BTFSC   _C
      INCFSZ  A4,W
      ADDWF   A1
      MOVF    A3,W
      BTFSC   _C
      INCFSZ  A3,W
      ADDWF   A0
      BTFSC   T0,MSB
      GOTO    ACOMP32
      BTFSS   _C
      GOTO    FIXSIGN32
      RRF     A0    ; shift right and increment AX
      RRF     A1
      RRF     A2
      INCF    AX
      GOTO    FIXSIGN32
ACOMP32 BTFSC   _C
      GOTO    NRM32   ; normalize and fix sign
      COMF    A0    ; negate, toggle sign bit and
      COMF    A1    ; then normalize
      COMF    A2
      INCF    A2
      BTFSC   _Z
      INCF    A1
      BTFSC   _Z
      INCF    A0
      MOVLW   0x80
      XORWF   SIGN
      GOTO    NRM32
END
 


Staženo před cca šesti léty z FTP časopisu CircuitCellar
00.22.zip