What of lack this CRC-CCITT (Initial Value 0xFFFF) Encode? - c

I'm create CRC-CCITT Encode (Polynomail 0x1021 and Initial Value is 0xFFFF)
It is correct 8bit, 16bit, 24bit, 32bit ... (1 Byte, 2Byte, 3Byte ...)
But not correct answer 12bit, 20bit, 28bit (not Byte)
I find this algorithm
function crc(bit array bitString[1..len], int polynomial) {
shiftRegister := initial value // 00000000 OR 11111111
for i from 1 to len {
if (shiftRegister top bit) xor bitString[i] = 1
shiftRegister := (shiftRegister left shift 1) xor polynomial
else
shiftRegister := shiftRegister left shift 1
}
return shiftRegister
}
and my source code is like that
// crc_ccitt.h
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
static const char CRC_CCITT[] = "0001000000100001";
static char Shift_Register[] = "1111111111111111";
char* getCRC(char *, int);
void leftShift(char *);
void xorCalc();
char* getCRC(char* dataCode, int dataCodeLength) {
int i;
for (i = 0; i < dataCodeLength; i++) {
if ((Shift_Register[0] == '1' && dataCode[i] == '0')
|| (Shift_Register[0] == '0' && dataCode[i] == '1')) {
leftShift(Shift_Register);
xorCalc();
} else {
leftShift(Shift_Register);
}
printf("%c%c%c%c ", Shift_Register[0], Shift_Register[1], Shift_Register[2], Shift_Register[3]);
printf("%c%c%c%c ", Shift_Register[4], Shift_Register[5], Shift_Register[6], Shift_Register[7]);
printf("%c%c%c%c ", Shift_Register[8], Shift_Register[9], Shift_Register[10], Shift_Register[11]);
printf("%c%c%c%c ", Shift_Register[12], Shift_Register[13], Shift_Register[14], Shift_Register[15]);
printf("\n");
}
return Shift_Register;
}
void leftShift(char *Shift_Register) {
memmove(Shift_Register, Shift_Register + 1, strlen(Shift_Register) - 1);
memset(Shift_Register + strlen(Shift_Register) - 1, '0', 1);
}
void xorCalc() {
int i;
for (i = 0; i < 16; ++i) {
if ((Shift_Register[i] == '1' && CRC_CCITT[i] == '0')
|| (Shift_Register[i] == '0' && CRC_CCITT[i] == '1')) {
Shift_Register[i] = '1';
} else {
Shift_Register[i] = '0';
}
}
}
// crc_ccitt.c
#include "crc_ccitt.h"
int main() {
char dataCode[256];
char *CRC = "";
printf("Input Data Code: ");
gets(dataCode);
/*
puts(dataCode);
rightShift(dataCode);
puts(dataCode);
*/
CRC = getCRC(dataCode, strlen(dataCode));
//printf("%s", CRC);
return 0;
}
I confirm CRC Encode value with this page
http://www.lammertbies.nl/comm/info/crc-calculation.html
For example
Input 0001111111110010(1FF2)
page : C11F
my program : 1100 0001 0001 1111 (C11F)
But
Input 000111111111 (1FF)
page : FFAD
my program : 1101 0011 0000 1111 (D30F)
What of lack of my program??
Or, is algorithm is wrong??

Program OK
Algorithm OK
User input is likely the error.
Your CRC "0001000000100001" is for a 16-bit operation.
Your failed input is "000111111111", 12 bits.
Instead try using "0000000111111111" or "0001111111110000" (pad on the left or right)
Note: I would have tried it myself but you did not provide crc_ccitt.h

Related

I am not getting the byte values?

