Pgm_read_byte and 2D progmem arrays

Given the following array, how do I do the equivalent of g_arrayCodes[10][2] with pgm_read_byte etc.?

        int8_t *pCodeArray = pgm_read_ptr(g_arrayCodes + 10);
        int8_t nCode = pCodeArray[0];

The above does not work how I expected it to work.
I am getting random garbage in nCode.
So how do you index a 2D array in PROGMEM?

 const int8_t g_arrayCodes[CHAR_ARRAY_SIZE][DOT_DASH_ARRAY_SIZE] PROGMEM = {
                                                                            /*A*/{DELAY_DOT, DELAY_DASH, -1, -1, -1, -1, -1}, 
                                                                            /*B*/{DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, -1, -1, -1}, 
                                                                            /*C*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DOT, -1, -1, -1}, 
                                                                            /*D*/{DELAY_DASH, DELAY_DOT, DELAY_DOT, -1, -1, -1, -1}, 
                                                                            /*E*/{DELAY_DOT, -1, -1, -1, -1, -1, -1}, 
                                                                            /*F*/{DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DOT, -1, -1, -1}, 
                                                                            /*G*/{DELAY_DASH, DELAY_DASH, DELAY_DOT, -1, -1, -1, -1}, 
                                                                            /*H*/{DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DOT, -1, -1, -1}, 
                                                                            /*I*/{DELAY_DOT, DELAY_DOT, -1, -1, -1, -1, -1}, 
                                                                            /*J*/{DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DASH, -1, -1, -1}, 
                                                                            /*K*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, -1, -1, -1, -1}, 
                                                                            /*L*/{DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DOT, -1, -1, -1}, 
                                                                            /*M*/{DELAY_DASH, DELAY_DASH, -1, -1, -1, -1, -1}, 
                                                                            /*N*/{DELAY_DASH, DELAY_DOT, -1, -1, -1, -1, -1}, 
                                                                            /*0*/{DELAY_DASH, DELAY_DASH, DELAY_DASH, -1, -1, -1, -1}, 
                                                                            /*P*/{DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DOT, -1, -1, -1}, 
                                                                            /*Q*/{DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DASH, -1, -1, -1}, 
                                                                            /*R*/{DELAY_DOT, DELAY_DASH, DELAY_DOT, -1, -1, -1, -1}, 
                                                                            /*S*/{DELAY_DOT, DELAY_DOT, DELAY_DOT, -1, -1, -1, -1}, 
                                                                            /*T*/{DELAY_DASH, -1, -1, -1, -1, -1, -1}, 
                                                                            /*U*/{DELAY_DOT, DELAY_DOT, DELAY_DASH, -1, -1, -1, -1}, 
                                                                            /*V*/{DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DASH, -1, -1, -1},
                                                                            /*W*/{DELAY_DOT, DELAY_DASH, DELAY_DASH, -1, -1, -1, -1}, 
                                                                            /*X*/{DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DASH, -1, -1, -1}, 
                                                                            /*Y*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DASH, -1, -1, -1}, 
                                                                            /*Z*/{DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DOT, -1, -1, -1}, 
                                                                            
                                                                            /*0*/{DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DASH, -1, -1}, 
                                                                            /*1*/{DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DASH, -1, -1}, 
                                                                            /*2*/{DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DASH, -1, -1}, 
                                                                            /*3*/{DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DASH, -1, -1}, 
                                                                            /*4*/{DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DASH, -1, -1}, 
                                                                            /*5*/{DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DOT, -1, -1}, 
                                                                            /*6*/{DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DOT, -1, -1}, 
                                                                            /*7*/{DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, -1, -1}, 
                                                                            /*8*/{DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DOT, -1, -1}, 
                                                                            /*9*/{DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DOT, -1, -1}, 
                          
                                                                            /*?*/{DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DOT, -1}, 
                                                                            /*!*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DASH, -1}, 
                                                                            /*.*/{DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DASH, -1}, 
                                                                            /*,*/{DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DASH, -1}, 
                                                                            /*;*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DOT, -1}, 
                                                                            /*:*/{DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, -1}, 
                                                                            /*+*/{DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DOT, -1, -1}, 
                                                                            /*-*/{DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DASH, -1}, 
                                                                            /*/*/{DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DOT, -1, -1}, 
                                                                            /*=*/{DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DASH, -1, -1},
                                                                            /*&*/{DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, -1, -1},
                                                                            /*@*/{DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DOT, -1},
                                                                            /*(*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DOT, DELAY_DASH, -1},
                                                                            /*)*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DOT, -1, -1},
                                                                            /*x*/{DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DASH, -1, -1},
                                                                            /*%*/{DELAY_DASH, DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DOT, -1, -1},
                                                                            /*'*/{DELAY_DOT, DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DASH, DELAY_DOT, -1},
                                                                            /*"*/{DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DOT, -1},
                                                                            /* */{DELAY_DASH, DELAY_DOT, DELAY_DOT, DELAY_DOT, DELAY_DASH, DELAY_DOT, DELAY_DASH}
                                                                          };

2D arrays do not contain pointers.

static_cast<int8_t>(pgm_read_byte(&g_arrayCodes[r][c]));

See avr-libc: Data in Program Space

One can access array element a[i][j]
as
a + i *(ELEMENTS_IN_ROW) + j

Not if a is a multidimensional array.

This was the problem:

nCode = pgm_read_byte(uint32_t(g_arrayCodes) + (nIndex * DOT_DASH_ARRAY_SIZE) + nJ);

I had this originally without the uint32_t cast.
But casting the array to a uint32_t makes it work the way I expected it to.
I don't really understand why though.

Works for me.

It may compile for some boards that have the -fpermissive flag enabled, but it is invalid. Multidimensional arrays do not decay to a pointer to the first element.

int a[3][3] {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
};

void test(int i, int j) {
    int val = *(a + i * 3 + j);
}
error: invalid conversion from 'int*' to 'int' [-fpermissive]
    8 |     int val = *(a + i * 3 + j);
      |                ~~~~~~~~~~~^~~~
      |                           |
      |                           int*

Don't use C-style casts to convert pointers to integers.
Use the approach I mentioned in my first post:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.