Searching \ for '[PIC] Two's complement comparisons' 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/microchip/devices.htm?key=pic
Search entire site for: 'Two's complement comparisons'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] Two's complement comparisons'
2008\10\28@001901 by David Duffy (AVD)

flavicon
face
I have an temperature controller application where I want to take action
based on the current temperature and low and high set points.

There's 3 registers in signed (two's complement) format:
curr_temp
lo_trip
hi_trip

The high and low set points are actually called from ee at the moment
but I can pre-fetch them into registers if that's easier.

I have code that works when using positive temps (0..127), but want to
change it to deal with -ve temperatures as well. (-127...+127)

2008\10\28@010345 by cdb

flavicon
face


::T he high and low set points are actually called from ee at the
:: moment
:: but I can pre-fetch them into registers if that's easier.
::
:: I have code that works when using positive temps (0..127), but
:: want to
:: change it to deal with -ve temperatures as well. (-127...+127)

Hi David,

I don't quite follow, are you looking for a conversion that takes your existing code and makes it signable, or asking about how to go about deducting one  number from the other?
Wouldn't temporarily making the numbers positive work?

comf some_reg, f
incf some_reg,f

or if working via W reg   sublw 0

I'm assuming your coding in assembler?

Colin


--
cdb, spam_OUTcolinTakeThisOuTspambtech-online.co.uk on 28/10/2008

Web presence: http://www.btech-online.co.uk  

Hosted by:  http://www.1and1.co.uk/?k_id=7988359






2008\10\28@012358 by David Duffy (AVD)

flavicon
face
cdb wrote:
{Quote hidden}

Yes, coding in assembler.

I have one value that varies (temperature) along with low and high set
points. All are in signed (two's complement) format and are in
registers. (none are constants)

I need some code that can compare the current temperature with the two
set points and branch as below:
A) Current temperature is lower than low set point
B) Current temperature is between low and high set points
C) Current temperature is higher than high set point

I'm just having a mental block with this. It must be not that hard! :-)
David...

2008\10\28@013526 by Marcel Birthelmer

flavicon
face
> I need some code that can compare the current temperature with the two
> set points and branch as below:
> A) Current temperature is lower than low set point
> B) Current temperature is between low and high set points
> C) Current temperature is higher than high set point
>
>
David,
the easiest thing to do would be to subtract your value from the high set
point, check the result (look through the instruction set listing in the
data book to see how the flags are affected by the numbers), and then
subtract the low set point from your value.
- Marcel

2008\10\28@021612 by Jinx

face picon face
David,

        movfw   current
        subwf   high_trip,w
        bnc     hi_less      ;branch if current > high

        movfw   current
        xorwf   high_trip,w
        bz      hi_less      ;branch if current = high

        movfw   low_trip
        subwf   current,w
        bnc     low_gtr      ;branch if current < low

        movfw   current
        xorwf   low_trip,w
        bz      low_gtr      ;branch if current = low

hi_less  nop

low_gtr  nop

If you're using the 18F then you have the N and OV flags as well
as the CPF instructions

2008\10\28@022231 by David Duffy (AVD)

flavicon
face
Marcel Birthelmer wrote:
>> I need some code that can compare the current temperature with the two
>> set points and branch as below:
>> A) Current temperature is lower than low set point
>> B) Current temperature is between low and high set points
>> C) Current temperature is higher than high set point
>>    
> David,
> the easiest thing to do would be to subtract your value from the high set
> point, check the result (look through the instruction set listing in the
> data book to see how the flags are affected by the numbers), and then
> subtract the low set point from your value.
> - Marcel
>  

Aha, I need to check the result msb and not the carry bit!
I was too focussed on the carry bit but that's no use here.
David...

2008\10\28@033157 by Tamas Rudnai

face picon face
David,

Two's complement is good because you do not need extra for calculation or
comparison.

compare
       movf    first,W
       subwf   second,W
       btfss   STATUS,C
       goto    Greater ; W is greater than second
       btfsc   STATUS,Z
       goto    Equal   ; they are equal
       goto    Less    ; W is less than second


If you were looking for DC, then you would check if the low 4 bits (low
nibble) are greater or lower... therefore your range is -16..+15

Tamas


On Tue, Oct 28, 2008 at 6:22 AM, David Duffy (AVD) <
.....davidKILLspamspam@spam@audiovisualdevices.com.au> wrote:

