delay function and interrupt problem

When inserting delays in a function I assumed that hitting a switch on an interrupt pin at any time would kick me out. Right now I have text on a display that displays info, pauses, next line and then only jumps to the next function only after the first is completely done. If there is some way is immediately jumping to the next or previous function on left or right button press it would be perfect. Right now I have no idea how to go about this.

My code now is something like this:

//interrupt pin setup

void setup()
{
attachInterrupt(0, Next_Screen_Rise, RISING);
attachInterrupt(1, Previous_Screen_Rise, RISING);
}

{
//interrupt pin rise and fall code for debounce
}

void loop()
{
case 0:
First_Screen();

case 1:
Second_Screen();

case 2:
Thrid_Screen();
}

void First_Screen(void)
{
display text on the lcd;
delay(2000);
display text on the lcd;
delay(2000);
}

void Second_Screen(void)
{
display text on the lcd;
delay(2000);
display text on the lcd;
delay(2000);
}

void Third_Screen(void)
{
display text on the lcd;
delay(2000);
display text on the lcd;
delay(2000);
}

In loop, you need to have a switch statement, to define what 0, 1, and 2 match.

An interrupt will occur when the appropriate switch is pressed. Upon completion of the ISR, control returns to the place it was before the interrupt occured. So, branching elsewhere when the interrupt occurs is not possible.

You really should get rid of all those delays, and use millis(), as in the blink without delay example, to determine what to do, when.

Once you do, you will probably discover that interrupts are not required.

Damn. None of my code is usable. I suppose it would be fine now for just showing one page of text on every pushbutton back and fourth. What would you recommend as some type of layout? Case statements are definitely out of the question as you mentioned. I can now see how that would never work for getting out of the loop it is in with long pauses between each of the deisplayed text lines. I'm trying to wrap my head around the millis() function but it seems a bit to complicated since precision delays are not necessary but maybe i'm missing something important.

Thanks,
Mike

Grab a piece of paper, a pencil, and a stopwatch. Write down the steps you would perform to show some data on a display for two minutes (since we are slower than the Arduino).

Show some data on the screen.
Write down when that happened.

Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? Yes.

Show some data on the screen.
Write down when that happened.

Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? No.
Check the watch. Is it time to show new data? Yes.

See a pattern? The millis() function replaces the stopwatch. The Arduino can keep track of when things occured.

To best make use of this capability, you would need to have a separate function to display each screen full of text.

It isn't clear when you want to change what is displayed, or why there are three functions (in this example) for displaying text on the screen.

Perhaps you should move from the generic case to a specific case, and provide some more details. Once you know how to handle a specific case, the general case is generally easier to understand, too.

I've been trying all morning to get a non case statement structure using millis() function to be able to jump between three screens with delays() present but no luck. I've cleaned up the original code and attached below. If anyone could give me another hint it would be appreciated. All of the code I have now is bits I've found cobbled together. If some has some type of menu selection already working then I could work on that. Right now i'm using the 4D Systems 120x120 OLEd display connected to and Arduino UNO with pushbuttons. It works great for static screens. If anyone wants the associated files just send me a message.

#include <WProgram.h>

//Start library for the OLED display
#include "uOLED.h"
uOLED uoled;

int display_reset_pin = 7; //the display's reset pin

// Start general variables
int mode = 0; //select which mode the watch is in
int lastmode = 0; // last mode the watch was in, used for knowing when modes switch
int modechange = 0; // for passing the mode switch into the functions
int n=0;
#define screen_pixels_x 127 // size of the screen in pixels - 1, i.e. 128 pixel screen is 127 for the 0-127 index
#define screen_pixels_y 127 // size of the screen in pixels - 1, i.e. 128 pixel screen is 127 for the 0-127 index
#define screen_adjust_x 16 // move to center programs written for the the 96x64 pixels screen
#define screen_adjust_y 32 // move to center programs written for the the 96x64 pixels screen
// End general variables

//Start color scheme variables
unsigned int color = 63488;
unsigned int fast_color = 65504;
unsigned int med_color = 150;
unsigned int slow_color = 63488;
unsigned int background_color = 0;
//End color scheme variables

//int uppin = 9;
//int downpin = 8;

