Searching \ for 'fast 16 bit counter' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/timers.htm?key=count
Search entire site for: 'fast 16 bit counter'.

Truncated match.
PICList Thread
'fast 16 bit counter'
1998\04\25@224331 by Dwayne Reid

flavicon
face
Hiya, gang.

I'm trying to measure the period of a pulse that varies from 5mS through
30mS with at better than 10 uS resolution.  The target processor is running
at 4 MHz (1uS instruction cycles).  My problem is that I need a timeout
function, so that a missing signal doesn't become a fatal condition.

The easiest way seemed to call for a 16 bit counter.  I immediately thought
of Andrew Warren's fast 5 cycle counter, but I can't think of an easy way to
detect overflow without increasing the loop time drastically.

so... I came up with the following:

;measure HI period

   clrf        HiPerLO
   clrf        HiPerHI
   movlw       1

MeasHiPerLoop                       ;8 cycles per count
   addwf       HiPerLO,F           ;add puts carry in known state
   skpnc                           ;lower byte roll over?
     addwf     HiPerHI,F
   skpnc                           ;upper byte roll over?
     goto      TimeOut
   btfsc       PIN                 ;pin still HI?
     goto      MeasHiPerLoop

I get 8 cycles for the loop.  I can also limit my timeout period by using
bit tests on the high byte if necessary (replace the 2nd 'skpnc' with a
btfsc  HiPerHI, n).  But I REALLY like Andy's 5 cycle version and am hoping
that someone can come up with an idea on how to do better than what I've
come up with.

Just a reminder: here is Andy's 5 cycle timing loop:

Andrew Warren wrote:
       ; 5 cycles per count

        CHECK_PULSE:

            INCFSZ   pulse_width_lo
            DECF     pulse_width_hi

            BTFSC    PULSE_PORT,PULSE_BIT
            GOTO     CHECK_PULSE

        DONE:

            MOVF     pulse_width_lo,W
            ADDWF    pulse_width_hi


My other thought was to use Andy's version, then use the watchdog timer to
limit how long I would wait for the pulse to end.  But I need the prescaler
for my main timekeeping routines - and I couldn't reliably measure pulses
that would approach the full time that the counters would be capable of.

Ideas, suggestions?

Thanks!

dwayne

1998\04\25@230031 by Dwayne Reid

flavicon
face
Well, it looks as if I forgot something - the watchdog timer!  So my loop is
now going to be 9 cycles.  I may just stick a 'nop' in there and make it 10
cycles for 10 uS resolution <grin>.

;measure HI period

   clrf        HiPerLO
   clrf        HiPerHI
   movlw       1

MeasHiPerLoop                       ;9 cycles per count
   clrwdt
   addwf       HiPerLO,F           ;add puts carry in known state
   skpnc                           ;lower byte roll over?
     addwf     HiPerHI,F
   skpnc                           ;upper byte roll over?
     goto      TimeOut
   btfsc       PIN                 ;pin still HI?
     goto      MeasHiPerLoop


Ideas, suggestions?

Thanks!

dwayne

1998\04\26@102432 by Jan Erik Bertram

flavicon
face
Dwayne Reid wrote:

> Well, it looks as if I forgot something - the watchdog timer!  So my loop is
> now going to be 9 cycles.  I may just stick a 'nop' in there and make it 10
> cycles for 10 uS resolution <grin>.

This loop takes 7 Cycles (8 with clrwdt)

clrf        CounterLo
clrf        CounterHi

Loop:
   btfss PULSE_PORT,PULSE_BIT  ; If low then end
   goto MeasureEnd
   incfsz CounterLo
   decf  CounterHi
   incfsz CounterHi
   goto Loop
   goto TimeOut


Ciao
 Jan Erik

1998\04\26@135358 by Sujay Sirur

flavicon
picon face
Hi Dwayne Reid,

I'm new to PIC, but have worked with other mc's. Am sending my comment,
might be of use.

If I had to measure the pulse width using 80C51 or 80C552 I would AND the
input pulse and a 100KHz (10uS resolution) clock and give it to the on-chip
counter. If the onchip counter is 8 bit, I would program it to generate an
interrupt on overflow, and use the interrupt to inc. the high byte/word.

Something equivalent should be possible with PIC.

At 20:43 4/25/98 -0600, Dwayne Reid wrote:
{Quote hidden}

1998\04\26@183412 by Dwayne Reid

