How to convert UInt16 into Integer - bit-manipulation

I am facing issue with conversion, I have 2 UInt8 byte and converted as UInt16 by using
let testLiveSpeed : UInt16
let bytes: [UInt8] = [data[3], data[4]] //where data has contain array of `UInt8`,
self.testLiveSpeed = UnsafePointer(bytes).withMemoryRebound(to: UInt16.self, capacity: 1) {
$0.pointee
}
But self.testLiveSpeed it give unsigned Integer value , but i want signed Int value. Please help

Please use the following code:
let testLiveSpeed : Int16
let data: [UInt8] = [1, 1, 1, 127, 255]
let bytes: [UInt8] = [data[3], data[4]]
testLiveSpeed = UnsafePointer(bytes).withMemoryRebound(to: Int16.self, capacity: 1) {
$0.pointee
}
print(testLiveSpeed);

Related

Efficiently store multiple integral numbers in a single variable (and retrieve them)

Let's assume that we have up to 3 IDs (we don't know the number of IDs before, can be 0 to 3), each of them can consist of up to 4 digits, leading to numbers from 1 to 9999. Since these IDs are small enough, we want to store them in a single variable and not an array (for whatever reasons), such as a double. Here is an example of what I mean:
We have 3 IDs: ID_1 = 1234, ID_2 = 0987, and ID_3 = 6543. We pair these and obtain the following as a result: 654309871234
As we can see, the numbers are still there and could be obtained from it.
Something like this, we could accomplish by using the following code:
int maxDigits = 4;
double result = 1; // needed at the start, so that log10 works
int id[3] = {1234, 0987, 6543};
for (int i=0; i<3; ++i) {
int pos = log10(result) / maxDigits;
result += pow(10, pos * maxDigits + 1) * id;
}
This would have a slightly different outcome: result = 6543098712341, but we can still retrieve the information.
However, I don't think that this is an efficient way of handling this. Maybe one should rather operate in binaries and not decimals? What would be a better (more efficient) approach?
(The above-mentioned ID range mustn't be the same for other possible solutions.)
The IDs can go up to 9999, which requires 14 bits max. 3 integers of 14 bits each would require 42 bits max. You can easily store that in a 64-bit unsigned long or uint64_t with some manual bit-shifting, eg:
uint16_t get_id(uint64_t ids, uint8_t which)
{
return (ids >> (14 * (which & 3))) & 0x3FFF;
}
void set_id(uint64_t &ids, uint8_t which, uint16_t id)
{
uint64_t shift = 14 * (which & 3);
ids = (ids & ~((0x3FFF << shift))) | ((id & 0x3FFF) << shift);
}
uint64_t ids = 0;
set_id(ids, 0, 1234);
set_id(ids, 1, 0987);
set_id(ids, 2, 6543);
...
id1 = get_id(ids, 0);
id2 = get_id(ids, 1);
id3 = get_id(ids, 2);
Or, you can use bitfields to let the compiler handle the bit-shifting for you, eg:
struct s_ids
{
uint64_t id1: 14;
uint64_t id2: 14;
uint64_t id3: 14;
};
s_ids ids;
ids.id1 = 1234;
ids.id2 = 0987;
ids.id3 = 6543;
...
id1 = ids.id1;
id2 = ids.id2;
id3 = ids.id3;
Or, you could just use a normal struct of normal 16-bit integers and don't do any fancy bit-twiddling at all:
struct s_ids
{
uint16_t id1;
uint16_t id2;
uint16_t id3;
};
s_ids ids;
ids.id1 = 1234;
ids.id2 = 0987;
ids.id3 = 6543;
...
id1 = ids.id1;
id2 = ids.id2;
id3 = ids.id3;
You cannot store these values in an easy way in a double: If you remove the sign and the exponent bits from a double, you're left with 52 bits to store your value. However lg(52) = 15.65... (lg denoting the logarithm with a basis of 2 here). This means you'd be left with less than 4 decimal digits per ID which is insufficient to store the kind of info you want to store.
Instead use a unsigned integer type that's guaranteed to contain enough bits. 64 bit happens to be sufficient to store 4 ids containing 16 bits each (2^16 = 65536) and you can retrieve the ids efficiently using bit operations:
/**
* \param previous the combined ids storing new value
* \param index an index between 0 and 3 (inclusive) for the id to store
* \param value the id to store
* \return the new combined value after replacing the id at index with value
*/
uint64_t storeId(uint64_t previous, uint64_t index, uint64_t value)
{
return (previous ^ (0xffff << (index * 16))) | (value << (index * 16));
}
/**
* \return the id stored in value at index index
*/
uint64_t getId(uint64_t value, uint64_t index)
{
return (value >> (index * 16)) & 0xffff;
}

Convert a char Array to a time structure

I use in my current project a structure: for time information
struct SFileDateTime
{
uint8 nYear; // Years since 1900
uint8 nMonth; // Month [1, 12]
uint8 nDay; // Day of month [1, 31]
uint8 nHour; // Hours [0, 23]
uint8 nMinute; // Minutes [0, 59]
uint8 nSecond; // Seconds [0, 59]
};
typedef unsigned char uint8;
In some situations I get from external calls just a date char array
char [17] "1998012609260000"
I have now the problem to bring the char array to the SFileDateTime structure. I tried a memcpy call but this will cause a crash.
I currently do not understand why memcpy will not work. Is there any other way to convert it?
Is casting the right choice?
U have 2 great answers in comments below your question. Hope this helps you a bit.
typedef unsigned char uint8; //Max size is 255 in decimal ( 1111 1111 )
struct SFileDateTime
{
uint8 nYear; // Years since 1900
uint8 nMonth; // Month [1, 12]
uint8 nDay; // Day of month [1, 31]
uint8 nHour[20]; // Hours [0, 23]
uint8 nMinute[]; // Minutes [0, 59]
uint8 nSecond; // Seconds [0, 59]
};
int main()
{
SFileDateTime nene;
nene.nYear = 33; // ASCII code for !
nene.nMonth = 'M'; // One char which is 77 in ASCII
nene.nDay = 255; // max number in ASCII which is space
nene.nSecond = 256 ; // No go||=== warning: large integer
//implicitly truncated to unsigned type [-Woverflow]|
char one[] = "Hello";
cout<<one<<endl;
nene.nHour[0] = 'A';
nene.nHour[1] = 'b';
nene.nHour[2] = 'b';
nene.nHour[3] = 'y';
return 0;
}
if u want to use strcpy use typedef char
U should convert it to single chars if you want to use your struct.
Here you can find a good reference : https://en.cppreference.com/w/c/chrono/localtime

Addition of long values show different o/p

I am facing problem in doing addition of long values
example
typedef unsigned short UINT16;
UINT16* flash_dest_ptr; // this is equal to in hexa 0XFF910000
UINT16 data_length ; // hex = 0x000002AA & dec = 682
//now when I add
UINT16 *memory_loc_ver = flash_dest_ptr + data_length ;
dbug_printf( DBUG_ERROR | DBUG_NAVD, " ADD hex =0x%08X\n\r",memory_loc_ver );
Actual O/p = 0xFF910554
// shouldn't o/p be FF9102AA ?
It's pointer arithmetic, so
UINT16 *memory_loc_ver = flash_dest_ptr + data_length ;
advances flash_dest_ptr by data_length * sizeof (UINT16) bytes.
Typically, sizeof (UINT16) would be 2, and
2 * 0x2AA = 0x554
When you add integers to a pointer value, you are actually moving the pointer as many bytes as it would take to move data_length UINT16s away in memory, not data_length bytes.

modifying array values using location in c++

lets suppose I have an unsigned int* val and unsigned char mat[24][8]. Now the val stores the location of the variable mat. Is it possible to modify the bits in the mat variable using the location in val?
for ex:
val = 0x00000001 and location of val in memory is 0x20004000
the first element of mat is located at 0x00000001.
Now i want to modify the value of mat at, say, 10,4. Is it possible to do this using C++?
Yes, it is possible, unless either of the array members or the pointer target is const.
For example:
int array[3][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
int *p = &array[1][1];
*p = 42;
// array is now: { { 0, 1 }, { 2, 42 }, { 4, 5 } };
Yes, you can change the value of your matrix using the address(what you called location), but you have to calculate the right offset from the start. The offset calculation should be something like this :
(matrix_x_len * Y + X) * sizeof(unsigned int) + offset to the beggining of the matrix
then when you have the offset you can change mat like this : *(val + offset) = new_value.
can do it but making val as unsigned char*
val = &mat;
will make easy to do modification of bits
You can of course modify the bits since unsigned char mat[24][8] gives you a memory chunk with 24*8*sizeof(char) bytes.
(I assume that unsigned char is 1 byte (=8 bits) in size and unsigned int is 4 Bytes (=32 bits) from here but this may be dependant on your system.
But accessing memory elements of 1 byte width using a pointer to elements with 4 bytes width is tricky and can easily produce errors.
If you set element 0 of the int array to 1 for example
#define ROWS 24
#define COLS 8
unsigned char mat[ROWS][COLS];
unsigned int * val = (unsigned int*)&mat;
val[0] = 1;
You will see that mat[0][0] is 0, mat[0][1] is 0, mat[0][2] is 0 and mat[0][3] is 1.
Please not that you cannot edit the elements of mat directly using their offset in memory via such a "miss-typed" pointer.
Accessing val[10*8+4] for example will access byte 336 from the beginning of your memory chunk which has only 192 bytes.
You will have to calculate your index correctly:
size_t byte_index = (10*COLS+4)*sizeof(unsigned char); // will be 84
size_t int_index = byte_index / sizeof(unsigned int); // will be 21
size_t sub_byte = byte_index%sizeof(unsigned int); // will be 0
Therefore you can access val[int_index] or val[21] to access the 4 bytes that contain the data of element mat[10][4] which is byte number sub_byte of the refered unsigned int value.
If you have the same types there is no problem except that you need to calculate the correct offset.
#define ROWS 24
#define COLS 8
unsigned char mat[ROWS][COLS];
unsigned char * val = &mat;
val[10*8+4] = 12; // set mat[10][4] to 12
*(val+10*8+5) = 13; // set mat[10][5] to 13

Given an array of uint8_t what is a good way to extract any subsequence of bits as a uint32_t?

I have run into an interesting problem lately:
Lets say I have an array of bytes (uint8_t to be exact) of length at least one. Now i need a function that will get a subsequence of bits from this array, starting with bit X (zero based index, inclusive) and having length L and will return this as an uint32_t. If L is smaller than 32 the remaining high bits should be zero.
Although this is not very hard to solve, my current thoughts on how to do this seem a bit cumbersome to me. I'm thinking of a table of all the possible masks for a given byte (start with bit 0-7, take 1-8 bits) and then construct the number one byte at a time using this table.
Can somebody come up with a nicer solution? Note that i cannot use Boost or STL for this - and no, it is not a homework, its a problem i run into at work and we do not use Boost or STL in the code where this thing goes. You can assume that: 0 < L <= 32 and that the byte array is large enough to hold the subsequence.
One example of correct input/output:
array: 00110011 1010 1010 11110011 01 101100
subsequence: X = 12 (zero based index), L = 14
resulting uint32_t = 00000000 00000000 00 101011 11001101
Only the first and last bytes in the subsequence will involve some bit slicing to get the required bits out, while the intermediate bytes can be shifted in whole into the result. Here's some sample code, absolutely untested -- it does what I described, but some of the bit indices could be off by one:
uint8_t bytes[];
int X, L;
uint32_t result;
int startByte = X / 8, /* starting byte number */
startBit = 7 - X % 8, /* bit index within starting byte, from LSB */
endByte = (X + L) / 8, /* ending byte number */
endBit = 7 - (X + L) % 8; /* bit index within ending byte, from LSB */
/* Special case where start and end are within same byte:
just get bits from startBit to endBit */
if (startByte == endByte) {
uint8_t byte = bytes[startByte];
result = (byte >> endBit) & ((1 << (startBit - endBit)) - 1);
}
/* All other cases: get ending bits of starting byte,
all other bytes in between,
starting bits of ending byte */
else {
uint8_t byte = bytes[startByte];
result = byte & ((1 << startBit) - 1);
for (int i = startByte + 1; i < endByte; i++)
result = (result << 8) | bytes[i];
byte = bytes[endByte];
result = (result << (8 - endBit)) | (byte >> endBit);
}
Take a look at std::bitset and boost::dynamic_bitset.
I would be thinking something like loading a uint64_t with a cast and then shifting left and right to lose the uninteresting bits.
uint32_t extract_bits(uint8_t* bytes, int start, int count)
{
int shiftleft = 32+start;
int shiftright = 64-count;
uint64_t *ptr = (uint64_t*)(bytes);
uint64_t hold = *ptr;
hold <<= shiftleft;
hold >>= shiftright;
return (uint32_t)hold;
}
For the sake of completness, i'am adding my solution inspired by the comments and answers here. Thanks to all who bothered to think about the problem.
static const uint8_t firstByteMasks[8] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
uint32_t getBits( const uint8_t *buf, const uint32_t bitoff, const uint32_t len, const uint32_t bitcount )
{
uint64_t result = 0;
int32_t startByte = bitoff / 8; // starting byte number
int32_t endByte = ((bitoff + bitcount) - 1) / 8; // ending byte number
int32_t rightShift = 16 - ((bitoff + bitcount) % 8 );
if ( endByte >= len ) return -1;
if ( rightShift == 16 ) rightShift = 8;
result = buf[startByte] & firstByteMasks[bitoff % 8];
result = result << 8;
for ( int32_t i = startByte + 1; i <= endByte; i++ )
{
result |= buf[i];
result = result << 8;
}
result = result >> rightShift;
return (uint32_t)result;
}
Few notes: i tested the code and it seems to work just fine, however, there may be bugs. If i find any, i will update the code here. Also, there are probably better solutions!