Searching \ for '[PIC]: signed math' in subject line. ()
Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/math/index.htm?key=math
Search entire site for: 'signed math'.

Exact match. Not showing close matches.
'[PIC]: signed math'
2001\12\03@022704 by

ooops, with corrected topic again:
{Quote hidden}

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:

If you're talking about signed int in the form (1 sign bit + 8 bits
absolute value), this is rather easy.

For positive values (MSB = 0), both are equal (assuming that a sign bit = 0
means "positive"). For negative values, you just have to use the rules for
2th complement to complement the remaining 8 bit (bitwise inverting, then
incrementing).

Note that the two representations do not cover the same range: 2th
complement goes from -256 to +255, signed int goes from -255 to +255 (with
two representations for 0). Trying to convert -256 will result in -0, which
is wrong.

But if you're talking about the C language definition of "signed int", it
IS 2th complement...  ;)  just that it is probably 16 bits. You just have
to fill the whole MSByte with the content of the MSbit.

ge

At 09:22 12/03/2001 +0200, Vasile Surducan wrote:
{Quote hidden}

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:

Hi,
Perhaps if you would elaborate a bit on the actual
formula you intend to use I can give some hints.

Signed/unsigned is fairly trivial
unless you mix data of variable size and signed/unsigned
then it starts to get a bit tricky :)

We have had some disscussions about signed/unsigned on the list
check the archives.

But a short re-cap ( signed math ):

Top bit set (msbit) = Value is negative
Top bit clear (msbit) = Value is positive

For addition/subtraction you need no special routines,
unless there are possibilities for overflow.

To 'convert' from negative to positive ( or the other way around ):

;++++++++++++
;
; NORM_16 - Normalises a 16 bit variable ( i.e make two's complement )
; argument must point to most significant byte, arg16+1 is lsb

NORM_16 MACRO   ARG_16
; first make one's complement
COMF    LOW(ARG_16+1),F
COMF    LOW(ARG_16),F
; then add one to form two's complement
MOVLW   1
SKPNC
ENDM

/Tony

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:

Thanks Gerhart and Tony

On Mon, 3 Dec 2001, [Iso-8859-1] Kübek Tony wrote:

> Hi,
> Perhaps if you would elaborate a bit on the actual
> formula you intend to use I can give some hints.
>   OK here is:
temperature = temp_read - 1/2LSB + [ (count_per_degree - count_remain /
count_per_degree) ]

All values are 9 bit numbers, Truncated half-degree bit ( temp_read - 1/2LSB ) its a simple task:
bcf status_c
The new value ( 9 bit too ) will have resolution of only 1 C degree
instead of 0.5 C and will be contained in temp_read_lo, temp_read_hi ( the sign )
Application note 105 from Dallas said :
"convert truncated value from 2's complement to signed integer"
This is the problem I have. Application note does say nothing more about.
But also it seems that measuring only positive temperatures I will not
have errors even I will not perform that conversion. About division, I've plan to use a standard 16bit division routine,
maybe Nikolay will point to a 9 bit division one ?

> We have had some disscussions about signed/unsigned on the list
> check the archives.
There are some problems by checking archives even for registered people
because of overloading ( 1search/minute ) At my low transfer rate in one
minute I've got nothing . What money are necesarry to improve the piclist server ?

Thanks, Vasile
--
http://www.piclist.com hint: PICList Posts must start with ONE topic:

Hi Vasile,
I suspected there was abit more to this then the subject led on :),
in this case to understand why/what
caused the problem with signed/unsigned i consulted the maxim
site and the app. notes for the DS1620.

http://dbserv.maxim-ic.com/quick_view2.cfm?qv_pk=2735

Now I can understand your concerns, however there might be an solution :)
After an quick glance through the app-notes, I think the following
assumptions are correct:

-Data output in 8 bit+sign bit in 0.5 degrees resolution ( rounded )
-Possibility to read the slope/count registers manually to achive
higher accuracy.
-the examples uses float variables which is 'a tad bit' overkill
for temperature calculation on an pic.

