Trying to make an Array of Arrays

I'm trying to make an array of several two dimensional arrays. Here's some of the relevant code:

char A[][3]={
      {0,1,0},
      {1,0,1},
      {1,1,1},
      {1,0,1},
      {1,0,1}};
  char B[][3]={
      {1,1,0},
      {1,0,1},
      {1,1,0},
      {1,0,1},
      {1,1,0}};
  char C[][3]={
      {0,1,1},
      {1,0,0},
      {1,0,0},
      {1,0,0},
      {0,1,1}};
char* Word[]={A,B,C};

Right now I'm getting an error: "cannot convert 'char ()[3]' to 'char' in intialization

I'm wondering if anyone can help me out and get this working.

This...

char* Word[]={&A[0][0],&B[0][0],&C[0][0]};

...will get you past the error.

A different approach could be to create a struct to hold the data for a letter.

typedef struct Letter {
  unsigned line1 : 3;
  unsigned line2 : 3;
  unsigned line3 : 3;
  unsigned line4 : 3;
  unsigned line5 : 3;
  unsigned : 0;
};

Letter a = { 
  B010,
  B101,
  B111,
  B101,
  B101
};

Letter *word[] = { &a /*expand this*/ };

The Letter struct just saved you 13 bytes per letter, 13*26 = 338 bytes saved on the alphabet.

When you use it, you can either create a function like readBitFromLetter(letter, line, pos ) or you can make a function in the struct like letter.read( line, pos ) or you can access the data in a normal fashion (which is shown here):

//[UNTESTED CODE]
//assumes a:Letter is available

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

  Serial.print( bitRead( a.line1 , 2 ) );
  Serial.print( bitRead( a.line1 , 1 ) );
  Serial.println( bitRead( a.line1 , 0 ) );

  Serial.print( bitRead( a.line2 , 2 ) );
  Serial.print( bitRead( a.line2 , 1 ) );
  Serial.println( bitRead( a.line2 , 0 ) );

  Serial.print( bitRead( a.line3 , 2 ) );
  Serial.print( bitRead( a.line3 , 1 ) );
  Serial.println( bitRead( a.line3 , 0 ) );

  Serial.print( bitRead( a.line4 , 2 ) );
  Serial.print( bitRead( a.line4 , 1 ) );
  Serial.println( bitRead( a.line4 , 0 ) );

  Serial.print( bitRead( a.line5 , 2 ) );
  Serial.print( bitRead( a.line5 , 1 ) );
  Serial.println( bitRead( a.line5 , 0 ) );
}

Happy Coding! :slight_smile:

Thanks Coding Badly but is there any way to make the array without referencing specific elements.

AlphaBeta I'm thinking I'm going to use your method. If I use your method would I have to limit all my letters to 5x3s? I'm thinking I would have to define multiple letters to get 5x4 and 5x5s. Would I need something like Letter3 Letter4 and Letter5 or is there another way?

Something like this should work...

typedef char tLetter[5][3];

tLetter* Word[] = { &A, &B, &C };

Would I need something like Letter3 Letter4 and Letter5 or is there another way?

There is another way :slight_smile:

Enter: template

//this is what defines a Letter on the most primitive letter
struct BaseLetter {
      virtual char get( byte line, byte bit ) = 0;
      virtual byte width( void ) = 0;
      
      static const byte NUMBER_OF_LINES = 5;
};

//Define letters of variable width using this template struct
template<byte size>
struct Letter : public BaseLetter {
      Letter( byte l0, byte l1, byte l2, byte l3, byte l4) : 
            line0(l0),line1(l1),line2(l2),line3(l3),line4(l4) {
      }
      unsigned line0 : size;
      unsigned line1 : size;
      unsigned line2 : size;
      unsigned line3 : size;
      unsigned line4 : size;
      unsigned : 0;
      
      virtual char get( byte line, byte bit ) {
            switch (line){
                  case 0: return (line0&(1<<bit%size)?1:0); break;
                  case 1: return (line1&(1<<bit%size)?1:0); break;
                  case 2: return (line2&(1<<bit%size)?1:0); break;
                  case 3: return (line3&(1<<bit%size)?1:0); break;
                  case 4: return (line4&(1<<bit%size)?1:0); break;
            }
            return -1;
      }
      virtual byte width() { return size; }
};

/*
DEFINE THE LETTERS
*/
Letter<3> a = Letter<3>( 
      B010,
      B101,
      B111,
      B101,
      B101
);

Letter<4> n = Letter<4>( 
      B1001,
      B1101,
      B1011,
      B1001,
      B1001,
);

Letter<5> m = Letter<5>(
      B10001,
      B11011,
      B10101,
      B10001,
      B10001,
);


/*
DEFINE THE WORD
*/
const byte WORD_LENGTH = 3;

BaseLetter* word[WORD_LENGTH] = { &a, &n, &m };

void setup(){
      Serial.begin(9600);
}

void loop(){
      //loop through all letters in the word
      for (int wordIndex=0; wordIndex<WORD_LENGTH; wordIndex++){
            //loop through all the lines of the letter
            for (int line=0; line<BaseLetter::NUMBER_OF_LINES; line++){
                  //loop through all the bits of the line
                  for (int bit=0; bit<word[wordIndex]->width(); bit++){
                        //print the value at the current letter, at the current line at the current bit
                        Serial.print(word[wordIndex]->get(line,bit),DEC);
                  }
                  Serial.println();
            }
      }
}

So I'm working on making a function to read the individual bits in the Letter type. This is what I have:

typedef struct Letter{
  unsigned line1 : 5;
  unsigned line2 : 5;
  unsigned line3 : 5;
  unsigned line4 : 5;
  unsigned line5 : 5;
  unsigned : 0;};

int readL(Letter Let, int line, int pos){
   if(line == 1){
      if(pos == 1){return bitRead(Let.line1,1);}
      if(pos == 2){return bitRead(Let.line1,2);}
      if(pos == 3){return bitRead(Let.line1,3);}
      if(pos == 4){return bitRead(Let.line1,4);}
      if(pos == 5){return bitRead(Let.line1,5);}
    }
    if(line == 2){
      if(pos == 1){return bitRead(Let.line2,1);}
      if(pos == 2){return bitRead(Let.line2,2);}
      if(pos == 3){return bitRead(Let.line2,3);}
      if(pos == 4){return bitRead(Let.line2,4);}
      if(pos == 5){return bitRead(Let.line2,5);}
    }
    if(line == 3){
      if(pos == 1){return bitRead(Let.line3,1);}
      if(pos == 2){return bitRead(Let.line3,2);}
      if(pos == 3){return bitRead(Let.line3,3);}
      if(pos == 4){return bitRead(Let.line3,4);}
      if(pos == 5){return bitRead(Let.line3,5);}
    }
    if(line == 4){
      if(pos == 1){return bitRead(Let.line4,1);}
      if(pos == 2){return bitRead(Let.line4,2);}
      if(pos == 3){return bitRead(Let.line4,3);}
      if(pos == 4){return bitRead(Let.line4,4);}
      if(pos == 5){return bitRead(Let.line4,5);}
    }
    if(line == 5){
      if(pos == 1){return bitRead(Let.line5,1);}
      if(pos == 2){return bitRead(Let.line5,2);}
      if(pos == 3){return bitRead(Let.line5,3);}
      if(pos == 4){return bitRead(Let.line5,4);}
      if(pos == 5){return bitRead(Let.line5,5);}
    }}

I'm getting an error: 'Letter' was not declared in this scope In function 'int readL(Letter, int, int)'

Note right now I have these between the setup function and the loop function.

Try this...

typedef struct {
  unsigned line1 : 5;
  unsigned line2 : 5;
  unsigned line3 : 5;
  unsigned line4 : 5;
  unsigned line5 : 5;
  unsigned : 0;} Letter;

Also, instead of

if(line == 1){
      if(pos == 1){return bitRead(Let.line1,1);}
      if(pos == 2){return bitRead(Let.line1,2);}
      if(pos == 3){return bitRead(Let.line1,3);}
      if(pos == 4){return bitRead(Let.line1,4);}
      if(pos == 5){return bitRead(Let.line1,5);}
    }

You could write

if(line == 1){
      return bitRead(Let.line1,pos);
    }

-Mike

Nope still getting the same error. I think it's something with the readL function because I can declare letters elsewhere just fine.

http://www.arduino.cc/playground/Code/Struct#FAQ

Using an additional header for the Letter struct and the functions using it should solve this annoying error.

[edit]did you see the code I posted here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1256522369/0#5

Retrieving data from a letter is much simpler. Simply Let.get( line , bit ) no more need for long if clauses.

The code posted there also is as RAM friendly as possible.

Running that code should print:

010
101
111
101
101
1001
1101
1011
1001
1001
10001
11011
10101
10001
10001

Which shows that it contains sufficient data to represent A N and M.[/edit]

