Scenario:
[Node A] < -------- Rf-interface ------> [Node B]
question:
Node A send a payload to Node B which is 6 bytes long. In this payload there is some information regarding available slots e.g. there are in total 6 bytes * 8 bits = 48 slots. Each slot can be either ON 1 or OFF 0.
For an example, then these slot numbers 0,2,5,7 are all ON. The bit representation of the payload will be:
10100101000000000 .... till the 48th bit.
These information are then send to Node B in the payload over the RF-interface.
At Node B, I need to convert the position of each bit representation in to decimal representation in an array (for some gui representation).
back to the example:
I need to convert the payload with the bits: 10100101000000000... into active slots presentation in an array: e.g.
myArray[0] = 1;
myArray[1] = 0;
myArray[2] = 1;
myArray[3] = 0;
myArray[4] = 0;
myArray[5] = 1;
.
.
myArray[48] = x;
I am not good in bit mask, so any help wold be appreciated
Thanks for all help!
How about this?:
char *bitsToArray(char *data, int length)
{
char *rv = malloc(8*length);
int i = 0;
for(;i < length; ++i)
{
int j = 0;
for(; j < 8; ++j)
{
rv[i*8+j] = (data[i]>>j)&1;
}
}
return rv;
}
It stores the least significant bit first. If you would like it to work in opposite bit order, you can change the line rv[i*8+j] = (data[i]>>j)&1; to rv[i*8+j] = (data[i]>>(7-j))&1;
Based on your example, I'm assuming the bitmap, the given 6-byte array is:
unsigned char bitmap[6] = {0xa5, 0x00, 0x00, 0x00, 0x00, 0x00};
And the results are destined for:
int myArray[48];
I would be inclined to loop through myArray from back to front and assign each value based on a test of the lowest order bit in the bitmap, then shift right for each loop iteration.
int bmi = 5; // set bitmap index to end
int mai = 47; // set myArray index to end
int i = 0;
while (mai >= 0) {
for (i = 0; i < 8; i++) {
myArray[mai] = bitmap[bmi] & 0x01;
bitmap[bmi] >>= 1;
--mai;
}
--bmi;
}
for (mai = 0; mai < 48; mai++) printf("%d", myArray[mai]);
printf("\n");
for (int i = 0; i < buffer_size; i++) {
for (int j = 7; j >= 0; j--) { // most significant bit first
myArray[8 * i + j] = buffer[i] >> j & 1;
}
}
Related
I'm developing a gameboy game in GBDK but I've got a problem with right-shifting (8bit) unsigned variables. The code looks like this.
#include <gb/gb.h>
#include <stdio.h>
#define GAME_OBJ_MAX_WIDTH 10
#define GAME_OBJ_MAX_HEIGHT 8
struct game_obj
{
UBYTE matrix[GAME_OBJ_MAX_WIDTH];
UBYTE width, height;
};
void draw_game_obj(struct game_obj *object)
{
for (unsigned char i = 0; i < object->width && i < GAME_OBJ_MAX_WIDTH; i++)
{
printf("BASE->%d\n", object->matrix[i]);
for (unsigned char j = 0; j < object->height && j < GAME_OBJ_MAX_HEIGHT; j++)
printf("Shift by %d->%u\n", j, object->matrix[i] >> j);
}
}
void main() {
struct game_obj racer;
racer.height = 4;
racer.width = 3;
racer.matrix[0] = 10;
racer.matrix[1] = 7;
racer.matrix[2] = 10;
draw_game_obj(&racer);
}
The output is:
BASE->10
Shift by 0->235
Shift by 1->117
Shift by 2->58
Shift by 3->29
BASE->7
Shift by 0->235
Shift by 1->117
Shift by 2->58
Shift by 3->29
BASE->10
Shift by 0->235
Shift by 1->117
Shift by 2->58
Shift by 3->29
Basically any unsigned value right shifted (even by 0) changes to 235, 117, 58 and so on... I'm trying to understand why is that.
Solution
Issue fixed by assigning object->matrix[i] to separate variable.
void draw_game_obj(struct game_obj *object)
{
for (unsigned char i = 0; i < object->width && i < GAME_OBJ_MAX_WIDTH; i++)
{
printf("BASE->%d\n", object->matrix[i]);
UBYTE u = object->matrix[i];
for (unsigned char j = 0; j < object->height && j < GAME_OBJ_MAX_HEIGHT; j++)
printf("Shift by %d->%u\n", j, u >> j);
}
}
I have matrix of '1' and '0' with the dimensions 8x8. I need to store the whole matrix in one unsigned long long variable bit by bit. How can i do that?
For example, let's take the matrix of '1' and '0' that is 2x2:
The matrix 2x2:
1 0
0 1
The variable must contain: 1001 in bits.
The same example, but over the matrix 8x8 and unsigned long long variable.
That's what i've tried to do:
#include <stdio.h>
int main()
{
unsigned long long result = 0;
char matrix[8][8]; // lets that the matrix is already filled by '1' and '0'
for (i=0; i<SIZE; i++)
{
for (j=0; j<SIZE; j++)
{
result = result | ((unsigned long long)(matrix[i][j] - '0'));
result <<= 1;
}
}
return 0;
}
Is it right? I implemented this nested loop in my algorithm and that didn't work properly.
Converting the text representation of an integer into its integer value can be done using strtoull().
char buf[sizeof(matrix)+1];
memcpy(buf, matrix, sizeof(matrix));
buf[sizeof(matrix)] = '\0';
result = strtoull(buf, NULL, 2);
try this
const int mx_size = 8;
int main() {
unsigned long long result = 0;
bool matrix[8][8]; // lets that the matrix is already filled by '1' and '0'
for (int i =0; i < mx_size; ++i)
matrix[i][i] = 1;
for (int i = 0; i < mx_size; i++) {
for (int j = 0; j < mx_size; j++) {
result |= (unsigned long long)matrix[i][j] << (i*mx_size + j);
}
}
return 0;
}
Here you have the code (a bit more
#include <stdio.h>
#include <stdint.h>
uint64_t convert(char matrix[8][8], int order, char zero)
{
uint8_t byte;
uint64_t result = 0;
for(size_t row = 0; row < 8; row++)
{
byte = 0;
for(size_t column = 0; column < 8; column++)
{
byte <<= 1;
byte |= matrix[row][column] != zero ? 1 : 0; //anything != defined zero char is 1
}
if (order)
{
result |= (uint64_t)byte << (8 * row);
}
else
{
result |= (uint64_t)byte << (56 - 8 * row);
}
}
return result;
}
int main(void) {
char matrix[8][8] =
{
{'1','0','1','0','1','0','1','0'},
{'0','1','0','1','0','1','0','1'},
{'1','1','1','0','0','0','1','1'},
{'0','0','0','1','1','1','0','0'},
{'1','1','1','1','1','0','0','0'},
{'0','0','0','0','1','1','1','1'},
{'1','1','0','0','1','1','0','0'},
{'0','0','1','1','0','0','1','1'},
};
unsigned long long result = convert(matrix, 0, '0');
for(size_t index = 0; index < 64; index ++)
printf("%1d", !!(result & (1ULL << index)));
printf("\n");
result = convert(matrix,1, '0');
for(size_t index = 0; index < 64; index ++)
printf("%1d", !!(result & (1ULL << index)));
printf("\n");
return 0;
}
This question already has answers here:
How can I convert an integer to a hexadecimal string in C?
(7 answers)
Closed 5 years ago.
I have these input variables:
uint16 temperature = 0x1f12;
uint8 array[8] = {0,0,0,...0}
And I want to have
array8[0] = '1';
array8[1] = 'f';
array8[2] = '1';
array8[3] = '2';
array8[4] = '\0';
array8[5] = '\0';
array8[6] = '\0';
array8[7] = '\0';
However, for memory problems (I'm working with microcontrollers!) I need to avoid functions such as sprintf, printf, puts, etc.
How should I do?
Best regards,
Use recursion to determine 1 hex digit at a time.
// print digit at the end and return the next address
static char *itohexa_helper(char *dest, unsigned x) {
if (x >= 16) {
dest = itohexa_helper(dest, x/16);
}
*dest++ = "0123456789abcdef"[x & 15];
return dest;
}
char *itohexa(char *dest, unsigned x) {
*itohexa_helper(dest, x) = '\0';
return dest;
}
int main(void) {
char array[8];
uint16_t temperature = 0x1f11;
puts(itohexa(array, temperature));
puts(itohexa(array, 0));
puts(itohexa(array, 0x1234567));
puts(itohexa(array, UINT_MAX & 0xFFFFFFF));
}
Output
1f11
0
1234567
fffffff
This code uses only 8 additional bytes in stack(int i, j).
int i;
for (i = 0; i < 8; i++) {
array[7 - i] = temperature % 16;
temperature /= 16;
if (temperature == 0)
break;
}
if (i == 8)
i--;
int j;
for (j = 0; j <= i; j++)
array[j] = array[7 - i + j];
for (j = i + 1; j < 8; j++)
array[j] = 0;
for (j = 0; j < 8; j++)
if (array[j] < 10)
array[j] += '0';
else
array[j] += 'a' - 10;
This code first converts temperature = 0x1f12 to array[8] = { 0, 0, 0, 0, 1, 15, 1, 2}.
Then shifts the elements of array so that it becomes array[8] = { 1, 15, 1, 2, 0, 0, 0, 0 }.
And then converts the numbers to corresponding characters: array[8] = { '1', 'f', '1', '2', '0', '0', '0', '0' }.
Note also that this if condition
if (i == 8)
i--;
is never met, since break condition always suffices in the first for loop, even for temperature >= 0x10000000. It's just there in the hope that it might help someone understand this code.
int convert()
{
uint16_t temperature = 0x1f11;
uint8_t array[8] = {0,0,0,0,0,0,0,0};
int i = 0;
for(i = 0; i < 8; i++){
array[i] = (0xf000 & temperature) >> 12 ;
temperature <<= 4;
printf("array[%d] = %x\n", i ,array[i]);
}
return(0);
}
I have spent more 10hr+ on trying to sort the following(hexadecimals) in LSD radix sort, but no avail. There is very little material on this subject on web.
0 4c7f cd80 41fc 782c 8b74 7eb1 9a03 aa01 73f1
I know I have to mask and perform bitwise operations to process each hex digit (4 bits), but have no idea on how and where.
I'm using the code (I understand) from GeeksforGeeks
void rsort(int a[], int n) {
int max = getMax(a, n);
for (int exp = 1; max / exp > 0; exp *= 10) {
ccsort(a, n, exp);
}
}
int getMax(int a[], int n) {
int max = a[0];
int i = 0;
for (i = 0; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
void ccsort(int a[], int n, int exp) {
int count[n];
int output[n];
int i = 0;
for (i = 0; i < n; i++) {
count[i] = 0;
output[i] = 0;
}
for (i = 0; i < n; i++) {
++count[(a[i] / exp) % 10];
}
for (i = 1; i <= n; i++) {
count[i] += count[i - 1];
}
for (i = n - 1; i >= 0; i--) {
output[count[(a[i] / exp) % 10] - 1] = a[i];
--count[(a[i] / exp) % 10];
}
for (i = 0; i < n; i++) {
a[i] = output[i];
}
}
I have also checked all of StackOverFlow on this matter, but none of them covers the details.
Your implementation of radix sort is slightly incorrect:
it cannot handle negative numbers
the array count[] in function ccsort() should have a size of 10 instead of n. If n is smaller than 10, the function does not work.
the loop for cumulating counts goes one step too far: for (i = 1; i <= n; i++). Once again the <= operator causes a bug.
you say you sort by hex digits but the code uses decimal digits.
Here is a (slightly) improved version with explanations:
void ccsort(int a[], int n, int exp) {
int count[10] = { 0 };
int output[n];
int i, last;
for (i = 0; i < n; i++) {
// compute the number of entries with any given digit at level exp
++count[(a[i] / exp) % 10];
}
for (i = last = 0; i < 10; i++) {
// update the counts to have the index of the place to dispatch the next
// number with a given digit at level exp
last += count[i];
count[i] = last - count[i];
}
for (i = 0; i < n; i++) {
// dispatch entries at the right index for its digit at level exp
output[count[(a[i] / exp) % 10]++] = a[i];
}
for (i = 0; i < n; i++) {
// copy entries batch to original array
a[i] = output[i];
}
}
int getMax(int a[], int n) {
// find the largest number in the array
int max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
void rsort(int a[], int n) {
int max = getMax(a, n);
// for all digits required to express the maximum value
for (int exp = 1; max / exp > 0; exp *= 10) {
// sort the array on one digit at a time
ccsort(a, n, exp);
}
}
The above version is quite inefficient because of all the divisions and modulo operations. Performing on hex digits can be done with shifts and masks:
void ccsort16(int a[], int n, int shift) {
int count[16] = { 0 };
int output[n];
int i, last;
for (i = 0; i < n; i++) {
++count[(a[i] >> shift) & 15];
}
for (i = last = 0; i < 16; i++) {
last += count[i];
count[i] = last - count[i];
}
for (i = 0; i < n; i++) {
output[count[(a[i] >> shift) & 15]++] = a[i];
}
for (i = 0; i < n; i++) {
a[i] = output[i];
}
}
void rsort16(int a[], int n) {
int max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
for (int shift = 0; (max >> shift) > 0; shift += 4) {
ccsort16(a, n, shift);
}
}
It would be approximately twice as fast to sort one byte at a time with a count array of 256 entries. It would also be faster to compute the counts for all digits in one pass, as shown in rcgldr's answer.
Note that this implementation still cannot handle negative numbers.
There's a simpler way to implement a radix sort. After checking for max, find the lowest power of 16 >= max value. This can be done with max >>= 4 in a loop, incrementing x so that when max goes to zero, then 16 to the power x is >= the original max value. For example a max of 0xffff would need 4 radix sort passes, while a max of 0xffffffff would take 8 radix sort passes.
If the range of values is most likely to take the full range available for an integer, there's no need to bother determining max value, just base the radix sort on integer size.
The example code you have shows a radix sort that scans an array backwards due to the way the counts are converted into indices. This can be avoided by using an alternate method to convert counts into indices. Here is an example of a base 256 radix sort for 32 bit unsigned integers. It uses a matrix of counts / indices so that all 4 rows of counts are generated with just one read pass of the array, followed by 4 radix sort passes (so the sorted data ends up back in the original array). std::swap is a C++ function to swap the pointers, for a C program, this can be replaced by swapping the pointers inline. t = a; a = b; b = t, where t is of type uint32_t * (ptr to unsigned 32 bit integer). For a base 16 radix sort, the matrix size would be [8][16].
// a is input array, b is working array
uint32_t * RadixSort(uint32_t * a, uint32_t *b, size_t count)
{
size_t mIndex[4][256] = {0}; // count / index matrix
size_t i,j,m,n;
uint32_t u;
for(i = 0; i < count; i++){ // generate histograms
u = a[i];
for(j = 0; j < 4; j++){
mIndex[j][(size_t)(u & 0xff)]++;
u >>= 8;
}
}
for(j = 0; j < 4; j++){ // convert to indices
m = 0;
for(i = 0; i < 256; i++){
n = mIndex[j][i];
mIndex[j][i] = m;
m += n;
}
}
for(j = 0; j < 4; j++){ // radix sort
for(i = 0; i < count; i++){ // sort by current lsb
u = a[i];
m = (size_t)(u>>(j<<3))&0xff;
b[mIndex[j][m]++] = u;
}
std::swap(a, b); // swap ptrs
}
return(a);
}
void int_radix_sort(void) {
int group; //because extracting 8 bits
int buckets = 1 << 8; //using size 256
int map[buckets];
int mask = buckets - 1;
int i;
int cnt[buckets];
int flag = NULL;
int partition;
int *src, *dst;
for (group = 0; group < 32; group += 8) {
// group = 8, number of bits we want per round, we want 4 rounds
// cnt
for (int i = 0; i < buckets; i++) {
cnt[i] = 0;
}
for (int j = 0; j < n; j++) {
i = (lst[j] >> group) & mask;
cnt[i]++;
tmp[j] = lst[j];
}
//map
map[0] = 0;
for (int i = 1; i < buckets; i++) {
map[i] = map[i - 1] + cnt[i - 1];
}
//move
for (int j = 0; j < n; j++) {
i = (tmp[j] >> group) & mask;
lst[map[i]] = tmp[j];
map[i]++;
}
}
}
After hours of researching I came across the answer. I'm still do not understand what is going on in this code/answer. I cannot get my head wrapped around the concept. Hopefully, someone can explain.
I see your points. I think negative numbers are easy to sort after the list has been sorted with something like loop, flag, and swap. wb unsigned float points? – itproxti Nov 1 '16 at 16:02
As for handling floating points there might be a way, for example 345.768 is the number, it needs to be converted to an integer, i.e. make it 345768, I multiplied 1000 with it. Just like the offset moves the -ve numbers to +ve domain, so will multiplying by 1000, 10000 etc will turn the floats to numbers with their decimal part as all zeros. Then they can be typecasted to int or long. However with large values, the whole reformed number may not be accomodated within the entire int or long range.
The number that is to be multiplied has to be constant, just like the offset so that the relationship among the magnitudes is preserved. Its better to use powers of 2 such as 8 or 16, as then bitshifting operator can be used. However just like the calculation of offset takes some time, so will calculation of the multiplier will take some time. The whole array is to be searched to calculate the least number that when multiplied will turn all the numbers with zeros in decimal parts.
This may not compute fast but still can do the job if required.
I have an array with 16 elements. I would like to evaluate these to a boolean 0 or 1 and then store this in 2 bytes so i can write to a binary file. How do I do this?
Something like this you mean?
unsigned short binary = 0, i;
for ( i = 0; i < 16; ++i )
if ( array[i] )
binary |= 1 << i;
// the i-th bit of binary is 1 if array[i] is true and 0 otherwise.
You have to use bitwise operators.
Here's an example:
int firstBit = 0x1;
int secondBit = 0x2;
int thirdBit = 0x4;
int fourthBit = 0x8;
int x = firstBit | fourthBit; /*both the 1st and 4th bit are set */
int isFirstBitSet = x & firstBit; /* Check if at least the first bit is set */
int values[16];
int i;
unsigned short word = 0;
unsigned short bit = 1;
for (i = 0; i < 16; i++)
{
if (values[i])
{
word |= bit;
}
bit <<= 1;
}
This solution avoid the use of the if inside the loop:
unsigned short binary = 0, i;
for ( i = 0; i < 16; ++i )
binary |= (array[i] != 0) << i;
Declare an array result with two bytes, then you loop through the source array:
for (int i = 0; i < 16; i++) {
// calclurate index in result array
int index = i >> 3;
// shift value in result
result[index] <<= 1;
// check array value
if (theArray[i]) {
// true, so set lowest bit in result byte
result[index]++;
}
}
Something like this.
int values[16];
int bits = 0;
for (int ii = 0; ii < 16; ++ii)
{
bits |= (!!values[ii]) << ii;
}
unsigned short output = (unsigned short)bits;
the expression (!!values[ii]) forces the value to be 0 or 1, if you know for sure that the values array already contains either a 0 or a 1 and nothing else, you can leave of the !!
You could also do this if you don't like the !! syntax.
int values[16];
int bits = 0;
for (int ii = 0; ii < 16; ++ii)
{
bits |= (values[ii] != 0) << ii;
}
unsigned short output = (unsigned short)bits;