How can I retrieve the address of bitmaps in PROGMEM to show it on OLED display without using a switch..case construct?

I have a rather complex application which controls the number of cups of coffee that are drawn. After different numbers the water tank has to be filled or the coffee grounds has to be discarded.

This application performs well for several years and now I want to add a fan to dry the coffee grounds to prevent mold, which now forms after several days.

The available space in flash is almost eaten up (around 100 bytes left after several loops of optimization).

Randomly bitmaps (smileys) are displayed, the bitmaps are 392 byte in size each, I have 7 of them.

They are stored as follows:

//const unsigned char Sm1Dimension[] PROGMEM = {56, 56};
const unsigned char Smiley1[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00,
    0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x00,
... (cut out several lines of bytes)
    0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xc0, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
};
const unsigned char Smiley2[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00,
    0x3f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00,
... (cut out several lines of bytes)
    0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
... and so on until 
const unsigned char Smiley7[] PROGMEM = {...};

In the first approach I selected the to be displayed bitmap by means of a switch..case construct which works perfectly. The Adafruit GFX library accepts the pointers and displays the bitmaps as expected.

Below the part of working code:

        switch(cSmileySelect)       // select Smiley
    {
        case 1: 
            pSmileyAdresse = Smiley1;
            break;
        case 2:
            pSmileyAdresse = Smiley2;
            break;
        case 3:
            pSmileyAdresse = Smiley3;
            break;
        case 4:
            pSmileyAdresse = Smiley4;
            break;
        case 5:
            pSmileyAdresse = Smiley5;
            break;
        case 6:
            pSmileyAdresse = Smiley6;
            break;
        case 7:
            pSmileyAdresse = Smiley7;
            break;
        default:    
            pSmileyAdresse = Smiley1;
            break;
    }
// void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t width, int16_t height, uint16_t color);
    display.drawBitmap((128 - cSmileyBreite) / 2, 0 + (64 - cSmileyHoehe) / 2, pSmileyAdresse,
            (unsigned int)cSmileyBreite, (unsigned int)cSmileyHoehe, WHITE);

After again experiencing memory shortage when adding the logic to drive a fan, I found, that this switch..case construct uses up plenty of flash.

I tried to replace the switch..case by means of mathematics to derive the pointer to the bitmap in flash, but I get no result.

My test are as so:

pSmileyAdresse = (uint8_t*)(uint16_t)((Smiley7) + (2352 - (((cSmileySelect - 1) % 7) * (sizeof(Smiley7))  )));

The magic number 2352 is the size of the complete array of 7 smileys, the bitmaps are stored in descending order (smiley7 at the lowest address).

My expectation was, adding the size of each Smiley bitmap should derive the address of the next smiley, but to no avail.

Next approach was, to build up an array of pointers to the smileys…

const unsigned char*  Smileys[] = {
&Smiley1[0], &Smiley2[0], &Smiley3[0], &Smiley4[0], &Smiley5[0], &Smiley6[0], &Smiley7[0], &Smiley13_bw[0]
};

…and get the address of the selected smiley by this:

pSmileyAdresse = (const uint8_t*)(Smileys[cSmileySelect - 1][0]);

This might have worked, but this small addition to my code swells the code in flash by 3166 byte, busting the maximum by ~2000 byte.

Why this?

And lastly:
Is there a way of deriving the PROGMEM addresses of the smileys by simple mathematics, not busting the flash limit?

Thanks!

New contributor

Harry S is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

7

void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t width, int16_t height, uint16_t color);

AdafruitGFX offers two overloaded methods for drawBitmap(). This particular method allows you to pass in a pointer to a bitmap that is located in the RAM, as you can see from the source code, it doesn’t read the data from the PROGMEM, but simply get a byte with b = bitmap[j * byteWidth + i / 8];. So if you are calling the method with the function signature, data need to be first copy into a ram buffer and calling the function with the pointer to ram buffer, obviously that would take up to the RAM memory of the size of Smileyx.

The correct API to call is the second overloaded method:

void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)

Noticed that the subtle difference is the const uint8_t bitmap[] and the source code indicated that it read a byte directly from the PROGMEM with:

b = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);

This would take only 1 byte of RAM to store the b instead of the size of Smiley1. To use this method, all it needs is to directly pass in the Smiley1 as:

display.drawBitmap(x, y, Smiley1, w, h, color);

3

The initial question arose when I was on search for code optimization to free flash memory for further enhancing the program by additional functions. I back then found, that commenting out the switch…case construct, I used to get the adress of the to be displayed bitmap, frees a considerable amount of flash space.
But I missed the fact, that the now no longer referenced bitmaps are optimized away by the linker.
So I was mislead into thinking, the switch…case construct uses up so much space and has to be replaced by something more efficient.
In the end, supported by @Maximilian and @hcheung, I found, that every approach leads to the same memory shortage as the initial switch…case construct.
Finally: No solution but gain in knowledge 🙂

New contributor

Harry S is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật