apply checksum in c to a char - c

How do you apply checkksum to a char in c?

A checksum reduces a sequence of bits to a shorter sequence, such that a change to the larger sequence results in a random change to the shorter checksum.
A char is already quite small. To produce a checksum you will need a bitfield. Actually, you will need two, since one bitfield alone will be padded at least to a full byte.
struct twochars_checksum {
unsigned sum_a : CHAR_BIT / 2;
unsigned sum_b : CHAR_BIT / 2;
};
void sum_char( char c, struct twochars_checksum *dest, int which ) {
int sum;
sum = c ^ c >> CHAR_BIT / 2; // suboptimal, but passable
if ( which == 0 ) {
dest->sum_a = sum;
} else {
dest->sum_b = sum;
}
}

Suggest to follow similar approach to transfer a byte of data with checksum.
The algorithm for calculating checksum is quite simple and is as follows.
1.Check if the bit is on then add the corresponding bit value ( ie 2 to the power of bit position ) to the check sum.
2.If the bit is off then detect the sum by 1.
Note : You can use your own checksum algorithm by altering function calculate_checksum().
You can include your own processing logic in set_transfer_data().
#include <stdio.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#define NUM_BITS (8)
uint16_t calculate_checksum(const uint8_t data)
{
uint16_t checksum = 0;
uint8_t bit_index = 0;
uint8_t bit_value = 0;
while( bit_index < NUM_BITS )
{
bit_value = 1 << bit_index++;
checksum += ( data & bit_value ) ? bit_value : -1;
}
return ( checksum );
}
uint8_t set_transfer_data( uint32_t *dest_data , const uint8_t src_data , const uint16_t checksum )
{
uint8_t return_value = 0;
*dest_data = checksum << NUM_BITS | src_data ;
return ( return_value );
}
int main()
{
uint8_t return_value = 0;
uint8_t source_data = 0xF3;
uint32_t transfer_data = 0;
uint16_t checksum = 0;
checksum = calculate_checksum( source_data );
printf( "\nChecksum calculated = %x",checksum );
return_value = set_transfer_data( &transfer_data,source_data,checksum );
if( 0 == return_value )
{
printf( "\nChecksum added successfully; transfer_data = %x",
transfer_data );
}
else
{
printf( "\nError adding checksum" );
}
return ( 0 );
}

Related

How to set the values of an array to a single variable

