I expect from is_bitwise_serializable trait to serialize class like following (without serialize function):
class A { int a; char b; };
BOOST_IS_BITWISE_SERIALIZABLE(A);
A a{2, 'x'};
some_archive << a; // serializes a bitwisely
I wonder, why is there a need to provide serialize function for bitwise_serializable class?
From the documentation:
Some simple classes could be serialized just by directly copying all bits of the class. This is, in particular, the case for POD data types containing no pointer members, and which are neither versioned nor tracked. Some archives, such as non-portable binary archives can make us of this information to substantially speed up serialization.
To indicate the possibility of bitwise serialization the type trait defined in the header file is_bitwise_serializable.hpp is used:
Here are the key points: this optimization
is optional in the archive types where it does apply
doesn't apply to all archive types e.g.
a binary archive that needs to be portable could not be implemented by copying out the raw memory representation (because it is implementation and platform depenedent)
a text archive might not desire to optimize this (e.g. it has different goals to, like "human readable XML", they might not want to encode your vector<A> as a large bas64 encoded blob).
Note that this also explains that is_bit_wise_serializable<T> is not partially specialized for any type that has is_pod<T>::value == true (This could technically be done easily):
some classes might not be interested in serializing all their state (so using bitwise copy would take a lot more space than just selecting the interesting bits (pun intended))
You didn't ask, specifically, but this is what the working implementation would look like:
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <sstream>
struct A { int a; char b;
template <typename Ar> void serialize(Ar& ar, unsigned) {
ar & a;
ar & b;
}
};
BOOST_IS_BITWISE_SERIALIZABLE(A)
int main() {
std::ostringstream oss;
boost::archive::binary_oarchive oa(oss);
A data { 1, 'z' };
oa << data;
}
UPDATE
In response to the commenter who basically posed the same question again, I came up with a demonstration when bitwise serializability would (a) kick in making a visible difference (b) not resulting in the smaller archive:
Live On Coliru
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/serialization.hpp>
#include <array>
#include <fmt/ranges.h>
#include <span>
#include <sstream>
struct A {
int a;
char b;
void serialize(auto& ar, unsigned) { ar& a& b; }
};
#ifdef BITWISE
BOOST_IS_BITWISE_SERIALIZABLE(A)
#endif
int main() {
std::ostringstream oss;
{
boost::archive::binary_oarchive oa(oss,
boost::archive::no_header |
boost::archive::no_tracking |
boost::archive::no_codecvt);
std::array<A, 26> data{{
{1, 'z'}, {2, 'y'}, {3, 'x'}, {4, 'w'}, {5, 'v'}, {6, 'u'}, {7, 't'},
{8, 's'}, {9, 'r'}, {10, 'q'}, {11, 'p'}, {12, 'o'}, {13, 'n'}, {14, 'm'},
{15, 'l'}, {16, 'k'}, {17, 'j'}, {18, 'i'}, {19, 'h'}, {20, 'g'}, {21, 'f'},
{22, 'e'}, {23, 'd'}, {24, 'c'}, {25, 'b'}, {26, 'a'},
}};
oa << data;
}
auto raw = oss.str();
fmt::print("raw serialized form {} bytes: {::#04x}\n", //
raw.size(), std::vector(raw.begin(), raw.end()));
}
When built an run:
for def in REGULAR BITWISE; do g++ -std=c++20 -O2 -Wall -pedantic main.cpp -lboost_serialization -lfmt -o $def -D$def & done; wait
set -x; ./REGULAR; ./BITWISE
Prints
+ ./REGULAR
raw serialized form 148 bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00, 0x00, 0x00, 0x77, 0x05, 0x00, 0x00, 0x00, 0x76, 0x06, 0x00, 0x00, 0x00, 0x75, 0x07, 0x00, 0x00, 0x00, 0x74, 0x08, 0x00, 0x00, 0x00, 0x73, 0x09, 0x00, 0x00, 0x00, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x71, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x0c, 0x00, 0x00, 0x00, 0x6f, 0x0d, 0x00, 0x00, 0x00, 0x6e, 0x0e, 0x00, 0x00, 0x00, 0x6d, 0x0f, 0x00, 0x00, 0x00, 0x6c, 0x10, 0x00, 0x00, 0x00, 0x6b, 0x11, 0x00, 0x00, 0x00, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x69, 0x13, 0x00, 0x00, 0x00, 0x68, 0x14, 0x00, 0x00, 0x00, 0x67, 0x15, 0x00, 0x00, 0x00, 0x66, 0x16, 0x00, 0x00, 0x00, 0x65, 0x17, 0x00, 0x00, 0x00, 0x64, 0x18, 0x00, 0x00, 0x00, 0x63, 0x19, 0x00, 0x00, 0x00, 0x62, 0x1a, 0x00, 0x00, 0x00, 0x61]
+ ./BITWISE
raw serialized form 221 bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x77, 0x7f, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x76, 0x7f, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x7f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x74, 0x7f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x73, 0x7f, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x7f, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x71, 0x7f, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x6c, 0x7f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x69, 0x7f, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x66, 0x7f, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x65, 0x7f, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x64, 0x7f, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x63, 0x7f, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00]
Related
Problem:
I am printing unsigned char array to display an image on a 7.5" waveshare e-Paper display using ESP32 with the following function:
Paint_DrawImage(const unsigned char *image_buffer, UWORD xStart, UWORD yStart, UWORD W_Image, UWORD H_Image)
That function prints an image to an e-paper display image where you also define the starting pixels (xStart, yStart) and the image size in pixels (W_Image, H_Image).
I have the code working with a sample unsigned char array below:
const unsigned char gImage_7in5_V2_b[2056] = { /* 0X00,0X01,0X20,0X03,0XE0,0X01, */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
.... not showing the whole array to save space};
There are some images that will save me a lot of time that are already converted into a similar format which is as an unsigned int with the example below:
const unsigned int icon64_50n[132]= {
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x03000000,0x000000E0,0x1F000000,0x000000E0,0x7F000000,0x000000E0,
.... not showing the whole array to save space};
I have tried defining the array as an unsigned char but that didn't work and was really slow uploading to the ESP32 with lots of warnings.
Question:
Is this considered a byte array? I am new to this data type and need guidance on how/what to search for here.
How do I convert the unsigned int array to unsigned char?
There are a lot of solutions available for passing 2D arrays to an function, but I can not figure out how to assign that array to my object in the constructor. Any help would be appreciated.
I have an array of bytes:
int demo1_rows = 9;
int demo1_id[9] = { 0x0A1, 0x0A2, 0x0A0, 0x0A1, 0x0A2, 0x0A0, 0x0A1, 0x0A2, 0x0A0 };
uint8_t demo1[9][8] = {
{0x00, 0x00, 0x00, 0xC3, 0x00, 0xC3, 0x00, 0xC3},
{0x00, 0x00, 0x00, 0xB9, 0x00, 0xB9, 0x00, 0xB9},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xA5, 0x00, 0xA5, 0x00, 0xA5},
{0x00, 0x00, 0x00, 0xAF, 0x00, 0xAF, 0x00, 0xAF},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xB4, 0x00, 0xB4, 0x00, 0xB4},
{0x00, 0x00, 0x00, 0xB4, 0x00, 0xB4, 0x00, 0xB4},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
};
My object:
Program Demo1(demo1, demo1_id, demo1_size);
My Class:
class Program
{
private:
uint8_t **program;
int *id;
int arraySize;
public:
Program(uint8_t func[][8], int new_id[], int size) {
program = func;
id = new_id;
arraySize = size;
}
}
There is an error when trying to assign func to program.
If you want to fix your current code, with minimal changes, and store the multidimentional array as a reference, you can do this:
typedef the array type, and store it as a reference. Then use the member initializer list in the constructor to take the reference and assign it. This will be similar to storing the pointer to the entire array.
#include <stdint.h>
int demo1_rows = 9;
int demo1_id[9] = { 0x0A1, 0x0A2, 0x0A0, 0x0A1, 0x0A2, 0x0A0, 0x0A1, 0x0A2, 0x0A0 };
uint8_t demo1[9][8] = {
{0x00, 0x00, 0x00, 0xC3, 0x00, 0xC3, 0x00, 0xC3},
{0x00, 0x00, 0x00, 0xB9, 0x00, 0xB9, 0x00, 0xB9},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xA5, 0x00, 0xA5, 0x00, 0xA5},
{0x00, 0x00, 0x00, 0xAF, 0x00, 0xAF, 0x00, 0xAF},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xB4, 0x00, 0xB4, 0x00, 0xB4},
{0x00, 0x00, 0x00, 0xB4, 0x00, 0xB4, 0x00, 0xB4},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
};
typedef uint8_t MyArray[9][8];
class Program
{
private:
MyArray& program;
int* id;
int arraySize;
public:
Program(MyArray& func, int new_id[], int size)
: program (func)
{
id = new_id;
arraySize = size;
// you can now access program[3][3] etc
}
};
int main()
{
Program p(demo1, demo1_id, demo1_rows);
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
For a product I am co-designing I want to display bitmap icons on an LCD screen. Inspired by among others this tutorial I created a separate C-file with the byte array of the icon I am trying to display.
When I try to display the icon directly it seems to work. But when I try to do it indirectly - which is going to be nessecary eventually - it fails.
What really baffles me and what I seek to understand is; when I print out the array of the garbage icon (CHAR ARRAY) to the serial monitor and compare it to the byte array it is suppose to represent they match correctly.
But when I do the same for the image that is displayed correctly (ICON ARRAY), what I print to the serial monitor does not match the byte array it is displaying, the information I printed is not even consistent... How can this be ?!
I have been cracking my head over this for a week now so any help would be greatly appreciated.
The main file:
// --------------------------------------------------------------------------------------
// | This program is made for an arduino mega 2560 used in conjunction with the |
// | (chinese) OPEN-SMART 3.2 inch TFT LCD Shield ILI9327 |
// | This version of the program is a slimmed down one to clearly convey the problem |
// | I am currenlty having drawing pictures on this setup |
// --------------------------------------------------------------------------------------
// This program is based on the library obtained from
// https://drive.google.com/open?id=0B6uNNXJ2z4CxYktCQlViUkI1Sms
// There is also a demo available on YouTube
// https://www.youtube.com/watch?v=JQHGYnKeC0M&t=2s
#include <Adafruit_GFX.h> // Core graphics library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
// -------------------------------------------------------------------------------------
// | Variable declaration |
// -------------------------------------------------------------------------------------
// Set colors
#define BLACK 0x0000
#define BACKGROUND 0x07FF
// No idea with this does tbh
uint16_t g_identifier;
// Spacing variables
uint8_t cube_size = 75;
uint8_t padding = 3;
uint8_t ix1 = 5+2 * padding;
uint8_t ix2 = 5+3 * padding + cube_size;
uint8_t ix3 = 5+4 * padding + 2 * cube_size;
uint8_t ix4 = 5+5 * padding + 3 * cube_size;
uint16_t ix5 = 5+(6 * padding) + 4 * cube_size;
uint8_t iy1 = 5+1 * padding;
uint8_t iy2 = 5+3 * padding + cube_size;
uint8_t iy3 = 5+4 * padding + 2 * cube_size;
//Progmem Icon init
extern uint8_t icon_from_progmem[];
// -------------------------------------------------------------------------------------
// | Functions |
// -------------------------------------------------------------------------------------
// Standard drawbitmap function
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) {
int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
uint8_t byte = 0;
for (int16_t j = 0; j < h; j++, y++) {
for (int16_t i = 0; i < w; i++) {
if (i & 7) byte <<= 1;
else byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
if (byte & 0x80) tft.drawPixel(x + i, y, color);
}
}
}
// -------------------------------------------------------------------------------------
// | Setup |
// -------------------------------------------------------------------------------------
// I just copied this part to get the screen to work
void setup(void) {
Serial.begin(9600);
Serial.println(F("TFT LCD test"));
// tft.reset(); //we can't read ID on 9341 until begin()
g_identifier = tft.readID(); //
Serial.print("ID = 0x");
Serial.println(g_identifier, HEX);
if (g_identifier == 0x00D3 || g_identifier == 0xD3D3) g_identifier = 0x9481; // write-only shield
if (g_identifier == 0xFFFF) g_identifier = 0x9341; // serial
// g_identifier = 0x9329; // force ID
tft.begin(g_identifier); //to enable ILI9327 driver code
tft.setRotation(3); //Change orientation (landscape and portrait)
}
// -----------------------------------------------------------------------------------
// | Loop |
// -----------------------------------------------------------------------------------
void loop(void) {
tft.fillScreen(BACKGROUND); //
unsigned char myCharArray[512];
byte myChar;
for (int k = 0; k < 512; k++) {
// Create myCharArray from icon_from_progmem
myChar = pgm_read_byte(icon_from_progmem + k);
myCharArray[k] = char(myChar);
// Print data from myCharArry to the serial monitor
Serial.print("CHAR ARRAY: ");
Serial.print(k);
Serial.print(" ");
Serial.println(myChar);
}
// Visual separtion string
Serial.println("------------------------------------------------------------------");
// Print data from icon_from_progmem to serial monitor
for (int k=0; k<512; k++){
Serial.print("ICONS ARRAY: ");
Serial.print(k);
Serial.print(" ");
Serial.println(icon_from_progmem[k]);
}
// Draw the two icons on the screen
drawBitmap(ix2, iy1, myCharArray, 64, 64, BLACK);
drawBitmap(ix4, iy1, icon_from_progmem, 64, 64, BLACK);
delay(600000);
} // end of void loop
The separate file for the bitmap:
#include <avr/pgmspace.h>
// 'PlafLamp', 64x64px
const unsigned char icon_from_progmem [] PROGMEM = {
0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xc0, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x7f, 0x00, 0x00,
0x00, 0x01, 0xfc, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00,
0x00, 0x0f, 0x80, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00,
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00,
0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x07, 0xc0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x03, 0xe0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7c, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x80, 0x3f, 0x00, 0x00,
0x00, 0x01, 0xf8, 0x03, 0xc0, 0x1f, 0x80, 0x00, 0x00, 0x03, 0xf0, 0x03, 0xc0, 0x0f, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x03, 0xc0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xe0, 0x00,
0x00, 0x07, 0x80, 0x03, 0xc0, 0x01, 0xe0, 0x00, 0x00, 0x03, 0x00, 0x03, 0xc0, 0x00, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00
};
What is displayed on the screen
The image on the left is the CHAR ARRAY and the image on the right is the ICON ARRAY.
in drawBitmap() you are iterating through bytes via pgm_read_byte()
In the avr-libc docs it says
Read a byte from the program space with a 16-bit (near) address.
Note:
The address is a byte address. The address is in the program space.
Your array that is a copy of the bitmap, "myCharArray", is not in program space so pgm_read_byte() does not operate correctly.
I'm trying to implement MD5 hash function in C++ and get correct results for some input values that I have found through some websites online which are some hexadecimal values. Up till this point I have been able to get it work correctly. However, when I try to do the same thing with ASCII strings, I'm out of luck and cannot really understand exactly what else should I do.
The first thing I have done is to convert ASCII string into hex value and append single 0x80 at the end after which follows a bunch of 0x00 s and at the last eight bytes the length of the non-appended message in hexadecimal.
For example, "test123" is represented in hexadecimal as "0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33" and its length in bytes is 7. Then the byte array to be used as input to hash function is as far as I get it is as below,
const uint8_t test123Array[64] = {
0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07
};
And when I applied the hash function, the result I get is,
e7 54 fa ea 1e d7 69 ba 85 59 62 bf 16 e9 98 48
Whereas result I get through online hash generator websites is something like
cc 03 e7 47 a6 af bb cb f8 be 76 68 ac fe be e5
The length of the data is not counted in bytes, but rather in bits. So, the length is not 7, but 56 (0x38). This length is then encoded into 64 bit in Little-Endian byte order.
The prepared input should look like this:
const uint8_t test123Array[64] = {
0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
The specification of MD5 you linked to contains everything you need to know about that. Take a closer look at Section "3.2 Step 2. Append Length" and the Encode function in Section "A.3 md5c.c".
I have three array, like this, that contains my bitmap images:
static unsigned char __attribute__ ((progmem)) impostazioni_logo[]={
0x00, 0x02, 0x7E, 0x02, 0x00, 0x00, 0x78, 0x10, 0x08, 0x08, 0x08, 0x70, 0x10, 0x08, 0x08, 0x08,
0x70, 0x00, 0x00, 0x78, 0x10, 0x08, 0x08, 0x08, 0x10, 0x60, 0x00, 0x00, 0x60, 0x10, 0x08, 0x08,
0x08, 0x10, 0x60, 0x00, 0x00, 0x30, 0x48, 0x48, 0x08, 0x08, 0x10, 0x00, 0x00, 0x08, 0x7E, 0x08,
0x08, 0x08, 0x00, 0x00, 0x50, 0x48, 0x48, 0x48, 0x70, 0x00, 0x00, 0x08, 0x08, 0x08, 0x48, 0x28,
0x18, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x60, 0x10, 0x08, 0x08, 0x08, 0x10, 0x60, 0x00, 0x00, 0x78,
0x10, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x08, 0x0F, 0x08, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x7F, 0x08, 0x08,
0x08, 0x08, 0x04, 0x03, 0x00, 0x00, 0x03, 0x04, 0x08, 0x08, 0x08, 0x04, 0x03, 0x00, 0x00, 0x04,
0x08, 0x08, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00, 0x07, 0x08, 0x08, 0x08, 0x00, 0x07, 0x08, 0x08,
0x08, 0x04, 0x0F, 0x00, 0x00, 0x0C, 0x0A, 0x09, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00,
0x03, 0x04, 0x08, 0x08, 0x08, 0x04, 0x03, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F,
0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
Now i want a function return the correct array to display on lcd by passing the page parameter.
unsigned char logo(int page){
char buffer[32];
switch(page){
case 1:
for(int i=0;i<sizeof(impostazioni_logo);i++){
strcpy_P(buffer,pgm_read_byte(&(impostazioni_logo[i]))); //<==pgm_read_byte comes from here:http://www.arduino.cc/en/Reference/PROGMEM
}
break;
}
return buffer;
}
it doesn't work. Compiler tell me something wrong about conversion.
EDIT:
caller is a simply function that draw the right image. Images can be different for different pages. Number of pages are near 20:
void drawLogo(){
glcd.drawbitmap(15,1, logo(), 90,16); //display lcd library for ST7565
}
There are a few issues with this code:
return type for logo is unsigned char while you are returning char *
pgm_read_byte supposedly returns a byte, so you could simply do buffer[i]=pgm_read_byte(...)
buffer that you are trying to return is allocated on the stack and will not exist after function returns.
You should probably be using strlcpy_P instead.
Update:
1. Assuming you have a fixed number of pages. Try creating a bitmap per page, like:
static unsigned char __attribute__ ((progmem)) impostazioni_logo_page1[]={..}
2. return a pointer to each pages' logo:
unsigned char* logo(int page)
{
switch(page)
{
case 1:
return impostazioni_logo_page1;
break;
}
return NULL;
}
If you like to have all bitmaps in a single array, calculate an offset in the array and return that instead:
int offset = page_num*page_size_in_chars;
return &impostazioni_logo_all_pages[offset];
Update 2: Another option to manage pages:
static unsigned char* pages[] = { impostazioni_logo_page1, impostazioni_logo_page2, ... }
...
glcd.drawbitmap(15,1, pages[page_index], 90,16);