Writing/reading uint64_t's into PROGMEM

Hello everyone,

I have to put an uint64_t array into PROGMEM, and then make a copy of it into RAM.

Since there is no pgm_read_uint64 macro, I’m trying to reproduce it’s functionality copying the data byte by byte.

Considering the following sketch:

const uint64_t attrib[5] PROGMEM = { 0ULL, 1ULL, 2ULL, 3ULL, 4ULL}; 

void setup() {
Serial.begin(115200);

 for (int i = 0; i < 5; i++)
    {
      for (int k = 7 ; k >= 0; k--) {
        byte b = pgm_read_byte(&attrib[i] + k); 
          for (int j = 7; j >= 0; j--) { Serial.print(bitRead(b,j)); } ;
        Serial.print(" ");
      }
      Serial.println(); 
    }
}

void loop() { }

It should write this data into progmem:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000011
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100

and then display it in the form above.

Unfortunately I get only the last column proper, the 1-7 columns does contain other bits:

10100000 11011000 01110011 00000100 00000011 00000010 00000001 00000000 
00000010 10100000 11011000 01110011 00000100 00000011 00000010 00000001 
10110001 00000010 10100000 11011000 01110011 00000100 00000011 00000010 
10110001 10110001 00000010 10100000 11011000 01110011 00000100 00000011 
10110010 10110001 10110001 00000010 10100000 11011000 01110011 00000100

Does anyone have a clue, where am I wrong ?

Regards,
Ciprian

pgm_read_byte(&attrib[i] + k)

This is the address of the (i + k) th element of the uint64_t array.

pgm_read_byte(((uint8_t *) (attrib + i)) + k)

should work better.

The function you want is memcpy_P. It lets you read blocks of arbitrary size from PROGMEM.

const uint64_t TEST PROGMEM = 0xFEDCBA9876543210;

uint64_t pgm_read_64( void *ptr )
{
  uint64_t result;
  memcpy_P( &result, ptr, sizeof(uint64_t) );
  return result;
}

void setup()
{
  uint64_t local = pgm_read_64(&TEST);
}

Whandall:

pgm_read_byte(((uint8_t *) (attrib + i)) + k)

should work better.

It worked!
I've never thought about using an array without specifying it's nth element... thanks Whandall!!

pisicaverde:
It worked!
I've never thought about using an array without specifying it's nth element... thanks Whandall!!

It is specifying the element through. Arrays are pretty interchangeable with pointers, so pointer + i is equivalent to &array[i]. You just need to then convert that pointer into a uint8_t* so that you can access individual bytes of the type.

Or you can just use the function I showed, which handles all of that behind the scenes.