PDA

View Full Version : Bitwise shifting and ORing HexaDecimal Value



nagabathula
14th November 2010, 07:18
Hello Every One,
I am stuck with a problem with bitwise shifting and ORing of 2 bytes.. Actually i am getting data on RS232 port in ascii which i convert into hex and save the converted data into the db.


data = (QByteArray::fromRawData(buff,numBytes)).toHex();

now i need to bitshift left and OR each byte from the db to get the valid data. This is the first time i am doing some thing like this. So i am confused don't know how to go about it.

This the Hexa Decimal data which i have saved into the database . Here i need to Bitwise shift left the first byte "1d" by 5 times , Next i need to bitwise shift left the second byte "17" and OR the second and the first byte. so on for all the consecutive data.


1d17110009008f008f008f008f008f008f008f008f008f008f 008f008f008f008f008f008f008f008f008f008f
1d1711000a008f008f008f008f008f008f008f008f008f008f 008f008f008f008f008f008f008f008f008f008f
1d1711000b008f008f008f008f008f008f008f008f008f008f 008f008f008f008f008f008f008f008f008f008f
1d1711000c008f008f008f008f008f008f008f008f008f008f 008f008f008f008f008f008f008f008f008f008f





QSqlQuery sq1("select ChannelData from Bulkdb where rowid = (" + QString::number(rowcnt) + ")");
if(sq1.exec())
{
if (sq1.first())
{
do
{
rowdata.push_back(sq1.value(0).toString());
} while(sq1.next());
}
}

for(int j = 0; j < rowdata.count(); j++)
databuff.append(rowdata.at(j));

