Consider this snippet, compiled with Arduino IDE:
PROGMEM char charSet[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xA , 0x6, 0xE, 0x1, 0x9,0x5, 0xD, 0x3,0xB,0x7,0xF };
char reversed[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xA , 0x6, 0xE, 0x1, 0x9,0x5, 0xD, 0x3,0xB,0x7,0xF };
char ff;
for (int i=0; i < 16; i++) {
Serial.print(" ");
Serial.print(reversed[i], HEX);
}
Serial.println(" ");
for (int i=0; i < 16; i++) {
Serial.print(" ");
ff = pgm_read_byte(&charSet[i]);
Serial.print(ff);
}
I would expect the two for loops to produce same output. But the output is:
0 8 4 C 2 A 6 E 1 9 5 D 3 B 7 F
FFFFFF94 FFFFFFB0 6 FFFFFF80 FFFFFF91 FFFFFFC7 3 62 FFFFFFE3 E FFFFFF94 5E 29 FFFFFF99 23 39
What am I missing?
Yes, the const keyword is missing.
Probably it is not a good idea to use prog_char, as it is marked as deprecated in gcc-avr, see avr/pgmspace.h
Well the answer was the PROGMEM declaration. I had to move it out from function, adding const keyword. Other changes as datatypes were not working.
The full answer is on Arduino forum.
You have the wrong datatype. From http://arduino.cc/en/Reference/PROGMEM:
Some cryptic bugs are generated by using ordinary datatypes for program memory calls.
You can't use char — you have to use prog_char
So:
PROGMEM prog_char charSet[] = {0x0, 0xB}
That should work.
by the way: You don't have to do Serial.println(" "); You can just do Serial.println();
PROGMEM char charSet[] = ...
This is not good - for PROGMEM data, you can't use ordinary in-memory types. What you should do is
PROGMEM prog_char charSet[] = ...
Related
In my application microcontroller stm32f103 is receiving by USART fixed lenght messages, they contains gps velocity which is big endian data. But elements in structure are small endian. Is there any way without doing it manually to write it in correct way?
typedef struct {
uint32_t test1;
uint16_t test2;
}Mst;
uint8_t myArray[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
void main()
{
Mst * myStruct_p = (Mst)myArray;
}
But after that myStruct_p->test1 equals 0x030201, but should be 0x010203, and myStruct_p->test2 equals 0x0605, but should be 0x0506.
As it is ARM-Cortex M3 we can use special processor instructions. ARM CMSIS have a very handy intrinsic functions __REV & __REV16 which actually compile to the single machine code instruction.
typedef union
{
struct
{
uint32_t test1;
uint16_t test2;
};
uint8_t bytes[6];
}Mst;
Mst mst = {.bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }};
void main()
{
mst.test1 = __REV(mst.test1);
mst.test2 = __REV16(mst.test2);
}
Casting in that way won't work.
You can do a "deserialize" operation.
Although this might be slower than some other methods, it allows you to control the protocol better (e.g. the struct member order doesn't have to follow the protocol) And, there might be padding in the struct, which would show up if we added (e.g.) uint32_t test3; to the end of the struct.
Here's the code:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint32_t test1;
uint16_t test2;
} Mst;
uint8_t myArray[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
uint32_t
get32(uint8_t **base)
{
uint8_t *ptr;
uint32_t val = 0;
ptr = *base;
for (int len = sizeof(uint32_t); len > 0; --len) {
val <<= 8;
val |= *ptr++;
}
*base = ptr;
return val;
}
uint16_t
get16(uint8_t **base)
{
uint8_t *ptr;
uint16_t val = 0;
ptr = *base;
for (int len = sizeof(uint16_t); len > 0; --len) {
val <<= 8;
val |= *ptr++;
}
*base = ptr;
return val;
}
int
main(void)
{
Mst myS;
uint8_t *arr = myArray;
myS.test1 = get32(&arr);
myS.test2 = get16(&arr);
printf("test1=%8.8X test2=%4.4X\n",myS.test1,myS.test2);
return 0;
}
UPDATE:
Yes guys that will work but, i would like to use the processor as little as possible. This is rather manualy putting bytes in to correct order. Also Procedure Mst * struct_p = (Mst*)myArray works safe, because while defining struct i use __attribute__((packed)), just forgoten to write this
I was going to mention/suggest packed as a possibility.
In either case you can use [under GNU]: byteswap.h to get bswap_*. Endian swapping is quite common, so these are [highly] optimized for the given arch. They can even invoke compiler intrinsics (e.g. __builtin_bswap32) which utilize any special instructions the arch has (e.g. x86 has the bswap instruction, and arm has rev16).
So, you can do [i.e. replace the for loop with] (e.g.) bswap_*:
#include <stdio.h>
#include <stdint.h>
#include <byteswap.h>
typedef struct {
uint32_t test1;
uint16_t test2;
uint32_t test3;
} __attribute__((__packed__)) Mst;
uint8_t myArray[] = {
0x01, 0x02, 0x03, 0x04,
0x05, 0x06,
0x07, 0x08, 0x09, 0x0A
};
void
getall(Mst *myS)
{
myS->test1 = bswap_32(myS->test1);
myS->test2 = bswap_16(myS->test2);
myS->test3 = bswap_32(myS->test3);
}
int
main(void)
{
Mst *myS = (Mst *) myArray;
getall(myS);
printf("test1=%8.8X test2=%4.4X test3=%8.8X\n",
myS->test1,myS->test2,myS->test3);
return 0;
}
Overlaying a struct pointer onto a byte array may not necessarily work due to alignment issues and structure padding.
The proper way would be to first use memcpy to copy over the elements:
Mst myStruct;
memcpy(&myStruct.test1, myArray, sizeof(myStruct.test1);
memcpy(&myStruct.test2, myArray + 4, sizeof(myStruct.test2);
Then use ntohs and ntohl which converts 16 and 32 bit values respectively from big endian format to the host's endianness.
myStruct.test1 = ntohl(myStruct.test1);
myStruct.test2 = ntohs(myStruct.test2);
If you just need to convert 8bit data into big endian let say data format will be in order (A B C D) and in little endian data format will be (D C B A) if final result will be stored in 32bit variable and if 16 bit variable then format will (A B) and (B A) .
So this can be done with little bit shifting technique if you know your UART data comming in which format.
Let us first assume that your UART data comes in Little endian and you want it in big endian then you can do like this.
//no structure required
uint32_t myValue;
uint16_t value;
uint8_t myArray[4] = { 0x04, 0x03, 0x02, 0x01 };
// little endian data for 32 bit
uint8_t A[2] = {0x02 ,0x01}; // little endian data for 16 bit
void main()
{
myValue = myArray[3]<<24 | myArray[2]<<16 | myArray[1]<<8 | myArray[0]; // result in big endian 32 bit value
value = A[1]<<8 | A[0]; // result in big endian 16bit value
}
#define F_CPU 16000000UL // AVRJazz28PIN Board Used 16MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_CS PB2
void SPI_Write(uint8_t addr, uint8_t dataout)
{
// Enable CS Pin
SPI_PORT &= ~(1<<SPI_CS);
// Start Address transmission (MOSI)
SPDR = addr;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Data transmission (MOSI)
SPDR = dataout;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Disable CS Pin
SPI_PORT |= (1<<SPI_CS);
}
char digit[10] = {0,0,0,0,0,0,0,0,0,0};
digit[0] = 0x7E
digit[1] = 0x30
digit[2] = 0x6D
digit[3] = 0x79
digit[4] = 0x33
digit[5] = 0x5B
digit[6] = 0x5F
digit[7] = 0x70
digit[8] = 0x7F
digit[9] = 0x7B
void main()
{
char ch;
char digits_disp[10] = {0,0,0,0,0,0,0,0,0,0};
ch = digits_disp[3];
}
this is a very basic code. I am designing a clock using the MAX 7219 display driver. Before i go into the detail of it, I wanted to get a basic code working where I will initialise the SPI and then declare the value of each character using the datasheet of MAX7219 and then just write a short array to display random numbers. But this code is not working propoerly and keeps saying:
../exp3.c:45: error: conflicting types for 'digits_disp'
../exp3.c:44: error: previous definition of 'digits_disp' was here
Can you please help me on what I am doing wrong and could you tell me how I can initialize my array so that I can display the character '3' on my simulation? In other words, what line of code will i need to add in order to display the characters in my array?
Thank you.
I can't really make sense of your code, but this part of the code is syntactically invalid:
char digit[10] = {0,0,0,0,0,0,0,0,0,0};
digit[0] = 0x7E
digit[1] = 0x30
digit[2] = 0x6D
digit[3] = 0x79
digit[4] = 0x33
digit[5] = 0x5B
digit[6] = 0x5F
digit[7] = 0x70
digit[8] = 0x7F
digit[9] = 0x7B
You probably want to do this instead:
char digit[10] = { 0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B };
From the comment in the 1st line I gather you are using one of the Atmel chips. If so, here is the article that should help you:
http://www.adnbr.co.uk/articles/max7219-and-7-segment-displays
You can use their code as the starting point:
https://gist.github.com/adnbr/2352797
Here is also Arduino version in case anyone else is interested:
https://gist.github.com/nrdobie/8193350
I want to perform Golay encoding/decoding on a easurement, which is stored in a char array. Thus, I need to access consecutive 12 bits of the measurement, which are passed to the encoder/decoder.
The char array is 22 byte long and looks like this, for example:
unsigned char measurement1[22] =
{0xb5, 0x31, 0xc6, 0x51, 0x84, 0x26, 0x2c, 0x69, 0xfd, 0x9e,
0xef, 0xd4, 0xcf, 0xf1, 0x24, 0xd4, 0xf1, 0x97, 0xe5, 0x81,
0x02, 0xf8}
At the moment, I am converting the char array into an array of corresponding bits and pass this to the encoder. However, this approach is quite memory exhausting, since the bit array also is a array of chars - 0 or 1 - with 176 bytes (22 * 8) in total.
Is there a more memory-saving approach, which does not depend on converting the byte array into a series of bits, but rather accesses consecutive 12 bits and passes them to the decoder?
Best regards,
P.
Convert an index i not to a 1-byte based offset to 8 bits, but to a 12-bit based offset instead. Then it depends on whether you are indexing an even or odd 12-bit triple:
for (i=0; i<22*8/12; i++)
{
printf ("%03x ", (i & 1) ? measurement1[3*i/2+1]+((measurement1[3*i/2] & 0x0f)<<8) : (measurement1[3*i/2]<<4)+((measurement1[3*i/2+1]>>4) & 0x0f) );
}
This assumes your measurement array is read left-to-right, i.e.
0xb5, 0x31, 0xc6
translates to
0xb53 0x1c6
If your order is different, you need to adjust the bit shifts.
Does it matter that your measurement array does not contain a multiple of 12 bits?
Untested, off the top of my head, I'm sure you can simplify it further...
int i = 0, left = 8, v = 0;
do
{
v = 0;
switch (left)
{
case 8:
{
v = measurement1[i++];
v = (v << 4) | (measurement1[i] >> 4); // please handle end here correctly
left = 4;
break;
}
case 4:
{
v = measurement1[i++] & 0x0F; // lower nibble
v = (v << 8) | measurement1[i++]; // please handle end here correctly
left = 8;
break;
}
}
// Now encode v
} while (i < 22);
You could "parse" the mesurement as an 12 bit array:
typedef union { // you can use union or struct here
uint16_t i : 12;
} __attribute__((packed)) uint12_t;
printf("%u", ((uint12_t*) mesurement)[0]);
This will print the first 12 bits of your array.
I have a function which receives 8-byte data on UART and I am using one of the data byte in a way that I read that data byte and call a function that modulates the volume of the MP3 codec that I am going to use.
The MP3 codec function that sets the volume is a little weird that it sets the sound as if the input to it is 0x00, the 100% volume and if it happens to be 0x64 then its 0%.
Now, the LabVIEW firmware is set up (by some other developer in team) in such a manner that if it wants to set the volume to be 100% then it sends 0x64, and 0x00 for 0%, through the UART into the data byte that I am going to read, as I said above.
Avoiding the complications on this post, what I have tried to do is, to implement a simple C code that would take the input from console and print the processed output. Say if input is 0x00, then the output should be 0x64 and if input happens to be 0x64 then output should be 0x00.
Following is the code that I have written, in which I am getting the Error that says:
Disallowed system call: SYS_socketcall
The code below may appear to be very inefficient and of very basic level, but that is for the sake of understanding.
int main(void)
{
int input = 0x00, output = 0x00, i = 0x00, j = 0x64, var = 0x00;
int in_arr[100], out_arr[100];
for(i = 0x00; i < 0x65; i++, j--)
{
out_arr[i] = j;
in_arr[i] = i;
}
printf("Input : ");
scanf("%x",&input);
for(var = 0x00; var < 0x64; var++)
{
if(input == in_arr[var])
{
output = out_arr[var];
printf("0x%x",output);
break;
}
}
return 0;
}
for(i = 0x00; i < 0x65; i++, j--) // Should be i < 0x64
Here i can have maximum of 101 elements (0 to 100) since 0x65 => 101 but declared to contain only 100 elements.
Make it as i < 0x64 and it should work.
To avoid such confusions, the best is to have macro as #define MAX_ELE 100 and use MAX_ELE in all the places of 0x64.
First, I'm a student still. So I am not very experienced.
I'm working with a piece of bluetooth hardware and I am using its protocol to send it commands. The protocol requires packets to be sent with LSB first for each packet field.
I was getting error packets back to me indicating my CRC values were wrong so I did some investigating. I found the problem, but I became confused in the process.
Here is Some GDB output and other information elucidating my confusion.
I'm sending a packet that should look like this:
|Start Flag| Packet Num | Command | Payload | CRC | End Flag|
0xfc 0x1 0x0 0x8 0x0 0x5 0x59 0x42 0xfd
Here is some GDB output:
print /x reqId_ep
$1 = {start_flag = 0xfc, data = {packet_num = 0x1, command = {0x0, 0x8}, payload = {
0x0, 0x5}}, crc = 0x5942, end_flag = 0xfd}
reqId_ep is the variable name of the packet I'm sending. It looks all good there, but I am receiving the CRC error codes from it so something must be wrong.
Here I examine 9 bytes in hex starting from the address of my packet to send:
x/9bx 0x7fffffffdee0
0xfc 0x01 0x00 0x08 0x00 0x05 0x42 0x59 0xfd
And here the problem becomes apparent. The CRC is not LSB first. (0x42 0x59)
To fix my problem I removed the htons() that I set my CRC value equal with.
And here is the same output above without htons():
p/x reqId_ep
$1 = {start_flag = 0xfc, data = {packet_num = 0x1, command = {0x0, 0x8}, payload = {
0x0, 0x5}}, crc = 0x4259, end_flag = 0xfd}
Here the CRC value is not LSB.
But then:
x/9bx 0x7fffffffdee0
0xfc 0x01 0x00 0x08 0x00 0x05 0x59 0x42 0xfd
Here the CRC value is LSB first.
So apparently the storing of C is LSB first? Can someone please cast a light of knowledge upon me for this situation? Thank you kindly.
This has to do with Endianness in computing:
http://en.wikipedia.org/wiki/Endianness#Endianness_and_operating_systems_on_architectures
For example, the value 4660 (base-ten) is 0x1234 in hex. On a Big Endian system, it would be stored in memory as 1234 while on a Little Endian system it would be stored as 3412
If you want to avoid this sort of issue in the future, it might just be easiest to create a large array or struct of unsigned char, and store individual values in it.
eg:
|Start Flag| Packet Num | Command | Payload | CRC | End Flag|
0xfc 0x1 0x0 0x8 0x0 0x5 0x59 0x42 0xfd
typedef struct packet {
unsigned char startFlag;
unsigned char packetNum;
unsigned char commandMSB;
unsigned char commandLSB;
unsigned char payloadMSB;
unsigned char payloadLSB;
unsigned char crcMSB;
unsigned char crcLSB;
unsigned char endFlag;
} packet_t;
You could then create a function that you compile differently based on the type of system you are building for using preprocessor macros.
eg:
/* Uncomment the line below if you are using a little endian system;
/* otherwise, leave it commented
*/
//#define LITTLE_ENDIAN_SYSTEM
// Function protocol
void writeCommand(int cmd);
//Function definition
void writeCommand(int cmd, packet_t* pkt)
{
if(!pkt)
{
printf("Error, invalid pointer!");
return;
}
#if LITTLE_ENDIAN_SYSTEM
pkt->commandMSB = (cmd && 0xFF00) >> 8;
pkt->commandLSB = (cmd && 0x00FF);
# else // Big Endian system
pkt->commandMSB = (cmd && 0x00FF);
pkt->commandLSB = (cmd && 0xFF00) >> 8;
#endif
// Done
}
int main void()
{
packet_t myPacket = {0}; //Initialize so it is zeroed out
writeCommand(0x1234,&myPacket);
return 0;
}
One final note: avoid sending structs as a stream of data, send it's individual elements one-at-a-time instead! ie: don't assume that the struct is stored internally in this case like a giant array of unsigned characters. There are things that the compiler and system put in place like packing and allignment, and the struct could actually be larger than 9 x sizeof(unsigned char).
Good luck!
This is architecture dependent based on which processor you're targeting. There are what is known as "Big Endian" systems, which store the most significant byte of a word first, and "Little Endian" systems that store the least significant byte first. It looks like you're looking at a Little Endian system there.