I'm reading the values from a SD card in an ARM micro:
Res = f_read(&fil, (void*)buf, 6, &NumBytesRead);
where fil is a pointer, buf is a buffer where the data is stored.
And that's the problem: it's an array but I'd like to have the contents of that array in a single variable.
To give an actual example: the 6 bytes read from the file are:
buf[0] = 0x1B
buf[1] = 0x26
buf[2] = 0xB3
buf[3] = 0x54
buf[4] = 0xA1
buf[5] = 0xCF
And I'd like to have: uint64_t data be equal to 0x1B26B354A1CF. That is, all the elements of the array "concatenated" in one single 64 bit integer.
Without type punning you can do as below.
uint64_t data = 0;
for (int i=0; i<6; i++)
{
data <<= 8;
data |= (uint64_t) buf[i];
}
Use union but remember about the endianes.
union
{
uint8_t u8[8];
uint64_t u64;
}u64;
typedef union
{
uint8_t u8[8];
uint64_t u64;
}u64;
typedef enum
{
LITTLE_E,
BIG_E,
}ENDIANESS;
ENDIANESS checkEndianess(void)
{
ENDIANESS result = BIG_E;
u64 d64 = {.u64 = 0xff};
if(d64.u8[0]) result = LITTLE_E;
return result;
}
uint64_t arrayToU64(uint8_t *array, ENDIANESS e) // for the array BE
{
u64 d64;
if(e == LITTLE_E)
{
memmove(&d64, array, sizeof(d64.u64));
}
else
{
for(int index = sizeof(d64.u64) - 1; index >= 0; index--)
{
d64.u8[sizeof(d64.u64) - index - 1] = array[index];
}
}
return d64.u64;
}
int main()
{
uint8_t BIG_E_Array[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
ENDIANESS e;
printf("This system endianess: %s\n", (e = checkEndianess()) == BIG_E ? "BIG":"LITTLE");
printf("Punned uint64_t for our system 0x%lx\n", arrayToU64(BIG_E_Array, e));
printf("Punned uint64_t for the opposite endianess system 0x%lx\n", arrayToU64(BIG_E_Array, e == BIG_E ? LITTLE_E : BIG_E));
return 0;
}
To things to take care of here:
have the bytes be ordered correctly
read the six bytes into one 64bit integer
Issue 1 can be taken care of by storing the byte coming in in network byte order (Big Endian) into the 64 bit integer in host byte order by for example using the two marcos below:
/* below defines of htonll() and ntohll() are taken from this answer:
https://stackoverflow.com/a/28592202/694576
*/
#if __BIG_ENDIAN__
# define htonll(x) (x)
# define ntohll(x) (x)
#else
# define htonll(x) ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# define ntohll(x) ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
#endif
Issue 2 can be solved in multiple ways:
Extending your approach
#define BUFFER_SIZE (6)
...
assert(BUFFER_SIZE <= sizeof (uint64_t));
uint8_t buffer[BUFFER_SIZE];
FILE * pf = ...; /* open file here */
/* test if file has been opened successfully here */
... result = f_read(pf, buffer, BUFFER_SIZE, ...);
/* test result for success */
uint64_t number = 0;
memset(&number, buffer, BUFFER_SIZE)
number = ntohll(number);
Use "Type Punning" by using a union
union buffer_wrapper
{
uint8_t u8[sizeof (uint64_t)];
uint64_t u64;
}
Instead of
uint8_t buffer[BUFFER_SIZE];
use
union buffer_wrapper buffer;
and instead of
memcpy(&number, buffer, BUFFER_SIZE)
number = ntohll(number)
use
number = ntohll(buffer.u64)

How to write only 12 bits to a char array in C?

I'm trying to implement a FAT12 file system in which there's a FAT table data structure which is an unsigned char array. I need to write a function which given an array index would write a value to the next 12 bits (because it's FAT12) which is quite tricky because part of the value needs to go to one byte and the other part needs to go the half of the second byte.
This is the get value function I came up with:
//FAT is the unsigned char array
int GetFatEntry(int FATindex, unsigned char * FAT) {
unsigned int FATEntryCode; // The return value
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
if (FATindex % 2 == 1){ // If the index is odd
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode >>= 4; // Extract the high-order 12 bits
}
else{ // If the index is even
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode &= 0x0fff; // Extract the low-order 12 bits
}
return FATEntryCode;
}
I'm struggling to come up with the function which would set a value given a FATindex. I would appreciate any suggestions.
This seems to work. The data that should be written should be in the first 12 bits of data
void WriteFatEntry(int FATindex, unsigned char * FAT, unsigned char data[2]) {
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
unsigned char d;
if (FATindex % 2 != 0){ // If the index is odd
// Copy from data to d and e, and shift everything so that second half of
// e contains first half of data[1], and first half of e contains second
// half of data[0], while second half of d contains first half of data[0].
// First half of d contains a copy of first four bits in FAT[FatOffset]
// so that nothing changes when it gets written
unsigned char e=data[1];
e>>=4;
d=data[0];
e|=(d<<4) & 0b11110000;
d>>=4;
d |= FAT[FatOffset] & 0b11110000;
FAT[FatOffset]=d;
FAT[FatOffset+1] = e;
}
else{ // If the index is even
d = data[1] & 0b11110000;
d |= FAT[FatOffset+1] & 0b00001111;
FAT[FatOffset] = data[0];
FAT[FatOffset+1] = d;
}
}
#include <stdio.h>
#if 1 /* assuming MSB first */
#define MSB (idx)
#define LSB (idx+1)
#else /* assuming LSB first */
#define MSB (idx+1)
#define LSB (idx)
#endif
unsigned fat_getval(unsigned char * tab, unsigned num)
{
unsigned idx;
unsigned val;
idx = num + num/2;
val = (tab[MSB] <<8 ) + (tab[idx+1] ) ;
if (num %2 ==0) val >>= 4;
return val & 0xfff;
}
void fat_putval(unsigned char * tab, unsigned slot, unsigned val)
{
unsigned idx;
idx = slot + slot/2;
if (slot %2 ==0) { /* xyz_ */
val <<= 4;
val |= tab[LSB] & 0xf;
}
else { /* _xyz */
val |= (tab[MSB] & 0xf0) << 8;
}
tab[MSB] = val >>8;
tab[LSB] = val &0xff;
}
#undef MSB
#undef LSB
unsigned char fattable[] = "\x01\x23\x45\x67\x89\xab"; // 12 nibbles
int main(void)
{
unsigned idx, ret;
for (idx = 0; idx < 6; idx++) { // 6 bytes -> 12 nibbles */
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(0,0xabc):\n");
fat_putval(fattable, 0, 0xabc);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(3,0xdef):\n");
fat_putval(fattable, 3, 0xdef);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Get(0 to 4):\n");
for (idx = 0; idx < 4; idx++) { // 12 / 3 ~> 4 * 12bit entries
ret = fat_getval( fattable, idx);
printf("%u := %x\n", idx, ret );
}
printf("\n");
return 0;
}

Premultiplying image alpha efficiently

Load a 32bit image into a buffer and I then premultiply the color values with the corresponding alpha to use for blending.
The following works but I am wondering if there is a more efficient way of doing this, even if it only results in a good-enough approximation?
image data is a pointer of this type:
typedef struct rgba_pixel
{
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} rgba_pixel;
rgba_pixel * image_data;
for ( i = 0; i < length; i++ )
{
if ( image_data[i].a == 0 )
image_data[i].r = image_data[i].g = image_data[i].b = 0;
else if ( image_data[i].a < 255 )
{
alpha_factor = image_data[i].a / 255.0;
image_data[i].r = image_data[i].r * alpha_factor;
image_data[i].g = image_data[i].g * alpha_factor;
image_data[i].b = image_data[i].b * alpha_factor;
}
}
Given that your a, r, g and b components are unsigned char, you can improve performance by turning floating point multiplication to integer multiplication and use shr 8 (division by 256) instead of dividing by 255:
for ( i = 0; i < length; i++ )
{
if ( image_data[i].a == 0 )
image_data[i].r = image_data[i].g = image_data[i].b = 0;
else if ( image_data[i].a < 255 )
{
image_data[i].r = (unsigned short)image_data[i].r * image_data[i].a >> 8;
image_data[i].g = (unsigned short)image_data[i].g * image_data[i].a >> 8;
image_data[i].b = (unsigned short)image_data[i].b * image_data[i].a >> 8;
}
}
This will convert 1 fp division and 3 fp multiplications into 3 integer multiplications and 3 bit shifts.
Another improvement which can be done is using union struct for the pixel data:
typedef union rgba_pixel
{
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
uint32_t u32;
} rgba_pixel;
And then assigning zero to r, g and b at once:
//image_data[i].r = image_data[i].g = image_data[i].b = 0;
image_data[i].u32 = 0; //use this instead
According to https://godbolt.org/ with x86-64 gcc 7.2, the latter generates less instructions at -O3. Which of course may or may not be faster in practice.
Another thing to be considered is partial loop unrolling, i.e. processing multiple (for example 4) pixels per loop iteration. If you are guaranteed that your rows are multiples of 4 in width, you do it even without additional checks.

Best Way to Simulate Logic Gates in C?

Hi I was wondering if anyone would be able to explain to me what is the best path to take if I wanted to simulate logic gates in a c program?
Lets say for example I create a program and use command line arguments
AND GATE
[console]% yourProgram 11001010 11110000
<console>% 11000000
If anyone could explain to me what the best route is to start with, I would greatly appreciate it. This is the code I have so far...
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
if( argc >= 3){
int result = atoi(argv[1])&&atoi(argv[2]);
printf("Input 1 is %d\n",atoi(argv[1]));
printf("Input 2 is %d\n",atoi(argv[2]));
printf("Result is %c\n",result);
}
return 0;
In addition to the comment suggesting basic corrections, if you want to make it a bit more useful and flexible, you could calculate the most significant bit and then use that to format a simple binary print routine to examine your bitwise operation.
The primary concepts are taking the input as a string of binary digits and converting them to a number with strtoul (base 2), and then following &'ing the inputs together to obtain result it is just a matter of computing how many bytes to print out and whether to format a single byte into nibbles or simply separate multiple bytes.
#include <stdio.h>
#include <stdlib.h>
/* BUILD_64 */
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif
/* BITS_PER_LONG */
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
/* CHAR_BIT */
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
char *binstrfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep);
static __always_inline unsigned long msbfls (unsigned long word);
int main (int argc, char **argv) {
if ( argc < 3) {
fprintf (stderr, "error: insufficient input. usage: %s b1 b1\n", argv[0]);
return 1;
}
/* input conversion and bitwise operation */
unsigned long b1 = strtoul (argv[1], NULL, 2);
unsigned long b2 = strtoul (argv[2], NULL, 2);
unsigned long result = b1 & b2;
/* variables to use to set binary print format */
unsigned char msb, msbmax, width, sepwidth;
msb = msbmax = width = sepwidth = 0;
/* find the greatest most significant bit */
msbmax = (msb = msbfls (b1)) > msbmax ? msb : msbmax;
msbmax = (msb = msbfls (b2)) > msbmax ? msb : msbmax;
msbmax = (msb = msbfls (result)) > msbmax ? msb : msbmax;
msbmax = msbmax ? msbmax : 1;
/* set the number of bytes to print and the separator width */
width = (msbmax / CHAR_BIT + 1) * CHAR_BIT;
sepwidth = width > CHAR_BIT ? CHAR_BIT : CHAR_BIT/2;
/* print the output */
printf("\n Input 1 : %s\n", binstrfmt (b1, width, sepwidth, '-'));
printf(" Input 2 : %s\n", binstrfmt (b2, width, sepwidth, '-'));
printf(" Result : %s\n\n", binstrfmt (result, width, sepwidth, '-'));
return 0;
}
/** returns pointer to formatted binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binstrfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
static char s[2 * BITS_PER_LONG + 1] = {0};
char *p = s + 2 * BITS_PER_LONG;
unsigned char i;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (n >> i & 1) ? '1' : '0';
}
return p;
}
/* return the most significant bit (MSB) for the value supplied. */
static __always_inline unsigned long msbfls(unsigned long word)
{
if (!word) return 0;
int num = BITS_PER_LONG - 1;
#if BITS_PER_LONG == 64
if (!(word & (~0ul << 32))) {
num -= 32;
word <<= 32;
}
#endif
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
num -= 16;
word <<= 16;
}
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
num -= 8;
word <<= 8;
}
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
num -= 4;
word <<= 4;
}
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
num -= 2;
word <<= 2;
}
if (!(word & (~0ul << (BITS_PER_LONG-1))))
num -= 1;
return num;
}
Example Output
$ ./bin/andargs 11001010 11110000
Input 1 : 1100-1010
Input 2 : 1111-0000
Result : 1100-0000
$ ./bin/andargs 1100101011110000 1111000011001010
Input 1 : 11001010-11110000
Input 2 : 11110000-11001010
Result : 11000000-11000000
Use this code. (for AND operation):
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
if( argc >= 3){
int i=0;
printf("1st i/p = %s\n2nd i/p = %s\n",argv[1],argv[2]);
for (i=0; argv[1][i]!='\0'; i++){ //this assumes there are 2 inputs, of equal size, having bits(1,0) as its digits
argv[1][i] = argv[1][i] & argv[2][i]; //modifies argv[1] to your required answer
}
printf("Answer: %s\n",argv[1]);
}
return 0;
}