flavicon
face
Hiya Jan

I must be particularily obtuse today, but I don't see how this can work.
The first count terminates the loop.

{Quote hidden}

Kind of neat how you correct the count in CounterHi !

how about:

Loop                                                CntHi   CntLo
   btfss PULSE_PORT,PULSE_BIT  ; If low then end    00      00
   goto MeasureEnd
   incf        CounterLo                            00      01
   skpnz                                skip next
     incfsz    CounterHi
       goto    Loop
   goto        TimeOut

It looks as if this might work.  Thanks for the tip!

Any other ideas on how I can speed this up even more?

dwayne

1998\04\26@215908 by Russell McMahon

picon face
What PIC cpu are you using?
On eg 16F84 you could perhaps use interrupt on change caused
by the end of the pulse to drag you out of the fast counter
loop.

If you haven't got interrupts available this may not be easy
to implement :-)



{Original Message removed}

1998\04\27@120417 by Scott Dattalo

face
flavicon
face
On Sun, 26 Apr 1998, Dwayne Reid wrote:

>
> Loop                                                CntHi   CntLo
>     btfss PULSE_PORT,PULSE_BIT  ; If low then end    00      00
>     goto MeasureEnd
>     incf        CounterLo                            00      01
>     skpnz                                skip next
>       incfsz    CounterHi
>         goto    Loop
>     goto        TimeOut
>
> It looks as if this might work.  Thanks for the tip!
>
> Any other ideas on how I can speed this up even more?
>

Sure! This will get you back down to 5 cycles per sample and
it can be scaled to how ever many bytes you wish. I show 3
just as an example.

       MOVLW   C_LOW
       MOVWF   count_low

       MOVLW   C_MID
       MOVWF   count_mid

       MOVLW   C_HIGH
       MOVWF   count_high

s1:
       BTFSC   IOPORT,IOBIT
        goto   went_high

       DECFSZ  count_low,F
        goto   s1

       NOP

       BTFSC   IOPORT,IOBIT
        goto   went_high

       DECFSZ  count_mid,F
        goto   s1

       NOP

       BTFSC   IOPORT,IOBIT
        goto   went_high

       DECFSZ  count_high,F
        goto   s1

time_out:

The three-byte count is pre-loaded with the desired time-out. If
the code reaches the label 'time_out' then the IOPORT didn't
change states.

One caveat: The three byte count is actually:

COUNT = C_LOW + 257*C_MID + 257^2 * C_HIGH

(note 257 and not 256). So to preset the count you'll need to do
something like:


C_LOW   EQU     COUNT % 257
C_MID   EQU     (COUNT / 257) % 257
C_HIGH  EQU     (COUNT / 257 / 257) % 257

Scott

1998\04\27@142049 by paulh

flavicon
face
You don't need a 4 cycle loop to check something every 4 cycles.
Here is a 16 cycle loop with a test every 4 cycles.

NOTE: This hasn't been assembled or tested.  Before using, make sure
I test the correct status bits, and include ,f and ,w where appropriate.
Also, make that the btfss's shouldn't be btfsc and vice versa.

I've been busy recently and have switched to the digest format.  So,
someone else may have answered, and I missed it.  Also, this uses many
words of program space.  I didn't try to make it small.  There are
many oportunities for optimization.

;
; Sample pin PulseBit of port PulsePort every 4 cycles until it
; goes high, or 2^18 passes through the loop, whichever comes first.
; The low 2 bits of the count will be in HiPerLo, the next 8 bits
; will be in HiPerMid, the high 8 bits in HiPerHi.
;
; preload HiPerMid and HiPerHi with some other value to get the loop
; to timeout sooner.
;
; Check my cleanup logic for when the middle byte goes from 255 -> 0.
;
 clrf  HiPerMid
 clrf  HiPerHi

sampleloop;
 btfsc pulsePort,PulseBit    ; 1  Test the bit
 goto  gotpulse0             ; 2
 nop                         ; 3
 incf  HiPerMid,f            ; 4  increment the middle 8 bits

 btfsc pulsePort,PulseBit    ; 1  Test the bit again
 goto  gotpulse1             ; 2
 btfsc status,z              ; 3  Does it carry into the high 8 bits
 incf  HiPerHi,f             ; 4

 btfsc pulsePort,PulseBit    ; 1 and again
 goto  gotpulse2             ; 2
 btfsc status,z              ; 3
 goto  timeout               ; 4

 btfsc pulsePort,PulseBit    ; 1 and again
 goto  gotpulse3             ; 2
 goto  sampleloop            ; 4

