Otáčkoměr - toť opravdu vděčné téma pro konstruktéra. Lze ho pojmout na mnoho způsobů. Dnes si ukážeme jak se to dělá u protinožců. Tato konstrukce vyšla v roce 2006 v časopisu SiliconChip. Předesílám - časopis nevlastním a vše co o konstrukci mám je v článku.

Záladní vlastnosti:
  • Fast 32-LED circular bargraph
  • Dot or bargraph option
  • 4-digit display
  • Gear shift indicator LED
  • Limiter signal output
  • Display from 0-9999 RPM or above 10,000 RPM (optional)
  • Two display options for RPM above 9999 RPM
  • Options for 1 RPM, 10 RPM or 100 RPM display resolution
  • Automatic display dimming in low ambient light
  • Set-up for 1, 2, 3, 4, 5, 6, 8, 10 & 12-cylinder 4-stroke engines and 1, 2, 3, 4, 5 & 6-cylinder 2-stroke engines
  • Selectable red line RPM
  • Selectable shift light RPM
  • Selectable limiter RPM
  • Selectable number of red line LEDs
  • Selectable display update period
  • Selectable RPM hysteresis for LED bargraph
  • Selectable limiter minimum on time











Zdrojový kod:

; LED Tachometer
        ERRORLEVEL -302
        ERRORLEVEL -306

        list P=16F88
        #include p16f88.inc

;Program Configuration Register 1
                __CONFIG    _CONFIG1, _CP_ALL & _CCP1_RB0  & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC

;Program Configuration Register 2
                __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF
; Define variables at memory locations


