Extract data from the frame using C - c

I have a function as follows:
union u_t
{
uint16_t u16;
uint8_t u8[2];
};
uint16_t Frame2Data(uint8_t *data,uint8_t startBit,uint16_t length)
{
uint16_t mask;
uint8_t start;
uint8_t firstByte,offset;
uint8_t numShift;
union u_t ut;
for(i=0;i<16;i++)
{
if(length == i)
mask|=(1<<i);
}
firstByte = startBit / 8;
offset = (firstByte+2) * 8;
start = startBit + length;
numShift = offset - start;
ut.u8[1] = data[firstByte];
ut.u8[0] = data[firstByte+1];
return (ut.u16 >> numShift) & mask;
}
The start bit is 46 and length is 7 and the data in 8 bytes is 0x00 0x09 0x03 0x84 0x03 0x70 0x02 0xA8 has to be passed. I have to extract the data with start bit 46 and upto a length of 7 bits and find out its value. I have a doubt with numbershift and is my function working correctly? It would be great if someone confirms this.Thanks in advance.

Your problem here, is the way in which you set your mask:
for(i=0;i<16;i++)
{
if(length == i)
mask|=(1<<i); /* BTW, mask is not initialized */
}
is simply equivalent to:
mask |= (1 << length);
which will set only one bit in you mask. So either you substruct one from mask after the for, or you set it directly:
#define UINT16_WIDTH 16
mask = (1u << (length & (UINT16_WIDTH - 1))) - 1u;

Related

CRC implementing a specific polynomial. How does the polynomial relate to the polynomial used in code?

I have the following CRC function:
#define CRC8INIT 0x00
#define CRC8POLY 0x18 //0X18 = X^8+X^5+X^4+X^0
// ----------------------------------------------------------------------------
uint8_t crc8 (uint8_t *data, uint16_t number_of_bytes_in_data)
{
uint8_t crc;
uint16_t loop_count;
uint8_t bit_counter;
uint8_t b;
uint8_t feedback_bit;
crc = CRC8INIT;
for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++) {
b = data[loop_count];
bit_counter = 8;
do {
feedback_bit = (crc ^ b) & 0x01;
if (feedback_bit == 0x01) {
crc = crc ^ CRC8POLY;
}
crc = (crc >> 1) & 0x7F;
if (feedback_bit == 0x01) {
crc = crc | 0x80;
}
b = b >> 1;
bit_counter--;
} while (bit_counter > 0);
}
return crc;
}
How does 0x18 relate to the polynomial X^8+X^5+X^4+X^0?
X^8+X^5+X^4+X^0 = 100110001
0x18 = 00011000
What if I define CRC8POLY as 0xEA instead (I have seen this), what polynomial would that represent?
How does 0x18 relate to the polynomial X^8+X^5+X^4+X^0?
Since the code is a right shifting CRC, the "most significant bit" of each byte is bit 0 instead of bit 7. The poly needs to be reversed from 100110001 to 100011001, which is 0x119, after the right shift, bit 0 of 0x119 is shifted off, so 0x118 can be used instead. The code uses a second if statement to or in (0x100) >> 1 == 0x80 if the feedback bit is 1. As an alternative, since feedback_bit is 0 or 1, then (0-feeback_bit) can be used as a mask (assuming two's complement math) for the poly instead of using an if statement.
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
#define CRC8INIT 0x00
#define CRC8POLY 0x8c // 0x119 >> 1
uint8_t crc8 (uint8_t *data, uint16_t number_of_bytes_in_data)
{
uint8_t crc;
uint16_t loop_count;
uint8_t bit_counter;
uint8_t b;
uint8_t feedback_bit;
crc = CRC8INIT;
for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++) {
b = data[loop_count];
bit_counter = 8;
do {
feedback_bit = (crc ^ b) & 0x01;
crc = (crc >> 1) ^ ((0-feedback_bit) & CRC8POLY);
b = b >> 1;
bit_counter--;
} while (bit_counter > 0);
}
return crc;
}
That CRC code is written rather oddly, where the polynomial is applied in two different places, breaking up the bits. That is, at crc = crc ^ CRCPOLY and conditionally crc = crc | 0x80. It would normally be written more like this:
unsigned crc8(unsigned char const *dat, size_t len) {
unsigned crc = 0;
for (size_t i = 0; i < len; i++) {
crc ^= dat[i];
for (int k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x8c : crc >> 1;
}
return crc;
}
where 0x8c is that polynomial reversed, without the x8 term.
Referring to Wiki article on CRC , it's crc8 realization as used in Dallas 1-wire chips. Note, that polinomial can be represented in Normal, Reversed, Reciprocal and Reversed reciprocal representations (see also Polynomial representations). Seems, that it is Reversed reciprocal representation with highest bit omitted.

How to pass hexadecimal data inside the following function

I have my following program that has a function that will extract the particular Bytes from a frame of 8 Bytes data and will give a corresponding value needed based on the start bit and bit length (length counted from the start bit).
How can i pass the data of 8 bytes which is in hexa decimal to my pointer *data in the main function.
For example this is my frame data in hexadecimal '05 00 00 00 00 03 E8 00'. Here is my program. Would be grat if someone help me to solve this. Should i take an array and pass the data as 0x05 0x00 0x00 0x00 0x00 0x03 0xE8 0x00 into the array and then give assign address of the array to the pointer variable? or just take a variable that holds 0x050000000003E800 and assign this address to the pointer.Are the both same? Thanks in advance.
union u_t
{
uint16_t u16;
uint8_t u8[2];
};
uint16_t Frame2Data(uint8_t *data,uint8_t startBit,uint16_t length)
{
uint16_t mask;
uint8_t start;
uint8_t firstByte,offset;
uint8_t numShift;
union u_t ut;
/*if(length == 8) //preliminary, has to be fixed by correct function.
mask = 0xff;*/
if(length == 7)
mask = 0x7F;
if(length == 10)
mask = 0x3ff;
if(length == 12)
mask = 0xfff;
firstByte = startBit / 8;
offset = (firstByte+2) * 8;
start = startBit + length;
numShift = offset - start;
ut.u8[1] = data[firstByte];
ut.u8[0] = data[firstByte+1];
return (ut.u16 >> numShift) & mask;
}
int main()
{
??????????
uint8_t sB = 46;
uint16_t l = 7;
uint16_t extractValue = Frame2Data(?,sB,l);
return 0;
}
To pass data written in hexadecimal to data, you can simply write:
uint8_t data [] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE8, 0x00};
Note that variable mask is uninitialized, because l is equal to 7 and all instructions to initialize variable mask are dead code, as show in red, with a source code analyzer:
https://taas.trust-in-soft.com/tsnippet/t/6d486c5b

Circular shift 28 bits within 4 bytes in C

I have an unsigned char *Buffer that contains 4 bytes, but only 28 of them are relevant to me.
I am looking to create a function that will do a circular shift of the 28 bits while ignoring the remaining 4 bits.
For example, I have the following within *Buffer
1111000011001100101010100000
Say I want to left circular shift by 1 bit of the 28 bits, making it
1110000110011001010101010000
I have looked around and I can't figure out how to get the shift, ignore the last 4 bits, and have the ability to shift either 1, 2, 3, or 4 bits depending on a variable set earlier in the program.
Any help with this would be smashing! Thanks in advance.
Only 1 bit at a time, but this does a 28 bit circular shift
uint32_t csl28(uint32_t value) {
uint32_t overflow_mask = 0x08000000;
uint32_t value_mask = 0x07FFFFFF;
return ((value & value_mask) << 1) | ((value & overflow_mask) >> 27);
}
uint32_t csr28(uint32_t value) {
uint32_t overflow_mask = 0x00000001;
uint32_t value_mask = 0x0FFFFFFE;
return ((value & value_mask) >> 1) | ((value & overflow_mask) << 27);
}
Another version, based on this article. This shifts an artbitrary number of bits (count) within an arbitrarily wide bit field (width). To left shift a value 5 bits in a 23 bit wide field: rotl32(value, 5, 23);
uint32_t rotl32 (uint32_t value, uint32_t count, uint32_t width) {
uint32_t value_mask = ((uint32_t)~0) >> (CHAR_BIT * sizeof(value) - width);
const uint32_t mask = (width-1);
count &= mask;
return value_mask & ((value<<count) | (value>>( (-count) & mask )));
}
uint32_t rotr32 (uint32_t value, uint32_t count, uint32_t width) {
uint32_t value_mask = ((uint32_t)~0) >> (CHAR_BIT * sizeof(value) - width);
const uint32_t mask = (width-1);
count &= mask;
return value_mask & ((value>>count) | (value<<( (-count) & mask )));
}
The above functions assume the value is stored in the low order bits of "value"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
const char *uint32_to_binary(uint32_t x)
{
static char b[33];
b[0] = '\0';
uint32_t z;
for (z = 0x80000000; z > 0; z >>= 1)
{
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
uint32_t reverse(uint32_t value)
{
return (value & 0x000000FF) << 24 | (value & 0x0000FF00) << 8 |
(value & 0x00FF0000) >> 8 | (value & 0xFF000000) >> 24;
}
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
int main(int argc, char** argv) {
char b[] = { 0x98, 0x02, 0xCA, 0xF0 };
char *buffer = b;
//uint32_t num = 0x01234567;
uint32_t num = *((uint32_t *)buffer);
if (!is_big_endian()) {
num = reverse(*((uint32_t *)buffer));
}
num >>= 4;
printf("%x\n", num);
for(int i=0;i<5;i++) {
printf("%s\n", uint32_to_binary(num));
num = rotl32(num, 3, 28);
}
for(int i=0;i<5;i++) {
//printf("%08x\n", num);
printf("%s\n", uint32_to_binary(num));
num = rotr32(num, 3, 28);
}
unsigned char out[4];
memset(out, 0, sizeof(unsigned char) * 4);
num <<= 4;
if (!is_big_endian()) {
num = reverse(num);
}
*((uint32_t*)out) = num;
printf("[ ");
for (int i=0;i<4;i++) {
printf("%s0x%02x", i?", ":"", out[i] );
}
printf(" ]\n");
}
First you mask the top four most significant bits
*(buffer + 3) &= 0x0F;
Then you can perform the circular shift of the remaining 28 bits by x bits.
Note: This will work for little endian architecture(x86 Pc's and most microcontrollers)
[...] that contains 4 bytes, but only 28 of them [...]
We got it, but...
I guess that you mis-typed the second number of your example. Or you '''ignore''' 4 bits from left and right so you're actually interrested in 24 bits? Anyway:
Use same principle as in
Circular shift in c.
You need to convert your Buffer to a 32 bit arithmetic type, before. Maybe uint32_t is what you need?
Where did Buffer get his value? You may need to think about endianness.

CRC Calculation in C

I have a device, which sends me Data with CRC Calculation.
Every 16 Bytes there are 2 CRC Bytes.
The generator polynomial is x16 + x13 + x12 + x11 + x10 + x8 + x6 + x5 + x2 + 1
My code looks like this:
int crc16(unsigned char *addr, int num, int crc)
{
uint16_t poly = 0x3D65;
int i;
for (; num > 0; num--) /* Step through bytes in memory */
{
crc = crc ^ ((unsigned short)*addr++ << 8); /* Fetch byte from memory, XOR into CRC top byte*/
for (i = 0; i < 8; i++) /* Prepare to rotate 8 bits */
{
if (crc & 0x10000) /* b15 is set... */
crc = (crc << 1) ^ poly; /* rotate and XOR with XMODEM polynomic */
else /* b15 is clear... */
crc <<= 1; /* just rotate */
} /* Loop for 8 bits */
crc &= 0xFFFF; /* Ensure CRC remains 16-bit value */
} /* Loop until num=0 */
return(crc); /* Return updated CRC */
}
I've also tried this code with other polynomials like 0x9CB2. I think there's an error located in the code.
Which compiler/platform are you using? Are you sure the int datatype is 32 bits? Try it with long and compare the results.
Also, there is a point in which you make the following if:
if ( crc & 0x10000 )
and in the comment you state that you are verifying the 15th bit. No, that's not true, you will be verifying the 16th bit. For the 15th it would be ( crc & 0x8000 ).

How to circular shift an array of 4 chars?

I have an array of four unsigned chars. I want to treat it like a 32-bit number (assume the upper bits of the char are don't care. I only care about the lower 8-bits). Then, I want to circularly shift it by an arbitrary number of places. I've got a few different shift sizes, all determined at compile-time.
E.g.
unsigned char a[4] = {0x81, 0x1, 0x1, 0x2};
circular_left_shift(a, 1);
/* a is now { 0x2, 0x2, 0x2, 0x5 } */
Edit: To everyone wondering why I didn't mention CHAR_BIT != 8, because this is standard C. I didn't specify a platform, so why are you assuming one?
static void rotate_left(uint8_t *d, uint8_t *s, uint8_t bits)
{
const uint8_t octetshifts = bits / 8;
const uint8_t bitshift = bits % 8;
const uint8_t bitsleft = (8 - bitshift);
const uint8_t lm = (1 << bitshift) - 1;
const uint8_t um = ~lm;
int i;
for (i = 0; i < 4; i++)
{
d[(i + 4 - octetshifts) % 4] =
((s[i] << bitshift) & um) |
((s[(i + 1) % 4] >> bitsleft) & lm);
}
}
Obviously
While keeping in mind plain C the best way is
inline void circular_left_shift(char *chars, short shift) {
__int32 *dword = (__int32 *)chars;
*dword = (*dword << shift) | (*dword >> (32 - shift));
}
Uhmm, char is 16 bits long, was not clear for me. I presume int is still 32 bit.
inline void circular_left_shift(char *chars, short shift) {
int i, part;
part = chars[0] >> (16 - shift);
for (i = 0; i < 3; ++i)
chars[i] = (chars[i] << shift) | (chars[i + 1] >> (16 - shift));
chars[3] = (chars[3] << shift) | part;
}
Or you could just unwind this cycle.
You could dig further into asm instruction ror, on x86 it's capable of performing such shift up to 31 bits left. Something like a
MOV CL, 31
ROR EAX, CL
Use union:
typedef union chr_int{
unsigned int i;
unsigned char c[4];
};
It's safer (because of pointer aliasing) and easier to manipulate.
EDIT: you should have mention earlier that your char isn't 8 bits. However, this should do the trick:
#define ORIG_MASK 0x81010102
#define LS_CNT 1
unsigned char a[4] = {
((ORIG_MASK << LS_CNT ) | (ORIG_MASK >> (32 - LS_CNT))) & 0xff,
((ORIG_MASK << (LS_CNT + 8)) | (ORIG_MASK >> (24 - LS_CNT))) & 0xff,
((ORIG_MASK << LS_CNT + 16)) | (ORIG_MASK >> (16 - LS_CNT))) & 0xff,
((ORIG_MASK << (LS_CNT + 24)) | (ORIG_MASK >> ( 8 - LS_CNT))) & 0xff
};

Resources