{Quote hidden}

> -

2008\10\28@080734 by David Duffy

flavicon
face
No, that's not the function I need. There's a changing value and *two*
set points. (one lower and one higher) Doing the subtracts and testing
the msb of the result works correctly.
David...

Tamas Rudnai wrote:
{Quote hidden}

>> --

2008\10\28@085253 by Harold Hallikainen

face
flavicon
face

>> I need some code that can compare the current temperature with the two
>> set points and branch as below:
>> A) Current temperature is lower than low set point
>> B) Current temperature is between low and high set points
>> C) Current temperature is higher than high set point
>>

There's some window check code at
http://www.piclist.org/techref/microchip/rangechk.htm

Harold


--
FCC Rules Updated Daily at http://www.hallikainen.com - Advertising
opportunities available!

2008\10\28@093110 by Tamas Rudnai

face picon face
Sorry, I do not get it, how do you make difference if +5 or -5 is less than
-128 ?
Or -120 or +120 is less than -128?

Tamas


On Tue, Oct 28, 2008 at 12:07 PM, David Duffy <
.....davidKILLspamspam.....audiovisualdevices.com.au> wrote:

{Quote hidden}

2008\10\28@140307 by Peter

picon face
David Duffy (AVD <david <at> audiovisualdevices.com.au> writes:

> I have code that works when using positive temps (0..127), but want to
> change it to deal with -ve temperatures as well. (-127...+127)

Just add the numbers together and check for carry and zero flags. You can figure
it out with a number axis drawing.

Peter



2008\10\28@171303 by David Duffy

flavicon
face
It's signed (two's complement) format. The MSB is the sign. (set when
negative)
David...

Tamas Rudnai wrote:
{Quote hidden}

2008\10\28@174619 by Jinx

face picon face
> > Sorry, I do not get it, how do you make difference if +5 or -5 is less
> > than -128 ?

> It's signed (two's complement) format. The MSB is the sign. (set when
> negative)

I think the point that Tamas was making is that there are two ways to
consider the values. Conceptually, the MSb being set denotes a negative
number. However, in reality, the byte contains only postive numbers

By setting the MSb, the most "negative" number becomes the most
"positive". It seems to me that you should complement the current value
before testing, as you've effectively inverted the scale between low
and high trigger points

2008\10\28@184354 by Isaac Marino Bavaresco

flavicon
face
You are forgetting the mathematical overflow.

Suppose you set the limits at +25 (lower) and +100 (upper ).

Value read: +10

+10 - ( +25 ) = -15
+10 - ( +100 ) = -90
So it is below both limits

Value read: +30

+30 - ( +25 ) = +5
+30 - ( +100 ) = -70
So it is between the lower and the upper limits.

Value read: +120

+120 - ( +25 ) = +95
+120 - ( +100 ) = +20
So it is above both limits.

But suppose you read -50

-50 - ( +25 ) = -75
-50 - ( +100 ) = -150 <= problem here. A 8-bit two's complement number
can not go below -128

-50 in two's complement is 206 and -100 is 156, so the above subtraction
becomes:

206 + 156 = 362. This number gets truncated to 106, which is positive.
That´s right: 206 + 156 = 106 !!!

You must test the OVERFLOW bit also, but the 12-bit and 14-bit
instruction PICs do not have it. The PIC18 has.

You will need to do more tests and calculations to get the correct result.

David Duffy escreveu:
{Quote hidden}

__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

2008\10\28@190904 by Harold Hallikainen

face
flavicon
face

>> > Sorry, I do not get it, how do you make difference if +5 or -5 is less
>> > than -128 ?
>
>> It's signed (two's complement) format. The MSB is the sign. (set when
>> negative)
>
> I think the point that Tamas was making is that there are two ways to
> consider the values. Conceptually, the MSb being set denotes a negative
> number. However, in reality, the byte contains only postive numbers
>
> By setting the MSb, the most "negative" number becomes the most
> "positive". It seems to me that you should complement the current value
> before testing, as you've effectively inverted the scale between low
> and high trigger points
>


Another way of thinking of two's complement numbers is to consider, just
like unsigned binary, each bit has a "weight." For 8 bit unsigned, the
weight of the msb is +128. For two's complement, the weight of the msb is
-128. Otherwise, the interpretation of the number is the same (add the
weights where the corresponding bit is a 1).

