Intteruption and GOTO

Is there any way to get back to the 'loop' function when ever a interruption is detected? I tried GOTO but it can't move to another function.

Is there any way to get back to the 'loop' function when ever a interruption is detected? I tried GOTO but it can't move to another function.

When the interrupt handler ends, control returns to the last instruction executed before the interrupt occurred. You should not need to "get back to 'loop'" from your ISR.

Please explain why you think you need to.

Basically, I built an led cube with an attiny2313 (i’m using arduino ide to program it), now i’m trying to add a button to switch between the animations.I used a 555 monostable mode to debounce the signal and connected it to INT 0 pin.

there is my ‘void loop’ function’ and the interrupt fucntion

void interrupt{
animation++;
}

void loop() {

  switch(animation)
  {
  case 0: 
    rotate(); 
    break; 
  case 1: 
    rain(); 
    break;
  case 2:
    random_led();
    break;
  case 3: 
    upndown(); 
    break;
  case 4:
    animation = 0;
    break;
  }


}

each animation takes a few seconds to be executed , therefore, if the button is pressed while the animation is being executed I have to wait until it ends
Shortly: it doesn’t switch between the animation immediately

I thought of solve it with lots of if statements, However it is inefficient due to lack of memory ( attiny2313 as just 2KB ).

You need to post all your code.

It would appear that each of your functions does something that involves delay(). If there are loops involved, you can test whether the interrupt occurred easily.

Add a global boolean, interrupted. Set it to false on each pass through loop. Set it to true in the ISR.

Then, in any loop in the functions, test the interrupted flag.