You should be using & when passing letters [or any other nonprimitive type] around with functions. Then you won't force the processor to copy all the data, it simply uses data already in RAM :slight_smile: (the exact data of the Letter passed as argument, if you modify member variables it will be modified for that Letter.)

Alpha I'm using the code you posted above and I'm trying to take the values that it's printing and put them into another array. I changed your code slightly though so that it goes through all the rows in a column of the letter before moving to the next column. This simplifies things for me when I want to add those numbers to another array. A weird thing is happening though, every other letter is backwards. Actually every letter is backwards, I just couldn't figure it out because A and M are both identical forwards and backwards. I can't figure out why, it was also happening with your original code.

int Tx = 0;
int Ty = 0;
//this is what defines a Letter on the most primitive letter
struct BaseLetter {
      virtual char get( byte line, byte bit ) = 0;
      virtual byte width( void ) = 0;

      static const byte NUMBER_OF_LINES = 5;
};

//Define letters of variable width using this template struct
template<byte size>
struct Letter : public BaseLetter {
      Letter( byte l0, byte l1, byte l2, byte l3, byte l4) :
            line0(l0),line1(l1),line2(l2),line3(l3),line4(l4) {
      }
      unsigned line0 : size;
      unsigned line1 : size;
      unsigned line2 : size;
      unsigned line3 : size;
      unsigned line4 : size;
      unsigned : 0;

      virtual char get( byte line, byte bit ) {
            switch (line){
                  case 0: return (line0&(1<<bit%size)?1:0); break;
                  case 1: return (line1&(1<<bit%size)?1:0); break;
                  case 2: return (line2&(1<<bit%size)?1:0); break;
                  case 3: return (line3&(1<<bit%size)?1:0); break;
                  case 4: return (line4&(1<<bit%size)?1:0); break;
            }
            return -1;
      }
      virtual byte width() { return size; }
};

/*
DEFINE THE LETTERS
*/
Letter<3> A = Letter<3>(
      B010,
      B101,
      B111,
      B101,
      B101
);
Letter<5> M = Letter<5>(
      B10001,
      B11011,
      B10101,
      B10001,
      B10001
);
Letter<5> N = Letter<5>(
      B10001,
      B11001,
      B10101,
      B10011,
      B10001
);
Letter<3> Z = Letter<3>(
      B111,
      B001,
      B010,
      B100,
      B111
);
Letter<1> Ls = Letter<1>(
      B0,
      B0,
      B0,
      B0,
      B0
);

/*
DEFINE THE WORD
*/
const byte WORD_LENGTH = 7;

BaseLetter* word1[WORD_LENGTH] = { &A, &Ls, &N, &Ls, &M, &Ls, &Z };
char Text[5][5*WORD_LENGTH];


void setup() {
  Serial.begin(9600);
  //Create Text array of just 0s
  for(Ty=0;Ty<(5*WORD_LENGTH);Ty++){
     for(Tx=0;Tx<=5;Tx++){
       Text[Tx][Ty]=0;
     }
   }
   Tx=0;
   Ty=0;
   //Take letters and put them into text array
   for (int wordIndex=0; wordIndex<WORD_LENGTH; wordIndex++){
            //loop through all the columns
        for (int bit=0; bit<word1[wordIndex]->width(); bit++){
                  //loop through all the rows
            for (int line=0; line<BaseLetter::NUMBER_OF_LINES; line++){
                     //print the value at the current letter, at the current line at the current bit
                     //Serial.print(word1[wordIndex]->get(line,bit),DEC);
                           Text[Tx][Ty]=int(word1[wordIndex]->get(line,bit));
                           Tx++;
                           //Serial.print(Text[Tx][Ty],DEC);
                  }
                  //Serial.println();
                        Tx=0;
                        Ty++;
            }
      }
        Tx = 0;
        Ty = 0;
        //Print out text array for analysis
        for(Tx=0;Tx<5;Tx++){
          for(Ty=0;Ty<(5*WORD_LENGTH);Ty++){
            Serial.print(Text[Tx][Ty],DEC);
          }
          Serial.println();
        }
}

void loop() {

}

As a workaround I changed the for loop that looped through the columns from This

 for (int bit=0; bit<word1[wordIndex]->width(); bit++)

to This

for (int bit=(word1[wordIndex]->width()-1); bit>=0; bit--)

It just starts at the last column and works toward the first. I'm still curious as to why they were backwards, I believe it has something to do with the get function but I don't know why.

Well I pretty much got it working look for my post in the exhibition forum. Thanks for your guys help, here's a demo Homemade scrolling LED sign run by arduino - YouTube

PS ignore the soundtrack...