gotpulse0
 clrf  HiPerLo     ; low 2 bits zero
                   ; add delay here for constant path length.
                   ; otherwise the loop is fastest when the low
                   ; 2 bits are zero.
 return
gotpulse1
 decf   HiPerMid,f ; undo last increment
 movlw  1
 movwf   HiPerLo
 goto    fixupa
gotpulse2
 movlw   2
 movwf   HiPerLo
 goto    fixupb
gotpulse3
 movlw   3
 movwf   HiPerLo
fixupb
 movf    HiPerMid,f   ; Test for zero
 btfsc   status,z     ; optionally undo inc of Hi byte
 decf    HiPerHi,f
fixupa
 decf    HiPerMid,f
 return

timeout ;
 ;  Do something usefull here.
 return

==================================
I do something similar in my latest sonar code.  There I'm checking for
and echo on 4 transducers every 4 cycles.  The transducers are hooked
pins 0-3 on porta, pin 4 is pulled low.  I swapf porta,w, then 4 cycles
later  iorwf  porta,w.  Testing the Z flag tells if any transducer saw
an echo.  Looking at the bits in W tells which transducer(s) and whether
it saw the echo on the 1st or second test in the loop.

--
spam_OUTpaulhTakeThisOuTspamhamjudo.com  http://www.hamjudo.com
The April 97 WebSight magazine describes me as "(presumably) normal".

1998\04\27@142110 by Mike Keitz

picon face
On Sun, 26 Apr 1998 16:32:05 -0600 Dwayne Reid <.....dwaynerKILLspamspam@spam@PLANET.EON.NET>
writes:

>Any other ideas on how I can speed this up even more?

Use a timer interrupt for the timeout.  Rather than return from the ISR,
jump out to the timeout handler.  The counter routine needs to be at the
top-level (i.e. not a subroutine) so corrupting the stack by not
returning from the interrupt doesn't cause problems.  A similar approach
uses a hardware interrupt caused by the pulse being measured to stop the
counting.


_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]

1998\04\27@151013 by Dwayne Reid

flavicon
face
Hi there Sujay

>If I had to measure the pulse width using 80C51 or 80C552 I would AND the
>input pulse and a 100KHz (10uS resolution) clock and give it to the on-chip
>counter. If the onchip counter is 8 bit, I would program it to generate an
>interrupt on overflow, and use the interrupt to inc. the high byte/word.

I don't have any of those available.  I'm using the 12c508 with the internal
clock - no external fast clock is available and there are no interrupts on
this chip.  I'm measuring duty cycle of an incoming signal - absolute times
are not important but the ratio of HI period to LO period is important.

Thanks anyways!

dwayne

1998\04\27@151445 by Dwayne Reid

flavicon
face
Excellent!!

just a minor bit of subtraction to find the actual number of samples and
home free.  Many thanks.

dwayne

{Quote hidden}

1998\04\27@173502 by Dwayne Reid

flavicon
face
Scott - since I don't need a particular timeout for this application, why
wouldn't INCFSZ work.  That is:

   clrf    c_low
   clrf    c_mid
   clrf    c_high

s1:
       BTFSC   IOPORT,IOBIT
        goto   went_high

       INCFSZ  c_low,F
        goto   s1

       clrwdt                  ;

       BTFSC   IOPORT,IOBIT
        goto   went_high

       INCFSZ  c_mid,F
        goto   s1

       nop

       BTFSC   IOPORT,IOBIT
        goto   went_high

       INCFSZ  c_high,F
        goto   s1

time_out:

Note also that your routine lets me take care of the watchdog with no added
penalty!

Now, since incrementing each added byte of counter causes the previous bytes
to miss a count (the mod 257 that you alluded to in your message),
correcting to mod 256 should be easy.  The modulus changes as you extend the
counter: in the 3 byte counter above, the lowest byte misses the counts
accumulated by both of the upper bytes; the mid byte misses the counts
accumulated by the high byte.  A first pass of the correction routine
follows - but its pretty stinky and I'm sure that I am missing something
obvious.