For the task at hand, doing a window comparison on two's complement
numbers, you could use the unsigned code I posted before, but add 128 to
each number before passing it in to the comparison routine. This biases
the signed numbers up to always be between 0 and 255.

Harold

--
FCC Rules Updated Daily at http://www.hallikainen.com - Advertising
opportunities available!

2008\10\28@203557 by David Duffy (AVD)

flavicon
face
Harold Hallikainen wrote:
> For the task at hand, doing a window comparison on two's complement
> numbers, you could use the unsigned code I posted before, but add 128 to
> each number before passing it in to the comparison routine. This biases
> the signed numbers up to always be between 0 and 255.
>  

Yes, I thought of doing the same thing (biasing it up by 128) but ended
up with testing the msb which seems to work for all test cases I've tried.
David...

2008\10\28@212706 by David Duffy (AVD)

flavicon
face
OK, so it looks as though my method only works for a range values. Not
good. I will instead just add 128 to all numbers first (to pull them
into a 0-255 range) and then do the comparisons. Thanks everyone for
their input.
David...

Isaac Marino Bavaresco wrote:
{Quote hidden}

--
___________________________________________
David Duffy        Audio Visual Devices P/L
Unit 8, 10 Hook St, Capalaba 4157 Australia
Ph: +61 7 38235717      Fax: +61 7 38234717
Our Web Site: http://www.audiovisualdevices.com.au
___________________________________________

2008\10\29@020848 by Wouter van Ooijen

face picon face
> I think the point that Tamas was making is that there are two ways to
> consider the values. Conceptually, the MSb being set denotes a negative
> number. However, in reality, the byte contains only postive numbers

There is no reality, only interpretation. Two of the possible
interpretations are "binary unsigned" and "binary 2-s complement". "2-s
complement" can indeed be visualized the way you describe.

--

Wouter van Ooijen

-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu

2008\10\29@034714 by Jinx
face picon face
> the byte contains only postive numbers
>
> There is no reality, only interpretation

That's correct, and I did think about "representation" after the
mail had gone

2008\10\29@213704 by Isaac Marino Bavaresco

flavicon
face
David Duffy (AVD) escreveu:
> OK, so it looks as though my method only works for a range values. Not
> good. I will instead just add 128 to all numbers first (to pull them
> into a 0-255 range) and then do the comparisons. Thanks everyone for
> their input.
> David...]
I just wrote some C code and looked at the compiler generated assembly
code. After some hand-optimizations I got the following (be careful, I
may have introduced some errors):

;==============================================================

; signed char Var_a, Var_b, Tmp;

;==============================================================
; if( Var_a < Var_b )

A_LESS_THAN_B:
       movf    Var_a,W
       xorlw    0x80
       movwf    Tmp
       movf    Var_b,W
       xorlw    0x80
       subwf    Tmp,F
       btfsc    STATUS,C
       goto    A_LESS_THAN_B_FALSE

A_LESS_THAN_B_TRUE:

       ; Your code here

A_LESS_THAN_B_FALSE:

;==============================================================
; if( Var_a <= Var_b )

A_LESS_THAN_OR_EQUAL_TO_B:

       movf    Var_b,W
       xorlw    0x80
       movwf    Tmp

       movf    Var_a,W
       xorlw    0x80

       subwf    Tmp,F
       btfss    STATUS,C
       goto    A_LESS_THAN_OR_EQUAL_TO_B_FALSE

A_LESS_THAN_OR_EQUAL_TO_B_TRUE:

       ; Your code here

A_LESS_THAN_OR_EQUAL_TO_B_FALSE:

;==============================================================
; if( Var_a == Var_b )

A_EQUAL_TO_B:

       movf    Var_a,W
       xorwf    Var_b,W
       btfss    STATUS,Z
       goto    A_EQUAL_TO_B_FALSE

A_EQUAL_TO_B_TRUE:

       ; Your code here

A_EQUAL_TO_B_FALSE:

;==============================================================
; if( Var_a >= Var_b )

A_GREATER_THAN_OR_EQUAL_TO_B:

       movf    Var_a,W
       xorlw    0x80
       movwf    Tmp_a
     
       movf    Var_b,W
       xorlw    0x80
     
       subwf    Tmp_a,F
       btfss    STATUS,C
       goto    A_GREATER_THAN_OR_EQUAL_TO_B_FALSE

