This worked for CDC sort of like an none macro version of F() [not sure if it is otherwise different]:
const char HEADER[] PROGMEM = { "-A--B---C----D-----E=A==B===C====D=====E"};
__FlashStringHelper* HP_columns = (__FlashStringHelper*)HEADER;
_
It does not work to send to OLED - like F() doesn't - in place of a string.
I got this to work and it saves RAM - not sure it is optimal yet:
const char P_line1[] PROGMEM = "String 0";
const char P_Hello[] PROGMEM = "Hello World";
const char P_Tinu[] PROGMEM = "Tinusaur";
const char P_Pro[] PROGMEM = "DigiSpark Pro!";
const char P_Test[] PROGMEM = "testing 1 2 3";
char PszBuff[21];
#define GetPsz( x ) (strcpy_P(PszBuff, (char*)x)) // 5242 and 114 RAM
SSD1306.ssd1306_string_font6x8( GetPsz( P_Hello ));
SSD1306.ssd1306_char_f8x16(64, 0, GetPsz(P_Tinu ));
*use of strcpy_P seemed to bring in 150 bytes of code, it (like anything) requires the buffer (PszBuff[]) to pull into. So F() will have to allocate a buffer on demand as well it seems - and something about F() was oddly breaking my CDC examples use of those string (while all else worked) when ram was pushing up to 300 bytes - maybe from that allocation. Something else even in this usage is adding some RAM overhead that I didn't see yet. I made this a #define after I made it a function and it seemed to be more code efficient as a #define:char * GetPsz( const char * ccSz )
{ return strcpy_P(PszBuff, (char*)ccSz);}