How to split a text file bit by bit into two files

How can I split a text file into two other files bit by bit. I need all the even numbered bits in file A and all the odd ones in B. In other words, if File X is:
0101010111110000
Then File A would be: 00001100
and B would be: 11111100
Then I need to save those as .txt files. After that, I will need to merge them back together to get X again.
I am using c.
The code I have so far is as follows:
#include <stdio.h>
void printchar( unsigned char to_print )
{
unsigned char mask = 0x80;
for( int i = 0; i < 8; ++i )
{
if( (mask & to_print) > 0 )
{
printf( "%d", 1 );
}
else
{
printf( "%d", 0 );
}
mask = mask >> 1;
}
printf( "\n" );
}
void split( unsigned char * left, unsigned char * right, unsigned char input1, unsigned char input2 )
{
unsigned char mask = 0x80;
for( int i = 0; i < 4; ++i )
{
(*left) |= ( (input1 & mask) << i );
(*left) |= ( (input2 & mask) >> (4-i) );
mask = mask >> 1;
(*right) |= ( (input1 & mask) << (i+1) );
(*right) |= ( (input2 & mask) >> (3-i) );
mask = mask >> 1;
}
}
int main (int argc, const char * argv[])
{
unsigned char left = 0;
unsigned char right = 0;
unsigned char input1 = 0xA6;
unsigned char input2 = 0xB5;
split( &left, &right, input1, input2 );
printchar( left );
printchar( right );
return 0;
}
read char by char
in youre code build two buffer chars one with even and other with odd bits
to fully build 2 chars you need to read 2 chars from file
when you have read 4 chars from input file you can write 2 chars you have built
and so one
for part to same approach but in reverse.
You should be careful with the order of reading /writing even/odd bits

Resources