A math question

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have the fllowing bit of code on an Xmega:

TD1 = TsyncS1 - TsyncM1;
TD2 = TsyncM2 - TsyncS2;
TDelay = (TD1 + TD2) / 2;
TDiff = TDelay - TD1;

I have a break point on the line just below what is shown. I get the following values:

TD1      0xe422e02f    int32_t{data}@0x2fdd ([R28]+1)
TD2      0xe62f010e    int32_t{data}@0x2fe1 ([R28]+5)
TDelay   0x2a2f0000    int32_t{data}@0x2fe5 ([R28]+9)
TDiff    0x081eec2f    int32_t{data}@0x2fe9 ([R28]+13)

TsyncS1	 0x000b1d40    uint32_t{data}@0x29d8
TsyncM1	 0x000b4032    uint32_t{data}@0x29d4
TsyncM2	 0x000b407e    uint32_t{data}@0x29b7
TsyncS2	 0x00093d68    uint32_t{data}@0x29b3

What puzzles me is the value of TDelay. My calculations give me 0xCA51E13D (-900,603,587) but as can be sen above the program gets a result of 0x2a2f0000 which is a positive number.
Am I just missing something here or am I doing something wrong?
:(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have to be very careful with uint32_t aand int32_t

You can treat most AVR timers etc as uint16_t
If you subtract two uint32_t values, you can treat the result as signed. Obviously you need to be in the correct range.

Having got your signed result, you can do signed arithmetic.

Addition has more problems. Imagine that you add 0x9000000u and 0x90000000u. The result would be 0x2000000u. (and a carry)

TD1 is -ve
TDelay is +ve
TDiff is +ve with a carry.

Either test the operands before doing the int32_t arithmetic or extend to 64-bit.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

TDelay is +ve

Yes I know. That is really my question. Why is it positive. Should the result not be 0xCA51E13D which does fit within the signed number?
I thought that the compiler would at least use 64 bits to store the result of adding two 32 bit numbers.
If you add the 2 largest values kept in 32 bits together and then divide by 2 the result should fit into 32 bits??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No. C does not extend on your behalf. However, you can give it some guidance. e.g. cast your operands to bigger width.

This can get inefficient. Especially when a few tests can give you smaller code.

You need to hand-trace your algorithm with suitable test values. Then you discover the cases that go wrong. e.g. try averaging 37267 and -32768.

Most of the time, your TD1, TD2 will be fairly small +ve or -ve numbers. What happens when you have large numbers?

The elegant solution is probably to cast to monster widths. It will be inefficient and unnecessary for 99.999% of your cases.

David.