Spin to C Translation Assistance, Please [SOLVED]

I have a Spin program that can extract five 16-bit Little Endian values from a byte array that is returned by a sensor. As Spin aligns variables of the same size in the order they're declared, I can update the five word variables with a single line.
Am I correct in thinking that a C struct maintains the alignment of the member variables as they're declared, in other words, can I do this and now that the memory layout is variable1.lowbyte, variable1.highbyte, variable2.lowbyte, ...
Thanks.
bytemove(@value1, @array[6], 10)
Am I correct in thinking that a C struct maintains the alignment of the member variables as they're declared, in other words, can I do this and now that the memory layout is variable1.lowbyte, variable1.highbyte, variable2.lowbyte, ...
struct block {
uint16_t variable1;
uint16_t variable2;
uint16_t variable3;
uint16_t variable4;
uint16_t variable5;
};
And if that is the case, how can I move 10 bytes from array[6] to the structure? I have the K&R on my desk and am experimenting, but would appreciate some coaching from those with experience.Thanks.
Comments
struct packed { unsigned short v1; unsigned short v2; unsigned short v3; unsigned short v4; unsigned short v5; } data; unsigned char array[10]; int main() { array[0] = 1; array[1] = 0; array[2] = 2; array[3] = 0; array[4] = 3; array[5] = 0; array[6] = 4; array[7] = 0; array[8] = 5; array[9] = 0; memcpy(&data, array, 10); unsigned short v = data.v3; print("Value: %d\n", v);
Mike
struct something { int varA; int varB; short varC; char varD; };
Or, if GCC, use that non-standard "__attribute__((pack))" option. I prefer the more portable approach though.This if for the Pixy2 camera (used to be called CMU cam. It responds with a variable length array of bytes. In the case of a block (tracked target), the response will be six bytes (header) plus 14 bytes of block information -- I only care about the first 10 bytes which are unsigned, 16-bit values. Note that if the Pixy returns two targets, the stream will be 24 bytes: header (6) + block (14) + block (14), etc., up to the maximum number of blocks allowed to be returned in one call.
In another case, I pass two pointers to a function and update the variables like this:
int32_t pixy2_getResolution(uint16_t *fWidth, uint16_t *fHeight) { clearBuffer(); serial_txChar(pixy2, 0xAE); serial_txChar(pixy2, 0xC1); serial_txChar(pixy2, REQUEST_RESOLUTION); serial_txChar(pixy2, 0x01); serial_txChar(pixy2, 0x00); recvPacket(); if (validateChecksum() != RESULT_OK) { return RESULT_CHECKSUM_ERROR; } else { if (response[2] == RESPONSE_RESOLUTION) { *fWidth = extract16(6); *fHeight = extract16(8); return RESULT_OK; } else return (int32_t)(0xFFFFFF00 | response[2]); } }
This works great. I could duplicate this and pass five pointers for the block values, but that would make the function call unwieldy. I want to grab 10 consecutive bytes out of the stream based on the block (if multiples) that I want to extract.In my demo app I have these variables defined:
uint16_t signature; uint16_t xpos; uint16_t ypos; uint16_t width; uint16_t height;
This is the function that I'm attempting to use but it's giving me grief.
int32_t pixy2_extractBlock(uint8_t i, uint16_t *block) { uint8_t ofs = 6 + (i * BLOCK_SIZE); if (response[2] == RESPONSE_BLOCKS) { memcpy(*block, response[ofs], 10); return RESULT_OK; } else return RESULT_ERROR; }
The program tells me I have blocks, but the data always comes back as 0.Note that the compiler complains, too -- this is the output.
I doesn't like what I'm doing with memcpy, but I don't understand the error messages vis-a-vis type arguments.
Again, C is not my normal language -- please be patient and gentle with me.
memcpy(block, &response[ofs], 10);
Edit: You also need & in front of response[ofs] to get the address of that array element.
Do I need to change the way I'm defining my block variables in C? ATM, they are consecutive words -- just as in my Spin program.
uint16_t signature; uint16_t xpos; uint16_t ypos; uint16_t width; uint16_t height;
I also don't see the definition of this function:*fWidth = extract16(6);
Maybe you could post all of your code?I put the block variables into a struct to force their order in memory:
struct block { uint16_t signature; uint16_t xpos; uint16_t ypos; uint16_t width; uint16_t height; } b;
Here's the updated function that moves the values from in receive buffer to the block variables. Again, a buffer can contain more than one block, hence the use of an index.
int32_t pixy2_extractBlock(uint8_t i, uint16_t *block) { uint8_t ofs = 6 + (i * BLOCK_SIZE); if (response[2] == RESPONSE_BLOCKS) { memcpy(block, &response[ofs], 10); return RESULT_OK; } else return RESULT_ERROR; }
Here's the little test loop that requests and displays blocks. All seems well now.
while(1) { blockCount = pixy2_getBlocks(SIG_MAP, MAX_BLOCKS); print("%d blocks detected\n\n", blockCount); if (blockCount > 0) { for (i = 0; i < blockCount; i++) { pixy2_extractBlock(i, &b.signature); print("sig: %1d x: %3d y: %3d w: %3d h: %3d\n", b.signature, b.xpos, b.ypos, b.width, b.height); } print("\n"); } pause(1000); }