trying to make one array point to another array

I recently opened a thread asking for help with addressing arrays and got some good pointers by econjack about pointers :slight_smile:
last thread here
I am trying to condense a large number of lines by using arrays to fill the variables.
I have entered the full program here :-

/* RG Matrix Example   v.2 8/1/08  BroHogan
 * Demos 2 color 8x8 matrix driven by 2 MAX7821's
 */
//#include "WProgram.h"                   // needed to compile with Rel. 0013 WHY?!
#include "LedControl.h"                 // to drive the matrix
#include <Wire.h>                                    //just to turn off the lcd light
#include <LiquidCrystal_I2C.h>                       //just to turn off the lcd light
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);//just to turn off the lcd light
#define ISR_FREQ 190     //190=650Hz    // Sets the speed of the ISR - LOWER IS FASTER
// prescaler is /128 -  125,000/ISR_FREQ+1 (i.e 249=500Hz, 190=650Hz)
// Tweaked depending on the overhead in the ISR & and other factors in the sketch
// Display will be slow if too FAST. Sketch will hang on delay() if way too fast!
#define GREEN 1                         // The address of the MAX7221 for the green leds
#define RED 0
// The address of the MAX7221 for the red leds
int maxInShutdown=GREEN;                // tells which MAX7221 is currently off
unsigned long ISRTime;                   // DEBUG to test how long in ISR
LedControl lc=LedControl(2,4,3,2); // pins 10=DataIn, 9=CLK, 8=LOAD + 2 MAX7221s
int line[]{255,129,189,189,189,189,129,255};
int line2[]{0,126,126,102,102,126,126,0};
int line3[]{0,0,60,36,36,60,0,0};
int data1[]={0,B11000000,B11000110,255,255,192,192,0};//put number 1 on screen
  //same as 0,192      ,198      ,255,255,192,192,0
int data2[]={0,198,227,243,219,207,198,0};//number 2
int dataX[]={0,195,102,60,60,102,195,0};//letter X
int colour[]{0,1,0,1,0,1,0,1};
int *datas[]={data1,data1,data1,data2,data2,data2,dataX,dataX,dataX};
int cols[]{0,1,0,0,1,0,0,1,0};
char colored=true;
char yellow=false;
int *ptr;
void setup() {
  lc.setIntensity(GREEN,6);            // 0 = dim, 15 = full brightness
  lc.setIntensity(RED,2);              // red needs less brightness
  setISRtimer();                        // setup the timer
  startISR();                           // start the timer to toggle shutdown
  Serial.begin(9600);
  lcd.begin (16,2);//just to turn off the lcd light
}
void loop() {
  lcd.noBacklight();//just to turn off the lcd light
 /*
  for (int i=0;i<8;i++){SetRow(0,i,line[i]);} //put reds on for multicolour
  for (int i=0;i<8;i++){SetRow(1,i,line2[i]);}//put greens on for multicolour
  delay(2000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(0,s,data1[s]);}//number 1 in red
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(1,s,data1[s]);}//number 1 in green
  delay(1000);
  for (int s=0;s<8;s=s+1){SetRow(0,s,data1[s]);}//add 1 in red to give yellow
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(0,s,data2[s]);}//number 2 in red
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(1,s,data2[s]);}//number 2 in green
  delay(1000);
  for (int s=0;s<8;s=s+1){SetRow(0,s,data2[s]);}//add 2 in red to give yellow
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(0,s,dataX[s]);}//letter X in red
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(1,s,dataX[s]);}//letter X in green
  delay(1000);
  for (int s=0;s<8;s=s+1){SetRow(0,s,dataX[s]);}//add X in red to give yellow
  delay(1000);ClearMatrix();
*/

  for (int t=0;t<9;t=t+1)
  {
    ptr=datas[t];
    for (int s=0;s<8;s=s+1)
    {
      SetRow(cols[t],s,*ptr++);
      Serial.print(s);
      Serial.print("  ");
      Serial.print(t);
      Serial.print("  ");
      Serial.print(*datas[t]);
      Serial.print("  ");
      Serial.print(*ptr++);
      Serial.print("  ");
      Serial.print(cols[t]);
      Serial.print("  ");
      Serial.println("here");
    }
    delay(1000);
    if (cols[t]==0)
      ClearMatrix();
  }





}
   
/////////////////////////////ISR Timer Functions ///////////////////////////
ISR(TIMER2_COMPA_vect) {  //This ISR toggles shutdown between the 2MAX7221's
  if(maxInShutdown==RED){
    lc.shutdown(GREEN,true);  // The order here is critical - Shutdown first!
    lc.shutdown(RED,false);   // . . . Then restart the other.

    maxInShutdown=GREEN;
  }
  else {
    lc.shutdown(RED,true);
    lc.shutdown(GREEN,false);
    maxInShutdown=RED;
  }
}  
 
void setISRtimer(){  // setup ISR timer controling toggleing
  TCCR2A = 0x02;                        // WGM22=0 + WGM21=1 + WGM20=0 = Mode2 (CTC)
  TCCR2B = 0x05;                // CS22=1 + CS21=0 + CS20=1 = /128 prescaler (125kHz)
  TCNT2 = 0;                            // clear counter
  OCR2A = ISR_FREQ;                     // set TOP (divisor) - see #define
}
 
void startISR(){  // Starts the ISR
  TCNT2 = 0;                            // clear counter (needed here also)
  TIMSK2|=(1<<OCIE2A);                  // set interrupts=enabled (calls ISR(TIMER2_COMPA_vect)
}
 
void stopISR(){    // Stops the ISR
  TIMSK2&=~(1<<OCIE2A);                  // disable interrupts
}
 
//////////////////////// simple LED display routine /////////////////////////////
void SkipRows() { // 1st pass alternates green & red, 2nd adds green to red making orange
  byte greenOn = true;                  // flag for lighting green for orange
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      if (greenOn == true) SetLed(GREEN,row,col,true);
      else SetLed(RED,row,col,true);
      greenOn = !greenOn;
    }
  }
  delay(500);                           // only so you can see the first pass
  greenOn = !greenOn;
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      delay(4);                         // only so you can see the update
      if (greenOn == true) SetLed(GREEN,row,col,true);
      greenOn = !greenOn;
    }
  }
 delay(500);
 ClearMatrix();
}
 
/////////   Wrappers for LedControl functions . . . //////////
void SetLed(byte Color, byte Row,byte Col, byte State){
  stopISR();            // disable interrupts - stop toggling shutdown when updating
  lc.setLed(Color,Row,Col,State);
  startISR();           // enable interrupts again
}
 
void SetRow(byte Color, byte Row, byte State){
  stopISR();            // disable interrupts - stop toggling shutdown when updating
  lc.setRow(Color,Row,State);
  startISR();           // enable interrupts again
}
 
void SetColumn(byte Color, byte Col, byte State){
  stopISR();            // disable interrupts - stop toggling shutdown when updating
  lc.setColumn(Color,Col,State);
  startISR();           // enable interrupts again
}
 
void ClearMatrix(){
  stopISR();            // disable interrupts - stop toggling shutdown when updating
  lc.clearDisplay(GREEN);
  lc.clearDisplay(RED);
  startISR();           // enable interrupts again
}

The commented out section

 /*
  for (int s=0;s<8;s=s+1){SetRow(0,s,data1[s]);}//number 1 in red
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(1,s,data1[s]);}//number 1 in green
  delay(1000);
  for (int s=0;s<8;s=s+1){SetRow(0,s,data1[s]);}//add 1 in red to give yellow
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(0,s,data2[s]);}//number 2 in red
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(1,s,data2[s]);}//number 2 in green
  delay(1000);
  for (int s=0;s<8;s=s+1){SetRow(0,s,data2[s]);}//add 2 in red to give yellow
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(0,s,dataX[s]);}//letter X in red
  delay(1000);ClearMatrix();
  for (int s=0;s<8;s=s+1){SetRow(1,s,dataX[s]);}//letter X in green
  delay(1000);
  for (int s=0;s<8;s=s+1){SetRow(0,s,dataX[s]);}//add X in red to give yellow
  delay(1000);ClearMatrix();
*/