Instead i propose the following:

Read data, store sign bit separately, if negative make 2's complement
and then perform remaing calculation for positive numbers only.
To avoid the float issue I think an alternative data format might be useful,
i.e the data is originally presented as 7Q1 in whole degrees ( 0.5 deg. 8
bits )
and formula is intended to extend the resolution to atleast 0.1 deg. Why
not multiply original data with 128 ( i.e leftshift by 7 ),
data would then be represented in two bytes as 8Q8. With the lowest byte as
fractional part ( i.e. fixed point ).
Use this data representation for all data from the device, then scaling
should not be an issue ( i.e. counter_remain, count_per_deg etc ).

pseuso hack/slash something like:

data_input      RES 2   ; storage for temp. data ( 9 bits from device )
count_rem       RES 2   ; storage for temp. internal counter
count_deg       RES 2 ; storage for temp. internal slope
bit_vars        RES 1 ; misc. bit varibales

#define _sign_bit               bit_vars,0      ; storage for sign

//pseudo..
data_input = read_data9bit()    // read data from device store in local ram

; store the sign bit for future use
BCF     _sign_bit               ; clear ev. previous sign
BTFSC   data_input,0    ; test sign bit
BSF     _sign_bit               ; temp. is negative

; if the 9'th bit is set then make 2's complemnt
BTFSS   data_input,0    ; set if negative
GOTO    DATA_SWAP
; negative, normalize data
COMF    data_input+1,F  ; 1's complement
MOVLW   D'1'

:DATA_SWAP
; at entry we have data in as 15q1 ( in full degrees )
; now we want to store data in 8q8 ( really 7q8 ) format instead
; as input is limited to <255 we can just swap the bytes
; and right shift by one
CLRC                            ; clear carry for byte rotation
RRF     data_input+1,W  ; get data, get lowest bit into carry
MOVWF   data_input              ; overwrite top byte
CLRF    data_input+1    ; and clear bottom byte
RRF     data_input+1,F  ; and rotate the carry into top bit
; data now represented in fixed point as 8q8 ( where the top bit is always
zero )
; note data is *not* truncated yet
; now read the count_rem and count_deg variables
; and store them in 8q1 format  ( similar to data, i.e. left shifted by 7 )
; then you can use 'normal' 16 bit division routines

