Hi, my i have a 12-bit AD-Converter and want to avoid wasting my precious memory space.
Is it possible to put 4k of this 12-bit-word into 1.5k unsigned int (32 bit) variables?
This stuff should be adressable as a kind of ring-buffer.
Think a struct with union should do. But as i'am a relative beginner i'am not sure about the syntax.
Of course it is possible, if you have enough CPU power and are willing to spend it on packing/unpacking the data.
Basically, you will need to write functions for reading/writing the packed array. These functions need to calculate in which 32-bit word(s) the required 12-bit variable is stored, and extract it with a couple of boolean operations and bit-shifts.
Think a struct with union should do.
That's probably not the best way to approach the problem, since there is no 12-bit data type in C.
One way would be to divide the circular buffer into 96-bit blocks (3*32 bit and 8*12 bit). A function that reads/writes to the buffer then first finds the block that contains the requested data. It then extracts the data using a scheme similar to:
data 0 - bits 0:11 of word0 data 1 - bits 12:23 of word0 data 2 - bits 24:31 of word0 OR bits 0:3 of word1 data 3 - bits 4:15 of word1 data 4 - bits 16:27 of word1 data 5 - bits 28:31 of word1 OR bits 0:7 of word2 data 6 - bits 8:19 of word2 data 7 - bits 20:31 of word2
This can be implement with a little bit of bit-masking and bit-shifting.
"... want to avoid wasting my precious memory space."
These days, memory is relatively cheap - exactly how "precious" is your memory?
"... put ... 12-bit-word into ... unsigned int (32 bit) variables?"
Yes, that would be wasteful!
You could just put them into short variables - they're 16 bits, so then you'd only be wasting 4 bits per value: www.keil.com/.../armccref_babfcgfc.htm
Would that be good enough?
If memory space is so tight, do you really need to store 12-bit values...?
It might be easier to use a 6k array of bytes. Then there are only two pack alternatives for a 12-bit value. Even ADC values starts with a byte and and requires 4 bit from next byte. Odd ADC values should take 4 bits and then the next byte.
It is trivial to convert from ADC value n into the start offset in the byte array.
It might be easier to use a 6k array of bytes.
Depending on the exact ARM architecture version used, using bytes may be fairly wasteful performance-wise. Memory accesses are costly on ARM, and a byte access takes as many (or even more) cycles as a word access.
Correct, but most users don't use a sampling speed high enough that it matters, and the simplified handling of being able to read/write values with a single odd/even if statement may offset the memory bandwidth issue.
It's the usual KISS contra maximum optimization.
Well, the OP now has a good set of options to choose from.
Only he can evaluate their relative merits according to his specific requirements, constraints, etc - unknown to the rest of us...
@ Andy Neil If memory space is so tight, do you really need to store 12-bit values...? Yes, testing showed difference between two samples can be in the range of +-4095. So i need full 12-bit storage.
The idea of my thread was to avoid wasting the empty 4 bit. When i store a 12-bit word in a short int (16 bit) the upper four bits are zero.
Idea was to put it all in a struct union.
// this is just an example, it doesn't work union{ struct{ //something useful }12_bit_data; struct{ //something usefull }32_bit_data; }sound;
Is it possible?
Your struct/union concept doesn't work for exactly the reason you have already received. C doesn't have a 12-bit data type, so you can't manage to align any contents of a struct or union at a 12-bit offset.
Whatever you do, any 12-bit value stored in a native C variable (whatever packing/grouping/aligning/... you do) will have to consume at least 16 bits.
The only way to not waste (at least) 12 bits/ADC value is to bit-mask and shift data, so that bits from more than one ADC sample is stored in the same native data variable.
Of course i can do some bit-shifting to pack two 12-bit words in three bytes.
But my hope was to explore an elegant method to let do C that for me.
There's lot of 4-bit nibble stuff in this Forum. For example http://www.keil.com/forum/docs/thread8951.asp
My idea was to access data in an array. Allways having three int ( 3*32 = 96 bits) together. Then having eight 12-bit words inside this structure.
Is this stupid?
Yes it is a bit stupid if there is no data type of size n*4 bits, where n is odd.
If you don't have a 4-bit native data type, then you can't have a union with two nibbles in a byte. If you don't have a 12-bit data type, you can't have a data structure wtih two 12-bit values in three bytes, or 8 12-bit values in a union of 96 bits (3*32-bit).
If there was no need for an array and your only goal was to store nibbles, then you could use bit fields. That would allow you to hide the masking and shifting and store two nibbles in a byte. But bit fields can't span several integers. And even if n*12 bits did perfectly match the size of an existing integer data type (normally 8, 16, 32, 64, 128, ...), you can not use array addressing to access these bit fields, so there would not be any elegance.
With a byte array, you could write a #define to set or get an ADC value in the array. However, I'm not too fond of the use of #define to hide code. It has a tendancy to result in a bloody nose somewhere in the future.