A_GREATER_THAN_OR_EQUAL_TO_B_TRUE:

       ; Your code here

A_GREATER_THAN_OR_EQUAL_TO_B_FALSE:

;==============================================================
; if( Var_a > Var_b )

A_GREATER_THAN_B:

   72   047     0871         movf    Var_b,W
   73   048     3A80         xorlw    0x80
   74   049     00F3         movwf    Tmp

   70   045     0870         movf    Var_a,W
   76   04B     3A80         xorlw    0x80

   77   04C     02F3         subwf    Tmp,F
   78   04D     1803         btfsc    STATUS,C
   79   04E     2850         goto    A_GREATER_THAN_B_FALSE

A_GREATER_THAN_B_TRUE:

       ; Your code here

A_GREATER_THAN_B_FALSE:

;==============================================================

PS.: You may convert the above code into macros to make it easier to use
them.

PPS.: Some time ago somebody talked about Hi-Tech PICC-Lite versus PRO
generated code.
I found that the Lite generates purposely (very) inefficient code, so
the PRO version looks even better.

Look how they do 'Var = 0;' :

bcf    STATUS,C
movlw   0
btfsc   STATUS,C
movlw   1
movwf   Var

'Var = 1;'

clrf   Var
bsf   STATUS,C
rlf   Var,f

'Var = 2;'

clrw
iorlw   2
movwf   Temp
movf   Temp,w
movwf   Var

And so on...
__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

2008\10\29@223453 by cdb

flavicon
face


:: Look how they do 'Var = 0;' :

Um think you've got these the wrong way around, :)

Colin
--
cdb, @spam@colinKILLspamspambtech-online.co.uk on 30/10/2008

Web presence: http://www.btech-online.co.uk  

Hosted by:  http://www.1and1.co.uk/?k_id=7988359







2008\10\30@054326 by Tamas Rudnai

face picon face
In my opinion you just have to rotate both numbers by 1 to the left, so the
range -128 .. +127 becomes 0..255 and the comparison can be made by simple
subwf or sublw and then you can check the C.

Something like:

storeLimit  macro  limit  ; desired limit in W
   addlw   .128   ; this is the rotation by 1...
   movwf   limit
   endm

start
   movlw    .100
   storeLimit    high_limit
   movlw    -.50
   storeLimit    low_limit

test_value
   movlw    .50

compare  ; current value in W
;----- if W is less or equal than the high_limit
   addlw    .128
   subwf    high_limit, W
   btfss    STATUS,C
   goto     out_of_range

;----- if W is greater or equal than low_limit
   ; restoring W for further checkings
   subwf    high_limit, W

   ; now we can check for low
   subwf    low_limit, W
   btfss    STATUS,Z ; are they equal?
   btfss    STATUS,C
   goto     in_range

   goto     out_of_range



We needed two extra instruction for the low_limit checkings (restoring W and
check if W is equal to the limit), however, if that is essential we can
store the low limit as the difference from the high limit so the W
restoration is not needed plus we can reduce that number by 1 so there is no
need to check for equality...

Tamas



On Thu, Oct 30, 2008 at 1:39 AM, Isaac Marino Bavaresco <
KILLspamisaacbavarescoKILLspamspamyahoo.com.br> wrote:

{Quote hidden}

>

2008\10\30@065104 by cdb

flavicon
face


:: so the range -128 .. +127 becomes 0..255

You'd need to have a clear carry instruction, after each of the calls
to storeLimit, otherwise if you had a value of -128 the Carry flag
would be set on exit of the macro.

Making the subsequent test of the Carry flag liable to error.

Colin
--
cdb, RemoveMEcolinTakeThisOuTspambtech-online.co.uk on 30/10/2008

Web presence: http://www.btech-online.co.uk  

Hosted by:  http://www.1and1.co.uk/?k_id=7988359







2008\10\30@075852 by Isaac Marino Bavaresco

flavicon
face
I didn't get your point,

You are saying that Hi-Tech didn't crippled PICC Lite on purpose or that
the code example I presented don't work?

cdb escreveu:
{Quote hidden}

__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

2008\10\30@081340 by cdb

flavicon
face


:: I didn't get your point,
::
:: You are saying that Hi-Tech didn't crippled PICC Lite on purpose
:: or that
:: the code example I presented don't work?

No, what I meant was the order in which you gave the code was the
wrong way around.

You posted.

