Krupski:
I'm wondering... since the high byte has the sign bit as bit 7, could I do the signed conversion THERE before I slide everything down?
I've been racking my brain on this and I'm just not seeing it... I KNOW it must be simple but I just don't see it.
It may be even simpler than you think.
From the Arduino Refrence page describing the bitshift operators at http://arduino.cc/en/Reference/Bitshift:
When you shift x right by y bits (x >> y), and the highest bit in x is a 1, the behavior depends on the exact data type of x. If x is of type int, the highest bit is the sign bit, determining whether x is negative or not, as we have discussed above. In that case, the sign bit is copied into lower bits, for esoteric historical reasons...
For your program, x is indeed of type int. You're starting with the sign bit in the MSB. Based on this snippet of the reference, all you have to do is shift the value to the right until it's scaled right, and the program will automatically extend the sign bit. Looks like it's done for more than historical reasons - with this behavior, we can divide a negative integer by 2N by shifting right by N bits, just like we do for a positive integer. If x were declared as unsigned int, the sign bit wouldn't be extended, and zeroes would shift in at the MSB.
Also - and this might be the best reason - when I tested your code, I found that this line
x = (x & 0b0000001000000000) ? ((x & 0b0000000111111111) - 0b0000001000000000) : (x & 0b0000000111111111); // convert sign :(
didn't have any effect. I got the same correct answers with it, and without it
You might be overthinking this.
Edit: Or maybe not. After reflection, I recall that you want a general solution that doesn't rely on a 16-bit length for an integer. The method shown in this post relies on that, since it relies on the fact that the sign bit is in the MSB. Back to the drawing board for me.