Convert HEX value to (chars, string, letters and numbers) - c

I'm programming AVR microcontroller Atmega16 in C.
I don't understand C, i spend my time programming in PHP, and i just don't get it in C.
I don't get also how can i post sourcecode here.
If someone know, please fix my tags.
My problem is, i have this function:
unsigned char
convert_sn_to_string (const unsigned char *SN_a /* IDstring */ )
{
unsigned char i;
for (i = 0; i < 6; i++) //6 byte az SN
{
if(SN_a[i]==0x00)
{
Send_A_String("00");
}
}
return 1;
}
Inside for loop i can acces 6 byte value by hex.
Inside variable SN_A i can have
SN_A[0]=0x00;
SN_A[1]=0xFF;
SN_A[3]=0xAA;
SN_A[4]=0x11;
(...)
and similar.
It could be from 00 to FF.
What i need, is to convert that code to 12 char string.
If i have
SN_A[0]=0x00;
SN_A[1]=0xFF;
SN_A[3]=0xAA;
SN_A[4]=0x11;
(...)
I would like get at output
new[0]=0;
new[1]=0;
new[2]=A;
new[3]=A;
new[4]=1;
new[5]=1;
(...)
and so to 12, because i would like change that 6 (double) AA values, to separated.
So then i can do a loop
for i=0 i<12 i++
{
do_something_with_one_letter(new[i]);
}
Now i can play with that values, i can send them to display, or anything i need.

A hex value is simply another way of writing integers. 0xFF == 255.
So, if you want to "split" them, you need to first decide how you want to split them. This, essentially, decides on the exact way you stuff the split values into your new array.
To split a value, something like this can be used:
hexval = 0x1A
low_nybble = hexval & 0xF
high_nybble = (hexval >> 4) & 0xF
You now have 1 stored in high_nybble and 10 stored in low_nybble.

Related

Compute the crc16 of a bytearray / userdata in lua

I am writing a Wireshark protocol dissector in lua. The protocol it parses contains a crc16 checksum. The dissector should check whether the crc is correct.
I have found a crc16 implementation written in C already with the lua wrapper code here. I have successfully compiled it and run it (e.g. crc16.compute("test")). The problem is it expects a string as input. From wireshark, I get a buffer that seems to be of lua type userdata. So when I do
crc16.compute(buffer(5, 19))
Lua complains bad argument #1 to compute (string expected, got userdata).
compute() in the crc16 implementation looks like this:
static int compute(lua_State *L)
{
const char *data;
size_t len = 0;
unsigned short r, crc = 0;
data = luaL_checklstring(L, 1, &len);
for ( ; len > 0; len--)
{
r = (unsigned short)(crc >> 8);
crc <<= 8;
crc ^= crc_table[r ^ *data];
data ++;
}
lua_pushinteger(L, crc);
return 1;
}
It seems luaL_checklstring fails. So I guess I would either need to convert the input into a lua string, which I am not sure it works, as not all bytes of my input are necessarily printable characters. Or I would need to adjust the above code so it accepts input of type userdata. I found lua_touserdata(), but this seems to return something like a pointer. So I would need a second argument for the length, right?
I don't necessarily need to use this implementation. Any crc16 implementation for lua that accepts userdata would perfectly solve the problem.
The buffer that you get from wireshark can be used as a ByteArray like this:
byte_array = Buffer(5,19):bytes();
ByteArray has a _toString function that converts the bytes into a string representation of the bytes represented as hex. So you can call the crc function like this:
crc16.compute(tostring(byte_array))
'Representation of the bytes represented as hex' means an input byte with the bits 11111111 will turn into the ASCII string FF. The ASCII string FF is 01000110 01000110 in bits or 46 46in hex. This means what you get in C, is not the original bytearray. You need to decode the ascii representation back into the original bytes before computing the crc, otherwise we will obviously get a different crc.
First, this function converts a single character c containing one ascii hex character back into the value it represents:
static char ascii2char(char c) {
c = tolower(c);
if(c >= '0' && c <= '9')
return c - '0';
else if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
}
Now in the compute function we loop through the string representation, always combining two characters into one byte.
int compute(lua_State *L) {
size_t len;
const char * str = lua_tolstring(L, 1, &len);
uint8_t * data = (uint8_t *) malloc(len/2);
for(int n=0; n<len/2; n++) {
data[n] = ascii2char(str[2*n]) << 4;
data[n] |= ascii2char(str[2*n+1]);
}
crc16_t crc = crc16_init();
crc = crc16_update(crc, data, len/2);
crc = crc16_finalize(crc);
lua_pushinteger(L, crc);
free(data);
return 1;
}
In this example, I used the crc functions crc16_init, crc16_update and crc16_finalize generated using pycrc, not the crc implementation linked in the question. The problem is that you need to use the same polynom etc. as when generating the crc. Pycrc allows you the generate crc functions as needed.
My packets also contain a crc32. Pycrc can also generate code for crc32, so it works all the same way for crc32.
Christopher K outlines what is mostly the correct answer, but the conversion of hex values back into bytes seemed a little like hardwork, but this got me looking as I was searching for something like this.
The trick missed was that as well as calling the function with a buffer:bytes() you can also call
buffer:raw()
This provides exactly what is needed: a simple TSTRING that can be parsed directly without the need to do ascii conversions that would, I imagine, add significantly to the load in the C code.

