Searching \ for 'Negative numbers?' 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/index.htm?key=negative+numbers
Search entire site for: 'Negative numbers?'.

Truncated match.
PICList Thread
'Negative numbers?'
1995\12\08@053456 by Steven Addison

picon face
I need to check that a value, which will be a slightly variable code value,
is between an upper and a lower threshold (or not).

The way I have thought of doing it is to subtract it from the upper
threshold and retain the result, then subtract the lower threshold from it
and retain that result. If the two results are positive then the code is
within the limits and is good but if either are less than zero then the code
is no good.

       _______________________ upper threshold



               code value


       _______________________ lower threshold


Here is my problem: How do I check for a <0 (negative) value in a PIC register?

Does anybody know? Is it possible? If not what am I going to do?

Later,

Desperate Steve.

1995\12\08@080506 by Clyde Smith-Stubbs

flavicon
face
> Here is my problem: How do I check for a <0 (negative) value in a PIC
register?

Simple! Just test bit 7 of the register! But, if you're interested in the
result of a subtract, you might need to look instead at the carry flag.
It all depends on exactly what you're doing.

A useful trick too is that if you want to do a signed comparison, you
have a problem with overflow if you just subtract a constant value
from a signed number, but you can do a signed comparison with an
unsigned subtract if you remap the range of values. IOW if your
byte value is equivalent to -128 through +127, by remapping this
to a range of 0-255 you can use unsigned arithmetic (and just
use the carry and zero flags). Now here's the trick; the
remapping just involves xoring the high bit of each number, so
you do something like:

       movlw   80h
       xorwf   reg,f
       movlw   bound ^ 80h
       subwf   reg,w

