2020/11/04 10:26:38
TomasParrado
I have an intermittent stream of 8bit SPI data in 32bit chunks that I need to work with that is in the form;
    8bit command  +  24bit signed data.
 
 
I'm on the slave side and cannot alter the command/data structure.
XC16 doesn't support uint24_t integer types, but is there a best practise for dealing with this signed conversion?
 
The received data gets held in a buffer and I presume the quickest method is bit shifting as follows;

int8_t command;
int32_t data;

command = buffer[0];
data = (buffer[1] << 24) + (buffer[2] << 16) + (buffer[3] << 8);  //Shift everything up
data >>= 8;  //Shift back down (bringing 1s if negative)

 
but I have seen others doing an if<0 statement, so I thought it prudent to ask for the wisdom of the crowd?
 
2020/11/04 12:10:34
BroadwellConsultingInc
You're sure the data comes in Big endian?  It'd be convenient if it was little instead.
I'd be inclined to try doing a union where I copied the three least significant bytes where they needed to go, then bit test the 24th bit.  If it's set, top byte = 0xFF else top byte = 0.  Probably less efficient, but it's the only thing I can think of.
2020/11/04 13:21:04
TomasParrado
I'm fairly confident it comes in both most significant bit and byte first (I'd have to check).
My point was more about the bit test/if statement - I've seen others do similar to...

 
int32_t x;
 
x = (byte1 << 16) + (byte2 << 8) + byte3;
 
if (x > 0x7FFFFF) x += 0xFF000000;
 

But I assume (possibly wrongly) that a test followed by a set is slower than a shift...

 
int32_t x;
 
x = (byte1 << 24) + (byte2 << 16) + (byte3 << 8);
 
x >>= 8;
 

So I was wondering if there is an error/problem with the shift. Maybe it doesn't guarantee 1's are shifted if x is negative? Or perhaps it's just personal preference. I'll be debugging and possibly answering the question for myself in a few days, but I was wondering if there was a prefered method that might save me some head scratching?
2020/11/04 13:28:38
BroadwellConsultingInc
The compiler manual appendix A talks about how the compiler does things that have implementation specific variation, such as right shift of signed integers.  You're in luck, the sign is preserved.  Not guaranteed to be portable to other platforms...
2020/11/04 13:51:46
TomasParrado
Thank you!
I see it in section "2.4.11 Right-shifting Signed Values". Barring anyone else jumping in to point out a flaw I think that's my answer.
2020/11/04 14:05:12
ric
TomasParrado
...
But I assume (possibly wrongly) that a test followed by a set is slower than a shift...

Why assume anything?
If both versions give the correct result, just have a look at the assembly language output and see which one uses more instructions.
 
2020/11/04 14:16:23
1and0
What are the data types of buffer[] and bytex?  I presume they are uint8_t or int8_t; if so, then none of them will work. ;)
 
2020/11/04 14:27:47
JPortici
if we remain within XC16, the instruction set for PIC24/dSPIC have a sign extend instruction
"Sign-extend the byte in Ws and store the 16-bit result in Wnd"
this can become a very simple assembly routine, maybe there's already a builtin available
 
 
2020/11/04 14:54:10
TomasParrado
ric
TomasParrado
...
But I assume (possibly wrongly) that a test followed by a set is slower than a shift...

Why assume anything?
If both versions give the correct result, just have a look at the assembly language output and see which one uses more instructions.
 

...because I don't know how to do that. (And if I did, is every line of assembler 1 instruction? I assume it is Smile: Smile)


2020/11/04 14:56:10
TomasParrado
1and0
What are the data types of buffer[] and bytex?  I presume they are uint8_t or int8_t; if so, then none of them will work. ;)
 


x = (uint32_t)(byte1 << 24) + (uint32_t)(byte2 << 16) + (byte3 << 8);
Happy? 
© 2021 APG vNext Commercial Version 4.5

Use My Existing Forum Account