Embedded C AVR Bit stuffing an array

Can anyone help me with some code i need to implement bit stuffing on an array of data? The program is for an AVR micro-controller (Tiny84A) using GNU C.
unsigned char datas[3] = {00011111,10000001,00000000};
To add 0 to each set of 5 one’s i.e. after every five consecutive 1′s appear a zero
Therefore data should be
00011111,10000001 becomes 00011111 01000000 10000000
I'm unsure where to start, an example would be great!
There are lots of examples on the web for bit stuffing (inserting a 0 after 5 1s). Unfortunately, many of them involve reading and writing strings of characters 0 and 1.
There are also examples of bit streams. It looks like you need to find examples of each and combine them.
You need to expand your question to explain more of the design decisions you have made.
In particular, it looks like you are expecting the input to be in an array instead of a stream. Are you expecting to write the output to the same array? That is a little bit trickier than writing to a different array. A stream of bits would be different again.
The basic idea is to keep counters of where you are in the input and output streams, and load and write bytes appropriately as you reach the end of 8 bits.
unsigned char datas[3] = {00011111,10000001,00000000};
int in_byte, in_bit, out_byte, out_bit;
void init()
{
in_byte = 0; in_bit = 0; out_byte = 0; out_bit = 0;
}
int get_bit()
{
int ret = 0;
if (datas[in_byte] & 1 << (7 - in_bit))
{
ret = 1;
{
++in_bit;
if (in_bit == 8)
{
in_bit = 0;
++in_byte;
}
return ret;
}
You have to write your own void put_bit(int bit), but it is similar using the "or" operator |.
You also need to make a function to do the loop that counts up to 5 and puts an extra 0. Look at the examples on the web for that.

Converting from hexadecimal string to byte array in C

I am sending byte arrays between a TCP socket server & client in C. The information that I am sending is a series of integers.
I have it working, but because I am not too conversant with C, I was wondering if anyone could suggest a better solution, or at least to look and tell me that I'm not being too crazy or using outdated code with what I'm doing.
First, I generate a random decimal value, let's say "350". I need to transmit this over the socket connection as a hex byte array. It is decoded back to its decimal value at the other end.
So far, I convert it to hex this way:
unsigned char hexstr[4];
sprintf(hexstr, "%02X", numToConvert); \\ where numToConvert is a decimal integer value like 350
At this point, I have a string in hexstr that's something like "15E" (again, using the hex value of 350 for an example).
Now, I need to store this in a byte array so that it looks something like: myArray = {0X00, 0X00, 0X01, 0X5E};
Obviously I can't just write: myArray = {0X00, 0X00, 0X01, 0X5E} because the values will be different every time, since a new random number is generated every time.
Currently, I do it like this (pseudocode because the string manipulation part is irrelevant but long):
lastTwoChars = getLastTwoCharsFromString(hexstr); // so lastTwoChars would now contain "5E"
Then (actual code):
sscanf(lastTwoChars, "%0X", &res); // now the variable res contains the byte representation of lastTwoChars, is my understanding
Then finally:
myArray[3] = res;
Then, I take the next two rightmost chars from hexstr (again, using the sample value of "15E", this would be "01" -- if there's only 1 more character, as in this case "1" was the only character left after taking out "5E" from "15E", I add 0s to the left to pad) and convert that the same way using sscanf, then insert into myArray[2]. Repeat for myArray[1] and myArray[0].
Then I send the array using write().
So, after hours of plugging away at it, this all does work... but because I don't use C very much, I have a nagging suspicion that there's something I am missing in all this. Can anyone comment if what I'm doing seems OK, or there's something obvious I'm using improperly or neglecting to use?
#include <stdio.h>
#include <limits.h>
int main(){
unsigned num = 0x15E;//num=350
int i, size = sizeof(unsigned);
unsigned char myArray[size];
for(i=size-1;i>=0;--i, num>>=CHAR_BIT){
myArray[i] = num & 0xFF;
}
for(i=0;i<size;++i){
printf("0X%02hhX ", myArray[i]);//0X02X
}
printf("\n");
return 0;
}
On the transmit side, convert a 32-bit number to a four byte array with this code
void ConvertValueToArray( uint32_t value, uint8_t array[] )
{
int i;
for ( i = 3; i >= 0; i-- )
{
array[i] = value & 0xff;
value >>= 8;
}
}
On the receive side, convert the byte array back into a number with this code
uint32_t ConvertArrayToValue( uint8_t array[] )
{
int i;
uint32_t value = 0;
for ( i = 0; i < 4; i++ )
{
value <<= 8;
value |= array[i];
}
return( value );
}
Note that it's important not to use generic types like int when writing this kind of code, since an int can be different sizes on different systems. The fixed-sized types are defined in <stdint.h>.
Here's a simple test that demonstrates the conversions (without actually sending the byte arrays over the network).
#include <stdio.h>
#include <stdint.h>
int main( void )
{
uint32_t input, output;
uint8_t byte_array[4];
input = 350;
ConvertValueToArray( input, byte_array );
output = ConvertArrayToValue( byte_array );
printf( "%u\n", output );
}
If your array is 4-byte aligned (and even if it isn't on machines that support unaligned access), you can use the htonl function to convert a 32-bit integer from host to network byte order and store the whole thing at once:
#include <arpa/inet.h> // or <netinet/in.h>
...
*(uint32_t*)myArray = htonl(num);

Decode FOUR_BITS of a byte in a byte array (in C)

I am writing a code to decode the byte array based on user input (EIGHT_BITS at a time or FOUR_BITS at a time). I've actually managed to decode the byte array based on EIGHT_BITS. Now I want to decode them in terms of FOUR_BITS.
INT DecodeElem(UINT8 *decodeBuf, UINT8 elemlen, UINT8 *tempBuf, UINT8 elemlength){
if (elemlength== EIGHT_BITS){
*tempBuf = getByte(decodeBuf + decodeByteCount);
decodeOffset = 0;
decodeByteCount++;
}
}
ie, if the elemlength= FOUR_BITS, I need to decode the first four bits of a particular byte in the byte array. Could someone let me know how do I do the same without modifying the case for the EIGHT_BITS which I have written above?
What I basically need is another if statement with if (elemlength == FOUR_BITS)
Note: tempBuf is CHAR * type and I can't change the type.
decodeByteCount and decodeOffset are global variables; *decodeBuf is the already encoded byte array which needs to be decoded. elemlen is for future use and I will take care of it.
This is my getByte function:
UINT8 getByte(UINT8 *byteBuf)
{
return ((UINT8)*byteBuf);
}
I'm not sure what decodeOffset and decodeByteCount does....
It should be something like that (assuming each byte has 2 4 bit values. If the assumption is wrong remove "/2" from the code):
if (elemlength== FOUR_BITS){
*tempBuf = getByte(decodeBuf + decodeByteCount / 2);
if(decodeByteCount % 2)
*tempBuff = (*tempBuff & 0xF0) >> 4;
else
*tempBuff = (*tempBuff & 0Xf);
// ???decodeOffset = 0;
// ???decodeByteCount++;
}

If I have to represent integers and char's in a single array, what would be an acceptable way to do this in C?

Can I declare an int array, then initialize it with chars? I'm trying to print out the state of a game after each move, therefore initially the array will be full of chars, then each move an entry will be updated to an int.
I think the answer is yes, this is permitted and will work because an int is 32 bits and a char is 8 bits. I suppose that each of the chars will be offset by 24 bits in memory from each other, since the address of the n+1'th position in the array will be n+32 bits and a char will only make use of the first 8.
It's not a homework question, just something that came up while I was working on homework. Maybe I'm completely wrong and it won't even compile the way I've set everything up?
EDIT: I don't have to represent them in a single array, as per the title of this post. I just couldn't think of an easier way to do it.
You can also make an array of unions, where each element is a union of either char or int. That way you can avoid having to do some type-casting to treat one as the other and you don't need to worry about the sizes of things.
int and char are numeric types and char is guaranteed smaller than int (therefore supplying a char where an int is expected is safe), so in a nutshell yes you can do that.
Yes it would work, because a char is implicitly convertible to an int.
"I think the answer is yes, this is permitted and will work because an int is 32 bits and a char is 8 bits." this is wrong, an int is not always 32 bits. Also, sizeof(char) is 1, but not necessarily 8 bits.
As explained, char is an int compatible type.
From your explanation, you might initially start with an array of int who's values are char, Then as the game progresses, the char values will no longer be relevant, and become int values. Yes?
IMHO the problem is not putting char into an int, that works and is built into the language.
IMHO using a union to allow the same piece of space to be used to store either type, helps but is not important. Unless you are using an amazingly small microcontroller, the saving in space is not likely relevant.
I can understand why you might want to make it easy to write out the board, but I think that is a tiny part of writing a game, and it is best to keep things simple for the rest of the game, rather than focus on the first few lines of code.
Let's think about the program; consider how to print the board.
At the start it could be:
for (int i=0; i<states; ++i) {
printf("%c ", game_state[i]);
}
Then as the game progresses, some of those values will be int.
The issue to consider is "which format is needed to print the value in the 'cell'?".
The %c format prints a single char.
I presume you would like to see the int values printed differently from ordinary printed characters? For example, you want to see the int values as integers, i.e. strings of decimal (or hex) digits? That needs a '%d' format.
On my Mac I did this:
#include <stdio.h>
#define MAX_STATE (90)
int main (int argc, const char * argv[]) {
int game_state[MAX_STATE];
int state;
int states;
for (states=0; states<MAX_STATE; ++states) {
game_state[states] = states+256+32;
}
for (int i=0; i<states; ++i) {
printf("%c ", game_state[i]);
}
return 0;
}
The expression states+256+32 guarantees the output character codes are not ASCII, or even ISO-8859-1 and they are not control codes. They are just integers. The output is:
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? # A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y
I think you'd like the original character to be printed (no data conversion) when the value is the initial character (%c format), but you do want to see data conversion, from a binary number to a string of digit-characters (%d or a relative format). Yes?
So how would the program tell which is which?
You could ensure the int values are not characters (as my program did). Typically, this become a pain, because you are restricted on values, and end up using funny expressions everywhere else just to make that one job easier.
I think it is easier to use a flag which says "the value is still a char" or "the value is an int"
The small saving of space from using a union is rarely worth while, and their are advantages to having the initial state and the current move available.
So I think you end up with something like:
#include <stdio.h>
#define MAX_STATE (90)
int main (int argc, const char * argv[]) {
struct GAME { int cell_state; int move; char start_value } game_state[MAX_STATE];
enum CELL_STATE_ENUM { start_cell, move_cell };
int state;
int states;
for (states=0; (state=getchar())!= EOF && states<MAX_STATE; ++states) {
game_state[states].start_value = state;
game_state[states].cell_state = start_cell;
}
// should be some error checking ...
// ... make some moves ... this is nonsense but shows an idea
for (int i=0; i<states; ++i ) {
if (can_make_move(i)) {
game_state[states].cell_state = move_cell;
game_state[states].move = new_move(i);
}
}
// print the board
for (int i=0; i<states; ++i) {
if (game_state[i].cell_state == start_cell) {
printf("'%c' ", game_state[i].start_value);
} else if (game_state[i].cell_state == move_cell) {
printf("%d ", game_state[i].move);
} else {
fprintf(stderr, "Error, the state of the cell is broken ...\n");
}
}
return 0;
}
The move can be any convenient value, there is nothing to complicate the rest of the program.
Your intent can be made a little more clear my using int8_t or uint8_t from the stdint.h header. This way you say "I'm using a eight bit integer, and I intend for it to be a number."
It's possible and very simple. Here is an example:
int main()
{
// int array initialized with chars
int arr[5] = {'A', 'B', 'C', 'D', 'E'};
int i; // loop counter
for (i = 0; i < 5; i++) {
printf("Element %d id %d/%c\n", i, arr[i], arr[i]);
}
return 0;
}
The output is:
Element 0 is 65/A
Element 1 is 66/B
Element 2 is 67/C
Element 3 is 68/D
Element 4 is 69/E

Resources