Resource Manager

Hi All,

I had mentioned this in other threads but thought this maybe the better place for it.

As some may know the use of the F() macro on text is great for saving RAM, but the this space is not optimised for duplicates.

As we ALL know space is a premium on any embedded controller.

So came the thought of a "Resource" manager for handling all those duplicates in Flash.

Now I am no trained programmer, so mostly I never know the "CORRECT" way to achieve the result. Sure I can make it work, but I would be the first against the wall for Code abuse.

So before I go off making a tool for auto creating a chunk of code, I thought I would feel out the best approach.

So consider this, In your code you use "TEXT", be they Strings, Char arrays or some other method I don't know of. If you use a lot of words then the chance of duplications is fairly high.?

This is where peoples blood will start to boil, So to print some text

Serial.Print("Some Text");
Serial.Println("Some Other Text");

move the Static text to flash,

Serial.Print(F("Some Text"));
Serial.Println(F("Some Other Text"));

Nice and Easy. Other methods:

char sometext[] = "Some Text";
char someothertext[] = "Some Other Text";

Serial.Print(sometext);
Serial.Println(someothertext));

OR

const char sometext[] PROGMEM = "Some Text";
const char someothertext[] PROGMEM = "Some Other Text";

Serial.Print(FPSTR(sometext));
Serial.Print(FPSTR(someothertext));

The last two were just from memory so they could be WRONG. But whatever, there are many ways to skin that cat.

So Text is tucked away in Flash, cool. but we end up with 5 whole words when perhaps 3 would have be ok.

now I understand that joining things can be bad, and may even take up more space than is saved but I ponder the use of a _F(index) function.

In this function the string is created from the various words. Be it a String or Char[] or even numeric.

const char T_some[] PROGMEM = "Some";
const char T_other[] PROGMEM = "Other";
const char T_text[]   PROGMEM = "Text";
const char T_space[] PROGMEM = " ";

String _F(int index){
 switch (index){
  case sometextindex: return (String) T_some + T_space + T_text;
  case someothertextindex: return (String) T_some + T_space + T_other + T_space + T_text;
  default: return (String) T_unknown + T_space + String(index);
 }
}

Serial.Print(_F(sometextindex));
Serial.Print(_F(someothertextindex));

Sure it looks ugly but if this was auto generated and you never needed to look at it then no foul. But I have no idea what this would do to things like the Heap & Stack.

Some may say that this will take up more space than it saves.. Perhaps, but maybe not.!

echo worthit ? 'y':'n';

Hv.

Serial.Print("Some Text");
Serial.Println("Some Other Text");

Are these Print and Println methods published anywhere?

CtrlAltElite:

Serial.Print("Some Text");

Serial.Println(“Some Other Text”);



Are these Print and Println methods published anywhere?

This is where peoples blood will start to boil,

Yes, Well apart from the upper case P.!

perhaps you were just literally taking the P. :wink:

Hv.

Just a quick a dirty edit removing "SOME" duplicate F() String got me a ~1k saving.

Both are the same project but the Client has Websocket Client also included.

::CLIENT IC

User-Agent: ESP8266-http-Update Size after F() String Squishing x-ESP8266-free-space: 1564672 x-ESP8266-sketch-size: 532176 x-ESP-sketch-size: 530896 x-ESP8266-chip-size: 4194304

x-ESP8266-sdk-version: 2.1.0(deb1901)

::Server IC

User-Agent: ESP8266-http-Update x-ESP8266-free-space: 1630208 x-ESP8266-sketch-size: 465712 x-ESP-sketch-size: 464448 x-ESP8266-chip-size: 8388608

x-ESP8266-sdk-version: 2.1.0(deb1901)

And oddly I did not remove the Duplicate Headers strings.!! Told you it was dirty.

Anyway, simple savings, though small, every little helps.

So back to the question of the Correct way to Define and concatenate chunks of text. And is it a bad thing to do for any reason.?

Anyone.?

for those that may wish to expand on this concept, another thought, or a different way of looking at the same thing.!

Question:? Within the C environment is there such a things as a dictionary.?

To avoid String duplication and to help minimise sketch size, I'm thinking, that any printable "Text" used in project libraries, should be publicly accessible for reuse in other parts of the users code/program.

Imagine, All this text is collected and stored in the "Dictionarray".

Then if you want to Print or send a word or a collection of words, you just use the existing defines. If the words your wanting to use don't exist, they get added.

A simply mechanism to collate and manage the dictionary appears to be the hardest part to me. Oh, that and not knowing how to Declare and concatenate text 'properly' perhaps.!

Hiddenvision: const char T_some[] PROGMEM = "Some"; const char T_other[] PROGMEM = "Other"; const char T_text[]   PROGMEM = "Text"; const char T_space[] PROGMEM = " ";

reductio ad absurdum:

const char* const a PROGMEM = "a";
const char* const b PROGMEM = "b";
const char* const c PROGMEM = "c";
const char* const d PROGMEM = "d";
...

As your skills broaden and improve, and if you still see this as a (portable) tool that you want to develop, you will see other opportunities/approaches. Meanwhile you will find it is best use few(er) string literals!

Thanks Bulldog. I shall use that type of format to start.

Use less strings,

true, but then it is sometimes nice to explain in readable text what the code is doing when running. Thus the need to Write words out to the Serial, SD, web socket or Printed to LCD. More output devices are available.

those pesky chunks of text just seem to find their way in, bit by bit

Hey perhaps we could assign a number to each letter.!! Oh darn , been done already. How about joining the letters together to make w......, darn someone did that too

What about assigning a number to whole words and joining those together, urgh, what nonsense.

Ahh, we could stick to binary then we only need two strings.!!

Anyway I have read enough to find there is conflicting opinions depending what camp you visit. So I may be best to just take my own random approach (with dogs' suggestions) and see what happens. No doubt if I get something actually usable then I will be able to select from multiple methods and compare the difference with minimal fuss. Now the hard part is done, what colour should the text box be.? :confused:

Just in case I did want to "build" a jumble of randomness out of the various words, Would it be best to return a String/Char[]/pointer from a function ? No, Pointer is BAD, string is destroyed on return,

or better to just use a global String/char to reference from anywhere. thinking the different approaches may impact Stack/Heap usage.

reductio ad absurdum:

Holy cow, it's all Greek to me. But I see the odds at 50/50 right now.

Hiddenvision: Thanks Bulldog. I shall use that type of format to start.

I was being facetious, you are on a bit of a fool's journey, in my opinion. Consider: wouldn't this have been done already?

if you want to add optional Serial output which you can quickly turn off/on you can use a macro:

#define DEBUG_SERIAL TRUE
#ifdef DEBUG_SERIAL
  #define DEBUG_PRINT(x) Serial.print(x)
#else
  #define DEBUG_PRINT(x)
#endif

void setup() {
   Serial.begin(9600);
   DEBUG_PRINT(F("Hello World\n"));
}

void loop() {
  
}

commenting out the first line will eliminate all of the DEBUG_PRINT statements (and their respective memory usage) unilaterally.

you can create modules of debug prints if you wish, using different defined macros

Would it be best to return a String/Char[]/pointer from a function ? No, Pointer is BAD, string is destroyed on return,

Oy. If you're thinking about using the String class, an Omniscient Resource Manager is the least of your worries.

I would suggest learning about:

* returning non-simple types (see Background subsection; it's ok to return structures/instances),

* The Evils of Arduino Strings (uppercase, not NUL-terminated C [u]s[/u]trings), and

* the difference between the preprocessor and the compiler (#define is like doing a search and replace before compiling).