the result is then 'read out' from the 16 bit variable
as whole degrees in top byte, and fractional degrees in
low byte ( 256'th of deg. ) If you want 'normal' 10's base
representation, Nikolai's code generator works wonders :)

/Tony

PS don't forget about truncation, 0.25 degrees ! DS

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:

Hi,

BTW:

Vasile Surduncan wrote:
<snip>
>Truncated half-degree bit ( temp_read - 1/2LSB ) its a simple task:
>  rrf temp_read_lo, f
>  bcf status_c
>  rlf temp_read_lo, f
<snip>

This is *not* correct, I hope you understand that.
Truncation should only be 0.25 degrees, i.e. 1/2 LSB !!!
*not* 1/2 degree !!!
Therefore digest my proposal and understand the reason I choosed
not to truncate data before conversion to fixed format. Removing
0.25 degree ( 1/2 LSB in this case ) is trivial if following my suggestion
as that only means an subtraction of the 16 bit value 0x0040 ( which is
0.25 degrees in 8q8 fixed format ). I.e.:

0x0040 is in 8q8 equal to:

0x00 ( top byte ) = 0 degrees
0x40 ( bottom byte ) -> 0x40/0xFF (implied decimal point) = 0.25 degrees

/tony

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:

Vasile,

I remember doing similar thing with one of those Texas Instrument temperature sensors.  What I did was simply change the higher 8 bits
(the high byte).  In other words, if the number is positive, leave it as it is, but if it is negative, change it to 0xFF.

That should take care of it...

Rudy

{Quote hidden}

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:

On Mon, 3 Dec 2001, [Iso-8859-1] Kübek Tony wrote:

> Hi,
>
> BTW:
>
> Vasile Surduncan wrote:
> <snip>
> >Truncated half-degree bit ( temp_read - 1/2LSB ) its a simple task:
> >  rrf temp_read_lo, f
> >  bcf status_c
> >  rlf temp_read_lo, f
> <snip>
>
> This is *not* correct, I hope you understand that.
> Truncation should only be 0.25 degrees, i.e. 1/2 LSB !!!
> *not* 1/2 degree !!!

YES... I've realised that last night...
I'll digest your mail, it's very close to my conclusions.
Thanks a lot, it seems you're a great specialist in maths tricks.

Best regards, Vasile

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

On Mon, 3 Dec 2001, Vasile Surducan wrote:

> Thanks Gerhart and Tony
>
> On Mon, 3 Dec 2001, [Iso-8859-1] K|bek Tony wrote:
>
> > Hi,
> > Perhaps if you would elaborate a bit on the actual
> > formula you intend to use I can give some hints.
> >
>   OK here is:
>
>   temperature = temp_read - 1/2LSB + [ (count_per_degree - count_remain /
>                                         count_per_degree) ]

I think your right most ')' is in the wrong place.
As I recall, count_per_degree is ~50.

Notice that the above formula can be reduced:

temperature = temp_read + [(count_per_degree - count_remain) /
count_per_degree] - count_per_degree/(2*count_per_degree)

= temp_read + [(2*count_per_degree - 2*count_remain) /
2*count_per_degree] - count_per_degree/(2*count_per_degree)

= temp_read + [(count_per_degree - 2*count_remain) /
2*count_per_degree]

or another form that may even be more useful:

temperature = temp_read + 1/2LSB  - count_remain / count_per_degree

I doubt you really need more than a few bits from the division. If not
then you can try the routine below. Note that this does a 4-bit division
for the low byte of the temperature. Also, for clarity I included some
debug code to illustrate its use. It should be clear from the variable
names on how to change this to a real interface to a ds1820.

cblock       0x0c
temp_hi
temp_lo
count_remain
count_per_degree
x
endc

movlw   0x20

; debug loop
l1

movlw   0x40
movwf   count_per_degree
movf    x,w
movwf   count_remain

call    div

; increment the temperature
incf    x,f
movf    x,w
skpc
goto   l1

clrf    x

goto    l1

; convert the temperature into a 12 bit result: 8-bit integer
; plus a 4-bit fraction. Note, negative temperatures are not handled

div:
movf   temp_read,w         ; Get the high 8 bits
movwf  temp_hi

; 4-bit division

movlw  0x08                ;Quotient of division is stored
movwf  temp_lo             ;here. Also used as a loop counter

movf   count_per_degree,w  ;Keep divisor in W

div_loop:
clrc
rlf    count_remain,f      ;Shift dividend

subwf  count_remain,f      ;If divisor is <= dividend
rlf    temp_lo,f           ;then C is set
btfss  temp_lo,0           ;If C was not set then
addwf  count_remain,f     ;we need to restore the subtraction

btfss  temp_lo,7           ;If msb is clear (the loop count bit)
goto  div_loop            ; we're done, else loop more

; through division. Low 4 bits of temp_lo contain result.
; we need to << 4, and subtract from "1/2" or 0x80/0x100.
; If the subtraction causes a borrow, then we need to
; decrement the high byte as well.

swapf  temp_lo,w           ;<<4
andlw  0xf0                ;get rid of loop count bit
addlw  0x80                ;"subtract" 1/2 note -1/2=0x80
movwf  temp_lo             ;save the low temperature

skpc                       ;If the division is less than 1/2
decf  temp_hi,f           ;get the borrow bit from the high byte

return

end

This routine works in this contrived example. There's a little room for
optimization too...

>
>  All values are 9 bit numbers,
> Truncated half-degree bit ( temp_read - 1/2LSB ) its a simple task:
>   rrf temp_read_lo, f
>   bcf status_c
>   rlf temp_read_lo, f

The same can be accomplished with:

But neither of these are the same for subtracting a 1/2 LSB.

You're going to need a whole other byte to store that extra bit.

If you want to subtract a half LSB do this:

decf  HI_BYTE,F
movlw 0x80
movwf LO_BYTE

You can now think of the LO_BYTE as a fraction of 0x80/0x100 = 1/2.

{Quote hidden}

The last time I checked, Nikolai was too busy working on his foos serve.

Scott

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

Oh my God,  Scott !
You have a really rested mind...
I'm wondering why the guys from Dalas haven't ...
However, the whole theory is shadowed by the instability of the
count_per_degree and count_remain values.
As many readings, as many values at the same temperature.

Thank you,
Vasile

On Tue, 4 Dec 2001, Scott Dattalo wrote:

{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2001\12\05@081511 by
Hi,

Vasile wrote:
<snip>
>Thanks a lot, it seems you're a great specialist in maths tricks.
<snip>

Nope but I've encountered a few on the list :)
hmm...let's see...

Scott Dattalo wrote:
<removed excellent implementation>
> This routine works in this contrived example. There's a little room for
> optimization too...

ah that's right, there's one :)

Great stuff,

/Tony

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

Hi,

Vasile Surduncan wrote:
<snip>
>However, the whole theory is shadowed by the instability of the
>count_per_degree and count_remain values.
>As many readings, as many values at the same temperature.

I'm curious, how much flucatuation are we talking about ?
Assuming you had the 0.5 degrees stable prior to trying to
extend it to 0.1 degrees, the unstability ( i.e. noice etc. )
should be less than 0.5 degrees.
If you have higher fluctuations then you have to look for other causes,
you are using one-shot mode ?

In this case I assume the an fairly small FIR should be of use,
let's say an average of 8 readings ? Would that produce 'better' results ?

/Tony

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

On Wed, 5 Dec 2001, Vasile Surducan wrote:

> However, the whole theory is shadowed by the instability of the
> count_per_degree and count_remain values.
> As many readings, as many values at the same temperature.

I'm not sure what you're saying here. Are you saying that the DS1820 is
inherently flawed because there several temperatures that have
different "count_per_degree" and "count_remain" values, or the algorithm
which I posted was flawed because different "count_per_degree" and
"count_remain" can produce the same temperature?

All I can say is that the algorithm is accurate to within 1/8 of a degree.
If count_remain and count_per_degree change, the algorithm will still work
properly (the only assumption is that count_remain is less than
count_per_degree). Study it, try it, and tell us how it works.

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservmitvma.mit.edu with SET PICList DIGEST in the body

On Thu, 6 Dec 2001, Scott Dattalo wrote:

> On Wed, 5 Dec 2001, Vasile Surducan wrote:
>
> > However, the whole theory is shadowed by the instability of the
> > count_per_degree and count_remain values.
> > As many readings, as many values at the same temperature.
>
> I'm not sure what you're saying here. Are you saying that the DS1820 is
> inherently flawed because there several temperatures that have
> different "count_per_degree" and "count_remain" values, or the algorithm
> which I posted was flawed because different "count_per_degree" and
> "count_remain" can produce the same temperature?
>

No, I don't say nothing ugly about your algorithm. Even by absurd it is
wrong I don't dare to do this... ( until I not understad it 100% )
I'm working with DS1620 but it seems the hi res algorithm is the same. If
count_per_degree is almost constant ( fluctuating between 0x_40 to 0x_65 )
count_remain have a fluctuation from less than count_per_degree to 0x_01df
at the constant test temperature of about 20 C.
I think is too much, because the division between these two should be
almost constant and is not ...
Thanks, Vasile

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-requestmitvma.mit.edu

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