for(int i=min; i<max && !interrupted; i++
{
}

With this approach, you will need to wait not more than 1 delay() call to know that the interrupt occurred.

If that’s still too long, well, quit using delay().

as I said before, there are too many for loop and the animation are goes 2 level deep ( the first function prosess what should be displayed and the deeper function display it to the LEDs)

there is the full coded:
(‘bin_prosses’ send to LEDs the bin[4][2])

#define LATCHPIN 12 // st_cp ( pin 12 )
#define CLOCKPIN 11 // sh_cp (pin 11)
#define DATAPIN  13 // DS (pin 14)

byte sequance[8]={
  0,1,2,3,3,2,1,0};

byte bin[4][2] = {
  {
    B00000000,B00000000        }
  ,{
    B00000000,B00000000        }
  ,{
    B00000000,B00000000        }
  ,{
    B00000000,B00000000        }
};

byte big_cube[4][2] = {
  {
    B11111001,B10011111        }
  ,{
    B10010000,B00001001        }
  ,{
    B10010000,B00001001        }
  ,{
    B11111001,B10011111        }
};

byte small_cube[4][2] = {
  {
    B00000000,B00000000        }
  ,{
    B00000110,B01100000        }
  ,{
    B00000110,B01100000        }
  ,{
    B00000000,B00000000        }
};

byte wall[4] = { 
  B10001000,B01000100,B00100010,B00010001};
byte wall2[2] = {
  B11110000,B00001111};

byte ser[6][2] = {
  {
    B10000100,B00100001          }
  ,{
    B01000100,B00100010          }
  ,{
    B00100010,B01000100          }
  ,{
    B00010010,B01001000          }
  ,{
    B00000011,B11000000          }
  ,{
    B00001100,B00110000          }
};

volatile byte animation=0;
byte seed = 12;


void setup() {

  //takes less memory
  DDRA = B00000011;
  DDRD = B00000111;
  DDRB = B00011100;



   /* //ecvivlent
   pinMode(4,INPUT); // interrupt
   
   pinMode(LATCHPIN, OUTPUT);
   pinMode(DATAPIN, OUTPUT);  
   pinMode(CLOCKPIN, OUTPUT);
   
   pinMode(0, OUTPUT);
   pinMode(1, OUTPUT);
   pinMode(2, OUTPUT);
   pinMode(3, OUTPUT); 
   */

  attachInterrupt(0,interrupt,RISING);
  
  
}



void interrupt()
 {
 animation++;
 }


void loop() {

  //if( (millis()%240000)-((animation+1)*60000) > 60000 ) animation++;

  switch(animation)
  {
  case 0: 
    rotate(); 
    break; 
  case 1: 
    rain(); 
    break;
  case 2:
    random_led();
    break;
  case 3: 
    upndown(); 
    break;
  case 4:
    animation = 0;
    break;
  }


}

// Animations

void rain()
{
  for(int i=0;i<3;i++)
   bitSet(bin[3][rand()%2],rand()%8);


  bin_prosses(20);

  for(int i=0;i<4;i++)
  {
    bin[i][0] = bin[i+1][0];
    bin[i][1] = bin[i+1][1];
  }

  bin[3][0] = 0;
  bin[3][1] = 0;


}

void rotate()
{

  for(int i=0;i<6;i++)
  {
    bin[3][0] = ser[i][0];
    bin[3][1] = ser[i][1];

    bin[2][0] = ser[(i+1)%6][0];
    bin[2][1] = ser[(i+1)%6][1];

    bin[1][0] = ser[(i+2)%6][0];
    bin[1][1] = ser[(i+2)%6][1];

    bin[0][0] = ser[(i+3)%6][0];
    bin[0][1] = ser[(i+3)%6][1];  

    bin_prosses(12); 
  }



}

void random_led()
{
  bitSet(bin[rand()%4][rand()%2],rand()%8);
  bin_prosses(5); 
  set_all(0);
  bin_prosses(5);
}


void upndown()
{

  for(byte j=0;j<3;j++)
  {
    for(byte i=0;i<8;i++)
    {  
      set_all(B00000000);
      bin[sequance[i]][0]= B11111111;
      bin[sequance[i]][1]= B11111111;         
      bin_prosses(8);
    }

  } 

  for(byte j=0;j<3;j++)
  { 
    for(byte i=0;i<8;i++)
    {
      set_all(wall[sequance[i]]); 
      bin_prosses(8);
    }

  }

  for(byte j=0;j<3;j++)
  { 
    for(byte i=0;i<8;i++)
    {
      set_all(B00000000);
      for(int z=0;z<4;z++)
        bin[z][(sequance[i]&2)>>1] = wall2[sequance[i]%2];
      bin_prosses(8);
    }

  }


  for(byte j=0;j<3;j++)
  { 

    set_array(small_cube);
    bin_prosses(40);

    set_array(big_cube);
    bin_prosses(40);

  }  





}


/// Prossesing fucntions below

void bin_prosses(byte times)
{


  for(byte j=0;j<times;j++) 
    for(byte i=0;i<4;i++)
    {


      PORTB = PORTB & B11110111; //digitalWrite(LATCHPIN, LOW);
      shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, bin[i][0]);
      shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, bin[i][1]);
      PORTB = PORTB | B00001000; //digitalWrite(LATCHPIN, HIGH);

      digitalWrite(i, HIGH);      

      delayMicroseconds(2000);

      digitalWrite(i, LOW);   


    }  


}

int rand() // random() is too big
{
  seed = ((seed*16476549 +millis())/16)%256;
  return seed;
}

void set_all(byte data)
{
  for(byte j=0;j<4;j++)
    for(byte i=0;i<2;i++)  
      bin[j][i]= data; 
}

void set_array(byte array[4][2])
{
  for(byte i=0;i<4;i++)
    for(byte z=0;z<2;z++)
      bin[i][z] = array[i][z];
}

as I said before, there are too many for loop and the animation are goes 2 level deep ( the first function prosess what should be displayed and the deeper function display it to the LEDs)

So, use the && !interrupted in each loop. You only need to make the change once.

PaulS:

as I said before, there are too many for loop and the animation are goes 2 level deep ( the first function prosess what should be displayed and the deeper function display it to the LEDs)

