Difference in QByteArray.data() and constData() - qt

With Qt 5.8.0.
This code runs as I expected.
static const char mydata[] = {
0x1, 0x2, 0x3, 0x4
};
QByteArray ba = QByteArray::fromRawData(mydata, sizeof(mydata));
const char *p = ba.constData();
const char *pp = QByteArray::fromRawData(mydata, sizeof(mydata)).constData();
qDebug("%p %p\n", p, pp);
output
0x40f548 0x40f548
dump
p 0x01 0x02 0x03 0x04
pp 0x01 0x02 0x03 0x04
But, I am struggling to understand what happens with this code after using data() instead of constData().
char *p = ba.data();
char *pp = QByteArray::fromRawData(mydata, sizeof(mydata)).data();
output
0x166941e8 0x166f8e70
dump
p 0x01 0x02 0x03 0x04
pp 0xee 0xfe 0xee 0xfe 0xee 0xfe ... (should be 0x01 0x02 0x03 0x04 ?)

As explained in Qt documentation, data() function gives you a deep copy of pointer to QByteArray data so every time that is called, it will gives you another value (different address).
While constData() gives you a read only pointer to main object so it value doesn't change on every time calling.
For more details you can check here for data() function description, and here for constData() description.

Related

What does data_ptr()->data() mean in QBitArray?

In short here is the code (qt5.9,wingw32 win10 debug32):
QBitArray array;
array.resize(32);
//...
//array in hex: 0xaabbccdd
char* data = array.data_ptr()->data();
qDebug() << data[0]; //output: 8
//and the size of data is 5:
//data[0]: 0x08
//data[1]: 0x55
//data[2]: 0xdd
//data[3]: 0x33
//data[4]: 0xbb
It seems not like the answer said.
And I did not find the explanation in qt.io documentation.

Raspi I2C communication with Arduino issues with wiringPi

I'm experiencing unexpected results using wiringPi's wiringPiI2CWriteReg16() function, and I'm not sure if it's due to incorrect usage, or something else. This is the declaration for the function:
extern int wiringPiI2CWriteReg16 (int fd, int reg, int data);
There are notes within the wiringPiI2C.c file that state it resembles Linux's SMBus code, if that helps.
On my Arduino (both an Uno R3 and a Trinket Pro), I am running this pared-down sketch:
#include <Wire.h>
#define SLAVE_ADDR 0x04
void receive_data (int num_bytes){
Serial.print("bytes in: ");
Serial.println(num_bytes);
while(Wire.available()){
int data = Wire.read(); // tried char, uint8_t etc
Serial.println(data);
}
Serial.print("\n");
}
void setup() {
Serial.begin(9600);
Wire.begin(SLAVE_ADDR);
Wire.onReceive(receive_data);
}
void loop() {
delay(500);
}
I would think that Wire.read() would break things apart at the byte boundary, but that's not occurring in my case. Perhaps this is my issue... a misunderstanding.
Nonetheless, I have this C code (requires wiringPi v2.36+ to be installed):
// word.c
#include <wiringPiI2C.h>
void main (){
int fd = wiringPiI2CSetup(0x04);
wiringPiI2CWriteReg16(fd, 0x00, 255);
wiringPiI2CWriteReg16(fd, 0x01, 256);
}
Compiled like this:
gcc -o word word.c -lwiringPi
When run, ./word, I receive the following on my Arduino's serial output:
bytes in: 3
0
255
0
bytes in: 3
1
0
1
In the first call to wiringPiI2CWriteReg16(), I expect the first byte in the output to be zero (0x00) as that's the register address I'm requesting. The second byte (255) is also correct. The third byte (0) is meaningless from what I can tell (as I'm only sending in one byte as data).
However, in the second call to that function, I do get the correct output for the register (first byte as 0x01 == 1), but the second byte is zero, and the third byte has what appears to be the correct remainder (255 == one byte, + 1). The problem is, is that the second byte is 0.
The exact same effect happens if I pass in 511 or for that matter, any number as the data in the call.
My question is whether I'm missing something glaringly obvious (I'm relatively new to C and Arduino), and/or if I can get some pointers on how to troubleshoot this more thoroughly.
I found that the problem was in my Arduino code. In the official Raspi forums, Gordon tipped me off that the bytes are read in separately, LSB first. Throughout all of my searching, I hadn't come across that, and really didn't quite understand what was happening. After changing my I2C read loop code in my Arduino sketch to this:
while(Wire.available()){
Wire.read(); // throw away register byte
int16_t data = Wire.read(); // LSB
data += Wire.read() << 8; // MSB
Serial.print("data: ");
Serial.println(data);
}
...everything works. In effect, that's at least one way to read two-byte values over I2C on the Arduino and put the bytes back together.

dereferencing a created pointer