went_hi

   movfw       c_mid       ;add mid byte to lower; propogate carries
   addwf       c_low,F
   movlw       1
   skpnc
     addwf     c_mid,F
   skpnc
     addwf     c_high,F

   movfw       c_high      ;add high byte to lowest; propogate carries
   addwf       c_low,F
   movlw       1
   skpnc
     addwf     c_mid,F
   skpnc
     addwf     c_high,F

   movfw       c_high      ;add high byte to mid; propogate carries
   addwf       c_low,F
   movlw       1
   skpnc
     addwf     c_mid,F
   skpnc
     addwf     c_high,F

Back to you, Scott (and the rest of the PicListers).

ideas, improvements?

dwayne

1998\04\28@005718 by Dwayne Reid

flavicon
face
After looking at the last message that Scott sent me, I think that I have a
solution that fits my purposes.  It will accumulate up to 65,535 counts
without error and times out after 65,791 counts.  The count in the region
between those two numbers is held at 65,535 (ffff).

;measure puse width on a 12c508 with 5 uSec resolution.
;Times out after about 327 mSec.

       clrf    c_low
       clrf    c_high

s1:
       BTFSC   IOPORT,IOBIT    ;5 cycles
        goto   went_high

       INCFSZ  c_low,F
        goto   s1

       clrwdt                  ;

       BTFSC   IOPORT,IOBIT    ;5 cycles
        goto   went_high

       INCFSZ  c_high,F
        goto   s1

;note: each time HI byte increments, LO byte to misses a count
;final count == LoByte + HiByte

time_out:
;do time out stuff here

went_high                       ;fix up the mod 257 counter

       movfw       c_high      ;
       addwf       c_low,F
       skpnc                   ;no carry - leave Hi byte alone
         incfsz    c_high,F    ;carry - does Hi byte contain ff?
           goto    $+2         ;either no carry or did not wrap
       movwf       c_low       ;wrapped past ffff - hold at ff
       movwf       c_high      ;ditto

The logic is simple - if the high byte contained ff and a carry was
generated when the 2 bytes were added together (which would wrap the high
byte to 00), the value in W (which could only be ff) is written to both
bytes.  The choice of $+2 for the junp is deliberate - both paths take the
same # of cycles.


My thanks to all who contributed ideas and suggestions.  Scott - Thank you
again for taking time out of your very busy day.

dwayne

1998\04\28@094512 by Scott Dattalo

face
flavicon
face
On Mon, 27 Apr 1998, Dwayne Reid wrote:

> After looking at the last message that Scott sent me, I think that I have a
> solution that fits my purposes.  It will accumulate up to 65,535 counts
> without error and times out after 65,791 counts.  The count in the region
> between those two numbers is held at 65,535 (ffff).

Scrap it.

Here's a routine that gives you 3-cycle resolution:

       CLRF    count_3lsbs
       CLRF    count_low
       CLRF    count_mid
       CLRF    count_high

loop
       BTFSC   IOPORT,IOBIT
        goto   went_high_1st

       MOVLW   1

       BTFSC   IOPORT,IOBIT
        goto   went_high_2nd

       ADDWF   count_low,F

       BTFSC   IOPORT,IOBIT
        goto   went_high_3rd

       RLF     count_3lsbs,W

       BTFSC   IOPORT,IOBIT
        goto   went_high_4th

       ADDWF   count_mid,F

       BTFSC   IOPORT,IOBIT
        goto   went_high_5th

       RLF     count_3lsbs,W

       BTFSC   IOPORT,IOBIT
        goto   went_high_6th

       ADDWF   count_high,F

       BTFSC   IOPORT,IOBIT
        goto   went_high_7th

       CLRWDT

       BTFSS   IOPORT,IOBIT
        goto   loop

went_high_8th
       INCF    count_3lsbs,F

went_high_7th
       SUBWF   count_high,F
       INCF    count_3lsbs,F

went_high_6th
       INCF    count_3lsbs,F

went_high_5th
       SUBWF   count_mid,F
       INCF    count_3lsbs,F

went_high_4th
       INCF    count_3lsbs,F

went_high_3rd
       DECF    count_low,F
       INCF    count_3lsbs,F

went_high_2nd
       INCF    count_3lsbs,F

went_high_1st

       CLRC
       RLF     count_low,F
       RLF     count_mid,F
       RLF     count_high,F

       RLF     count_low,F
       RLF     count_mid,F
       RLF     count_high,F

       RLF     count_low,F
       RLF     count_mid,F
       RLF     count_high,F

       MOVF    count_3lsbs,W
       ADDWF   count_low,F
       SKPZ
        goto   done

       INCFSZ  count_mid,F
        goto   done

       INCF    count_high,F

