Шрифт в PROGMEM

vadimb
Offline
Зарегистрирован: 23.11.2017

Добрый день!

Есть шрифт с переменной шириной символов, сгенерированные в TheDotFactory, да еще и с несколькими массивами описания (для экономии памяти, так как часть символов не используется). Шрифт сжирает крайне много ОЗУ. Если же массив шрифта хранить в PROGMEM, то на дисплее отображаются каракули, нагуглил функцию pgm_read_byte, но как её применить в функции отрисовки символа, не могу понять. Хелп...

uint8_t ww;
uint16_t oo;
void Gui_GetFontDescr(char c)
{
    for(int i=font.count_descr; i>0; i--)
    {
        if ((c>=font.charInfoLookup[i].startChar)&&(c<=font.charInfoLookup[i].endChar))
        {
            ww=font.charInfoLookup[i].charInfo[c-(font.charInfoLookup[i].startChar)].char_width;
            oo=font.charInfoLookup[i].charInfo[c-(font.charInfoLookup[i].startChar)].char_offset;
            return;
        }
    }
    ww=0;
    oo=0;
}
uint8_t Gui_DrawChar(const char c, uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor)
{
    const unsigned char *bitmap_ptr;
    const unsigned char *__bitmap_ptr;
    unsigned char tmp;
    uint8_t i, j, k, font_height_bytes;
    uint8_t current_char_width;
    uint16_t offset;
    uint8_t __x = x;
    uint8_t __y = y;

    // Get height in bytes
    font_height_bytes = (font.font_height)/8;
    if ((font.font_height)%8) font_height_bytes++;
    // Get width of current character
    Gui_GetFontDescr(c);
    current_char_width=ww;
    offset=oo;
    // Get pointer to data
    bitmap_ptr = &(font.font_bitmap_array[offset]);
    // Copy to temporary ptr
    __bitmap_ptr = bitmap_ptr;

    Gui_DrawRectFill(x,y,current_char_width,font.font_height,bgcolor);
    for(k=current_char_width; k>0; k--)
    {
        // Width of character
        for(i=font_height_bytes; i>0; i--)
        {
            // Height of character
            // Get data to "shift"
            tmp = *__bitmap_ptr;
            __bitmap_ptr += current_char_width;
            for(j=8; j>0; j--)
            {
                // Push byte
                if( (tmp & 0x01) ){Gui_DrawPoint(__x,__y,color);}
                else{/*Gui_DrawPoint(__x,__y,bgcolor);*/}
                tmp >>= 1;
                __y++;
            }
        }
        __x++;
        __y = y;
        __bitmap_ptr = ++bitmap_ptr;
    }
    return current_char_width;
}

 

b707
Онлайн
Зарегистрирован: 26.05.2017

Не вижу в коде, чтобы вы пытались использовать pgm_read_byte(). Ждете готового решения? - зря

В ваших многомерных описаниях фонтов копайтесь сами, а в общем случае работа с массивом в PROGMEM совсем несложна:

// если шрифт описан как массив
const byte PROGMEM array[] = {0,1,3,4,5,6};

// доступ к n-тому байту массива
aa = pgm_read_byte(&array[n]);

 

vadimb
Offline
Зарегистрирован: 23.11.2017

Код выложен исходный, который работает на данный момент с шрифтом в ОЗУ. С множественным описанием я разберусь, мне главное чтобы массив считывался правильно. Естественно я пытался и так и сяк использовать pgm_read_byte. Но или шрифт не рисуется совсем, или не компилируется. Не въезжаю я во все эти указатели и ссылки, потому и прошу помощи.

Logik
Offline
Зарегистрирован: 05.08.2014

vadimb пишет:

 Не въезжаю я во все эти указатели и ссылки

Ага. Мы это видем, а без этого нифига не будет. Учите матчасть.

b707
Онлайн
Зарегистрирован: 26.05.2017

vadimb пишет:

Естественно я пытался и так и сяк использовать pgm_read_byte. Но или шрифт не рисуется совсем, или не компилируется. Не въезжаю я во все эти указатели и ссылки, потому и прошу помощи.

выкладывайте код, где пытались использовать pgm_read_byte

vadimb
Offline
Зарегистрирован: 23.11.2017
for(j=8; j>0; j--)
            {
                // Push byte
                unsigned char ddd=pgm_read_byte(&tmp);
                if( (ddd & 0x01) ){Gui_DrawPoint(__x,__y,color);}
                else{/*Gui_DrawPoint(__x,__y,bgcolor);*/}
                ddd >>= 1;
                __y++;
            }

вот например. остальное в функции без изменений.

b707
Онлайн
Зарегистрирован: 26.05.2017

vadimb пишет:

for(j=8; j>0; j--)
            {
                // Push byte
                unsigned char ddd=pgm_read_byte(&tmp);
                if( (ddd & 0x01) ){Gui_DrawPoint(__x,__y,color);}
                else{/*Gui_DrawPoint(__x,__y,bgcolor);*/}
                ddd >>= 1;
                __y++;
            }

вот например. остальное в функции без изменений.

так работать не будет, tmp у вас - временная переменная в оперативке, зачем ее читать функцией pgm_read_byte() ?

Вам нужно читать непосредственно из массива фонта в прог-меме, то есть функцию нужно вставить в ту строку, где у вас считывается tmp:

- в строке 32 исходного кода попробуйте изменить оператор на

tmp = pgm_read_byte(__bitmap_ptr);

, остальное верните как было

vadimb
Offline
Зарегистрирован: 23.11.2017

Да, так работает, спасибо! А я еще пробовал вот так pgm_read_byte(&bitmap_ptr), потому что во всех примерах, что я находил, был амперсанд, и переменную брал bitmap_ptr, а не __bitmap_ptr, ведь выше они приравнивались, я и посчитал, что это одно и то же. А почему они разные?