I just have a quick question about what this code mean. Sorry, been reading other posts but I couldn't fully grasp the concept since none seems to resemble this piece of code that I'm currently working in my embedded system.
int8u buf[1024];
memset(buf, 0, sizeof(buf));
*((int16u*)&buf[2]) = 0xbb01;
can someone explain to me what these lines mean?
It basically interprets the array of bytes buf as 16-bit words and then changes the second word to 0xbb01. Alternative representation:
int8u buf[1024];
memset(buf, 0, sizeof(buf));
int16u *words = buf;
buf[1] = 0xbb01;
&buf[2] takes the address to the second byte in buf. Then the cast to (int16u *) informs the compiler that the result is to be treated as a 16-bit unsigned integer. Finally, the memory on that address is set to 0xbb01.
Depending on the endianness of your system, the contents of buf could then be 0x00, 0x00, 0xbb, 0x01 or 0x00, 0x00, 0x01, 0xbb (followed by more NULs due to the memset()).
Please see the comment of the code for explanation
int8u buf[1024]; // intializing int array of size 1024 in RAM.
memset(buf, 0, sizeof(buf)); // fill in buffer with zero.
(int16u*)&buf[2] is a type casting for pointer which points to int16. here casting is given to &buf[2] i.e. address of buf[2].
*((int16u*)&buf[2]) = 0xbb01; // updating content of int16 -two byte intger starting at buf2
Why this is done ?
This is done as buf array was created is of int8u. and now we need to update int16 value 0xbb01. To do this, in above code we have created int16 pointer.
Step by Step simplification of above pointer
((int16u)&buf[2]) = 0xbb01;
updating content of ((int16u*)&buf[2]) by 0xbb01
&buf[2] is pointer to int16u and update its value by 0xbb01
update value at buf[2],buf[3] by 0xbb01.[#]
[#]: exact content of buf[2], buf[3] will depend on type of core architecture: big endian or small endian.

Sending MIDI SysEx messages with the Arduino?

I would like to send a MIDI SysEx message like this to my Roland JX8P Synth.
F0 41 36 06 21 20 01 22 1B F7
This message would alter the VCF cutoff frequency of the synth. 1B is a variable hexadecimal value, swinging from 00 to 7F, relative to cutoff frequency.
In the MIDI library I've found the documentation for sending a SysEx message.
sendSysEx (int length, const byte *const array, bool ArrayContainsBoundaries=false)
From what I can tell bool ArrayContainsBoundaries specifies whether or not you want the library to include the F0 and F7 message start/stop tags (I don't so I'll set it to true). Int length denotes the message length in bytes(my message is 10 bytes, so this will be 10).
What I'm confused about is the array. Instead of storing all the values in the array can I just specify them like this?
MIDI.sendSysEx(10,0xF0 0x41 0x36 0x06 0x21 0x20 0x01 0x22 0x1B 0xF7,true);
Also, is adding the prefix 0x the correct way to specify the bytes here?
The basic answer is "no":
Your sendSysEx() function is looking for take two or three parameters:
Length
The array of data
The flag whether the array contains boundaries or not. This one is optional: if you omit it the parameter will be treated as false
By trying to pass your array data like this:
MIDI.sendSysEx(10,0xF0 0x41 0x36 0x06 0x21 0x20 0x01 0x22 0x1B 0xF7,true);
You are doing one of two things:
As written above, it is just a syntax error: the compiler doesn't know how to parse the list of numeric literals not separated by anything.
If you separated the items by a comma, the compiler says "Oh, he is passing 12 parameters. Let me look for a function that takes 12 integer parameters... oh, I don't have one. Sorry." That gives your no matching function for call to error.
So, one way to call your function is like this:
byte data[] = { 0xF0, 0x41, 0x36, 0x06, 0x21, 0x20, 0x01, 0x22, 0x1B, 0xF7 };
sendSysEx(10, data, true);
In C++11 you can get closer to what you want by initializing the list in the function call, something like sendSysEx(10,{0xF0, 0x41, 0x36, 0x06, 0x21, 0x20, 0x01, 0x22, 0x1B, 0xF7}, true);, however, you'll find that might run into another problem (depending on your toolchain): the compiler may assume that your initializer lists like that are lists of ints, not bytes, which will also cause a compiler error, unless you specifically told your compiler to assume integer literals to be 8 bits.

Getting TCP options (beyond tcphdr->doff) out of * char eth/ip/tcp packer representation

Playing around with http://www.tcpdump.org/sniffex.c to get packet options.
void payload (char *data) { // data contains full copied packet source without ethernet header.
char *ptr = NULL;
//ptr = data;
//struct ip *pip = (struct ip *) ptr;
ptr = data + sizeof(struct ip);
struct tcphdr *thdr = (struct tcphdr *) ptr;
ptr = data + sizeof(struct ip) + (thdr->doff*4);
char *txt = (char *) ptr;
// *txt can be fprint/cout'ed, returned OK.
}
data + struct ip points to TCP header in (pointer) (unsigned char) memory
data + struct ip + thdr->doff*4 points to end of TCP options = beginning of the data
Given the following structure,
typedef u_int tcp_seq;
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
Also there is a reference in TCPDump code:
tp = (struct tcphdr *)bp; // packet header.
hlen = TH_OFF(tp) * 4; // data length?
if (hlen > sizeof(*tp)) {
register const u_char *cp;
register u_int i, opt, datalen;
register u_int len;
hlen -= sizeof(*tp);
So, to read a part of packet, where options lie, it is needed to:
Assume that length specified in packet is > than a structure length
Read N bytes after (ethernet + ip + tcphdr) structure's length?
Drop those bytes off, now read payload.
Correct? It simply boils me off to read a random payload's byte sequence instead of actual data.
The options lie between data + sizeof(struct ip) + sizeof(struct tcphdr) and txt. There may be no options, in which case these pointers will be equal.
The comment "// data length?" is incorrect and should be "// TCP header length in bytes". The if (hlen > sizeof(*tp)) stmt checks if there are any options and also handles the case where random bits are misinterpreted as a TCP header, since that can produce a TH_OFF()*4 less than the min size of the header. After subtracting sizeof(*tp) from hlen, it now contains the size of the TCP options in bytes. The code can then proceed to walk the options. At no point does it read "a random payload's byte sequence instead of actual data", or at least not given what I think you mean...

Resources