int interrupt_one = 2; //right pin
int interrupt_two = 3; //left pin

int rightstate = 0;
int leftstate = 0;
//int upstate = 0;
//int downstate = 0;

volatile int buttonState = LOW; //initial button state

int buttonlaststate = 0;

volatile long lastDebounceTime = 0; // the last time the interrupt was triggered //NEW
long debounceDelay = 10; // the debounce time; decrease if quick button presses are ignored //NEW

void setup()
{
uoled.begin(display_reset_pin, 256000, &Serial); //using uart pins 0 and 1 on the Arduino UNO

attachInterrupt(0, Next_Screen_Rise, RISING); //Left and right navigation
attachInterrupt(1, Previous_Screen_Rise, RISING);
}

void Next_Screen_Rise()
{
long currentTime = millis();
if ((currentTime - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = currentTime;
if (buttonState == LOW)
{
buttonState = HIGH;
attachInterrupt(0, Next_Screen_Fall, FALLING);
}
mode++;
}
}

void Next_Screen_Fall()
{
long currentTime = millis();
if ((currentTime - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = currentTime;
if (buttonState == HIGH)
{
buttonState = LOW;
attachInterrupt(0, Next_Screen_Rise, RISING);
}
}
}

void Previous_Screen_Rise()
{
long currentTime = millis();

if ((currentTime - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = currentTime;
if (buttonState == LOW)
{
buttonState = HIGH;
attachInterrupt(1, Previous_Screen_Fall, FALLING);
}
mode--;
if(mode<1)
{
mode=0;
}
}
}

void Previous_Screen_Fall()
{
long currentTime = millis();
if ((currentTime - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = currentTime;
if (buttonState == HIGH)
{
buttonState = LOW;

attachInterrupt(1, Previous_Screen_Rise, RISING);
}
}
}

void loop()
{
if(lastmode != mode) // if the mode switches clear the screen and set the modechange variable for apps to use
{
uoled.Cls();
modechange = 1;
}
lastmode = mode;
switch(mode)
{
case 0:
First_Screen();
break;

case 1:
Second_Screen();
break;

case 2:
Third_Screen();
break;
}
}

void First_Screen(void)
{
uoled.Text(1,1, 0, 0x001F, "Would be nice",1);
delay(1000);
uoled.Text(1,3, 0, 0x001F, "to be able to",1);
delay(1000);
uoled.Text(1,5, 0, 0x001F, "jump FWD and back",1);
delay(1000);
uoled.Text(1,7, 0, 0x001F, "at any time",1);
delay(1000);
uoled.Text(1,9, 0, 0x001F, "on button press",1);
delay(1000);
}

void Second_Screen(void)
{
uoled.Text(1,1, 0, 0x001F, "Second Screen",1);
delay(1000);
uoled.Text(1,3, 0, 0x001F, "Second Screen",1);
delay(1000);
uoled.Text(1,5, 0, 0x001F, "Second Screen",1);
delay(1000);
uoled.Text(1,7, 0, 0x001F, "Second Screen",1);
delay(1000);
uoled.Text(1,9, 0, 0x001F, "Second Screen",1);
delay(1000);
}

void Third_Screen(void)
{
uoled.Text(1,1, 0, 0x001F, "Third Screen",1);
delay(1000);
uoled.Text(1,3, 0, 0x001F, "Third Screen",1);
delay(1000);
uoled.Text(1,5, 0, 0x001F, "Third Screen",1);
delay(1000);
uoled.Text(1,7, 0, 0x001F, "Third Screen",1);
delay(1000);
uoled.Text(1,9, 0, 0x001F, "Third Screen",1);
delay(1000);
}

If anyone could give me another hint it would be appreciated.

I don't see anywhere where you detach the old interrupt handler before attaching the new one.

Have you looked at the Menu library, on the playground?

Right now I never detach an old interrupt pin and it works perfectly. Maybe a fluke though. If I did detach then would it even make a difference? Possibly detach and then attach at the beginning in:

void First_Screen(void)
{
attach here?
...display stuff starts here...
}
there may be hope yet.

I could give the menu library on the playground a try if what I have now dosen't work out.

Thanks for the feedback PaulS.