Understanding the language, error messages, etc.
by qubist » Sat Aug 23, 2014 4:21 am
Hi,
I want to draw a bitmap from RAM not PROGMEM but it doesn't seem to work. Is there some trick?
The bitmaps that work I declare like this:
- Code: Select all
const byte x[] PROGMEM= {
84, 48,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
...
The bitmaps that don't work I declare like this:
- Code: Select all
byte x[]= {
84, 48,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
...
Why does this happen
Thanks!
-
qubist
-
- Posts: 31
- Joined: Thu Mar 27, 2014 1:58 am
- Location: USA
by microgamer » Sat Aug 23, 2014 5:57 am
I had the same problem on the microview that arrays around the 500 byte mark would use up all the free SRAM.
Try your code with a smaller bitmap?
Edit - the way PROGMEM arrays are accessed is slightly different. Maybe the routine you are using to display is set up for that?
-
microgamer
-
- Posts: 8
- Joined: Tue Aug 12, 2014 9:13 am
by Matrix828 » Sat Aug 23, 2014 8:21 am
The drawBitmap function only works with PROGMEM arrays.
-
Matrix828
-
- Posts: 43
- Joined: Tue Jul 22, 2014 7:44 pm
-
by Myndale » Sat Aug 23, 2014 8:37 am
It's easy enough to modify the drawBitmap function though, the key is this bit of code:
- Code: Select all
if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (B10000000 >> (i % 8))) {
drawPixel(x + i, y + j);
}
This code assumes that the bitmap is in progmem, so all you need to do it copy the entire function into your program, rename it and modify it to use RAM instead. Something like this should do it:
- Code: Select all
if (bitmap[j * byteWidth + i / 8] & (B10000000 >> (i % 8))) {
drawPixel(x + i, y + j);
}
-
Myndale
-
- Posts: 507
- Joined: Sat Mar 01, 2014 1:25 am
by Matrix828 » Sat Aug 23, 2014 8:45 am
Following on from Myndale, you'll also need to change
- Code: Select all
int8_t w = pgm_read_byte(bitmap);
int8_t h = pgm_read_byte(bitmap + 1);
To something like this:
- Code: Select all
int8_t w = bitmap[0];
int8_t h = bitmap[1];
-
Matrix828
-
- Posts: 43
- Joined: Tue Jul 22, 2014 7:44 pm
-
by qubist » Sun Aug 24, 2014 5:56 am
so all you need to do it copy the entire function into your program, rename it and modify it to use RAM instead.
Where would I find the entire function to copy and change that bit?
-
qubist
-
- Posts: 31
- Joined: Thu Mar 27, 2014 1:58 am
- Location: USA
by qubist » Sun Aug 24, 2014 8:06 pm
OK I found it in the library. Here is the original code:
- Code: Select all
void Display::drawBitmap(int8_t x, int8_t y, const uint8_t *bitmap) {
int8_t w = pgm_read_byte(bitmap);
int8_t h = pgm_read_byte(bitmap + 1);
bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
#if (ENABLE_BITMAPS > 0)
int8_t i, j, byteWidth = (w + 7) / 8;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (B10000000 >> (i % 8))) {
drawPixel(x + i, y + j);
}
}
}
#else
drawRect(x, y, w, h);
#endif
}
And here is what I changed it to:
- Code: Select all
void DrawBitmapRAM(int8_t x, int8_t y, const uint8_t *bitmap) {
int8_t w = bitmap[0];
int8_t h = bitmap[1];
bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
#if (ENABLE_BITMAPS > 0)
int8_t i, j, byteWidth = (w + 7) / 8;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
if (bitmap[j * byteWidth + i / 8] & (B10000000 >> (i % 8))) {
gb.display.drawPixel(x + i, y + j);
}
}
}
#else
drawRect(x, y, w, h);
#endif
}
It works now. Thanks!
-
qubist
-
- Posts: 31
- Joined: Thu Mar 27, 2014 1:58 am
- Location: USA
by Myndale » Mon Aug 25, 2014 2:04 am
On a similar note Rodot how would you feel about exposing the back buffer via the interface? It's easy enough to access it at the moment by externing it like so:
- Code: Select all
extern uint8_t _displayBuffer[LCDWIDTH * LCDHEIGHT / 8];
It would be nice to make it official though as it would allow people to write highly optimized custom routines without having to go through drawPixel.
-
Myndale
-
- Posts: 507
- Joined: Sat Mar 01, 2014 1:25 am
by rodot » Mon Aug 25, 2014 7:31 am
Myndale wrote:On a similar note Rodot how would you feel about exposing the back buffer via the interface? It's easy enough to access it at the moment by externing it like so:
- Code: Select all
extern uint8_t _displayBuffer[LCDWIDTH * LCDHEIGHT / 8];
It would be nice to make it official though as it would allow people to write highly optimized custom routines without having to go through drawPixel.
What do you mean "make it official"? Explain in the reference that you can use "extern uint8_t _dipsplayBuffer" ?
-
rodot
- Site Admin
-
- Posts: 1290
- Joined: Mon Nov 19, 2012 11:54 pm
- Location: France
-
by Myndale » Mon Aug 25, 2014 8:54 am
rodot wrote:What do you mean "make it official"? Explain in the reference that you can use "extern uint8_t _dipsplayBuffer" ?
In C there's a general convention that a variable with a leading underscore is considered private, in which case you don't reference it because your code could break in future. At the moment it's certainly possible to access the buffer by externing it, but doing so is bad form. Making it official would simply involve a getBackBuffer() function or something in the Display class, that would future proof the library and give you freedom to rename the buffer or overlay it with the SD buffer or whatever else you want to do without breaking existing code.
It's not a huge deal, just a coding convention thing. You could also just add the extern to the Display.h file, although for the reasons I state above I'd suggest stripping that leading underscore from the array name.
-
Myndale
-
- Posts: 507
- Joined: Sat Mar 01, 2014 1:25 am
Return to Programming Questions
Who is online
Users browsing this forum: No registered users and 59 guests