done

>
> My thanks to all who contributed ideas and suggestions.  Scott - Thank you
> again for taking time out of your very busy day.

It's really early in the morning right now...

Scott

1998\04\28@153259 by Dwayne Reid

flavicon
face
Scott Dattalo wrote:
>
>Scrap it.
>
>Here's a routine that gives you 3-cycle resolution:

most of routine snipped

BRAVO! BRAVO!

Fantastic!

Talk about lateral thinking!

I have 2 observations:  I don't see any way for the routine to time out.  It
looks as if I can either look after the watchdog or have timeout capability
but not both.  I'll keep looking, tho.

The other observation is slightly more serious, I think.  If the routine
exits without incrementing any counters, (enters the routine but the pin
went or was non-active - zero time) an erroneous result will occur.  I think
the solution is simple: relpace the 'SKPZ' below with 'SKPC'.  Of course - I
might be out to lunch . . .

This is at the end of the normalisation routine:
{Quote hidden}

This is extremely impressive, Scott.  Many thanks.

dwayne

1998\04\28@201841 by Scott Dattalo

face
flavicon
face
On Tue, 28 Apr 1998, Dwayne Reid wrote:

> I have 2 observations:  I don't see any way for the routine to time out.  It
> looks as if I can either look after the watchdog or have timeout capability
> but not both.  I'll keep looking, tho.

I think you can extend the concept to 16 samples (or whatever) per loop
instead of 8 and do something like this

       BTFSC   IOPORT,IOBIT
        goto   went_high_x

       BTFSS   count_high,7    ;Overflow bit
        BTFSC  IOPORT,IOBIT
         goto  went_high_y

       ....


       BTFSS   IOPORT,IOBIT
        goto   loop

went_high_z:

      .....

went_high_y:

       BTFSC   count_high,7
        goto   over_flowed

       ...

>
> The other observation is slightly more serious, I think.  If the routine
> exits without incrementing any counters, (enters the routine but the pin
> went or was non-active - zero time) an erroneous result will occur.  I think
> the solution is simple: relpace the 'SKPZ' below with 'SKPC'.  Of course - I
> might be out to lunch . . .

I thought about that too. The skpc to skpz change won't fix it though.
It may be easier to add a flag that's initialized before the sampling
begins, and is cleared in the loop. Then during the normalization you
can check the flag and process the counters accordingly. It might also
be necessary to sample the IOPORT once before the loop begins and abort
if it's already high. Tell us how you decide to solve it :).

Scott

1998\04\29@005240 by Dwayne Reid
flavicon
face
Scott Dattalo wrote:

>I think you can extend the concept to 16 samples (or whatever) per loop
>instead of 8 and do something like this

I'll look at that.


{Quote hidden}

Scott - how about a little bit different slant on things.  Instead of
shifting the counter bytes over to make room for the LSBs accumulated by
the main loop, why not just add those LSBs to the count, propogating
carries as required.  The main loop doesn't have to be a power of 2 states
and allows easy addition of the overflow logic.

That is:

Counter routine that gives 3-cycle resolution:

       CLRF    count_3lsbs
       CLRF    count_low
       CLRF    count_mid
       CLRF    count_high

loop
       BTFSC   IOPORT,IOBIT
        goto   went_high_1st

       MOVLW   1
       BTFSC   IOPORT,IOBIT
        goto   went_high_2nd

       ADDWF   count_low,F
       BTFSC   IOPORT,IOBIT
        goto   went_high_3rd

       RLF     count_3lsbs,W   ;shift C into W (add 0 or 1 to next byte)
       BTFSC   IOPORT,IOBIT
        goto   went_high_4th

       ADDWF   count_mid,F
       BTFSC   IOPORT,IOBIT
        goto   went_high_5th

       RLF     count_3lsbs,W
       BTFSC   IOPORT,IOBIT
        goto   went_high_6th

       ADDWF   count_high,F
       BTFSC   IOPORT,IOBIT
        goto   went_high_7th

       CLRWDT
       BTFSC   IOPORT,IOBIT
        goto   went_high_8th

       SKPC                    ;test for overflow
        BTFSC  IOPORT,IOBIT
         goto  went_high_9th

       BTFSS   IOPORT,IOBIT
        goto   loop