Look how they do 'Var = 0;' :

bcf    STATUS,C
movlw   0
btfsc   STATUS,C
movlw   1
movwf   Var   // I think you intended Var = 1

'Var = 1;'

clrf   Var
bsf   STATUS,C
rlf   Var,f     // Var = 0

Or am I all at 6's and 7's ?  :)

Colin
--
cdb, TakeThisOuTcolinEraseMEspamspam_OUTbtech-online.co.uk on 30/10/2008

Web presence: http://www.btech-online.co.uk  

Hosted by:  http://www.1and1.co.uk/?k_id=7988359






2008\10\30@082714 by Isaac Marino Bavaresco

flavicon
face
cdb escreveu:
> :: so the range -128 .. +127 becomes 0..255
>
> You'd need to have a clear carry instruction, after each of the calls
> to storeLimit, otherwise if you had a value of -128 the Carry flag
> would be set on exit of the macro.
>
> Making the subsequent test of the Carry flag liable to error.
>
> Colin
> --
> cdb, RemoveMEcolinspamTakeThisOuTbtech-online.co.uk on 30/10/2008
>  
> Web presence: http://www.btech-online.co.uk  
>  
> Hosted by:  http://www.1and1.co.uk/?k_id=7988359
>  

If the Carry Flag is the problem, you may use 'xorlw .128' instead of
'addlw .128'.
Both have the same effect on WREG (toggling the high order bit), but the
first don't change the Carry Flag.

__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

2008\10\30@083122 by Isaac Marino Bavaresco

flavicon
face
Tamas Rudnai escreveu:
> In my opinion you just have to rotate both numbers by 1 to the left, so the
> range -128 .. +127 becomes 0..255 and the comparison can be made by simple
> subwf or sublw and then you can check the C.
>
> Something like:
>
> storeLimit  macro  limit  ; desired limit in W
>     addlw   .128   ; this is the rotation by 1...
>     movwf   limit
>     endm
>  

OK, 'addlw .128' will offset the value range up so you can do an
unsigned test, but I would hardly call it "rotate 1 to the left".

__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

2008\10\30@085029 by Isaac Marino Bavaresco

flavicon
face
cdb escreveu:
> :: I didn't get your point,
> ::
> :: You are saying that Hi-Tech didn't crippled PICC Lite on purpose
> :: or that
> :: the code example I presented don't work?
>
> No, what I meant was the order in which you gave the code was the
> wrong way around.
>
> You posted.
>
> Look how they do 'Var = 0;' :
>
> bcf    STATUS,C
> movlw   0
> btfsc   STATUS,C
> movlw   1
> movwf   Var   // I think you intended Var = 1
>  
bcf    STATUS,C                CARRY = 0
movlw   0                WREG = 0
btfsc   STATUS,C        Skip next instruction if CARRY is clear ( == 0 )
movlw   1                This instruction is never executed
movwf   Var                Var = WREG

Usually just a 'clrf Var' is enough.

> 'Var = 1;'
>
> clrf   Var
> bsf   STATUS,C
> rlf   Var,f     // Var = 0
>  
clrf   Var                Var = 0
bsf   STATUS,C                CARYY = 1
rlf   Var,f                Rotate Var to left, inserting CARRY flag into bit 0


One way to do this is:

clrf   Var
incf   Var,f

Best regards,

Isaac
__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

2008\10\30@091429 by cdb

flavicon
face


:: bcf    STATUS,C
:::: movlw   0
:::: btfsc   STATUS,C  Woops missed that one.

Okey dokey, twas me at sixes and sevens.

My apologies.

Colin
--
cdb, colinEraseMEspam.....btech-online.co.uk on 30/10/2008

Web presence: http://www.btech-online.co.uk  

Hosted by:  http://www.1and1.co.uk/?k_id=7988359







2008\10\30@101010 by Tamas Rudnai

face picon face
> OK, 'addlw .128' will offset the value range up so you can do an
> unsigned test, but I would hardly call it "rotate 1 to the left".

You are right, I was so much concentrating on overflowing the negative
numbers, but yes, this is not a rotation of course, and has the same effect
as with the xorlw 0x80.

Cheers,
Tamas



On Thu, Oct 30, 2008 at 12:24 PM, Isaac Marino Bavaresco <
EraseMEisaacbavarescospamyahoo.com.br> wrote:

{Quote hidden}

>

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