dereferencing a created pointer - pointers

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.

Related

reading an array in a function

I am trying using the arduino IDE to write a sketch. I have data in progmem and want to move the data with a function to a memory address allocated using malloc. My code is below:
const uint8_t Data_6 [256] PROGMEM = { 0x11, 0x39......};
void setup() {
Serial.begin(57600);
oddBallData (Data_6, 0x00, 256);
}
void main() {
}
void oddBallData(const uint8_t *data, uint8_t mem, uint16_t bytes) {
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
if (buff1 = 0) {
Serial.println(F("FATAL ERROR - NO MEMORY"));
}
else {
for (uint16_t x = 0; x < 6; x++ ) {
buff1[x] = data[x]; //edited from data[0] to [x] made a mistake in post
Serial.println(buff1[x],HEX);
}
}
buff1[0] = data[0];
Serial.println(buff1[0],HEX);
free(buff1);
}
I have some data saved in progmem and want to write that data to a second device using i2c protocol. I have multiple constant arrays of data saved to my progmem, with different sizes. So I have used malloc to reserve some memory from the heap, inside of the function.
I have not been able to write the data from the progmem so I have stripped things back to so that I am just trying to point to the progmem data using malloc and then print it.
This is where I found a the problem. If I print a single array entry from the data constant. It prints the correct value. If I use a loop I get mixed results, the loop works as long as the condition check value is below 3 or sometimes below 6!!!...?
If above this value the entire print is just garbage. Can anyone explain what I am seeing?
The culprit is probably
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
sizeof(bytes) returns the size of the variable (which is probably 2 bytes) so you are just allocating 2 bytes of memory. You should use the value directly, eg:
uint8_t* buff1 = malloc(bytes);
Mind that the cast is not required in C since a void* is convertible to any other pointer type directly.
Again - AVR PROGMEM is not directly accessible from memory space, it needs different instruction than access into the RAM. If you are using it like this, you'll get RAM content on passed address, not the FLASH one. You have to use special functions for this. For example memcpy_P(ram_buff,flash_ptr); makes a copy from flash into the ram. Or you can read one byte by pgm_read_byte(flash_ptr + offset)
BTW: If you are using Data_6[0] and it's working, it's just because compiler sees it as a constant and constant can be replaced by its value compile time.
I Guess you just forgot to flush()
try to do Serial.flushI() after Serial.println(buff1[x],HEX);
you can also check flush documentation

Bitshifting QBytearray?

I'm looking for a way to sbitshift a QByteArray.
QByteArray statusByte = QByteArray::fromHex("40"); // 0100 0000
What i need to achieve is to get statusByte to 0x20 by bit shifting. Since I can't directly bit shift the QByteArray, what is the simplest method for achieving the shift?
You don't really need a byte array if you only want to get a single numeric (byte) value from a hexadecimal representation of one byte, not multiple bytes.
#if 1
// Qt 5, C++11 compilers
quint8 byte = QStringLiteral("40").toInt(nullptr, 16);
#endif
#if 0
// Qt 5, pre-C++11 compilers
quint8 byte = QStringLiteral("40").toInt(NULL, 16);
#endif
#if 0
// Qt 4
quint8 byte = QByteArray("40").toInt(NULL, 16);
#endif
byte >>= 1;
Q_ASSERT(byte == 0x20); // this is for demonstration only
If you need to bit-shift multiple bytes at once, of course it's also possible - please amend your question to make that clear.
Bit shifting is not a problem when you are talking about single byte, this is trivial (I don't know why you claim it is impossible).
QByteArray statusByte = QByteArray::fromHex("40");
statusByte[0] = statusByte[0]>>1;
statusByte[0]>>=1; // this should also work
if you have multiple bytes then it is more complicated!
endian! How do you define shift where the oldest bit should go, to next byte or to previos byte?
what should happen when array ends? loose data, or extend array?

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.

Automatic conversion of stucture to pointer in function call

We have a pretty normal looking printf style function in our project, with the modification that the %g format means to print a GUID instead of the normal floating-point type. For our case, a GUID looks something like this:
struct guid {
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
};
In reality, the print function expects a pointer to the GUID to be passed, as opposed to the structure itself:
struct guid myGuid = { 0x867FD1E7, 0x9AA7, 0x472A, { 0xAA, 0x56, 0xF2, 0xDA, 0x66, 0x62, 0xCD, 0x4D } };
print("%g", &myGuid);
There are several places in the source base, however, where for some reason the entire guid is passed:
print("%g", myGuid);
This style of call seems to work fine with MSVC2003 - is there some ABI requirement that makes the compiler translate that function call style to actually pass a pointer behind the scenes? When porting this codebase to use clang/llvm, it certainly doesn't do the same thing.
Can somebody explain why the second version of the call works with MSVC? A pointer to the appropriate documentation would be much appreciated!
I think I found some clarification on MSDN:
Any argument that doesn’t fit in 8 bytes, or is not 1, 2, 4, or 8 bytes, must be passed by reference.
Looks like it's time to fix clang!

Mac address ff:ff:ff:ff:ff:ff in C (hex)

How do I write the MAC address ff:ff:ff:ff:ff:ff as a char[] in C?
Do I just do char macaddress[6] = "%0xFF%0xFF%0xFF%0xFF%0xFF%0xFF";
I'm not sure. Thanks!
char macaddress[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
I rather do like this char macaddress[] = "\xff\xff\xff\xff\xff\xff";
There is some coding guide lines for char array initializations, because need to be null-terminated and the size is actually 7.
Do not initialize an array of
characters using a string literal with
more characters (including the '\0')
than the array. Therefore, it is
necessary to specify the correct size
of a string literal (char s[4] =
"abc";).
However, because the result
of the expectation always can be
obtained even if the size of the
string literal is changed, the method
of not describing the size (char s[] =
"abc";) is recommended.
ref:
http://www.caravan.net/ec2plus/guide.html

Resources