EEPROM0         equ     H'00'   ; non-volatile storage for redline RPM ms
EEPROM1         equ     H'01'   ; non-volatile storage for redline RPM ls
EEPROM2         equ     H'02'   ; non-volatile storage for number of red LEDs
EEPROM3         equ     H'03'   ; non-volatile storage for rpm /LED ms
EEPROM4         equ     H'04'   ; non-volatile storage for rpm /LED ls
EEPROM5         equ     H'05'   ; non-volatile storage for cylinder setting
EEPROM6         equ     H'06'   ; non-volatile storage for shift rpm ms byte
EEPROM7         equ     H'07'   ; non-volatile storage for shift rpm ls byte
EEPROM8         equ     H'08'   ; non-volatile storage for options (bar or dot, 3-LEDs or 1 LED dot, >10,000 rpm
EEPROM9         equ     H'09'   ; non-volatile storage for digital display update counter
EEPROMA         equ     H'0A'   ; non-volatile storage for LED bargraph hysteresis
EEPROMB         equ     H'0B'   ; non-volatile storage for limit RPM ms
EEPROMC         equ     H'0C'   ; non-volatile storage for limit RPM ls
EEPROMD         equ     H'0D'   ; non-volatile storage for limiter sense
EEPROME         equ     H'0E'   ; non-volatile storage for limiter on time

; Bank 0 RAM

RED_LINE1       equ     H'20'   ; redline rpm
RED_LINE2       equ     H'21'   ; redline rpm
RED_LEDS        equ     H'22'   ; number of red LEDs
TACHO_CAL1      equ     H'23'   ; calculation of rpm per LED (RED_LINE rpm/(32 - number of RED_LEDS)ms byte
TACHO_CAL2      equ     H'24'   ; calculation of rpm per LED (RED_LINE rpm/(32 - number of RED_LEDS)ls byte
CYL_SET         equ     H'25'   ; cylinder setting
SHIFT1          equ     H'26'   ; ms byte of shift rpm
SHIFT2          equ     H'27'   ; ls byte of shift rpm
COUNT0          equ     H'28'   ; ms 32-bit rpm counter
COUNT1          equ     H'29'   ; 32-bit rpm counter
COUNT2          equ     H'2A'   ; 32-bit rpm counter
COUNT3          equ     H'2B'   ; ls 32-bit rpm counter
RPM_VAL0        equ     H'2C'   ; ms byte calculated RPM
RPM_VAL1        equ     H'2D'   ; ls byte calculated RPM
OPTIONS         equ     H'2E'   ; options flags

LED_VALUE       equ     H'2F'   ; discrete LED rpm value (0-32)
IC1_LED1        equ     H'30'   ; 40-bit shift register for IC1 ls byte
IC1_LED2        equ     H'31'   ; 40-bit shift register for IC1
IC1_LED3        equ     H'32'   ; 40-bit shift register for IC1                                  
IC1_LED4        equ     H'33'   ; 40-bit shift register for IC1
IC1_LED5        equ     H'34'   ; 40-bit shift register for IC1 ms byte

IC2_LED1        equ     H'35'   ; 40-bit shift register for IC2 ls byte
IC2_LED2        equ     H'36'   ; 40-bit shift register for IC2
IC2_LED3        equ     H'37'   ; 40-bit shift register for IC2                                  
IC2_LED4        equ     H'38'   ; 40-bit shift register for IC2
IC2_LED5        equ     H'39'   ; 40-bit shift register for IC2 ms byte

CLK_CNT         equ     H'3A'   ; clock counter
COUNTER0        equ     H'3B'   ; ms 32-bit timer1 overflow counter
COUNTER1        equ     H'3C'   ; 32-bit timer1 overflow counter
NIL_SIG         equ     H'3D'   ; flag indicating if timer1 continues to overflows beyond COUNTER0
DELCNT          equ     H'3E'   ; delay counter
VALUE_1         equ     H'3F'   ; delay value
VALUE_2         equ     H'40'   ; delay value
SHIFT_MS        equ     H'41'   ; current rpm for shift light
SHIFT_LS        equ     H'42'   ; current rpm for shift light
UPDATE_TM       equ     H'43'   ; seven segment digital display update counter
UPDATE_CT       equ     H'44'   ; stored update
ONE_ONE         equ     H'45'   ; display values store
ONE_TWO         equ     H'46'   ; display values store
ONE_THREE       equ     H'47'   ; display values store
ONE_FOUR        equ     H'48'   ; display values store
ONE_FIVE        equ     H'49'   ; display values store
TWO_ONE         equ     H'4A'   ; display values store
TWO_TWO         equ     H'4B'   ; display values store
TWO_THREE       equ     H'4C'   ; display values store
TWO_FOUR        equ     H'4D'   ; display values store
TWO_FIVE        equ     H'4E'   ; display values store
STO_LEDVAL      equ     H'4F'   ; storage
STORE0          equ     H'50'   ; rpm storage
STORE1          equ     H'51'   ; rpm storage
HYSTERESIS      equ     H'52'   ; hysteresis
TWO_CNT         equ     H'53'   ; count of 2
TOTAL0          equ     H'54'   ; ms byte of rpm addition
TOTAL1          equ     H'55'   ; mid byte of rpm addition
TOTAL2          equ     H'56'   ; ls byte of rpm addition
TALLY_CNT       equ     H'57'   ; tally counter for averaging
TEN_THOU        equ     H'58'   ; over ten thousand flag
OPTION_STO      equ     H'59'   ; options storage
SETTINGS        equ     H'5A'   ; settings mode flag
LABEL           equ     H'5B'   ; label value

; math routines

BIN_0           equ     H'5C'   ; binary value lsd
BIN_1           equ     H'5D'   ; binary value
BCD_0           equ     H'5E'   ; BCD MS
BCD_1           equ     H'5F'   ; display value MS
BCD_2           equ     H'60'   ; display value LS
CNT_16          equ     H'61'   ; counter for BCD conversion

TEMP            equ H'62'
REMB3           equ H'63'
REMB2           equ     H'64'
REMB1           equ H'65'
REMB0           equ     H'66'
AARGB3          equ     H'67'
AARGB2      equ H'68'
AARGB1      equ H'69'
AARGB0      equ H'6A'   ; most significant byte of argument A
BARGB3      equ H'6B'
BARGB2      equ H'6C'
BARGB1      equ H'6D'
BARGB0      equ H'6E'   ; most significant byte of argument B
LOOPCOUNT   equ H'6F'   ; division counter

; All Banks RAM (70 to 7F)

W_TMP           equ     H'70'   ; storage of w before interrupt
STATUS_TMP      equ     H'71'   ; status storage before interrupt
PCLATH_TMP      equ     H'72'   ; PCLATH store

NUMER_0         equ     H'73'   ; rpm numerator value ms byte
NUMER_1         equ     H'74'   ; rpm numerator value mid byte
NUMER_2         equ     H'75'   ; rpm numerator value mid byte
NUMER_3         equ     H'76'   ; rpm numerator value ls byte
DELAY_FLG       equ     H'77'   ; flag for delay after switch press
START_FLG       equ     H'78'   ; start count down flag
LIMIT1          equ     H'79'   ; limiter rpm ms byte
LIMIT2          equ     H'7A'   ; limiter rpm ls byte
LIMIT_SENSE     equ     H'7B'   ; limiter sense
LIMIT_ON        equ     H'7C'   ; limiter on timer stored value
LIMIT_TM        equ     H'7D'   ; limiter on timer running value
NO_BAR          equ     H'7E'   ; no bargraph when shift light on flag
       
; preprogram EEPROM DATA
; initial values       
        ORG     H'2100'
        DE      H'23', H'28'; 9000rpm red line
        DE  D'05'               ; 5-red LEDs
        DE      H'01', H'4D'; 333rpm/LED 9000/(32-5)
        DE      D'04'           ; 4-cylinders
        DE      H'1F', H'40'; 8000rpm shift
        DE      B'00000001'     ; options, bit 0 dot/bar, 1&2 display format, 3&4 resolution
        DE      D'100'          ; digital display update count (2ms/value)
        DE      D'50'           ; rpm hysteresis for LED bargraph display
        DE  H'26', H'AC'; limit rpm 9900
        DE      D'00'           ; limiter sense
        DE      D'100'          ; limiter on period (2ms/value)

; start at memory 0

        org             H'0'    ; main program start
        goto    MAIN
        org     H'4'    ; interrupt vector 0004h, start interrupt routine here
        goto    INTRUPT        

;*******************************************************************************************


; Calculations

; 1.
; 1/2 pulse per rpm (1cyl 4-stroke)
; Timer 1 internal clock count /1
; capture every + edge
; 1Hz (120rpm) has 5M count (numerator needs to be 120 x 5 x 10^6)
; Calculations: min 600M/5M = 120rpm

; 2.
; 1 pulse per rpm (2cyl 4-stroke, 1 cyl 2-stroke)
; Timer 1 internal clock count /1
; capture every + edge
; 1Hz (60rpm) has 5M count (numerator needs to be 60 x 5 x 10^6)
; Calculations: min 300M/5M = 60rpm

; 3.
; 1.5 pulse per rpm (3cyl 4-stroke)
; Timer 1 internal clock count /1
; capture every + edge
; 1Hz (45rpm) has 5M count (numerator needs to be 45 x 5 x10^6)
; Calculations: min 225M/5M = 45rpm

; 4.
; 2 pulses per rpm (4cyl 4-stroke, 2 cyl 2-stroke)
; Timer 1 internal clock count /1
; capture every positive edge
; 1Hz (30rpm) has 5MHz count (numerator needs to be 30 x 5 x 10^6)
; Calculations: min 150M/5M = 30rpm

; 5.
; 2.5 pulses per rpm (5cyl 4-stroke)
; Timer 1 internal clock count /1
; capture every + edge
; 1Hz (24rpm) has 5M count (numerator needs to be 24 x 5 x 10^6)
; Calculations: min 120M/5M = 24rpm

; 6.
; 3 pulses per rpm (6cyl 4-stroke, 3 cyl 2-stroke)
; Timer 1 internal clock count /2
; capture every 4th edge
; 1Hz (20rpm) has 10M count (numerator needs to be 20 x 10 x 10^6)
; Calculations: min 200M/10M = 20rpm

; 7 (and 11) (caters for assymetrical twin engine)
; 1 pulse per rpm (2cyl 4-stroke, 1 cyl 2-stroke)
; Timer 1 internal clock count /2
; capture every 4th edge
; 1Hz (60rpm) has 10M count (numerator needs to be 60 x 10 x 10^6)
; Calculations: min 600M/10M = 60rpm

; 8.
; 4 pulses per rpm (8cyl 4-stroke, 4 cyl 2-stroke)
; Timer 1 internal clock count /2
; capture every 4th edge
; 1Hz (15rpm) has 10M count (numerator needs to be 15 x 10 x 10^6)
; Calculations: min 150M/10M = 15rpm

; 9 caters for assymetrically firing 3-cylinder 4-stroke
; 1.5 pulse per rpm (3cyl 4-stroke)
; Timer 1 internal clock count /2
; capture every 4th edge
; 1Hz (45rpm) has 10M count (numerator needs to be 45 x 10 x10^6)
; Calculations: min 450M/10M = 45rpm
 
; 11 see 7

; 10.
; 5 pulses per rpm (10 cyl 2-stroke)
; Timer 1 internal clock count /2
; capture every 4th edge
; 1Hz (12rpm) has 10M count (numerator needs to be 12 x 10 x 10^6)
; Calculations: min 120M/20M = 12rpm

; 12
; 6 pulses per rpm (12cyl 4-stroke, 6 cyl 2-stroke)
; Timer 1 internal clock count /2
; capture every 4th edge
; 1Hz (10rpm) has 10M count (numerator needs to be 10 x 10 x 10^6)
; Calculations: min 100M/10M = 10rpm           

; INTERRUPT

; start interrupt by saving w and status registers before altered by interrupt routine

INTRUPT
        movwf   W_TMP           ; w to w_tmp storage
        swapf   STATUS,w        ; status to w
        movwf   STATUS_TMP      ; status in status_tmp
        bcf     STATUS,RP0      ; bank 0
        btfss   PIR1,CCP1IF     ; if capture place into Count2,3, clear NIL_SIG
        goto    CK_TMR_O
        bcf             T1CON,0         ; stop timer
       
; check for capture before
; overflow flag set
       
        btfss   PIR1,TMR1IF     ; if timer overflow flag set, ignore values
        goto    XFER_VAL        ; capture and no overflow then values are valid
TMR_CLFLG
        bcf             PIR1,TMR1IF     ; clear flag
        bcf             PIR1,CCP1IF     ; clear flag
        clrf    NIL_SIG         ; signal captured so clear value
       
        goto    CLR_COUNT

; check timer overflow
CK_TMR_O       
        btfss   PIR1,TMR1IF     ; if timer overflow flag set, increase COUNTER1
        goto    RECLAIM         ;
        bcf             PIR1,TMR1IF     ; clear flag
        incfsz  COUNTER1,f      ; overflow counter FFFF to 0000
        goto    RECLAIM
        incf    COUNTER0,f      ; increase ms byte if ls byte overflows
        btfsc   COUNTER0,0      ; if past count of ~ 67 000 000 clear
        bsf             NIL_SIG,0       ; set flag if overflows beyond COUNTER0
        goto    RECLAIM
XFER_VAL
        bcf             PIR1,CCP1IF     ; clear flag
        clrf    NIL_SIG         ; signal captured so clear value

; transfer COUNTER0,1 to COUNT0,1
; CCPR1L and H to COUNT2,3
        movf    COUNTER0,w
        movwf   COUNT0          ; ms 32-bit rpm counter
        movf    COUNTER1,w
        movwf   COUNT1          ; 32-bit rpm counter
        movf    CCPR1H,w        ; capture compare value
        movwf   COUNT2          ; 32-bit rpm counter
        movf    CCPR1L,w
        movwf   COUNT3          ; ls 32-bit rpm counter

; clear counters
CLR_COUNT
        movf    CCP1CON,w       ; store value
        clrf    CCP1CON         ; clears prescaler

        movwf   CCP1CON         ; restore value capture compare (bank 0)
        clrf    COUNTER0
        clrf    COUNTER1
        clrf    CCPR1L
        clrf    CCPR1H

        clrf    TMR1L
        clrf    TMR1H
        bsf             T1CON,0         ; restart timer

; end of interrupt reclaim w and status

RECLAIM 
        swapf   STATUS_TMP,w; status temp storage to w
        movwf   STATUS          ; w to status register
       
        swapf   W_TMP,f         ; swap upper and lower 4-bits in w_tmp
        swapf   W_TMP,w         ; swap bits and into w register
        retfie                          ; return from interrupt

; *********************************************************************************

; initialise ports

MAIN
; set limiter output   
        movlw   EEPROMD         ; Limiter sense
        call    EEREAD          ; get value
        movwf   LIMIT_SENSE     ; sense
        btfss   LIMIT_SENSE,0   ; if 0 set low
        goto    LIMITER_LOW1
        movlw   B'01111100'     ; limiter output high RB6
        goto    DRV_PORTB
LIMITER_LOW1
        movlw   B'00111100'     ; limiter output low RB6
DRV_PORTB
        movwf   PORTB           ; portB,7 output low, RB6 limiter out
        movlw   B'00000000'
        movwf   PORTA           ; portA,0 and 1 output low
        bsf             STATUS,RP0      ; select memory bank 1
        clrf    ANSEL           ; analog inputs off

; set inputs/outputs
        movlw   B'00000111'     ; comparators off
        movwf   CMCON
        movlw   B'00111101'     ; port B outputs/ inputs set
        movwf   TRISB           ; port B data direction register
        movlw   B'11100000'     ; outputs (0) and inputs (1)
        movwf   TRISA           ; port A data direction register
        movlw   B'00000111'     ; settings (pullups enabled TMR0/256)
        movwf   OPTION_REG
        bcf             STATUS,RP0      ; select memory bank 0

        call    DELAY1          ; delay
        clrf    SETTINGS        ; settings mode clear (set if down switch pressed)
        clrf    LABEL           ; label value
        clrf    UPDATE_TM       ; update timer
        clrf    LIMIT_TM        ; limit timer
        movlw   H'FF'
        movwf   START_FLG       ; start count down flag
        clrf    LED_VALUE       ; start LED bar at 0

; Read EEPROM

        movlw   EEPROM0         ; redline RPM ms
        call    EEREAD          ; get value
        movwf   RED_LINE1       ; redline rpm
        movlw   EEPROM1         ; redline RPM
        call    EEREAD          ; get value
        movwf   RED_LINE2       ; redline rpm

        movlw   EEPROMB         ; limit RPM ms
        call    EEREAD          ; get value
        movwf   LIMIT1          ; limit rpm
        movlw   EEPROMC         ; limit RPM
        call    EEREAD          ; get value
        movwf   LIMIT2          ; limit rpm

        movlw   EEPROM2         ; number of red LEDs
        call    EEREAD          ; get value
        movwf   RED_LEDS        ; red LEDs

        movlw   EEPROM3         ; rpm/LED ms byte
        call    EEREAD          ; get value
        movwf   TACHO_CAL1      ; calculation of rpm/LED
        movlw   EEPROM4         ; rpm/LED ls byte
        call    EEREAD          ; get value
        movwf   TACHO_CAL2      ; calculation of rpm/LED

        movlw   EEPROM5         ; cylinder setting
        call    EEREAD          ; get value
        movwf   CYL_SET         ; cylinder setting

        movlw   EEPROM6         ; shift rpm ms byte
        call    EEREAD          ; get value
        movwf   SHIFT1          ; ms byte of shift rpm
        movlw   EEPROM7         ; shift rpm ms byte
        call    EEREAD          ; get value
        movwf   SHIFT2          ; ls byte of shift rpm

        movlw   EEPROM8         ; options
        call    EEREAD          ; get value
        movwf   OPTIONS         ; ms byte of shift rpm

        movlw   EEPROM9         ; digital display update count
        call    EEREAD          ; get value
        movwf   UPDATE_CT       ; stored value

        movlw   EEPROMA         ; LED display hysteresis
        call    EEREAD          ; get value
        movwf   HYSTERESIS      ; hysteresis

        movlw   EEPROME         ; Limiter on period timer
        call    EEREAD          ; get value
        movwf   LIMIT_ON        ; LIMIT period

        movlw   D'10'           ; delay
        call    DELAY_1

; read switches
        btfsc   PORTB,5         ; if up switch on then settings mode
        goto    RES_PORTS       ; change ports
        bsf             PCLATH,3        ; page 1
        goto    WAIT_OPEN       ; SETTINGS mode

; ***********************************************************
; normal rpm run mode   
RES_PORTS
        clrf    SETTINGS        ; clear settings display mode
        clrf    PORTB           ; outputs low
        btfss   LIMIT_SENSE,0   ; if 0 set low
        goto    LIMITER_LOW2
        bsf             PORTB,6         ; limiter output high RB6
        goto    SET_IN_OUT
LIMITER_LOW2
        bcf             PORTB,6         ; limiter output low RB6
SET_IN_OUT
        bsf             STATUS,RP0      ; select memory bank 1
; set inputs/outputs
        movlw   B'00000001'     ; switch inputs as outputs
        movwf   TRISB           ; port B data direction register
        movlw   B'10000111'     ; settings (pullups disabled TMR0/256)
        movwf   OPTION_REG
        bcf             STATUS,RP0      ; select memory bank 0

; check cylinders and set required timer settings and numerator
CYL_VALUES
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'01'           ; 1 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_1
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'02'           ; 2 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_2
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'03'           ; 3 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_3
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'04'           ; 4 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_4
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'05'           ; 5 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_5
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'06'           ; 6 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_6
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'08'           ; 8 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_8
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'09'           ; 3 cyl 4-stroke (asymmetrically fired)
        btfsc   STATUS,Z
        goto    NO_9
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'10'           ; 10 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_10
        movf    CYL_SET,w       ; cylinder setting value 1 to 12
        xorlw   D'12'           ; 12 cyl 4-stroke
        btfsc   STATUS,Z
        goto    NO_12

; numbers 7 and 11 cater for assymetrical twin 4-stroke
NO_7_11                                 ; numerator is 600M
        movlw   H'23'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'C3'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'46'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'00'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    SIX_TWELVE_SETTING
NO_1                                    ; numerator is 600M
        movlw   H'23'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'C3'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'46'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'00'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    ONE_FIVE_SETTING
NO_2                                    ; numerator is 300M
        movlw   H'11'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'E1'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'A3'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'00'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    ONE_FIVE_SETTING
NO_3                                    ; numerator is 225M
        movlw   H'0D'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'69'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'3A'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'40'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    ONE_FIVE_SETTING
NO_4                                    ; numerator is 150M
        movlw   H'08'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'F0'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'D1'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'80'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    ONE_FIVE_SETTING
NO_5                                    ; numerator is 120M
        movlw   H'07'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'27'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'0E'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'00'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    ONE_FIVE_SETTING
NO_6                                    ; numerator is 200M
        movlw   H'0B'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'EB'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'C2'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'00'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    SIX_TWELVE_SETTING
NO_8                                    ; numerator is 150M
        movlw   H'08'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'F0'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'D1'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'80'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    SIX_TWELVE_SETTING
NO_9                                    ; numerator is 450M
        movlw   H'1A'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'D2'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'74'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'80'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    SIX_TWELVE_SETTING
NO_10                                   ; numerator is 120M
        movlw   H'07'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'27'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'0E'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'00'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    SIX_TWELVE_SETTING
NO_12                                   ; numerator is 100M
        movlw   H'05'
        movwf   NUMER_0         ; rpm numerator value ms byte
        movlw   H'F5'
        movwf   NUMER_1         ; rpm numerator value mid byte
        movlw   H'E1'
        movwf   NUMER_2         ; rpm numerator value mid byte
        movlw   H'00'
        movwf   NUMER_3         ; rpm numerator value ls byte
        goto    SIX_TWELVE_SETTING
ONE_FIVE_SETTING       
        movlw   B'00000001'     ; timer 1 prescaler /1 fosc/4
        movwf   T1CON           ; bank 0
        movlw   B'00000101'     ; every positive edge
        movwf   CCP1CON         ; capture compare (bank 0)
        goto    INIT
SIX_TWELVE_SETTING     
        movlw   B'00010001'     ; timer 1 prescaler /2 fosc/4
        movwf   T1CON           ; bank 0
        movlw   B'00000110'     ; every 4th edge
        movwf   CCP1CON         ; capture compare (bank 0)
; initial conditions
INIT
        bsf             NIL_SIG,0       ; set bit to cause overflow condition
        clrf    UPDATE_TM       ; digital display update counter
        movlw   H'FF'           ; set high the last rpm
        movwf   STORE0
        movwf   STORE1
        clrf    TOTAL0          ; totals for capture counts
        clrf    TOTAL1
        clrf    TOTAL2
        clrf    TALLY_CNT       ; number of tallys

; enable interrupts
        bsf             STATUS,RP0      ; select memory bank 1
        bsf             PIE1,TMR1IE     ; timer1 interupt enable for overflow (bank 1)
        bsf             PIE1,CCP1IE     ; capture compare interrupt
        bcf             STATUS,RP0      ; select memory bank 0
        bsf             INTCON,PEIE     ; enable peripheral interrupts
        bsf             INTCON,GIE      ; global interrupt enable

TACHO_RUN
; tachometer run
        movf    NIL_SIG,w       ; check if no signal
        btfss   STATUS,Z        ; if zero can calculate
        goto    RESET_VALUES

; divide to get rpm  values in  NUMER_x
        movf    NUMER_0,w              
        movwf   AARGB0          ; numerator ms byte
        movf    NUMER_1,w       ;
        movwf   AARGB1
        movf    NUMER_2,w       ;
        movwf   AARGB2          ;
        movf    NUMER_3,w       ; numerator ls byte
        movwf   AARGB3

; stop interrupt
        bcf             INTCON,PEIE
        nop
        movf    COUNT0,w        ; denominator ms byte
        movwf   BARGB0
        movf    COUNT1,w        ; denominator
        movwf   BARGB1
        movf    COUNT2,w        ; denominator
        movwf   BARGB2
        movf    COUNT3,w        ; denominator ls byte
        movwf   BARGB3

; allow interrupts
        bsf             INTCON,PEIE
        call    FXD3232U        ; divide to get rpm

Kod přesáhl délku, kterou je e107 schopna zpracovat, proto je zde pouze fragment. Kompletní kod je v přiloženém archivu.