went_high_10th
       INCF    count_3lsbs,F

went_high_9th
       INCF    count_3lsbs,F

went_high_8th
       INCF    count_3lsbs,F

went_high_7th
       skpnc
         goto  overflow
       SUBWF   count_high,F
       INCF    count_3lsbs,F

went_high_6th
       INCF    count_3lsbs,F

went_high_5th
       tstf    count_low       ;had low byte wrapped?
       skpnz
        decf   count_mid,F
       INCF    count_3lsbs,F

went_high_4th
       INCF    count_3lsbs,F

went_high_3rd
       DECF    count_low,F
       INCF    count_3lsbs,F

went_high_2nd
       INCF    count_3lsbs,F

went_high_1st

       MOVF    count_3lsbs,W
       ADDWF   count_low,F
       SKPC
        goto   done

       INCFSZ  count_mid,F
        goto   done

       INCFSZ  count_high,F
         goto  done

overflow                        ;wrapped past ff ff ff - hold at ff
       movlw   ff
       movwf   count_low
       movwf   count_mid
       movwf   count_high

done


Now, having done all that, I think that I see a fundamental problem with
the middle byte in your routine.  Assume that the loop terminated at the
6th, or later exits.  There is no way of knowing whether the middle byte
had incremented or not: the carry information is lost.  In other words,
just because the high byte didn't increment, that doesn't say that the
middle byte didn't also.  The middle byte could have incremented without
wrapping.  I fixed it by seeing if the low byte was zero at that point.
I think that it will work (I'll try tommorrow, after I've heard your
thoughts).

dwayne

1998\04\29@152622 by Dwayne Reid

flavicon
face
Hiya gang.  Hiya Scott.  The more I muddle with this, the deeper in
trouble I get.  My previous 2 attempts were useless, lets see how
this one does.

This is back to Scott's routine, with a few mods.

;up to 19 bit counter routine with 3-cycle resolution:

       CLRF    count_low
       CLRF    count_mid
       CLRF    count_high      ;used as known zero for main loop

loop
       BTFSC   IOPORT,IOBIT
        goto   went_high_1st

       MOVLW   1
       BTFSC   IOPORT,IOBIT
        goto   went_high_2nd

       ADDWF   count_low,F
       BTFSC   IOPORT,IOBIT
        goto   went_high_3rd

       RLF     count_high,W   ;get C into W lsb (adding 0 or 1)
       BTFSC   IOPORT,IOBIT
        goto   went_high_4th

       ADDWF   count_mid,F
       BTFSC   IOPORT,IOBIT
        goto   went_high_5th

       btfss   count_mid,5    ;5 = 16 bits; 6 = 17 bits; 7 = 18; skpc = 19
        BTFSC  IOPORT,IOBIT
         goto  went_high_6th

       nop
       BTFSC   IOPORT,IOBIT
        goto   went_high_7th

       CLRWDT

       BTFSS   IOPORT,IOBIT
        goto   loop

went_high_8th
       INCF    count_high,F    ;count_high now used to accumulate LSBs

went_high_7th
       INCF    count_high,F

went_high_6th
       INCF    count_high,F

went_high_5th
       btfsc   count_high,5    ;5 = 16 bits; 6 = 17 bits; 7 = 18; skpnc =19
         goto  overflow        ;
       SUBWF   count_mid,F
       INCF    count_high,F

went_high_4th
       INCF    count_high,F

went_high_3rd
       DECF    count_low,F
       INCF    count_high,F

went_high_2nd
       INCF    count_high,F

went_high_1st

       CLRC
       RLF     count_low,F     ;make room for lower 3 LSBs
       RLF     count_mid,F
       RLF     count_high,F    ;LSB count gets shifted safely out of the way

       RLF     count_low,F
       RLF     count_mid,F
       RLF     count_high,F

       RLF     count_low,F
       RLF     count_mid,F
       RLF     count_high,F

       RLF     count_high,F    ;get 3 LSBs that got moved into w
       swapf   count_high,w
       andlw   b'00000111'
       RRF     count_high,F
       iorwf   count_low,F
       goto    done

overflow                        ;do whatever we want here
       movlw   ff
       movwf   count_low
       movwf   count_mid
       movwf   count_high

done


I'm trying to figure out an easier way to simulate this.  Comments anyone?

