Jump to content
43oh

initializing multidimensional arrays from with switch-case


Recommended Posts

In my project, I would like to be able to play one of three different tunes based on a condition. Rather than initialize three separate <=100x2 global arrays and then having three identical loops to play the correct notes, I am trying to do this:

 

void PlayMusic(unsigned int status)
{
  delay_ms(500);

  switch (status)
  {
  case (DISABLED):
    //initialize array for "Ode To Joy"
   const unsigned int tune[][2] =
      {
      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, e, dquarter, d, eighth, d, half,

      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half,

      d, quarter, d, quarter, e, quarter, c, quarter, d, quarter, e, eighth, f, eighth, e, quarter,
  	   c, quarter, d, quarter, e, eighth, f, eighth, e, quarter, d, quarter, c, quarter, d, quarter, PAUSE, half,

      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half, 0, 0
      };
      break;

   case (ENABLED):
   const unsigned int tune[][2] =
      {
      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, e, dquarter, d, eighth, d, half,

      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half,

      d, quarter, d, quarter, e, quarter, c, quarter, d, quarter, e, eighth, f, eighth, e, quarter,
  	   c, quarter, d, quarter, e, eighth, f, eighth, e, quarter, d, quarter, c, quarter, d, quarter, PAUSE, half,

      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half, 0, 0
      };
      break;

   case (THREESTRIKES):
   const unsigned int tune[][2] =
      {
      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, e, dquarter, d, eighth, d, half,

      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half,

      d, quarter, d, quarter, e, quarter, c, quarter, d, quarter, e, eighth, f, eighth, e, quarter,
  	   c, quarter, d, quarter, e, eighth, f, eighth, e, quarter, d, quarter, c, quarter, d, quarter, PAUSE, half,

      e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
  	   c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half, 0, 0
      };
      break;
   }

   for (x = 0; tune[x][1]; x++)
   {
      if (!tune[x][0])
  	   delay_us( (tune[x][1]*100) );        // pause(DURATION) if NOTE = 0
      else
  	   beep((tune[x][0]), (tune[x][1]));        // beep(NOTE, DURATION) for each note in tune
   }

}

 

Right now, I am using the same data for all three cases, but I will be using three different sets of notes.

The compiler refuses to do it that way, though, giving me these errors:

 

Multiple markers at this line
   - #1148 a declaration cannot have a label
   - #102 "tune" has already been declared in the current
    scope
   - #179-D variable "tune" was declared but never
    referenced

 

Is there any way to make that work, or am I going to have to initialize three different global arrays and code three individual loops? Thanks..

Link to post
Share on other sites

The arrays are defined at compile time, not at run time. They are marked as constant. IIRC, that means they are hardwired into the code memory, not ram. Since you are using the same label "tune" for each, as a constant, the compiler gets confused that you are overwriting it.

Link to post
Share on other sites

OK... I can see that. So the only way to do this is to use three separate arrays and three loops, like this:

 

//initialize array for "Ode To Joy"
  const unsigned int OdeToJoy[][2] =
  {
     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, e, dquarter, d, eighth, d, half,

     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half,

     d, quarter, d, quarter, e, quarter, c, quarter, d, quarter, e, eighth, f, eighth, e, quarter,
        c, quarter, d, quarter, e, eighth, f, eighth, e, quarter, d, quarter, c, quarter, d, quarter, PAUSE, half,

     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half, 0, 0
  };


//initialize array for "Funeral March"
  const unsigned int FuneralMarch[][2] =
  {
     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, e, dquarter, d, eighth, d, half,

     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half,

     d, quarter, d, quarter, e, quarter, c, quarter, d, quarter, e, eighth, f, eighth, e, quarter,
        c, quarter, d, quarter, e, eighth, f, eighth, e, quarter, d, quarter, c, quarter, d, quarter, PAUSE, half,

     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half, 0, 0
  };

//initialize array for "Charge!"
  const unsigned int Charge[][2] =
  {
     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, e, dquarter, d, eighth, d, half,

     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half,

     d, quarter, d, quarter, e, quarter, c, quarter, d, quarter, e, eighth, f, eighth, e, quarter,
        c, quarter, d, quarter, e, eighth, f, eighth, e, quarter, d, quarter, c, quarter, d, quarter, PAUSE, half,

     e, quarter, e, quarter, f, quarter, g, quarter, g, quarter, f, quarter, e, quarter, d, quarter,
        c, quarter, c, quarter, d, quarter, e, quarter, d, dquarter, c, eighth, c, half, 0, 0
  };



void PlayMusic(unsigned int status)
{
  delay_ms(500);

  switch (status)
  {
      case (DISABLED):
       for (x = 0; OdeToJoy[x][1]; x++)
       {
          if (!OdeToJoy[x][0])
          delay_us( (OdeToJoy[x][1]*100) );                // pause(DURATION) if NOTE = 0
          else
          beep((OdeToJoy[x][0]), (OdeToJoy[x][1]));        // beep(NOTE, DURATION) for each note in tune
       }
          break;

       case (ENABLED):
       for (x = 0; Charge[x][1]; x++)
       {
          if (!Charge[x][0])
          delay_us( (Charge[x][1]*100) );                // pause(DURATION) if NOTE = 0
          else
          beep((Charge[x][0]), (Charge[x][1]));          // beep(NOTE, DURATION) for each note in tune
       }
          break;

       case (THREESTRIKES):
        for (x = 0; FuneralMarch[x][1]; x++)
       {
          if (!FuneralMarch[x][0])
          delay_us( (FuneralMarch[x][1]*100) );                // pause(DURATION) if NOTE = 0
          else
          beep((FuneralMarch[x][0]), (FuneralMarch[x][1]));    // beep(NOTE, DURATION) for each note in tune
       }
         break;
       }

}

 

right? Just seems overly redundant... Surely there is a better way to do this?

 

The array are declared and initialized gloablly here, because when I try to delcare them ahead of the switch inside the function, the routine never plays the music, as if the array is empty????

 

Maybe this would work?

 


//initialize array for "Ode To Joy"
  const unsigned int OdeToJoy[][2] =
  {
  };


//initialize array for "Funeral March"
  const unsigned int FuneralMarch[][2] =
  {
  };

//initialize array for "Charge!"
  const unsigned int Charge[][2] =
  {
  };

unsigned int **tune;

void PlayMusic(unsigned int status)
{
  delay_ms(500);

  switch (status)
  {
      case (DISABLED):
         **tune = OdeToJoy[0];
          break;

       case (ENABLED):
         **tune = Charge[0];
          break;

       case (THREESTRIKES):
         **tune = FuneralMarch[0];
          break;
       }

  for (x = 0; tune[x][1]; x++)
  {
     if (!tune[x][0])
        delay_us( (tune[x][1]*100) );            // pause(DURATION) if NOTE = 0
     else
        beep((tune[x][0]), (tune[x][1]));        // beep(NOTE, DURATION) for each note in tune
  }
}

 

???

Link to post
Share on other sites

Essentially want you want to do is dynamic allocation of memory. Determine which tune you're going to use at runtime, and allocate the memory using malloc(). You can find generic malloc tutorials on the web, and they should transition to the msp430 just fine (just be wary of the small amount of flash memory on your device, and don't attempt to allocate more than is available).

Link to post
Share on other sites

If I'm following along here though, the fact of the matter is, you have 3 tunes that need to be available to your MCU at runtime. There's no way around it, all 3 tunes need to get stored in flash somewhere.

 

Unless you want to investigate external storage solutions--like storing them in an external EEPROM, Flash or FRAM chip, and work on an SPI (or I2C, depending on how the chip is accessed) serial I/O peripheral driver to drive the process of going out and fetching the correct material from the external chip.

Or an SD card, for that matter, which can be driven using SPI. But typical drivers for accessing an SD card are rather big if I'm not mistaken.

Link to post
Share on other sites

Im guessing at this, because I'm not sure how pointers or arrays work exactly in this case, but why not make playmusic take the array instead? (From googling, pointers to multidimensional arrays in c is really really weird)

 

in main:

status = x
switch (status) {
 case (disabled):
   PlayMusic(OdeToJoy);
   break;
//snipped//

In Playmusic:

 

void PlayMusic(unsigned int tune[][2]) {
 for (x = 0; tune[x][1]; x++) {
    if (!tune[x][0])
      delay_us( (tune[x][1]*100) ); // pause(DURATION) if NOTE = 0
    else
      beep((tune[x][0]), (tune[x][1])); // beep(NOTE, DURATION) for each note in tune
 }
}

Link to post
Share on other sites

Thanks to my trusty "Teach Yourself C for Linux" book :smile: I figured this out, in case anyone else has this problem and needs to do this:

 

const unsigned int OdeToJoy[][2] = {note, duration, note, duration, ... , 0, 0}
const unsigned int FuneralMarch[][2] = {note, duration, note, duration, ... , 0, 0}

const unsigned int (*tune)[2];

void main(void)
 //snipped//
if (DISABLED)
PlayMusic(DISABLED);
else PlayMusic(ENABLED);
 //snipped//

void PlayMusic(unsigned int status)
{
switch (status)
{
 case (DISABLED):
 {
	 tune = FuneralMarch;
	 break;
 }
 case (ENABLED):
 {
	 tune = OdeToJoy;
	 break;
 }
}

for (x = 0; tune[x][1]; x++)
{
 if (!tune[x][0])
	 delay_us( (tune[x][1]*100) ); // pause(DURATION) if NOTE = 0
 else
	 beep((tune[x][0]), (tune[x][1])); // beep(NOTE, DURATION) for each note in tune
 }
}

 

I did have to switch from the xx2452 to the xx2553, though. Tunes take up a LOT of room! :grin:

Edited by rebeltaz
Link to post
Share on other sites

Yeah, because in that code you are storing both in RAM. If you use const then you would be storing them in FLASH. You can use const to store them in flash and then load them into ram, or just reference them in flash.

 

Oh, cool... All three tunes overran the 2553's memory as well, but I did the const trick and I was able to fit it all on the 2452. Thanks, dude!

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...