SX Specific Pulse Width Measurement

By Nikolai Golovchenko

; Pulse width capture test
;
; Board: SX Demo/Proto Board
;
; Three routines are tested - 8 bit, 16 bit, and 24 bit. The resolution
; is 4 cycles in every case. Testing is done manually in step mode.
;
; A routine is selected by three buttons at RB3, RB2, RB1:
;
;   RB3=0 - 8-bit
;   RB2=0 - 16-bit
;   RB1=0 - 24-bit
;
; A pulse is generated manually by pressing a button at RB0.
;
; The pulse measurement code is based on Scott Dattalo's idea.
;
; May 10, 2001
; by Nikolai Golovchenko

        DEVICE  SX28L, OSCHS2, TURBO, STACKX, OPTIONX
        RESET start


        ORG $08 ;global bank

pulse0  DS 1    ;LSB of the counter
pulse1  DS 1
pulse2  DS 1    ;MSB

        ORG $10 ;bank0
        ORG $30 ;bank1
        ORG $50 ;bank2
        ORG $70 ;bank3
        ORG $90 ;bank4
        ORG $B0 ;bank5
        ORG $E0 ;bank6
        ORG $F0 ;bank7

RA_DIR  EQU %00000000
RB_DIR  EQU %00001111
;RB.0 .. RB.3 - button inputs
RC_DIR  EQU %00000000


;input port pins
but_8   EQU RB.3        
but_16  EQU RB.2
but_24  EQU RB.1
pulse   EQU RB.0

OPTION_INIT EQU $7F     ;OPTION load value
;x--- ----      0 = register 01h addresses w
;-x-- ----      1 = RTCC roll-over interrupt is disabled
;--x- ----      1 = RTCC increments upon transition on RTCC pin
;---x ----      1 = RTCC increments on high-to-low transitions
;---- x---      1 = Prescaler is assigned to WDT, and divide rate on
;                   RTCC is 1:1
;---- -xxx      111 = Prescaler divider 1:128 (WDT)

;****************************************************************************
; Start of program
;****************************************************************************
        ORG $000        ;page 0
start
;init ports
        clr RA
        clr RB
        clr RC
        mov w, #RA_DIR
        mov !RA, w
        mov w, #RB_DIR
        mov !RB, w
        mov w, #RC_DIR
        mov !RC, w
;load option and make w addressable
        mov w, #OPTION_INIT
        mov !OPTION, w

;****************************************************************************
; Main loop:
; 1) wait a transition in pulse from 0 to 1
; 1) select the test routine
; 2) measure the pulse width
; 3) goto 1
;****************************************************************************
loop    
;wait the low to high transition
        snb pulse
         jmp $-1
        sb pulse
         jmp $-1
;select and run the test routine
        call select
;repeat
        jmp loop

;selection routine
select
        sb but_8
         jmp mpulse8    ;call pulse8 and return
        sb but_16
         jmp mpulse16   ;call pulse16 and return
        sb but_24
         jmp mpulse24   ;call pulse24 and return
        retp            ;if nothing selected just return

;****************************************************************************
; 8 bit pulse width measurement at 4 cycle resolution
;
; Return values at check points A and B (see below) will be:
; Check point:    A B A B A B A B ...
; Counter value:  1 2 3 4 5 6 7 8 ...
; 
; Size: 11 instruction words
;****************************************************************************
mpulse8
        mov w, #1       ;init counter
        mov pulse0, w
        mov w, #2       ;init increment size
mpulse8_loop
        sb pulse        ;check input the first time (A)
         jmp mpulse8a   ; if low, exit
        add pulse0, w   ;increment counter by two
        nop             ;wait a cycle to sample at an equal interval
;instead of nop we can restart the watchdog:
;       clrwdt
;or check the counter overflow:
;       sc
        snb pulse       ;check input the second time (B)
         jmp mpulse8_loop
;here the pulse end was detected after the second input check - correct the
;counter
        clrb pulse0.0
mpulse8a
;here the pulse end was detected after the first input check - leave the counter
;unchanged; if we fall here from the second input check, don't change counter 
;either.
        retp            ;return

;****************************************************************************
; 16 bit pulse width measurement at 4 cycle resolution
;
; Return values at check points A, B, and C (see below) will be:
; Check point:    A B C A B C A B C A ...
; Counter value:  0 1 2 3 4 5 6 7 8 9 ...
;
; Size: 23 instruction words
;****************************************************************************
mpulse16
        clr pulse0      ;clear LSB of the counter
        clr pulse1      ;clear MSB of the counter
        mov w, #3       ;init increment size
