Array of arrays in flash using PROGMEM

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

Good day!

My goal is to store array of arrays of uint8_t in PROGMEM and iterate over this data structure.

Data can look like this:

{
	{1,2,3,4,5},
	{6,7,8,9,10,11,12},
	{1,2,3,4,5,6,7,8,9,19}
}

Question:

- Is my approach right in general, maybe I'm missing more easy way?
- I can iterate over rows using uint8_t* pointer (named 'current' in my code). But how can I get number of items in current row?

#include 
#include 

#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))

const uint8_t array1[] PROGMEM = {1,2,3,4,5};
const uint8_t array2[] PROGMEM = {6,7,8,9,10,11,12};

const uint8_t* my_arrays[] PROGMEM = {
	array1,
	array2
};

uint8_t* current;
uint8_t x, size;

int main(void)
{
    current = (uint8_t*)array1;
	x = pgm_read_byte(current + 2); // read 3rd element of first array
	size = NUM_ELEM(array1);
	
	/*
		Question:
			How to calculate size of array to which 'current' is pointing?
			NUM_ELEM(current) will give me 2 (size of pointer in bytes on AVR)			
	*/
		
	current = (uint8_t*)array2;
	x = pgm_read_byte(current+1); // read 2nd element of second array
		
	current = (uint8_t*)pgm_read_word(my_arrays+1); 
	x = pgm_read_byte(current+5); // read #6 element of second array
		
	while(1)
    {

    }
}

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
const uint8_t* my_arrays[] PROGMEM = {
   array1,
   array2,
   array2+sizeof(array2)/sizeof(array2[0])
};
// pointer differences will give you sizes

Moderation in all things. -- ancient proverb

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

skeeve wrote:

const uint8_t* my_arrays[] PROGMEM = {
   array1,
   array2,
   array2+sizeof(array2)/sizeof(array2[0])
};
// pointer differences will give you sizes

I'm not sure that I understand the idea:

- Will it work for more than 2 arrays.
- How to get size in the future?

Thanks!

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

You can know sizeof(array1) and sizeof(array2) at compile time. If you want to find the size at runtime you need to add the sizeof() in your arrays somewhere.

It is quite possible that a Compiler places array1, array2, ... sequentially in memory. But it is not obliged to. So address subtraction may or may not work.
You can either add an array of sizes, or make my_arrays[] an array of structures.

Incidentally, you are being a bit cavalier with your types and pointers. I would add specific casts and definitely comment your 'use'.

Of course if your arrayn data is actually strings, you can simply use strlen_P(my_arrays[x])

David.

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

Thanks for the detailed response!

Finally I've created another array of sizes in PROGMEM I also replaced pointer math to more readable:

	x = pgm_read_byte(&array1[3]); // read 4rd element of first array
	// Read using pointer from pointer table in Flash (different syntax)
	current = (uint8_t*)pgm_read_word(&my_arrays[1]); 
	x = pgm_read_byte(current+6); // read #7 element of second array

Is it possible to make last example even more readable to cast 'current' as array and not pointer?

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

Quote:

to cast 'current' as array and not pointer?

Same thing:

 x = pgm_read_byte(¤t[6]); // read #7 element of second array 

would work just as well.

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

david.prentice wrote:
It is quite possible that a Compiler places array1, array2, ... sequentially in memory. But it is not obliged to. So address subtraction may or may not work.
You can either add an array of sizes, or make my_arrays[] an array of structures.
Good point.
Fortunately there is always brute force
#define data1 1,2,3,4,5
#define data2 6,7,8,9,10,11,12

const uint8_t array1[] PROGMEM = {data1, data2};

static const uint8_t fake1={data1};
static const uint8_t fake2={data2};

#define array2  \
        (array1+sizeof(fake1)/sizeof(fake1[0]))
#define array3  \
        (array2+sizeof(fake2)/sizeof(fake2[0]))
const uint8_t array1[] PROGMEM = {1,2,3,4,5};
const uint8_t array2[] PROGMEM = {6,7,8,9,10,11,12};

const uint8_t* my_arrays[] PROGMEM = {
   array1,
   array2,
   array3
};

Now pointer arithmetic will work.

Moderation in all things. -- ancient proverb

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

clawson wrote:
Quote:

to cast 'current' as array and not pointer?

Same thing:

 x = pgm_read_byte(¤t[6]); // read #7 element of second array 

would work just as well.


Thanks, this will work too :):

x = pgm_read_byte(&2[current]); 
Good point.
Fortunately there is always brute force 

Thanks! Seems to be a very neat trick, but for my task I just created another array of sizes.