So, use the && !interrupted in each loop. You only need to make the change once.

The bin_prosess i bing executed almost every milliseconds so i thought: to put there an IF statement that will change the STOCK so the next RETURN will return it to LOOP:

something like this:

if ( there_was_an innteruption )
{
delete_last_stock_recored();
return;
}

EDIT: I googled 'stack pointer arduino' but i coudn't find how to change the stack pointer

I googled 'stack pointer arduino' but i coudn't find how to change the stack pointer

For which you should grateful.

AWOL:
For which you should grateful.

:astonished: ?

kirill578:

AWOL: For which you should grateful.

:astonished: ?

Direct manipulation of the stack is a sure fire path to disaster and grief.

Lefty

Its one of those things if you knew enough to know how to do it already you would know enough to find a better way to do whatever you want to do.

You had:

void interrupt{

animation++;
}

You want:

volatile boolean interrupted = false;

void interrupt{
 interrupted = true;
}

Now it immediately knows when you had an interrupt. In the main loop:

void loop() {

  if (interrupted)
    {
    animation++;
    interrupted = false;
    }  // end of if

//   ... the rest of your stuff  

}

And in the time-consuming function here check the flag:

void bin_prosses(byte times)
{

  for(byte j=0;j<times;j++) 
    for(byte i=0;i<4;i++)
    {
    
    if (interrupted) 
      return;

     // blah blah

    }   // end for loop

}  // end of bin_prosses

Thanks for replaying, as you have mentioned changing the stuck pointer is dangerous. I don't really get why, In case I fully understand what is in my stuck and how it works, why not to manipulate it if it may save me few Bytes of memory? Is there a danger of physical damage to the chip?

Nick Gammon, this method is good, but not in my case unless how some how managed to compress the code much more (Which i assume is all most impossible)

you have mentioned changing the stuck pointer is dangerous. I don't really get why,... Is there a danger of physical damage to the chip?

Absolutely; in your rage of frustration, you may well stamp on it, or hurl it at the wall.

Think about what happens on the stack, and all the things it is used for.

kirill578: Nick Gammon, this method is good, but not in my case unless how some how managed to compress the code much more (Which i assume is all most impossible)

Can you quantify that? My method adds a couple of lines of code. In what way does that need much more compression? Can you show in what way it will not work in your case?

... why not to manipulate it if it may save me few Bytes of memory?

You may take more bytes to manipulate it than you save? In any case, playing with the stack pointer is hardly a good idea. Some kind of state machine might be memory efficient.

Is there any way to get back to the 'loop' function when ever a interruption is detected?

Yes. Save the animation variable to EEPROM, use the Watchdog to reset the processor, then load animation from EEPROM in setup.

As a nice bonus, the selected animation is "sticky".

How do you compile for an Attiny? It doesn't seem to be in my list of boards. (If I knew I could experiment a bit).

You could save quite a few bytes of flash if you used "memset" and "memcpy"

Sounds like a good idea, I will try it.

I used Arduino as ISP with this core : http://code.google.com/p/arduino-tiny/

AWOL:
You could save quite a few bytes of flash if you used “memset” and “memcpy”

I’ve managed to make a bit lither, just 1982 bytes. I’m pretty sure there is a way to compress the following with memcpy but i’m not quite sure how:

  for(int i=0;i<4;i++)
  {
    bin[i][0] = bin[i+1][0];
    bin[i][1] = bin[i+1][1];
  }

and this part as well

  for(int i=0;i<6;i++)
  {
    bin[3][0] = ser[i][0];
    bin[3][1] = ser[i][1];

    bin[2][0] = ser[(i+1)%6][0];
    bin[2][1] = ser[(i+1)%6][1];

    bin[1][0] = ser[(i+2)%6][0];
    bin[1][1] = ser[(i+2)%6][1];

    bin[0][0] = ser[(i+3)%6][0];
    bin[0][1] = ser[(i+3)%6][1];  

    bin_prosses(12); 
  }