Now you can just test carry as a sign bit (but note that it's
inverted! It's not a borrow) and the z flag for equality.


--
Clyde Smith-Stubbs       | HI-TECH Software,       | Voice: +61 7 3300 5011
spam_OUTclydeTakeThisOuTspamhitech.com.au      | P.O. Box 103, Alderley, | Fax:   +61 7 3300 5246
http://www.hitech.com.au  | QLD, 4051, AUSTRALIA.   | BBS:   +61 7 3300 5235
----------------------------------------------------------------------------
FREE! Download our shareware (FREE for noncommercial use) MS-DOS C Compiler!
            Point your Web browser at http://www.hitech.com.au/

1995\12\08@091739 by Markus Imhof

flavicon
face
>I need to check that a value, which will be a slightly variable code value,
>is between an upper and a lower threshold (or not).
>
...
>
>Here is my problem: How do I check for a <0 (negative) value in a PIC register?
>
>Does anybody know? Is it possible? If not what am I going to do?
>

Hi Steve,

That depends on the encoding of your numbers - but if you use plain vanilla
8-bit unsigned integers (or chars), you can't check for negative numbers,
since they don't exist. But (at least, IIRC), there's one bit in the PIC
registers which indicates whether an underflow/overflow has occured during
an add/subtract operation - so you might just check for that bit.
Or, use the parallax compiler - IIRC (and don't confuse it with AMD), it
provides compare functions.

Bye
 Markus

1995\12\08@140304 by Andrew Warren

flavicon
face
Steven Addison <.....PICLISTKILLspamspam@spam@MITVMA.MIT.EDU> wrote:

> I need to check that a value, which will be a slightly variable code
> value, is between an upper and a lower threshold (or not).
>
> The way I have thought of doing it is to subtract it from the upper
> threshold and retain the result, then subtract the lower threshold
> from it and retain that result. If the two results are positive then
> the code is within the limits and is good but if either are less
> than zero then the code is no good.
>
> Here is my problem: How do I check for a <0 (negative) value in a
> PIC register?

Steve:

It's simple.  After a subtraction, the Carry flag is set if the
result is positive, clear if it's negative.  Assuming that all three
values (your code, the upper threshold, and the lower threshold) are
8-bit unsigned numbers, and that you're using a 16Cxx part (NOT a
16C5x), the code to do what you want looks like this:

   MOVF    CODE,W          ;W = the value you're testing.
   ADDLW   -LOWER          ;Is it lower than "LOWER"?
   BNC     BAD             ;If so, it's bad.  Jump.
   ADDLW   -(UPPER-LOWER)  ;Otherwise, is it higher than "UPPER"?
   BC      BAD             ;If so, it's bad.  Jump.

   NOP                     ;Otherwise, it's good.  Do whatever here...

For those of you who care about such things, the standard "This code
has neither been tested nor assembled; you get what you pay for"
disclaimer applies.

-Andy

Andrew Warren - fastfwdspamKILLspamix.netcom.com
Fast Forward Engineering, Vista, California
http://www.geopages.com/SiliconValley/2499

1995\12\08@200800 by Eric Smith

flavicon
face
> I need to check that a value, which will be a slightly variable code value,
> is between an upper and a lower threshold (or not).

Here's an excerpt from a "comparison" tip page I'm working on:

Testing that a value lies within a range

In this example, the value in the W register will be tested to determine
whether it lies within the range specified by the constants loval and hival
(inclusive).  In other words, we're testing loval <= W <= hival.

It might seem that this would take six instructions (using the methods
previously described), but it can actually be done in four:

       addlw   256-hival
       addlw   (hival-loval)+1
       btfsc   status,cf
       goto    inrange

Of course, you can change the last two lines to:

       btfss   status,cf
       goto    outofrange

Cheers,
Eric
http://www.spies.com/~eric/pic/

1995\12\13@225224 by Bob Fehrenbach

picon face
>Here's an excerpt from a "comparison" tip page I'm working on:

>Testing that a value lies within a range

>In this example, the value in the W register will be tested to determine
>whether it lies within the range specified by the constants loval and hival
>(inclusive).  In other words, we're testing loval <= W <= hival.

>        addlw   256-hival
>        addlw   (hival-loval)+1
>        btfsc   status,cf
>        goto    inrange

  Let's try this with w = 254, hival = 255, loval = 253.

          254 + (256 - 255) = 255
          255 + (255 - 253 + 1) = 258
  which generates a carry.

  Now try  w = 75, hival = 100, loval = 50

          75 + (256 - 100) = 231
          231 + (100 - 50 +1) = 252
  which does not generate a carry.

  In both cases the starting value is in range.   Did I miss something?

--
Bob Fehrenbach    Wauwatosa, WI   .....bfehrenbKILLspamspam.....execpc.com

1995\12\14@020619 by John Payson

flavicon
face
> >        addlw   256-hival
> >        addlw   (hival-loval)+1
> >        btfsc   status,cf
> >        goto    inrange
>
>    Now try  w = 75, hival = 100, loval = 50
>
>            75 + (256 - 100) = 231
>            231 + (100 - 50 +1) = 252
>    which does not generate a carry.
>
>    In both cases the starting value is in range.   Did I miss something?

What's 231+(100-50 +1) ?

1995\12\14@032741 by adrian

flavicon
picon face
you wrote:

{Quote hidden}

The quote code is a bit broken.

You want to :-

  1. Subtract the lo value, which should not generate a carry
  2. Subtract the difference, which should generate a carry

i.e.

   addlw 256-loval
   btfsc status,cf
   goto  outofrange
   addlw 256-(hival-loval)
   btfss status,cf
   goto  outofrange
inrange:

You will want +1's in various places depending on the range being >= or >
and <= or = the limits.

There is probably a way with one less goto by making the sums both generate
carry, and skip the second add if not set... but its too early in the
morning and I havn't had my cup of coffee yet.

--
_
(_) _| _ . _  _   Tel +44 973 222257
( )(_|(  |(_|| )  Fax UK 0500 222258                    E&OE

1995\12\14@091557 by Bob Fehrenbach

picon face
John Payson <EraseMEsupercatspam_OUTspamTakeThisOuTMCS.COM> wrote:

>>
>>            75 + (256 - 100) = 231
>>            231 + (100 - 50 +1) = 252
>>    which does not generate a carry.

>What's 231+(100-50 +1) ?

  Hmmmm....

  OK, OK, so my arithmetic is a little rusty. <g>

--
Bob Fehrenbach    Wauwatosa, WI     bfehrenbspamspam_OUTexecpc.com

1995\12\14@151811 by Eric Smith

flavicon
face
I posted this code which tests whether the value in the W register lies
within a range:
>        addlw   256-hival
>        addlw   (hival-loval)+1
>        btfsc   status,cf
>        goto    inrange

To which John Payson <@spam@supercatKILLspamspamMCS.COM> replied:
>            75 + (256 - 100) = 231
>            231 + (100 - 50 +1) = 252

And to which Adrian Kennard <KILLspamadrianKILLspamspamRHANNA.DEMON.CO.UK> replied:

> The quote code is a bit broken.
>  You want to :-
>     1. Subtract the lo value, which should not generate a carry
>     2. Subtract the difference, which should generate a carry
...
[long-winded explanation of what needs to be done omitted]


If either of you had bothered to actually try my code, you would have found
that it works correctly, except that the 256 should have been 255.  This
minor error resulted in the whole range being offset by 1.

Certainly I didn't expect to be lectured on how to do comparisons "correctly"
by using 50% more words of memory.  The whole reason that I came up with
this method was to keep the cycle count low for time-critical code (the
collision detection in PIC-Pong), and to keep the cycle count deterministic.
The long approach can result in two different cycles counts for the
out-of-range case, depending on which side of the range is exceeded.

Sometimes I wonder why I bother trying to share code at all.  I could be
working on paying jobs rather than wasting time defending code I'm giving
away.

1995\12\15@153828 by adrian

flavicon
picon face
you wrote:

> I posted this code which tests whether the value in the W register lies
> within a range:
> >        addlw   256-hival
> >        addlw   (hival-loval)+1
> >        btfsc   status,cf
> >        goto    inrange
>
> If either of you had bothered to actually try my code, you would have found
> that it works correctly, except that the 256 should have been 255.  This
> minor error resulted in the whole range being offset by 1.

OK, post the correct code.

You code may have an out by one error, but it must also be mising a skip
after the first addlw, otherwise the carry is entirely based on the second
addlw, overwriting the first addlw. Some examples might be a good idea.


--
_                Happy Christmas and a Merry New Year
(_) _| _ . _  _   Tel +44 973 222257
( )(_|(  |(_|| )  Fax UK 0500 222258                    E&OE

1995\12\15@170413 by Andrew Warren

flavicon
face
A brief recap:

Eric Smith posted the following bit of code which tests whether the
value in W is in the range [loval-hival], inclusive:

>        addlw   256-hival
>        addlw   (hival-loval)+1
>        btfsc   status,cf
>        goto    inrange

Adrian Kennard then posted a response which used twice as many lines
of code to do exactly the same thing.

Eric responded as follows:

> If either of you had bothered to actually try my code, you would
> have found that it works correctly, except that the 256 should
> have been 255.  This minor error resulted in the whole range being
> offset by 1.

At this point, Adrian still didn't get it.  He wrote:

> OK, post the correct code.
>
> You code may have an out by one error, but it must also be mising a
> skip after the first addlw, otherwise the carry is entirely based on
> the second addlw, overwriting the first addlw. Some examples might
> be a good idea.

   Adrian:

   Before you embarrass yourself further, please take a moment to,
   as Eric suggested, "bother to actually try the code".

   It works perfectly.

   -Andy

Andrew Warren - RemoveMEfastfwdTakeThisOuTspamix.netcom.com
Fast Forward Engineering, Vista, California
http://www.geopages.com/SiliconValley/2499

1995\12\16@061325 by adrian

flavicon
picon face
you wrote:

{Quote hidden}

Okay, what can I say?

To explain, for any other people who didn't read it properly in the first
place... <-:

Ordinarily, with /normal/ maths, checking for a range A<X<B would require
two comparisions A<X, X<B and hence two branches or decisions would be
necessary. This is why I was sure there must be another skip instruction
somewhere.

What this code has done is firstly to shift the range. By adding 256-B you
shift the comparision to be (A+256-B)<X<256, so the two checks are
(A+256-B)<X and X<256, but in a byte X<256 is always true, so only ONE
comparision is necessary. By adding (B-A) you get the result of that
comparison in the carry flag. Clever.

Obviously the use of (B-A)+1, and 256-B or 255-B is all to do with whether
is is <= or < for the range.

Thank you for your code. I humbly apologise for posting in haste.

--
_                Happy Christmas and a Merry New Year
(_) _| _ . _  _   Tel +44 973 222257
( )(_|(  |(_|| )  Fax UK 0500 222258                    E&OE

1995\12\16@140320 by Greg Solberg

flavicon
face
Hi

> I posted this code which tests whether the value in the W register lies
> within a range:
> >        addlw   256-hival
> >        addlw   (hival-loval)+1
> >        btfsc   status,cf
> >        goto    inrange
>
> To which John Payson <spamBeGonesupercatspamBeGonespamMCS.COM> replied:
...

> And to which Adrian Kennard <TakeThisOuTadrianEraseMEspamspam_OUTRHANNA.DEMON.CO.UK> replied:
...

> Sometimes I wonder why I bother trying to share code at all.  I could be
> working on paying jobs rather than wasting time defending code I'm giving
> away.

Hold on there, don't blow your stack.  I for one am impressed with
your code and appreciate you sharing it with the group.  I find that
I use code to trim values all the time and have always wondered if
there's a faster way to do it.  To trim the value in val between MIN
and MAX I use:

       movlw    MIN        ; get min value
       subwf    val,w      ; w = val - MIN
       btfss    status,cf  ; if val < MIN
       subwf    val,f      ; then val = MIN
       movlw    MAX        ; get max value
       subwf    val,w      ; w = val - MAX
       btfsc    status,cf  ; if val >= MAX
       subwf    val,f      ; then val = MAX


Greg Solberg
RemoveMEgregspamTakeThisOuTacmeart.com

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