for(int i= 0;i<databuff.count() ;i++)
{
databuff1.append(databuff.at(i));
alignbuff = ((databuff1.at(ld) << 5) // I am trying to Bitwise shift left each byte here , not sure if what i am doing is correct .
final_data = secondByte OR | firstByte;
// Not able to figure out a logic
}


Not able to figure out a logic to OR the bytes like.. 2nd Byte|1st Byte, 4th Byte|3rd Byte , 6th Byte|5 byte , 8th byte|7th Byte and so on for all the data present.:confused:

some one Please who has an example or a suggestion it will help me a lot.

Thank You

tbscope
14th November 2010, 07:28
If you want the hexadecimal data, you do not use toHex(). This is for displaying the data, not using it.

You can use the [] operator.

Then you can use the normal bitwise operators on it.
Shifting 5 bits is done like this: << 5

ChrisW67
14th November 2010, 07:41
I really don't know why you want to try bitwise operations on a string of characters, which is what a the hexadecimal representaion is, when you already have the raw bytes. Something like this seems more sensible:

QByteArray data = QByteArray::fromRawData(buff,numBytes);
QByteArray result;
for (i = 0; i< data.size(); i += 2) {
result.append( ((data.at(i) << 5) | (data.at(i+1)) );
}

nagabathula
14th November 2010, 07:49
Thank You so much ChrisW. What you have suggested makes more sense. I din't know how to go about it before. I will implement what you have given now. I was breaking my head over this problem for hours. Thank you a million.

Regards

nagabathula
14th November 2010, 10:08
Hello ChrisW i have a small doubt from the code you suggested.

for (i = 0; i< data.size(); i += 2)
I din exactly understand how this for loop works what does " i+=2 " do in this loop.:confused:

This is the part of code in my program where i am trying to insert the data after the bitwise shift and ORing is done, But i am getting an error at Sqlite db insert query. Should i convert QByteArray to QString to insert into the db., how do i convert it.

if(port->bytesAvailable())
{
numBytes = port->bytesAvailable();
if(numBytes > sizeof(buff))
numBytes = sizeof(buff);
i = port->read(buff,numBytes);
QByteArray data = QByteArray::fromRawData(buff,numBytes);
QByteArray result;

for (i = 0; i< data.size(); i += 2)
{
result.append(((data.at(i) << 5) | (data.at(i+1))));

}
QString sq("INSERT INTO Bulkdb values(%1,%2)");
sq = sq.arg(rowcount)
.arg("'"+ result +"'"); //error C2668: 'QString::arg' : ambiguous call to overloaded function
m_query.exec(sq);
rowcount++;
textBrowser->append(result);
}

I am getting an error when i compile this code ChrisW. How do i insert QByteArray data into Sqlite DB..

error C2668: 'QString::arg' : ambiguous call to overloaded function

SixDegrees
14th November 2010, 10:31
'i += 2' mean 'add 2 to the value of i'.

Your string construction is failing because 'result' isn't a string; it's a byte array. You need to convert it to a string before performing string manupulations on it.

ChrisW67
14th November 2010, 22:06
Given the sample data you showed us, the bytes in your result don't look like a particularly meaningful ASCII or Latin1 string. The first two bytes are 0x1d and 0x17 and you do this:


0x1d = 0001 1101
Shift << 5 = 1010 0000 (Some bits lost out left end)
0x17 = 0001 0111
ORed = 1011 0111 (0xB7, an interpunct in ISO 8859-1 (Latin1) and not valid ASCII)

So, you probably want to store the data as a Base64, Hex or percent-encoded string, or directly in a BLOB column.
QByteArray::toBase64(),
QByteArray::toHex(),
QByteArray::toPercentEncoding()

nagabathula
15th November 2010, 09:44
Hello ChrisW ,

I have to actually use a 16 bit int variable, how should i do that how sud i assign the QByteArray to be 16 bits.?
You were right it is not in ascii format, i am converting it into Hex.


QByteArray data = (QByteArray::fromRawData(buff,numBytes)).toHex();




0x1d = 0000 0000 0001 1101
Shift << 5 = 0000 0011 1010 0000
0x17 = 0000 0000 0001 0111
ORed = 0000 0011 1011 0111




thank you

nagabathula
15th November 2010, 14:09
Hello i think i figured out what the problem is.. I am getting the ORed hex data but i am missing the first byte, i think it is taking only 8 bits so "03" is missing i am getting only "b7". How do i get a parameter as QByteArray and retrun a quint16 value.



0x1d = 0000 0000 0001 1101
Shift << 5 = 0000 0011 1010 0000
0x17 = 0000 0000 0001 0111

ORed = 0000 0011 1011 0111
----------------------------------------
0 3 b 7

But i am getting only b7 i think its because QByteArray is taking it as 8 bits only. How can i assign 16 bits to get the actual aligned data. ??

This is what i am doing in the test code.

QByteArray result;
QByteArray ba,da;

ba[0] = 0x1d;
ba[1] = 0x17;
ba[2] = 0x11;
ba[3] = 0x00;
ba[4] = 0x00;
// quint16 result = qFromBigEndian<quint16>((uchar*)result.data());

for (int i = 0; i < ba.size(); i+=2)
{
result.append(((ba.at(i) << 5)|(ba.at(i+1))));

}
da.append(result.toHex());
textBrowser->append(da);

How can i make QByteArray ba as a 16 bit. ?

thank you

nagabathula
16th November 2010, 02:39
Hello friends,

How do i make a QByteArray value to be stored in a 16 bit int to align the data. ..
I looked a lot every wer but not finding an example to do it right.

thank you

ChrisW67
17th November 2010, 00:38
A QByteArray stores bytes. It doesn't store anything else. Look at QVector or QList for storage of other types.

If you need to process two bytes into a single 16-bit int then you do this:


quint16 r = static_cast<unsigned char>(a) << 5 | static_cast<unsigned char>(b);

The casts are there to avoid sign-extension if the most-significant bit of the bytes are set (i.e. they are negative)

nagabathula
17th November 2010, 08:12
Hello ChrisW thank you so much for taking time and helping me out with my problem.

I have a doubt i actually wanted Each byte in the QByteArray to be of 16-bits size.?
I think now each byte is QByteArray is of 8-bits. So i am loosing the data,
only the first 8 bits are taken so i am loosing the other 8 bits. I am getting only "b7" . If i have a 16-bit size for each byte then i will get the right data.


ORed = 0000 0011 1011 0111
0 3 b 7

This is how i tried your code but i din't get any value appended to the Text Browser.
Is this the right way to do it.

QByteArray result;
QByteArray ba;
QByteArray da;
ba[0] = 0x1d;
ba[1] = 0x17;
ba[2] = 0x11;
ba[3] = 0x00;
for (int i = 0; i < ba.size(); i+=2)
{
//result.append(((ba.at(i) << 5)|(ba.at(i+1))));
quint16 result=((static_cast<unsigned int>(ba.at(i) << 5))|(static_cast<unsigned int>(ba.at(i+1))));

}
da.append(result.toHex());
textBrowser->append(da);


If i have each byte in QByteArray ba; as 16-Bits size. i think my problem will be solved.How do you think i should do it Chris. ?

regards

ChrisW67
18th November 2010, 22:03
Your code will output nothing because it never puts anything in the result QByteArray (compare line 10 and 11). Even if it did your result would not be what you expect.

A QByteArray stores bytes, nothing else. As in my last post you want to look at the QVector or QList templates to store other types.



ByteArray ba; // an array of bytes (chars actually)
ba[0] = 0x1d;
ba[1] = 0x17;
ba[2] = 0x11;
ba[3] = 0x00;

QList<quint16> result; // A list of 16 bit unsigned integers

for (int i = 0; i < ba.size(); i+=2)
result.append(
(static_cast<unsigned char>(ba.at(i) << 5))
| static_cast<unsigned char>(ba.at(i+1))
);
}

You have to convert result to hex entry by entry, there is no toHex() to rely on. If you don't need the result retained in binary form (i.e. the result QList) then you can build the hex string as you go along. Conversion

nagabathula
19th November 2010, 05:49
Hello ChrisW i got a suggestion from another person with the below code, it worked Thank You so much you helped me a lot with my problem.



quint16 r;
for (int i = 0; i < data.size(); i+=2)
{
r = (((quint16) data.at(i) << 5) |(data.at(i+1)));
char *ptrR = (char*) &r;
newdat.append(ptrR[1]);
newdat.append(ptrR[0]);
}

I even tried your code but there is no toHex() in QList so i am getting a error there.

what does you mean by
You have to convert result to hex entry by entry , If you don't need the result retained in binary form (i.e. the result QList) then you can build the hex string as you go along Do i have to convert the QList to QByteArray again or what. ?? i wanted to learn how we can do this the way you have told also.

Thank you so much again ChrisW

ChrisW67
19th November 2010, 07:22
You kept saying you wanted to obtain a set of 16 bit integers. You can convert these to a hex string int by int: there is no toHex() method in QList, and there is no QByteArray involved.

There are a lot of ways to do things vaguely like your request but you have to actually understand what you are trying to achieve and know some basic programming.



QList<quint16> result; // A list of 16 bit unsigned integers
for (int i = 0; i < ba.size(); i+=2)
result.append( (static_cast<unsigned char>(ba.at(i) << 5)) | static_cast<unsigned char>(ba.at(i+1)) );
// You now have a list of 16 bit ints like you requested.

// If you wanted only a hex string
QString hex;
for (int i = 0; i < ba.size(); i+=2) {
quint16 r = static_cast<unsigned char>(ba.at(i) << 5)) | static_cast<unsigned char>(ba.at(i+1);
result += QString(%1").arg(r, 4, 16, '0' ); // watch out for byte order if this needs to be portable
}


Given that you already have the data in a buffer, and the result will be exactly the same size as the source data, then you could have done the job in-situ with a bit of thought:


// char *buff
// int numbytes
for (int i = 0; i < numbytes; i+=2) {
unsigned char a = static_cast<unsigned char>( buff[i] );
unsigned char b = static_cast<unsigned char>( buff[i+1] );
buff[i] = a >> 3;
buff[i+1] = a << 5 | b;
}