Converting string and store in PROGMEM

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, this may seem easy to the initiated.

 

I would like to save a string to progmem, let say 

const char message[] PROGMEM = “AVRFREAKSISTHEBEST”

Now I want to read it back character by character and convert each character to its encoded value.

Let's say "A" = 15, "B" = 16, "C" = 19, "D" = 20, "E"= 24....  The letters don't follow a numerical sequence.

 

It is easy enough to read each character and the only way I currently know how to do it is something like

case "A" :
    character = 15;
    break;
    
case "B" :
    character = 16;
    break;

Now the above seem inefficient. Is there a better way, perhaps a macro that can do it?

 

The other idea in my head, of which I know effectively nothing, is some sort of directive that will convert my code into the correct values and shove that values into PROGMEM. I.e. let the compiler do the work of conversion...

 

As an example pseudo code

//Look here compiler, I want you to convert this string...
mystring = "AVRFREAKS";
for(repeat_until_done)
{
   //get first character
   //convert character to correct decimal
   //put character into an array
}

//put array of characters in PROGMEM
//thanks compiler! You saved me some code space and time...!

main()
//grab binary value from PROGMEM
//use it to flash and beep and move stuff

Is it possible and worth it?

Any other suggestions? 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is the alphabet you are converting?  26 ASCII upper case characters?  Use a lookup table, offset by 'A'.

 

A wider alphabet?  Use a 256 entry table?

 

Bergie5737 wrote:
It is easy enough to read each character and the only way I currently know how to do it is something like case "A" : character = 15; break;...

 

Well, that won't work.  Did you mean case 'A':

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Only simpler way I can think of is to store as an array of integers without going through the ASCII string. That is, something like

 

const uint8_t message[] PROGMEM = 15,16,19,20,24;

for A,B,C,D.  Uses the same amount of progmem space. But, now, your challenge is to access the members of that array in some useful way.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

switch statement should use char, not double- quoted string.

const char cString[] = "ABCD";

 

char ch = cString[n];

 

switch (ch)  {

 

case 'A':

}

Last Edited: Thu. Mar 31, 2016 - 08:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It might help us to know why your encoding letters to numbers, then we can perhaps provide a better solution! 

 

 

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd steal part of what Jim said:

const uint8_t message[] PROGMEM = 15,16,19,20,24;

then use it like this:

const uint8_t convert[] PROGMEM = 15,16,19,20,24;
const char message[] PROGMEM = “AVRFREAKSISTHEBEST”

uint8_t i;

int main(void) {
    for (i = 0; i < strlen(message); i++) {
        original = pgm_read_byte(&message[i]);
        encoded = pgm_read_byte(&convert[original - 'A']);
        use(encoded);
    }
}

I split that up to explain what's going on with some sensible variable names but obviously you could use:

    for (i = 0; i < strlen(message); i++) {
        use(pgm_read_byte(&convert[pgm_read_byte(&message[i]) - 'A']));
    }

though to be honest the code generated is probably identical in both cases and I think it helps the code to be self documenting by introducing the names "original" and "encoded".

 

PS before someone moans, yes the original uses characters up to 'T' yet the convert[] arrray currently only has entries for 5 characters ('A'..'E') and there's no checks for reading off the end of the array!

Last Edited: Fri. Apr 1, 2016 - 09:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mmmm. Thanks for the answers.

It is not as simple as I thought.

Well now I used a spreadsheet with a VLOOKUP function. It then simply generates the actual numerical presentation of the string. It does mean that I have to "consult" the spreadsheet when I change things around...

 

And I think my code was not clear, but the actual character, "A" was to be converted to a number first. So character "A" is  decimal 65. Of course it would have been easy to use if it was a simple ASCII sequence. In this case, I am converting to base 3...

 

In the end each character converts to three two bit binary pairs. (hence the base three, which only have zero, one and two...)

A = 01, 01, 01, or to store it in a byte, 00010101 with first two bits ignored. Bit operators extract the bit pairs. Those two pairs will then be used to drive an RGB LED, it will flash three times per character. So "01" is Red, "10" is Green, "11" is Blue. In this case a "00" value is invalid, thus the gaps.  (One LED must always be on, so I simply add one to the base 3 representation - quite a silly step, but it makes it slightly easier to understand my own code.)

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I still don't get it: why do you need the char step at all? Just store (and use) the raw values as suggested by Jim: that is, 0b010101 instead of A.

 

You could build them using some macros if that helps you. For example:

// Indiviual colors
#define R  01
#define G  10
#define B  11

// 3 colors set
#define col(c1, c2, c3)   col_(c1, c2, c3)
#define col_(c1, c2, c3)  0b##c1##c2##c3

// Usage example
const uint8__t colors[] PROGMEM = { col(R,R,R), col(R,G,B), … };

You could even define all of the 3³ possible values (that's only 27 of them after all), if you like better how the final code looks:

#define RRR  col(R,R,R)
#define RRG  col(R,R,G)
#define RRB  col(R,R,B)
#define RGR  col(R,G,R)
#define RGG  col(R,G,G)
#define RGB  col(R,G,B)
…

// And use them like this:
const uint8__t colors[] PROGMEM = { RRR, RGB, … };

ɴᴇᴛɪᴢᴇᴎ

Last Edited: Sun. Apr 3, 2016 - 08:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is your point to encode letters using RGB flashing sequences? Or is it to store flashing sequences using letters?

ɴᴇᴛɪᴢᴇᴎ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What does these lines do? Esp line two messes with me.

#define col(c1, c2, c3)   col_(c1, c2, c3)
#define col_(c1, c2, c3)  0b##c1##c2##c3

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bergie5737 wrote:
What does these lines do? Esp line two messes with me.

#define col(c1, c2, c3)   col_(c1, c2, c3)
#define col_(c1, c2, c3)  0b##c1##c2##c3

It just concatenates stuff:

col_(A, B, C)              => 0bABC
col_(whatever, you, want)  => 0bwhateveryouwant

 

ɴᴇᴛɪᴢᴇᴎ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Half forgotten by now...

I've simply used Calc in a spreadsheet that does the lifting, then copy and paste the resultant hexes into PROGMEM. Works like a charm, especially since I got it into my head to cypher the code with Enigma, LOL! Now every time it flashes the coordinates, the colors changes based on a random number.

Calc have a nice formula that can convert numbers to  virtually any base, no slogging required.