mpulse16loop
        sb pulse        ;check input the first time (A)
         jmp mpulse16a  ; if low, exit
        add pulse0, w   ;increment counter by three
        nop             ;wait a cycle to sample at an equal interval
;instead of nop we can restart the watchdog:
;       clrwdt
;or check the counter overflow:
;       sb pulse1.7     - counter value is limited to 0..32770
;or:    sb pulse1.6     - counter value is limited to 0..16387
;or:    sb pulse1.5     - counter value is limited to 0..8197
;or:    sb pulse1.4     - counter value is limited to 0..4099
;
        sb pulse        ;check input the second time (B)
         jmp mpulse16b
        snc             ;propagate carry to the higher byte
         inc pulse1     ;

        snb pulse       ;check input the third time (C)
         jmp mpulse16loop

;here we construct the correction value in w according to the check point - 
;A (w = 0), B (w = 2), or C (w = 1). Then counter is then corrected -
;pulse = pulse - w.

;point C entry
        xor w, #$03     ;3^3^2^3 = 1
        clc             ;clear carry to avoid following carry propagation
;point B entry
mpulse16b
        xor w, #$02     ;3^2^3 = 2
        snc             ;propagate carry if we didn't finish the addition
         inc pulse1     ;
;point A entry
mpulse16a
        xor w, #$03     ;3^3 = 0

;correct counter
        sub pulse0, w
        sc
         dec pulse1
;return
        retp    

;****************************************************************************
; 24 bit pulse width measurement at 4 cycle resolution
;
; Return values at check points A, B, C and D (see below) will be:
; Check point:    A B C D A B C D  A  B  C  D  A ...
; Counter value:  3 4 5 6 7 8 9 10 11 12 13 14 15 ...
;
; Size: 39 instruction words
;****************************************************************************
mpulse24
        clr pulse0      ;clear LSB of the counter
        clr pulse1      ;clear middle byte of the counter
        clr pulse2      ;clear MSB of the counter

        mov w, #1       ;init increment size
mpulse24loop
        sb pulse        ;check input the first time (A)
         jmp mpulse24a  ; if low, exit
        add pulse0, w   ;increment counter by one
        nop             ;wait a cycle to sample at an equal interval
;instead of nop we can restart the watchdog:
;       clrwdt
;or check the counter overflow:
;       sb pulse2.6     - counter value is limited to 0..2^24
;or:    sb pulse2.5     - counter value is limited to 0..2^23
;or:    sb pulse2.4     - counter value is limited to 0..2^22
;etc...
;
        sb pulse        ;check input the second time (B)
         jmp mpulse24b
        snc             ;propagate carry to the higher byte
         add pulse1, w  ;

        sb pulse        ;check input the third time (C)
         jmp mpulse24c
        snc             ;propagate carry to the higher byte
         add pulse2, w  ;

        snb pulse       ;check input the fourth time (D)
         jmp mpulse24loop

;here we construct the correction value in w according to the check point -
;A (w = 3), B (w = 0), C (w = 1), or D (w = 2). Then counter is then corrected -
;pulse = (pulse << 2) + w.
;
;for simplicity, the two lower bits can be shifted into pulse, but the bits
;should be reversed:
;A (w = 3), B (w = 0), C (w = 2), or D (w = 1)

;point D entry
        xor w, #$03     ;1^3^2^3^2 = 1
        clc             ;clear carry to avoid following carry propagation
        
;point C entry
mpulse24c
        xor w, #$02     ;1^2^3^2 = 2
        snc             ;propagate carry if we didn't finish the addition
         inc pulse2     ;
        clc             ;clear carry to avoid following carry propagation

;point B entry
mpulse24b
        xor w, #$03     ;1^3^2 = 0
        snc             ;propagate carry if we didn't finish the addition
         incsz pulse1   ;
        dec pulse2      ;
        inc pulse2      ;
;point A entry
mpulse24a
        xor w, #$02     ;1^2 = 3

;correct counter
        rr WREG
        rl pulse0
        rl pulse1
        rl pulse2
        rr WREG
        rl pulse0
        rl pulse1
        rl pulse2
;return
        retp

;****************************************************************************
       
        ORG $200        ;page 1
        ORG $400        ;page 2
        ORG $600        ;page 3