Using Progmem for display text

Hi all

I have a program on a Pro-mini that uses a small 128x32 Oled screen.

There is a lot of text for this screen, so I threw them to the PROGMEM using (as an example):

const char string_0[] PROGMEM =  "      AIR TANK";
const char string_1[] PROGMEM =  "     CONTROLLER";
const char string_2[] PROGMEM =  "  Calibrating Gyro";
const char string_3[] PROGMEM =  "   No Gyro found";
const char string_4[] PROGMEM =  " Set operation mode";

etc etc etc

const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7, string_8, string_9, string_10,
                                            string_11, string_12, string_13, string_14, string_15, string_16, string_17, string_18, string_19, string_20,
                                            string_21, string_22, string_23, string_24, string_25, string_26, string_27, string_28, string_29, string_30,
                                            string_31, string_32, string_33, string_34, string_35, string_36, string_37
                                           };
char buffer[20];

To display the text I use:

void DisplayText() {

  strcpy_P(buffer, (char*)pgm_read_word(&(string_table[txt])));                                               // Retrieves the string
  display1.print(buffer);
  display1.display();
}

I have 37 of these text lines and it all works fine. But.... my sketch uses 99% of the programming space and only 35% of the dynamic memory.

So I thought, just take them out of PROGMEM and free up some space.... nope

I clearly don't quite understand the process here. I thought PROGMEM allocated that text to the programming memory space. If I remove the PROGMEM command, does it not move to the dynamic memory?

Changing all 37 text commands to the following makes no difference at all to the compiling memory count?

const char string_2[] =  "  Calibrating Gyro";

Can someone please explain?

There's your explanation.

No, it makes sure they stay there.

So what is the point of using PROGMEM?

It saves RAM

Hmm... OK.

The program does run fine, but I don't like having it peaked at 99%... no room for adjustment.

There is probably a more efficient way of storing text. I will investigate.

Of course there are, lots of them (Huffman, RLC, LZ...)
But they all require decoding, which requires more code space...

(You could eliminate leading whitespace in your strings )

I did try eliminating the white spaces. But then they don't all fall within the 20 character buffer I am using.

My print routine uses the same SetCursor position (rather that state 37 different ones for each piece of text).

I suppose I could try that

If you have an initialized variable in ram, then the value that it is to be initialized TO has to be stored in flash. So you wind up with two copies. When you use program, you only need the copy that is in Flash.

You don't have to always use all of the buffer :roll_eyes:

You can work out the length of the string on the fly, and use that to centre/justify your txt

38 strings at 21 char each would need 798 bytes, that is not your problem.
You do not need to copy into ram if the display library inherits from print, just cast to __FlashStringHelper* instead of char*.

I don't know what that means.

As for not using all of the buffer, I thought if you declared 20 characters, it put that much aside, whether you use it or not

It's how the Print class works with the F() macro.
You have the source - why not take a look?

size_t Print::print(const __FlashStringHelper *ifsh)
{
  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    if (write(c)) n++;
    else break;
  }
  return n;
}
void DisplayText() {
  //strcpy_P(buffer, (char*)pgm_read_word(&(string_table[txt])));
  //Serial.println(buffer);
  Serial.println((__FlashStringHelper*)pgm_read_word(&string_table[txt]));
}

Shown here using Serial. Note that you can also use pgm_read_ptr, which does not require that you know the size of a pointer.