large array, how to save it in rom?

hy, i have two arrays:

int data[112][2]
and
int otherData[112][2]

so. when i just use one array and uncomment the other, it works fine. but when i try to use both arrays nothing works anymore and the arduino looks dead. i work on an diecimilla i have to say.

i found here in the forum a hint, that it could be to big for the ram, and there could be a possibilty to write it to the rom. theres a playground link, on a C programming site. but i can't figure out what to do with that code. yes, i'am a big stupid. :smiley:

could anyone explain me how to do this. or give a link to a helpful site?

thank you!!!

Hi,
Both of those arrrays will definetly not fit into RAM.

A much better explanation of the types of memory, and how to use PROGMEM, with relevant examples, is available at this link:

Note that PROGMEM is for read-only memory. If your arrays are not read-only, then the best thing to do is to re-design your program to use less memory.

HTH,

PROGMEM is a good option for large read-only arrays since there is a total of 16k FLASH on the Decimilla, but it isn't the only option. There's also the EEPROM, which IIRC is 512 bytes (enough for 1 of your arrays).

Technically these arrays will fit into memory (2 bytes/int * 2 arrays * 112 * 2 elements = 896 bytes), but if you happen to use e.g. the hardware serial code, you don't have enough.

If your values are small (0 to 255 or -128 to 127) you can use byte instead of int and cut the RAM utilization in half.

-j

If your arrays are not read-only, then the best thing to do is to re-design your program to use less memory.

And go to the wishlist on the playground and add a wish for a MEGA128 based Arduino :wink:

thanks for your answers. it was very helpful.

but i got a question:

in the reference for PROGMEM, there is the following code for reading back:
// read back a 2-byte int
displayInt = pgm_read_word_near(charSet + k)

this reads back only one value in the array, right?
as i have a two dimensional array, i need to give two values to locate the correct position.

can i do
// read back a 2-byte int
displayInt = pgm_read_word_near(charSet + k + i)

?

thank you
n

Close, but not quite. If your 2D array is a[J][K] then to address element a[i][n] the offset is calculated as i + K * n. (Or, technically, you could use i * J + n, just make sure you do it the same way every time!).

I'd handle it with some preprocessor directives, like so:

#define XDIM 112
#define YDIM 2

#define offset(X,Y) ((X) + (Y) * YDIM)

...

pgm_read_word_near(BASE + offset(k,i));

Sorry, I don't recall how the PGMEM stuff works, so you'll have to fill in a few blanks here. Maybe this is enough to get you started.

-j

in the reference for PROGMEM, there is the following code for reading back:
// read back a 2-byte int
displayInt = pgm_read_word_near(charSet + k)

this reads back only one value in the array, right?
as i have a two dimensional array, i need to give two values to locate the correct position.

can i do
// read back a 2-byte int
displayInt = pgm_read_word_near(charSet + k + i)

I think you should be able to let the C compiler do the math for you:

displayInt = pgm_read_word_near(&(charSet[k][i]));

(charSet[k] does the array calculations assuming a base address at charSet. "&" says to pass the address resulting from the array calculations to pgm_read_word_near instead of trying to find the value. and the function reinterprets the address as being somewhere in flash instead of in ram.)

I don't think that's gonna work. The name of an array is already a pointer, so you're doing a double indirection, which doesn't make any sense.

I'm pretty sure you need to leave off the &, then it may work as expected. The arduino PROGMEM reference page makes me wonder if it will work, though, and you may need to fall back on the charSet + i + K * n expression.

Besides, this is a Harvard architecture, not a von Neumann, so the PROGMEM data is in a different address space, not the normal address space C is working with; I'm not sure the pointer operators are going to work in FLASH address space.

-j

I don't think that's gonna work. The name of an array is already a pointer, so you're doing a double indirection

Yes, but the brackets WOULD cause a dereference without the "&". You'd have to have the correct definition of the array, of course.

Besides, this is a Harvard architecture, not a von Neumann, so the PROGMEM data is in a different address space, not the normal address space C is working with; I'm not sure the pointer operators are going to work in FLASH address space.

It shouldn't matter till the actual dereference, which happens in pgm_read_word... rather than in code produced by the compiler. Pointer arithmetic, including array indicies, should work on variable names regardless of which address space the data actually resides in. Of course, "should" doesn't mean it does. Experiments are called for, I think.

Ok. I actually did the experiment, and it looks like I'm right. (hooray!) I used this code (progmem_array.pde):

#include <avr/pgmspace.h>

void setup(void)
{
    Serial.begin(9600);
    while (Serial.read() != 32)
        delay(1); // Wait for space
}
const int mydata[10][10] PROGMEM = { 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', 'A',
    '1', '1', '2', '3', '4', '5', '6', '7', '8', 'B',
    '2', '1', '2', '3', '4', '5', '6', '7', '8', 'C',
    '3', '1', '2', '3', '4', '5', '6', '7', '8', 'D',
    '4', '1', '2', '3', '4', '5', '6', '7', '8', 'E',
    '5', '1', '2', '3', '4', '5', '6', '7', '8', 'F',
    '6', '1', '2', '3', '4', '5', '6', '7', '8', 'G',
    '7', '1', '2', '3', '4', '5', '6', '7', '8', 'H',
    '8', '1', '2', '3', '4', '5', '6', '7', '8', 'I',
    '9', '1', '2', '3', '4', '5', '6', '7', '8', 'Z' };

void loop(void) {
    int i,j;
    int n;
    Serial.println("\nData by Rows.");
    for (i=0; i < 10; i++) {
        Serial.println(" ");
        for (j=0; j < 10; j++) {
            n = pgm_read_word_near(&mydata[i][j]);
            Serial.print(n, BYTE);
        }
    }
    Serial.println(" ");
    Serial.println("\nData by Columns.");
    for (i=0; i < 10; i++) {
        Serial.println(" ");
        for (j=0; j < 10; j++) {
            n = pgm_read_word_near(&mydata[j][i]);
            Serial.print(n, BYTE);
        }
    }
    Serial.println(" ");    setup();    Serial.println(" ");  //start over
}

And it works exactly how I expected it to, correctly printing the array from flash memory (.text segment, in compiler-ese), and leaving the initialized data segment of the binary mercifully empty (.data segment):

BillW-MacOSX<1094> /Applications/arduino-0010/hardware/tools/avr/bin/avr-size progmem_array.elf
   text    data     bss     dec     hex filename
   2490      36     137    2663     a67 progmem_array.elf