Searching \ for 'Negative numbers?' in subject line. ()
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.
'Negative numbers?'
1995\12\08@053456 by

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.
> 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
clydehitech.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
----------------------------------------------------------------------------
>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

> 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"?
ADDLW   -(UPPER-LOWER)  ;Otherwise, is it higher than "UPPER"?

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 - fastfwdix.netcom.com
Fast Forward Engineering, Vista, California
http://www.geopages.com/SiliconValley/2499
> 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:

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/
>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.

>        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   bfehrenbexecpc.com
> >        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) ?
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.

btfsc status,cf
goto  outofrange
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
John Payson <supercatMCS.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     bfehrenbexecpc.com
I posted this code which tests whether the value in the W register lies
within a range:
>        btfsc   status,cf
>        goto    inrange

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

> 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.
you wrote:

> I posted this code which tests whether the value in the W register lies
> within a range:
> >        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
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:

>        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
> be a good idea.

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 - fastfwdix.netcom.com
Fast Forward Engineering, Vista, California
http://www.geopages.com/SiliconValley/2499
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
Hi

> I posted this code which tests whether the value in the W register lies
> within a range:
> >        btfsc   status,cf
> >        goto    inrange
>
> To which John Payson <supercatMCS.COM> 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
gregacmeart.com

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