Arrays to hold addresses of arrays

Ok, this could have been a continuation from another thread, but seeing as I have gone a long way from the original thread's title, and I am facing whole new problems, I figure it's worth starting a new thread with a relevant title for this.

What I am trying to do is use a pot to select a couple of wave arrays and to select the mix of the two chosen arrays to go to the output.

To save using processor time on continuous analogReads, I have set up a periodic analogRead using this:

  unsigned long currentTime = millis();
  if(currentTime - previousTime >= (readWave))                 //check to see if it's time to play the next sample based on pitch decided by the pitch pot
  {
    wave = analogRead(A0);                                  // potentiometer that controls the blend

Within the if statment, i want the two wave arrays to be selected by the position of the pot on A0. I have tried various methods for this already to no avail. My latest idea is to create two more arrays that hold the wave array addresses (pointers?) that I can access with index varialble "j".

I am having two problems with this. Firstly, I am struggling to get my new address/pointer arrays to be compatible with the wave arrays. When I verify it tells me there are problems with the two data types. Secondly, I'm not sure how to then call up the wave array data for the selected arrays. The loop currently looks like this:

void loop()
{
  unsigned long currentTime = millis();
  if(currentTime - previousTime >= (readWave))                 //check to see if it's time to play the next sample based on pitch decided by the pitch pot
  {
    wave = analogRead(A0);                                  // potentiometer that controls the blend between xthree and xfive
    previousTime = currentTime;                             // regester the current time in previousMillis 

    waveSelect = map(wave, 0, 1024, 0, 4);                  // works out which wavetables will be used (have to map an extra sector to take imaginary number 1024  

    waveMix1 = (((waveSelect+1)*256-1)-wave);                   // calculates the weight of first wave in osc1
    waveMix2 = (wave-(256*waveSelect));                         // calculates the weight of second wave in osc1

    j = waveSelect;                                             // j is the index for the arrays that holds the wave array addresses
  }

  osc1 = (wave1[j]*waveMix1)+(wave2[j]*waveMix2);            // wave1[] and wave2[] hold the selected array addresses

Here is the entire code, leaving out the figures in the wave arrays to save on charactors.
Any help you can give would be greatly appreciated!

Pete

long previousTime = 0;                                       // will store last time LED was updated
int readWave = 100;

short waveSelect;                                            // used to work out which oscillators to mix between
int wave;
int waveMix1;
int waveMix2;

unsigned int sine;                                            // sine wave array

unsigned int osc1;                                            // final oscillator 1 mix
unsigned int out;                                             // total output

short i = 0;                                          // "i" is soon to become the array index, and is set to start at index 0
short j = 0;                                          // "j" is the array index for the arrays containing the wave array addresses (wave1[] and wave2[])

char *wave1[4];                              // arrays containing the address of the arrays
char *wave2[4];

unsigned char xtwo[256] =                         // xtwo[] is an array that holds the sample data for a x2-base251 wave
{ 

};  

unsigned char xthree[256] =                          // xthree[] is an array that holds the sample data for a x3-base251 wave
{                                           

};  

unsigned char xfour[256] =                             // xfour[] is an array that holds the sample data for a x4-base251 wave
{ 

}; 

unsigned char xfive[256] =                            // xfive[] is an array that holds the sample data for a x5-base251 wave
{

};

unsigned char xsix[256] =                             // xsix[] is an array that holds the sample data for a x6-base251 wave
{

};

unsigned char xsine[256] =                             //sine wave array
{

};

void setup()
{
  DDRC = 255;                                                // 8 bit DAC on port C

  Serial.begin(9600);                                        // begin serial communication

wave1[0] = xtwo;                                              //arrays that hold the addresses of the wave arrays
wave1[1] = xthree;
wave1[2] = xfour;
wave1[3] = xfive;
wave2[0] = xthree;
wave2[1] = xfour;
wave2[2] = xfive;
wave2[3] = xsix;
}


void loop()
{
  unsigned long currentTime = millis();
  if(currentTime - previousTime >= (readWave))                 //check to see if it's time to play the next sample based on pitch decided by the pitch pot
  {
    wave = analogRead(A0);                                  // potentiometer that controls the blend between xthree and xfive
    previousTime = currentTime;                             // regester the current time in previousMillis 

    waveSelect = map(wave, 0, 1024, 0, 4);                  // works out which wavetables will be used (have to map an extra sector to take imaginary number 1024  

    waveMix1 = (((waveSelect+1)*256-1)-wave);                   // calculates the weight of first wave in osc1
    waveMix2 = (wave-(256*waveSelect));                         // calculates the weight of second wave in osc1

    j = waveSelect;                                             // j is the index for the arrays that holds the wave array addresses
  }

      Serial.println(wave1[j]);
      Serial.println(wave2[j]);
      Serial.println();
      Serial.println(xtwo[i]);
      Serial.println(xthree[i]);
      Serial.println();
      Serial.println();

  osc1 = (wave1[j]*waveMix1)+(wave2[j]*waveMix2);

  out = (osc1+(sine))/512;                                   //mix the wavetables with the sine wave
  
  PORTC = out;                                               // output the mixed signal before doing anything else for speed and accuracy?
  i++;                                                       // increase i in increments to cycle through the waveforms
    if(i >= 256)                                             // check if the index is at the end of the sample
      i = 0;                                                 // if it is, reset the sample to 0  
      
}
char *wave1[4];                              // arrays containing the address of the arrays
char *wave2[4];

unsigned char xtwo[256] =

Why are you mixing types? xtwo is an unsinged char *. You need to store it in an unsigned char *, not a char *.

      Serial.println(wave1[j]);

Why do you want to print the address?

I've tried several combination including unsigned char for both. Why do they both have to be the same when I am (hopefully) storing the address of one of them?

The serial.prints were all to help monitor what was going on, so i could see where my code was going wrong

Why do they both have to be the same when I am (hopefully) storing the address of one of them?

Because the compiler needs to know how increment and decrement the pointer. That means that the pointer needs to be stored in a variable that is the same type as the thing pointed to.

Cool, that makes sense! And it turns out I hadn't tried them both being unsigned char, because that's working now.

Ok, so my problem now is extracting the data back out from the address. My current attempts just give me the address, lol.

Here is where my problem seems to be:

  sample1 = wave2[j];
  sample2 = wave2[j];

  osc1 = (wave1[j]*waveMix1)+(wave2[j]*waveMix2);

wave1[] and wave2[] hold the addresses of the wave arrays, j being used as the index. When I try to compile, it highlights that first line and gives me this message:

Base251Sync_Array12B_headers.ino: In function 'void loop()':
Base251Sync_Array12B_headers:63: error: invalid types 'unsigned char[unsigned char]' for array subscript
Base251Sync_Array12B_headers:64: error: invalid types 'unsigned char[unsigned char]' for array subscript
Base251Sync_Array12B_headers:74: error: invalid operands of types 'unsigned char*' and 'int' to binary 'operator*'
Base251Sync_Array12B_headers:74: error: invalid operands of types 'unsigned char*' and 'int' to binary 'operator*'

Here is the complete code (I've tidied it up a bit by putting the wave arrays in header files).

# include "xtwo.h"
# include "xthree.h"
# include "xfour.h"
# include "xfive.h"
# include "xsix.h"
# include "sine.h"

long previousTime = 0;                                       // will store last time LED was updated
int readWave = 100;

short waveSelect;                                            // used to work out which oscillators to mix between
int wave;
int waveMix1;
int waveMix2;

int sample1;
int sample2;

unsigned int sine;                                            // sine wave array

unsigned int osc1;                                            // final oscillator 1 mix
unsigned int out;                                             // total output

unsigned char i = 0;                                          // "i" is soon to become the array index, and is set to start at index 0
unsigned char j = 0;                                          // "j" is the array index for the arrays containing the wave array addresses (wave1[] and wave2[])

unsigned char *wave1[4];                              // arrays containing the address of the arrays
unsigned char *wave2[4];

void setup()
{
  DDRC = 255;                                                // 8 bit DAC on port C

  Serial.begin(9600);                                        // begin serial communication

wave1[0] = xtwo;                                              //arrays that hold the addresses of the wave arrays
wave1[1] = xthree;
wave1[2] = xfour;
wave1[3] = xfive;
wave2[0] = xthree;
wave2[1] = xfour;
wave2[2] = xfive;
wave2[3] = xsix;
}


void loop()
{
  unsigned long currentTime = millis();
  if(currentTime - previousTime >= (readWave))                 //check to see if it's time to play the next sample based on pitch decided by the pitch pot
  {
    wave = analogRead(A0);                                  // potentiometer that controls the blend between xthree and xfive
    previousTime = currentTime;                             // regester the current time in previousMillis 

    waveSelect = map(wave, 0, 1024, 0, 4);                  // works out which wavetables will be used (have to map an extra sector to take imaginary number 1024  

    waveMix1 = (((waveSelect+1)*256-1)-wave);                   // calculates the weight of first wave in osc1
    waveMix2 = (wave-(256*waveSelect));                         // calculates the weight of second wave in osc1

    j = waveSelect;                                             // j is the index for the arrays that holds the wave array addresses
  }

  sample1 = wave2[j];
  sample2 = wave2[j];

  osc1 = (wave1[j]*waveMix1)+(wave2[j]*waveMix2);

  out = (osc1+(sine))/512;                                   //mix the wavetables with the sine wave
  
  PORTC = out;                                               // output the mixed signal before doing anything else for speed and accuracy?
  i++;                                                       // increase i in increments to cycle through the waveforms
    if(i >= 256)                                             // check if the index is at the end of the sample
      i = 0;                                                 // if it is, reset the sample to 0  
      
}

anyone? i'm seriously well stuck on this, spent hours trying to find away round this

Post your code.

Well...for starters your errors should be fairly simple to fix

  sample1 = (int)wave2[j];
  sample2 = (int)wave2[j];

  osc1 = ((int)wave1[j]*waveMix1)+((int)wave2[j]*waveMix2);

or make sample1 and sample2 unsigned char, that should also fix it...remember to keep the same data types.

No, doesn't seem to be that. It throws up the same error when I change them to unsigned char:

Base251Sync_Array12B_headers:74: error: invalid operands of types 'unsigned char*' and 'int' to binary 'operator*'

I've set up a new sketch to test just the arrays without any other clutter. I've also been learning some C++ and discovered that my understanding of the language for pointers was slightly off. From what I have read, referencing and dereferencing C pointers works the same as C++ pointers, is that right? I thought I might of sloved it but I'm still geting errors.

Here's the new code:

# include "xtwo.h"
# include "xthree.h"
# include "xfour.h"
# include "xfive.h"
# include "xsix.h"
# include "sine.h"

unsigned char sample1;
unsigned char sample2;

unsigned char i = 0;                                          // "i" is soon to become the array index, and is set to start at index 0
unsigned char j = 0;                                          // "j" is the array index for the arrays containing the wave array addresses (wave1[] and wave2[])

unsigned char *wave1[4];                                      // arrays containing the address of the arrays
unsigned char *wave2[4];

void setup()
{
  DDRC = 255;                                                // 8 bit DAC on port C

  Serial.begin(9600);                                        // begin serial communication

wave1[0] = &xtwo;                                              //arrays that hold the addresses of the wave arrays
wave1[1] = &xthree;
wave1[2] = &xfour;
wave1[3] = &xfive;
wave2[0] = &xthree;
wave2[1] = &xfour;
wave2[2] = &xfive;
wave2[3] = &xsix;
}


void loop()
{
  sample1 = wave2[j];
  sample2 = wave2[j];  
  
  Serial.println(sample1);
  Serial.println(sample2);
}

And here are the new errors:

ArrayOfArrays01.ino: In function 'void setup()':
ArrayOfArrays01:23: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01:24: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01:25: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01:26: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01:27: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01:28: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01:29: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01:30: error: cannot convert 'unsigned char ()[256]' to 'unsigned char' in assignment
ArrayOfArrays01.ino: In function 'void loop()':
ArrayOfArrays01:36: error: invalid conversion from 'unsigned char*' to 'unsigned char'
ArrayOfArrays01:37: error: invalid conversion from 'unsigned char*' to 'unsigned char'

I'm just guessing, since you didn't include all those include files, but is "xtwo" declared as something like:

char xtwo[] = { "something" };

If so, then:

wave1[0] = &xtwo;

should be:

wave1[0] = xtwo;

The same applies for all the other initializers in your setup function.

Regards,
Ray L.

Ok, I've actually solved the first part of the problem. I still wasn't referencing/dereferencing quite right.

Ray: You guessed correctly. Will that give the address of xtwo[] or the data?

What I want to use all those xwaves (xtwo, xthree etc...) in an array inside a set of commands for an interupt. The interupt will determine which wave I will use within my main loop. So within the interupt I need the location of one of the xwaves to be decided, then I want to increment the data within the xwave in for main loop.

I think I'm very nearly there, I'm storing the pointers within the arrays, accessing the address of the array and taking data from it. Just need to find a way to increment the data from the chosen array within the loop and I'll be sorted.

Wondering now, having read about multi dimensional arrays, if using one multi dimensional array to store all the wave arrays might make this easier.

here's my new code that nearly works anyway. My problem now is that my variable 'i' is currently useless as the position of the xwave arrays is fixed in the setup. I'll play around though, see what I can do.

# include "xtwo.h"
# include "xthree.h"
# include "xfour.h"
# include "xfive.h"
# include "xsix.h"
# include "sine.h"

unsigned char sample1;
unsigned char sample2;

unsigned char i = 0;                                          // "i" is soon to become the array index, and is set to start at index 0
unsigned char j = 0;                                          // "j" is the array index for the arrays containing the wave array addresses (wave1[] and wave2[])

unsigned char *wave1[4];                                      // arrays containing the address of the arrays
unsigned char *wave2[4];

void setup()
{
  DDRC = 255;                                                // 8 bit DAC on port C

  Serial.begin(9600);                                        // begin serial communication

wave1[0] = &xtwo[i];                                              //arrays that hold the addresses of the wave arrays
wave1[1] = &xthree[i];
wave1[2] = &xfour[i];
wave1[3] = &xfive[i];
wave2[0] = &xthree[i];
wave2[1] = &xfour[i];
wave2[2] = &xfive[i];
wave2[3] = &xsix[i];
}


void loop()
{
  sample1 = *wave1[j];
  sample2 = *wave2[j];
  
  Serial.println(i);
  Serial.println(j);
  Serial.println();
  Serial.println(sample1);
  Serial.println(sample2);
  Serial.println();
  
  i=i+1;
  if(i>=256)
    i=0;
  j=j+1;
  if(j>=4)
    j=0;

}

If xtwo is declared as an array of char, then the symbol xtwo IS a pointer to the first character of the array. xtwo[0] returns value of the first element of the array. You can use either xtwo[n] or *xtwo as the target of an assignment to change the value of the first element of the array. Though syntactically different, they are functionally identical.

char *xtwo[] = { "hello" };
char c;

xtwo[0] = 'x'; //These two lines are exactly equivalent, and change xtwo to "xello"
*xtwo = 'x';

xtwo[3] = 'x'; //These two lines are exactly equivalent, and change xtwo to "helxo"
*(xtwo+3) = 'x';

xtwo[0] = *(xtwo+4);//These two lines are exactly equivalent, and change xtwo to "oello"
*xtwo = xtwo[4];

Regards,
Ray L.

Ok, so there is no need to use the * while setting up the array of arrays? I guess that makes sense as the entire array isn't a specific number or character.

I'm gonna give some of these ideas a whirl tomorrow.

Thanks for all your help guys! I'll post the code again when it's working.

Pete