dwayne
Dwayne Reid   <dwaynerspamKILLspamplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, Alberta, CANADA
(403) 489-3199 voice     (403) 487-6397 fax

1998\04\30@022323 by Dwayne Reid

flavicon
face
Scott Dattalo wrote:

>The code looks good (your latest post - 19 bits of dynamic range).
>
>Probably the easiest way to test the code is with the stopwatch.
>Make IOPORT a ram register, single step to the first sample,
>clear the stopwatch, and press F9 (run). After it runs for a while,
>force a break. Then go modify the ram register to where IOPORT
>points. Single step and note the value of the stop watch when
>you break out of the loop. This value should be 3 times the value
>get in the counters.
>
>Repeat this process a few times - perhaps even attempt the timeout.
>
>Scott

Hi again, Scott.

Looking not too bad right now.  I found a couple errors: testing the wrong
register for overflow in 1 spot and I wasn't fixing up 'count_high' at the
end of the normalisation routine.  I've been simulating for the past couple
hours - no probelms so far, with no more than 1 count error between
calculated and actual count.  I'm about to stick the code into a 12c508
driving some LED displays (my standard serial stuff that I have on the
shelf) and I'm going to see if it actually works when I feed the output of a
pulse generator to it.

This is neat stuff, Scott.  I can't even begin to thank you for all your help.

dwayne


Here is the code for those interested.

;up to 19 bit counter with 3 cycle resolution
;original concept by Scott Dattalo; this version by Dwayne Reid

       CLRF    count_low
       CLRF    count_mid
       CLRF    count_high      ;used as known zero for main loop

loop
       BTFSC   PULSE
        goto   went_high_1st

       MOVLW   1
       BTFSC   PULSE
        goto   went_high_2nd

       ADDWF   count_low,F
       BTFSC   PULSE
        goto   went_high_3rd

       RLF     count_high,W   ;get C into W lsb (adding 0 or 1)
       BTFSC   PULSE
        goto   went_high_4th

       ADDWF   count_mid,F
       BTFSC   PULSE
        goto   went_high_5th
                               ;use either of the following lines (not both)
;        btfss   count_mid,5    ;5 = 16 bits; 6 = 17 bits; 7 = 18; skpc = 19
       skpc                   ;5 = 16 bits; 6 = 17 bits; 7 = 18; skpc = 19
        BTFSC  PULSE
         goto  went_high_6th

       nop
       BTFSC   PULSE
        goto   went_high_7th

       CLRWDT

       BTFSS   PULSE
        goto   loop

went_high_8th
       INCF    count_high,F    ;count_high now used to accumulate LSBs

went_high_7th
       INCF    count_high,F

went_high_6th
       INCF    count_high,F

went_high_5th                   ;use either of the following lines (not both)
;        btfsc   count_mid,5     ;5 = 16 bits; 6 = 17 bits; 7 = 18; skpnc =19
       skpnc                   ;5 = 16 bits; 6 = 17 bits; 7 = 18; skpnc =19
         goto  overflow        ;
       SUBWF   count_mid,F     ;undo increment, if any
       INCF    count_high,F

went_high_4th
       INCF    count_high,F

went_high_3rd
       DECF    count_low,F     ;undo increment
       INCF    count_high,F

went_high_2nd
       INCF    count_high,F

went_high_1st

       CLRC
       RLF     count_low,F     ;make room for lower 3 LSBs
       RLF     count_mid,F
       RLF     count_high,F    ;LSB count gets shifted safely out of the way

       RLF     count_low,F
       RLF     count_mid,F
       RLF     count_high,F

       RLF     count_low,F
       RLF     count_mid,F
       RLF     count_high,F

       RLF     count_high,F    ;get LSB count into w
       swapf   count_high,w
       andlw   b'00000111'
       RRF     count_high,F
       iorwf   count_low,F     ;put LSBs into low byte
       movlw   b'00000111'     ;toss extraneous bits - we're done with them
       andwf   count_high,F
       goto    done

overflow                        ;do whatever we want here
       movlw   0xff
       movwf   count_low
       movwf   count_mid
       movwf   count_high

done


dwayne
Dwayne Reid   <.....dwaynerKILLspamspam.....planet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, Alberta, CANADA
(403) 489-3199 voice     (403) 487-6397 fax

More... (looser matching)
- Last day of these posts
- In 1998 , 1999 only
- Today
- New search...