works perfectly putting different graphics on my 8 x 8 matrix.
I think I should be able to duplicate the same graphics using something like

  for (int t=0;t<9;t=t+1)
  {
    ptr=datas[t];
    for (int s=0;s<8;s=s+1)
    {
       SetRow(cols[t],s,*ptr++);
    }
    delay(1000);
    if (cols[t]==0)
    ClearMatrix();
  }

the array 'datas' is in the full sketch but try as I might I get different effects on the matrix but can't seem to get it to reproduce the first, long, part of the sketch.
Can someone see where I am going wrong?

    ptr=datas[t];

Don't must be:

    ptr=&datas[t];

?
ptr is a pointer to integer and datas[] is an array of integer, so you want to copy to ptr not the data itself (integer) but the pointer for the data.

orptr = datas;

aarg:
orptr = datas;

nope! Because t goes from 0 to 9. What could be was:

ptr = datas + t;

right?

Right.

ptr=&datas[t];

gives
cannot convert 'int**' to 'int*' in assignment

ptr = datas;

gives
cannot convert 'int* ()[9]' to 'int' in assignment
and

ptr = datas + t;

gives
cannot convert 'int**' to 'int*' in assignment
When compiled?
I think I have the format correct but just in the wrong place. I get the 1 and the 2 to show up on the screen but not as I want them, they both show up side by side?
I think if the section below was in the correct order it would work.

 for (int t=0;t<9;t=t+1)
  {
    ptr=datas[t];
    for (int s=0;s<8;s=s+1)
    {
       SetRow(cols[t],s,*ptr++);
    }
    delay(1000);
    if (cols[t]==0)
    ClearMatrix();
  }

ptr is a pointer to an int. datas is an array of pointers to ints. Therefore, despite all the preceding posts,

ptr = datas[t];

IS syntactically correct, as both ptr, and datas[t] are pointers to int.

ptr = &datas[t];

is syntactically incorrect, as ptr is a pointer to int, while &datas[t] is a pointer to a pointer to int, exactly as the error message states.

Regards,
Ray L.

ptr is not defined correctly...

int *ptr;

should be

int **ptr;

or it's too early in the morning to be posting here... :slight_smile:

RayLivingston:
ptr is a pointer to an int. datas is an array of pointers to ints. Therefore, despite all the preceding posts,

ptr = datas[t];

IS syntactically correct, as both ptr, and datas[t] are pointers to int.

ptr = &datas[t];

is syntactically incorrect, as ptr is a pointer to int, while &datas[t] is a pointer to a pointer to int, exactly as the error message states.

Regards,
Ray L.

Yes, you'r right. Was my mistake. I must make cunfusion between datas[] and data2[] (that is int []). Apologies for that.

I modify your code to this:

int line[]{255,129,189,189,189,189,129,255};
int line2[]{0,126,126,102,102,126,126,0};
int line3[]{0,0,60,36,36,60,0,0};
int data1[]={0,B11000000,B11000110,255,255,192,192,0};//put number 1 on screen
int data2[]={0,198,227,243,219,207,198,0};//number 2
int dataX[]={0,195,102,60,60,102,195,0};//letter X
int colour[]{0,1,0,1,0,1,0,1};
int *datas[]={data1,data1,data1,data2,data2,data2,dataX,dataX,dataX};
int cols[]{0,1,0,0,1,0,0,1,0};

int *ptr;

void setup() {
  Serial.begin(9600);
  
  for (int t=0;t<9;t=t+1)
  {
    ptr=datas[t];
    for (int s=0;s<8;s=s+1)
    {
      SetRow(cols[t],s,*ptr++);
    }
    delay(1000);
    if (cols[t]==0)
      ClearMatrix();
  }
  
}
void loop() {
}
   