I'm not able to get the right output when I do the following code. look at the comments for what I'm trying to print.
I did the code based on what I've been learning so far, but I'm still not getting the right output.
So any suggestions? What have I done, so I'm able to fix the problem.
When I print(A), I'm not getting 0100 0001, but it prints 49d or 49 sometimes
#include <stdio.h>
unsigned char getBit(unsigned char c, int n)
{
return ((c & (1 << n)) >> n);
}
unsigned char setBit(unsigned char c, int n)
{
c = c | (1 << n);
return c;
}
unsigned char clearBit(unsigned char c, int n)
{
c = c & (~(1 << n));
return c;
}
void printBits(unsigned char c)
{
printf("The bit of the character you inputed is %x \n", c);
}
int main(void)
{
unsigned char a = 'A';
printBits(a);
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); //should print 0100 0001, but it prints 49
putchar('\n');
a = clearBit(a, 2);
printBits(a);
putchar('\n');
}
Your current solution prints the value of c as a hexadecimal number using printf(). Since there is no printf format specifier to print a number in binary representation, we'll have to write our own solution.
#include <limits.h>
#include <stdio.h>
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) { // count from the with of a char
// in bits down to 1
putchar(c & 1 << --i // test the i-th bit (1-based)
? '1' // if true (different form 0) evaluates to '1'
: '0' // else evaluates to '0'
);
if (CHAR_BIT == 8 && i % 4 == 0) // if we use 8-bit-bytes and just
// finished printing the higher nibble
putchar(' '); // insert a seperator between the nibbles
}
}
... ftw!
No-nonsense version:
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) {
putchar(c & 1 << --i ? '1' : '0');
if (CHAR_BIT == 8 && !(i % 4))
putchar(' ');
}
}
`
unsigned char a = 'A';
printBits(a); // should print 0100 0001
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); // should print 0100 1101
putchar('\n');
a = clearBit(a, 2);
printBits(a); // should print 0100 1001
putchar('\n'

int to bitstring function to handle negative numbers

How would I change this function to handle negative numbers? It correctly outputs everything but it does not make the leading bit 1 when negative. I can't do a negative check then simply force the first bit to be 1 because the amount of 0s between the leading bit and rest of the numbers will be off.
char* fromInt(int bin){
static char str[33];
str[1] = '\0';
int n;
for (n = 128; n > 0; n >>= 1){
if( (bin & n) == n){
strcat(str, "1");
}else{
strcat(str, "0");
}
}
return str;
}
I guess what you want is:
char* fromInt(int bin)
{
static char str[33];
str[0] = '0' + ((bin & 0x80000000) == 0x80000000);
str[1] = '\0';
for (int n = 0x40000000; n > 0; n >>= 1) {
if ((bin & n) == n)
strcat(str, "1");
else
strcat(str, "0");
}
return str;
}
The function has two steps. First is to determine the setting of sign bit (assuming that int object has 32 bits and it uses two's complement arithmetic):
(bin & 0x80000000) == 0x80000000
yields either 1 or 0. Because it's about the sign, It might have been written simply as:
'0' + (bin < 0)
The second step is to loop over remaining bits from position 30 to 0, like in the original code.
Here is an example program:
int main(void)
{
printf("%s\n", fromInt(0));
printf("%s\n", fromInt(1536));
printf("%s\n", fromInt(-1));
return 0;
}
This will output:
00000000000000000000000000000000
00000000000000000000011000000000
11111111111111111111111111111111

Logic to set a bits of given number from first occurance of bits 1 as given example?

Logic to set a bits of given number (as show in example below) from first occurance of 1 next should must be 1 and then alternative 0 and 1 should continue till all bits field is filled up? example if num =10 then its binary is 0000 0000 0000 0000 0000 0000 0000 1010
out put should be 0000 0000 0000 0000 0000 0000 0000 1101
similar if it is 16 10000 then 0/p should be 11010 and if 15 ie 1111 then output 11010 when we get first bits as 1 in give number then next bits should be 1 and the alternative 0 and 1?my logic is below please help to fix it
int main()
{
int i,onetime=1,flag=1;
scanf("%d",&num);
for(i=31;i>=0;i++)
{
if(num & 1<<i)
break; // this will give first set bits of num ie 1
}
--i; // move to next adjacent bit and this should also be 1
for(;i>0;)
{
if(onetime=1) // here forcely making 1
{
num=num|1<<i;
onetime=0;
}
if(flag==1) // set to 0
{
num=num&~(1<<i)
flag=0;
}
if(flag==0) //set to 1
{
num=num|(1<<i);
flag =1-flag; //will keep on switch 0 and 1
}
}
}
While the logic behind doing what you want to do it fairly trivial, the implementation isn't. Ignoring the need to output a binary representation for the moment, the logic can be broken down to:
1.) finding the most significant bit (msb)
2.) toggling each bit beginning at (msb - 1) to 0 (subtracting 'x' from msb)
3.) setting each bit if (x % 2) == 0, clearing otherwise
The implementation isn't difficult, it is just rather involved (note: this is for 32-bit values only):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h> /* for CHAR_BIT */
inline int getmsb (uint32_t x);
char *fmtbinstr_32 (uint32_t x, const size_t szgrp, char *sep);
/* set or clear bit n */
inline void bit_set (uint32_t *bf, int n) { *bf |= (1 << n); }
inline void bit_clear (uint32_t *bf, int n) { *bf &= ~(1 << n); }
int
main (int argc, char *argv[]) {
if (argc < 2 ) {
fprintf (stderr, "Error: insufficient input, usage: %s int\n", argv[0]);
return 1;
}
uint32_t number = (uint32_t)atoi (argv[1]);
uint32_t newnum = number;
int msb = getmsb (number);
int it = 0;
printf ("\n number: %s\n msb : %d\n\n", fmtbinstr_32 (number, 4, "-"), msb);
it = (int)msb;
for (it = 1; it <= msb; it++) {
if ((it % 2) == 0)
bit_clear (&newnum, msb - it);
else
bit_set (&newnum, msb - it);
}
printf (" newnum: %s\n\n", fmtbinstr_32 (newnum, 4, "-"));
return 0;
}
/* return the most significant bit MSB for the value supplied (bit scan reverse)
* for 32-bit values. For 64-bit values, use 'bsrq'.
*/
inline int getmsb (uint32_t x)
{
asm ("bsr %0, %0" : "=r" (x) : "0" (x));
return x;
}
/* binary string of uint32_t x, in szgrp bits groups, separated by sep */
char *fmtbinstr_32 (uint32_t x, const size_t szgrp, char *sep)
{
char b [sizeof(uint32_t) * CHAR_BIT + 1] = {0};
static char fmtb [sizeof (uint32_t) * 2 * CHAR_BIT] = {0};
const size_t len = sizeof(uint32_t) * CHAR_BIT + 1;
register size_t z = 0;
register size_t idx = 0;
if (szgrp > ((len - 1) / 2) || szgrp <= 0) {
fprintf (stderr, "%s() error: invalid input: szgrp '%d' out of range (%d >= szgrp > 0)\n", __func__, (int) szgrp, (int) ((len - 1) / 2));
return NULL; // could make b static and return b instead
}
for (z = 0; z < len - 1; z++)
b [sizeof (uint32_t) * CHAR_BIT - 1 - z] = ((x>>z) & 0x1) ? '1' : '0';
if (sep [0] == '\0') {
fprintf (stderr, "%s() error: invalid input: 'sep' is undefined or empty string\n", __func__);
return NULL;
}
for (z = 0; z < len - 1; z++) {
if ((len - 1 - z) % szgrp == 0 && z > 0) {
fmtb [idx] = sep [0];
idx++;
}
fmtb [idx] = b [z];
idx++;
}
fmtb [idx] = '\0';
return fmtb;
}
output:
$ ./bin/bitalt 10
number: 0000-0000-0000-0000-0000-0000-0000-1010
msb : 3
newnum: 0000-0000-0000-0000-0000-0000-0000-1101
$ ./bin/bitalt 55
number: 0000-0000-0000-0000-0000-0000-0011-0111
msb : 5
newnum: 0000-0000-0000-0000-0000-0000-0011-0101
Basic Version
This version employs the same logic, but leaves out the binary print function and the getmsb function that uses assembler instructions to get the most significant bit. This example uses most of the logic from the original question, but adjust the loops as needed:
#include <stdio.h>
int main (void) {
int i = 0, msb = 0;
unsigned int num = 0;
printf ("\nEnter a number: ");
scanf ("%u", &num);
for (i = 31; i >= 0; i--) {
if (num & 1 << i)
break; // this will give first set bits of num ie 1
} // which is the most significant bit (msb)
msb = i; // save msb
printf ("\n The most significant bit (msb): %d\n", msb);
// we want the index [msb - i] to step down from (msb-1) to 0
// e.g. if num=10, then msb=3, so we want the indexes to be 2,1,0
// so let i start at 1 and we will do (msb -i) until i=msb
for (i = 1; i <= msb; i++) {
if ((i % 2) == 0) // if i mod 2 == 0, we clear the bit
num &= ~(1 << (msb - i)); // clear_bit (make it 0)
else
num |= (1 << (msb - i)); // set_bit (make it 1)
}
printf ("\n The resulting number is: %u\n\n", num);
return 0;
}
output:
$ ./bin/bas
Enter a number: 10
The most significant bit (msb): 3
The resulting number is: 13
$ ./bin/bas
Enter a number: 55
The most significant bit (msb): 5
The resulting number is: 53

Printing signbit

I feel like I am nearing an end on this assignment, but do not understand why it only works correctly every other time. If I enter "FFFFFFFF" my program prints out:
0xFFFFFFFF
signBit 1, expBits 255, fractBits 0x007FFFFF
QNaN
but if I enter "FFFFFFFF" again my program prints out:
0xFFFFFFFF
my program will not print out the correct output every time but yet every other time.
Is there anyone who can help me identify where the error occurs in my code?
Any help is greatly appreciated!
Thanks!
// do not change this code except in the following ways:
// * write code for the following functions:
// * bigOrSmallEndian()
// * getNextHexInt()
// * printLinesForNumber()
// * change studentName by changing "I. Forgot" to your actual name
#include <stdio.h>
#include <stdlib.h>
static char *studentName = "Tenzin Shakya";
// report whether machine is big or small endian
void bigOrSmallEndian()
{
int num = 1;
if(*(char *)&num == 1)
{
printf("\nbyte order: little-endian\n\n");
}
else
{
printf("\nbyte order: big-endian\n\n");
}
}
// get next int (entered in hex) using scanf()
// returns 1 (success) or 0 (failure)
// if call succeeded, return int value via i pointer
int getNextHexInt(int *i)
{
// replace this code with the call to scanf()
//*i = 0;
//return 1;
scanf ("%x", i);
return 1;
}
// print requested data for the given number
void printNumberData(int i)
{
//printf("%x %0#10x\n",i,*(int *)&i);
int tru_exp =0;
//int stored_exp;
int negative;
int exponent;
int mantissa;
printf("\n>");
scanf("%x", &i);
printf("\n0x%08X",i);
negative = !!(i & 0x80000000);
exponent = (i & 0x7f800000) >> 23;
mantissa = (i & 0x007FFFFF);
printf("\nsignBit %d, ", negative);
printf("expbits %d, ", exponent);
printf("fractbits 0x%08X", mantissa);
// "%#010x, ", mantissa);
if(exponent == 0)
{
if(mantissa != 0)
{
printf("\ndenormalized ");
}
}
else{
printf("\nnormalized: ");
tru_exp = exponent - 127;
printf("exp = %d", tru_exp);
}
if(exponent == 0 && mantissa == 0 && negative == 1)
{
printf("\n-zero");
}
if(exponent ==0 && mantissa == 0 && negative == 0)
{
printf("\n+zero");
}
if(exponent == 255 && mantissa != 0 && negative == 1)
{
printf("\nQNaN");
}
if(exponent == 255 && mantissa != 0 && negative == 0)
{
printf("\nSNaN");
}
if(exponent == 0xff && mantissa == 0 && negative == 1)
{
printf("\n-infinity");
}
if(exponent == 0xff && mantissa == 0 && negative == 0)
{
printf("\n+infinity");
}
printf("\n");
while(i != 0)
break;
}
// do not change this function in any way
int main(int argc, char **argv)
{
int i; // number currently being analyzed
int nValues; // number of values successfully parsed by scanf
printf("CS201 - A01p - %s\n\n", studentName);
bigOrSmallEndian();
for (;;) {
if (argc == 1) // allow grading script to control ...
printf("> "); // ... whether prompt character is printed
nValues = getNextHexInt(&i);
printf("0x%08X\n", i);
if (! nValues) { // encountered bad input
printf("bad input\n");
while (getchar() != '\n') ; // flush bad line from input buffer
continue;
}
printNumberData(i);
if (i == 0)
break;
}
printf("\n");
return 0;
}
You are inputting the user's number in getNextHexInt, but printNumberData asks for the input again with another scanf. You don't need the second scanf because the input i is already set to the user's input from getNextHexInt.
here's the code for doing that
float myFloat;
int myInt;
memcpy(&myInt, &myFloat, 4);
int signBit = ((1 << 31) & myInt) >> 31;
printf("%i\n", signBit)
I typed it up in a rush, hopefully it works, ill check it in a sec
Heres a program, but it displays -1 for some reason for sign
#include <string.h>
#include <stdio.h>
int main()
{
float a = 1337;
int* b = (int*)&a;
int signbit = ((1 << 31) & *b) >> 31;
printf("%i\n", signbit);
a *= -1;
signbit = ((1 << 31) & *b) >> 31;
printf("%i\n", signbit);
return 0;
}

Convert integer from (pure) binary to BCD

I'm to stupid right now to solve this problem...
I get a BCD number (every digit is an own 4Bit representation)
For example, what I want:
Input: 202 (hex) == 514 (dec)
Output: BCD 0x415
Input: 0x202
Bit-representation: 0010 0000 0010 = 514
What have I tried:
unsigned int uiValue = 0x202;
unsigned int uiResult = 0;
unsigned int uiMultiplier = 1;
unsigned int uiDigit = 0;
// get the dec bcd value
while ( uiValue > 0 )
{
uiDigit= uiValue & 0x0F;
uiValue >>= 4;
uiResult += uiMultiplier * uiDigit;
uiMultiplier *= 10;
}
But I know that's very wrong this would be 202 in Bit representation and then split into 5 nibbles and then represented as decimal number again
I can solve the problem on paper but I just cant get it in a simple C-Code
You got it the wrong way round. Your code is converting from BCD to binary, just as your question's (original) title says. But the input and output values you provided are correct only if you convert from binary to BCD. In that case, try:
#include <stdio.h>
int main(void) {
int binaryInput = 0x202;
int bcdResult = 0;
int shift = 0;
printf("Binary: 0x%x (dec: %d)\n", binaryInput , binaryInput );
while (binaryInput > 0) {
bcdResult |= (binaryInput % 10) << (shift++ << 2);
binaryInput /= 10;
}
printf("BCD: 0x%x (dec: %d)\n", bcdResult , bcdResult );
return 0;
}
Proof: http://ideone.com/R0reQh
Try the following.
unsigned long toPackedBcd (unsigned int val)
{
unsigned long bcdresult = 0; char i;
for (i = 0; val; i++)
{
((char*)&bcdresult)[i / 2] |= i & 1 ? (val % 10) << 4 : (val % 10) & 0xf;
val /= 10;
}
return bcdresult;
}
Also one may try the following variant (although maybe little inefficient)
/*
Copyright (c) 2016 enthusiasticgeek<enthusiasticgeek#gmail.com> Binary to Packed BCD
This code may be used (including commercial products) without warranties of any kind (use at your own risk)
as long as this copyright notice is retained.
Author, under no circumstances, shall not be responsible for any code crashes or bugs.
Exception to copyright code: 'reverse string function' which is taken from http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
Double Dabble Algorithm for unsigned int explanation
255(binary) - base 10 -> 597(packed BCD) - base 16
H| T| U| (Keep shifting left)
11111111
1 1111111
11 111111
111 11111
1010 11111 <-----added 3 in unit's place (7+3 = 10)
1 0101 1111
1 1000 1111 <-----added 3 in unit's place (5+3 = 8)
11 0001 111
110 0011 11
1001 0011 11 <-----added 3 in ten's place (6+3 = 9)
1 0010 0111 1
1 0010 1010 1 <-----added 3 in unit's place (7+3 = 10)
10 0101 0101 -> binary 597 but bcd 255
^ ^ ^
| | |
2 5 5
*/
#include <stdio.h>
#include <string.h>
//Function Prototypes
unsigned int binaryToPackedBCD (unsigned int binary);
char * printPackedBCD(unsigned int bcd, char * bcd_string);
// For the following function see http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
void reverse(char *str);
//Function Definitions
unsigned int binaryToPackedBCD (unsigned int binary) {
const unsigned int TOTAL_BITS = 32;
/*Place holder for bcd*/
unsigned int bcd = 0;
/*counters*/
unsigned int i,j = 0;
for (i=0; i<TOTAL_BITS; i++) {
/*
Identify the bit to append to LSB of 8 byte or 32 bit word -
First bitwise AND mask with 1.
Then shift to appropriate (nth shift) place.
Then shift the result back to the lsb position.
*/
unsigned int binary_bit_to_lsb = (1<<(TOTAL_BITS-1-i)&binary)>>(TOTAL_BITS-1-i);
/*shift by 1 place and append bit to lsb*/
bcd = ( bcd<<1 ) | binary_bit_to_lsb;
/*printf("=> %u\n",bcd);*/
/*Don't add 3 for last bit shift i.e. in this case 32nd bit*/
if( i >= TOTAL_BITS-1) {
break;
}
/*else continue*/
/* Now, check every nibble from LSB to MSB and if greater than or equal 5 - add 3 if so */
for (j=0; j<TOTAL_BITS; j+=4) {
unsigned int temp = (bcd & (0xf<<j))>>j;
if(temp >= 0x5) {
/*printf("[%u,%u], %u, bcd = %u\n",i,j, temp, bcd);*/
/*Now, add 3 at the appropriate nibble*/
bcd = bcd + (3<<j);
// printf("Now bcd = %u\n", bcd);
}
}
}
/*printf("The number is %u\n",bcd);*/
return bcd;
}
char * printPackedBCD(unsigned int bcd, char * bcd_string) {
const unsigned int TOTAL_BITS = 32;
printf("[LSB] =>\n");
/* Now, check every nibble from LSB to MSB and convert to char* */
for (unsigned int j=0; j<TOTAL_BITS; j+=4) {
//for (unsigned int j=TOTAL_BITS-1; j>=4; j-=4) {
unsigned int temp = (bcd & (0xf<<j))>>j;
if(temp==0){
bcd_string[j/4] = '0';
} else if(temp==1){
bcd_string[j/4] = '1';
} else if(temp==2){
bcd_string[j/4] = '2';
} else if(temp==3){
bcd_string[j/4] = '3';
} else if(temp==4){
bcd_string[j/4] = '4';
} else if(temp==5){
bcd_string[j/4] = '5';
} else if(temp==6){
bcd_string[j/4] = '6';
} else if(temp==7){
bcd_string[j/4] = '7';
} else if(temp==8){
bcd_string[j/4] = '8';
} else if(temp==9){
bcd_string[j/4] = '9';
} else {
bcd_string[j/4] = 'X';
}
printf ("[%u - nibble] => %c\n", j/4, bcd_string[j/4]);
}
printf("<= [MSB]\n");
reverse(bcd_string);
return bcd_string;
}
// For the following function see http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
void reverse(char *str)
{
if (str != 0 && *str != '\0') // Non-null pointer; non-empty string
{
char *end = str + strlen(str) - 1;
while (str < end)
{
char tmp = *str;
*str++ = *end;
*end-- = tmp;
}
}
}
int main(int argc, char * argv[])
{
unsigned int number = 255;
unsigned int bcd = binaryToPackedBCD(number);
char bcd_string[8];
printPackedBCD(bcd, bcd_string);
printf("Binary (Base 10) = %u => Packed BCD (Base 16) = %u\n OR \nPacked BCD String = %s\n", number, bcd, bcd_string);
return 0;
}
The real problem here is confusion of bases and units
The 202 should be HEX which equates to 514 decimal... and therefore the BCD calcs are correct
Binary code decimal will convert the decimal (514) into three nibble sized fields:
- 5 = 0101
- 1 = 0001
- 4 = 0100
The bigger problem was that you have the title the wrong way around, and you are converting Uint to BCD, whereas the title asked for BCD to Unint
My 2 cents, I needed similar for a RTC chip which used BCD to encode the time and date info. Came up with the following macros that worked fine for the requirement:
#define MACRO_BCD_TO_HEX(x) ((BYTE) ((((x >> 4) & 0x0F) * 10) + (x & 0x0F)))
#define MACRO_HEX_TO_BCD(x) ((BYTE) (((x / 10 ) << 4) | ((x % 10))))
A naive but simple solution:
char buffer[16];
sprintf(buffer, "%d", var);
sscanf(buffer, "%x", &var);
This is the solution that I developed and works great for embedded systems, like Microchip PIC microcontrollers:
#include <stdio.h>
void main(){
unsigned int output = 0;
unsigned int input;
signed char a;
//enter any number from 0 to 9999 here:
input = 1265;
for(a = 13; a >= 0; a--){
if((output & 0xF) >= 5)
output += 3;
if(((output & 0xF0) >> 4) >= 5)
output += (3 << 4);
if(((output & 0xF00) >> 8) >= 5)
output += (3 << 8);
output = (output << 1) | ((input >> a) & 1);
}
printf("Input decimal or binary: %d\nOutput BCD: %X\nOutput decimal: %u\n", input, output, output);
}
This is my version for a n byte conversion:
//----------------------------------------------
// This function converts n bytes Binary (up to 8, but can be any size)
// value to n bytes BCD value or more.
//----------------------------------------------
void bin2bcdn(void * val, unsigned int8 cnt)
{
unsigned int8 sz, y, buff[20]; // buff = malloc((cnt+1)*2);
if(cnt > 8) sz = 64; // 8x8
else sz = cnt * 8 ; // Size in bits of the data we shift
memset(&buff , 0, sizeof(buff)); // Clears buffer
memcpy(&buff, val, cnt); // Copy the data to buffer
while(sz && !(buff[cnt-1] & 0x80)) // Do not waste time with null bytes,
{ // so search for first significative bit
rotate_left(&buff, sizeof(buff)); // Rotate until we find some data
sz--; // Done this one
}
while(sz--) // Anyting left?
{
for( y = 0; y < cnt+2; y++) // Here we fix the nibbles
{
if(((buff[cnt+y] + 0x03) & 0x08) != 0) buff[cnt+y] += 0x03;
if(((buff[cnt+y] + 0x30) & 0x80) != 0) buff[cnt+y] += 0x30;
}
rotate_left(&buff, sizeof(buff)); // Rotate the stuff
}
memcpy(val, &buff[cnt], cnt); // Copy the buffer to the data
// free(buff); //in case used malloc
} // :D Done
long bin2BCD(long binary) { // double dabble: 8 decimal digits in 32 bits BCD
if (!binary) return 0;
long bit = 0x4000000; // 99999999 max binary
while (!(binary & bit)) bit >>= 1; // skip to MSB
long bcd = 0;
long carry = 0;
while (1) {
bcd <<= 1;
bcd += carry; // carry 6s to next BCD digits (10 + 6 = 0x10 = LSB of next BCD digit)
if (bit & binary) bcd |= 1;
if (!(bit >>= 1)) return bcd;
carry = ((bcd + 0x33333333) & 0x88888888) >> 1; // carrys: 8s -> 4s
carry += carry >> 1; // carrys 6s
}
}
Simple solution
#include <stdio.h>
int main(void) {
int binaryInput = 514 ; //0x202
int bcdResult = 0;
int digit = 0;
int i=1;
printf("Binary: 0x%x (dec: %d)\n", binaryInput , binaryInput );
while (binaryInput > 0) {
digit = binaryInput %10; //pick digit
bcdResult = bcdResult+digit*i;
i=16*i;
binaryInput = binaryInput/ 10;
}
printf("BCD: 0x%x (dec: %d)\n", bcdResult , bcdResult );
return 0;
}
Binary: 0x202 (dec: 514)
BCD: 0x514 (dec: 1300)
You can also try the following:
In every iteration the remainder ( represented as a nibble ) is positioned in its corresponding place.
uint32_t bcd_converter(int num)
{
uint32_t temp=0;
int i=0;
while(num>0){
temp|=((num%10)<<i);
i+=4;
num/=10;
}
return temp;
}

Resources