1. ## Need help with simple math code please!

Hey guys,

I'm having some trouble with some math code used for my PIC16F684.

Code:
```int16 PV, SP;
int16 E0;
uns8 gain;
int16 output;
uns16 temp;

SP = 128;

E0 = PV - SP;

output = gain*E0;

if(output > 0){
P1M1 = 0;
temp = output;
temp /= 4;		// Shift bits 3 to 10 of temp twice to the right
CCPR1L = temp;
}

if(output < 0){
P1M1 = 1;
temp = -output;
temp /= 4;		// Shift bits 3 to 10 of temp twice to the right
CCPR1L = temp;
}```
Don't worry about the A/D conversion, I just deleted the other code. The problem I'm having is that I don't believe the second if statement is working properly. I want to take the absolute value of "gain" but my compiler doesn't have the absolute function. Instead I just put "-gain" which compiles fine and I think works.

When output > 0, the PIC outputs a PWM square wave which shows up fine on the oscilloscope. It's when output should be < 0, the output on the oscilloscope is a very strange square wave, that looks noisy and has weird superimposing square waves. I think the problem is with the math though.

Can someone verify if the way I initialized the variables will properly store data? I get confused when I'm doing math with mixes of signed and unsigned numbers. Keep in mind CCPR1L and ADRESH can only store 8 bit numbers.

I'd appreciate the help a lot. Thanks!

2. Seems ok.

You can condense:
Code:
```if (output > 0) {
P1M1 = 0 ;
CCPR1L = (output >> 2) ; // Shift bits 3 to 10 of temp twice to the right
}

if (output < 0) {
P1M1 = 1;
CCPR1L = ((-output) >> 2) ; // Shift bits 3 to 10 of temp twice to the right
}```

3. Hey,

Unfortunately the compiler I use doesn't have that shift command for some reason .

Otherwise looks okay? My concern is with the temp. It's okay that it takes the -output value? That value is technically a signed integer, so does temp just throw away the sign bit?

4. Assuming you have a standard compiler... (and you obviously don't...), putting the - prefix on a signed field will flip the sign, just like multiplying by -1.

5. yea that makes sense. but my point is that "temp" is unsigned and -output is signed. When -output gets placed inside "temp", does it just drop the sign bit?

6. I wouldn't count on that.

if(number < 0) number *= -1;

Would be my preference.

7. My concern is that because i'm using a mix of signed and unsigned integers, the sign bit might be getting lost somewhere, or even worse used as a bit that is placed inside a register such as CCPR1L.

Code:
```int16 temp;
int16 output;

if(output < 0){
P1M1 = 1;
temp = -output;
CCPR1L = (unsigned char)temp/4;
}```
Would the code above guarantee that CCPR1L only gets the MSBs without the sign bit? For example, if temp is 10 bits of data + 1 sign bit (11 bits), would the CCPR1L register be given bits 2-9 (disregarding the 10th bit)? Hope this ain't too confusing lol

8. OK. the \$64 question.

WHY are you using a mix of signed and unsigned for your calculations?????

9. Well, I need to keep track of negatives so they must be signed integers. The only reason I'm using UNSIGNED is because "CCPR1L" is a register in a microcontroller. I do not want a sign bit being placed in a register as it will just consider it part of the numerical value. I want to make the number unsigned THEN put it into the register to ensure this.

I definitely am not an expert programmer so if someone knows a better way I'd really appreciate it. I simulated the code and the CCPR1L values are not correct in the (output < 0) part of the code. There is definitely something wrong with them but I can't figure it out

10. Originally Posted by MetaMorphicX
yea that makes sense. but my point is that "temp" is unsigned and -output is signed. When -output gets placed inside "temp", does it just drop the sign bit?
No, that is not what will happen.

Anyway, what you want is the absolute (positive) value of the number.

So use abs(). You may have to cast the return value to unsigned but that is okay.