void SetRow(byte Color, byte Row, byte State){
  //Serial.println(Row);
  //Serial.print("  ");
  //Serial.print(t);
  //Serial.print("  ");
  Serial.println(State, BIN);
}

void ClearMatrix(){
  Serial.println("##############################################");
}

It gives this, in the terminal monitor:

0
11000000
11000110
11111111
11111111
11000000
11000000
0
##############################################
0
11000000
11000110
11111111
11111111
11000000
11000000
0
0
11000000
11000110
11111111
11111111
11000000
11000000
0
##############################################
0
11000110
11100011
11110011
11011011
11001111
11000110
0
##############################################
0
11000110
11100011
11110011
11011011
11001111
11000110
0
0
11000110
11100011
11110011
11011011
11001111
11000110
0
##############################################
0
11000011
01100110
00111100
00111100
01100110
11000011
0
##############################################
0
11000011
01100110
00111100
00111100
01100110
11000011
0
0
11000011
01100110
00111100
00111100
01100110
11000011
0
##############################################

I can see the 'X' but the other 2 number not really. Is this output correct?

Changed 0/1 to ./*. Can you see them now?

.
**......
**...**.
********
********
**......
**......
.
##############################################
.
**......
**...**.
********
********
**......
**......
.
.
**......
**...**.
********
********
**......
**......
.
##############################################
.
**...**.
***...**
****..**
**.**.**
**..****
**...**.
.
##############################################
.
**...**.
***...**
****..**
**.**.**
**..****
**...**.
.
.
**...**.
***...**
****..**
**.**.**
**..****
**...**.
.
##############################################
.
**....**
.**..**.
..****..
..****..
.**..**.
**....**
.
##############################################
.
**....**
.**..**.
..****..
..****..
.**..**.
**....**
.
.
**....**
.**..**.
..****..
..****..
.**..**.
**....**
.
##############################################

Tanks oqibidipo . So, it seems that the code is working.

int data1[]={0,B11000000,B11000110,255,255,192,192,0};//put number 1 on screen
int data2[]={0,198,227,243,219,207,198,0};//number 2
int dataX[]={0,195,102,60,60,102,195,0};//letter X
int *datas[]={data1,data1,data1,data2,data2,data2,dataX,dataX,dataX};

So datas is an array of pointers to int, each element initialised to be equal to the start of one of your other arrays of int.

Kewl.

This means that you can use

  datas[2][4];

to get at one of the ints. datas[2] is a pointer to int, initialised to point at the first element of data1, and datas[2][4] is 255. datas does not contain any info about the size of the arrays it is pointing at, so we will have to use '8' as a magic number.

So, let's print out everything!

  for(int i = 0; i < sizeof(datas)/sizeof(*datas); i++) {
    for(int j=0; j<8; j++) {
      Serial.print(datas[i][j]);
      Serial.print(' ');
    }
    Serial.println();
  }

But, I don't want to be dereferencing datas inside that loop - I want to stuff it into a local variable. Ok.

  for(int i = 0; i < sizeof(datas)/sizeof(*datas); i++) {
    int *data = datas[i];
    for(int j=0; j<8; j++) {
      Serial.print(data[j]);
      Serial.print(' ');
    }
    Serial.println();
  }

What would be cool is to run through the pointers in datas without having to check agains the size of the array. To do this, we will include a null at the end to act as a delimiter:

  int *datas[]={data1,data1,data1,data2,data2,data2,dataX,dataX,dataX, NULL};

  for(int **datas_p =  datas; *datas_p; datas_p++) {
    int *data = *datas_p;
    for(int j=0; j<8; j++) {
      Serial.print(data[j]);
      Serial.print(' ');
    }
    Serial.println();
  }

The key to all this is the distinction that C makes between an lvalue and an rvalue. When an array variable is evaluated (this is a compile-time thing), its value is taken to be a pointer to its first element.