problem with interrupts and with a menu library

Hello everyone,

I'm posting here because I need help with 2 issues on my project for school.

I'm doing a menu for a system, using this library : http://forum.arduino.cc/index.php/topic,38053.0.html I've started from that code because I'm really not used to programming in C, and needed somewhere to start : http://www.coagula.org/content/pages/tutorial-manage-menu-and-lcd-display-arduino

I modified it, works really fine, but now I want to do an action, depending on the last menu I come from, the parent menu. So I want to add it it the function navigateMenus() and menuUsed() receiving an event (those are in Coagula's code in the second link), but I really don't know how to do this in C, I don't understand the code of the library with all the pointers, and the C-specific codings... So in navigateMenus() that should look like : if(currentMenu.getBack().getName()=="myMenu") But that one doesn't work, I get an error like smth is a non-class type of menuItem.

My second problem is with the interrupts, but here I don't understand anything about the behavior of those...

Here's my code :

void loop()
{
  if (ready){
    interrupts();
    while (ready){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("  program is");
      lcd.setCursor(0,1);
      lcd.print("   running");
      lcd.setCursor(14,1);
      lcd.print(millis()/1000);
      delay(500);
    }
  }
  else{
    noInterrupts();
    while (!ready){
      lcd.clear(); // those lcd displays are just for test
      lcd.setCursor(0,0);
      lcd.print(millis()/1000);
      delay(500);
      readButtons(); // those two functions here are the one I want to loop through
      navigateMenus();
    }
  }
}

So my ready variable is at TRUE at beginning, and when pressing a button I want to switch to the second while, but with the interrupts disabled. So my interrupt function set the variable ready to FALSE. But here the interupt function is passed several times through when pressing the button and the program freeze in the 2nd function, the millis() function doesn't refresh anymore.

Thank you for your help in advance.

but with the interrupts disabled.

Why? With interrupts disabled, serial data won't arrive and millis() won't increment (which delay() depends on) (among other things).

But that one doesn't work, I get an error like smth is a non-class type of menuItem.

Handwaving is worthless on this forum. Put your hands in your pockets when talking to us. Post specific code and EXACT error messages. And, quit mumbling; use whole words.

I suspect its unlikely that you need to use interrupts at all. Please give us a description of your full project and the role that you think interrupts are needed for.

Avoid using interrupts unless you are confident that you are able to debug code that uses them. in other words you are unlikely to need advice from the forum to figure out problems, or you are able to narrow down the problem to a specific question and a short piece of code.

...R

PaulS: Handwaving is worthless on this forum. Put your hands in your pockets when talking to us. Post specific code and EXACT error messages. And, quit mumbling; use whole words.

Sorry, the teacher was soonly leaving the class and I needed to end my post really quick otherwise I would lose all I had already written, but I didn't mean to mumble at all, is it only for the "smth" ? :o I'm not an english native... For the error I changed the code, and can't really find it back, but it's not important, I just didn't use the library well as I don't understand it at all. :/ So for the code, I can send it but it takes some place, here's the library :

#ifndef MenuBackend_h
#define MenuBackend_h

/*
    A menu item will be a container for an item that is a part of a menu
    Each such item has a logical position in the hierarchy as well as a text and maybe a mnemonic shortkey
*/
class MenuItem {
public:
    MenuItem(const char* itemName, char shortKey='\0' ) : name(itemName), shortkey(shortKey) {
        before = right = after = left = 0;
    }

    //void use(){} //update some internal data / statistics
    inline const char* getName() const { return name; }
    inline const char getShortkey() const { return shortkey; }
    inline const bool hasShortkey() const { return (shortkey!='\0'); }
    inline void setBack(MenuItem *b) { back = b; }
    inline MenuItem* getBack() const { return back; }
    inline MenuItem* getBefore() const { return before; }
    inline MenuItem* getRight() const { return right; }
    inline MenuItem* getAfter() const { return after; }
    inline MenuItem* getLeft() const { return left; }

    MenuItem *moveBack() { return back; }

    MenuItem *moveUp() { 
        if (before) { before->back = this; }
        return before; 
    }

    MenuItem *moveDown() { 
        if (after) { after->back = this; }
        return after; 
    }

    MenuItem *moveLeft() { 
        if (left) { left->back = this; }
        return left; 
    }

    MenuItem *moveRight() { 
        if (right) { right->back = this; }
        return right; 
    }

    //default vertical menu
    MenuItem &add(MenuItem &mi) { return addAfter(mi); }

    MenuItem &addBefore(MenuItem &mi) {
        mi.after = this;
        before = &mi;
        if ( !mi.back ) mi.back = back;
        return mi;
    }
    MenuItem &addRight(MenuItem &mi) {
        mi.left = this;
        right = &mi;
        if ( !mi.back ) mi.back = back;
        return mi;
    }
    MenuItem &addAfter(MenuItem &mi) {
        mi.before = this;
        after = &mi;
        if ( !mi.back ) mi.back = back;
        return mi;
    }
    MenuItem &addLeft(MenuItem &mi) {
        mi.right = this;
        left = &mi;
        if ( !mi.back ) mi.back = back;
        return mi;
    }
protected:

    const char* name;
    const char shortkey;

    MenuItem *before;
    MenuItem *right;
    MenuItem *after;
    MenuItem *left;
    MenuItem *back;
};

//no dependant inclusion of string or cstring
bool menuTestStrings(const char *a, const char *b) {
    while (*a) { if (*a != *b) { return false; } b++; a++; }
    return true;
}
bool operator==(MenuItem &lhs, char* test) {
    return menuTestStrings(lhs.getName(),test);
}
bool operator==(const MenuItem &lhs, char* test) {
    return menuTestStrings(lhs.getName(),test);
}
bool operator==(MenuItem &lhs, MenuItem &rhs) {
    return menuTestStrings(lhs.getName(),rhs.getName());
}
bool operator==(const MenuItem &lhs, MenuItem &rhs) {
    return menuTestStrings(lhs.getName(),rhs.getName());
}

struct MenuChangeEvent {
    const MenuItem &from;
    const MenuItem &to;
};

struct MenuUseEvent {
    const MenuItem &item;
};

typedef void (*cb_change)(MenuChangeEvent);
typedef void (*cb_use)(MenuUseEvent);

class MenuBackend {
public:

    MenuBackend(cb_use menuUse, cb_change menuChange = 0) : root("MenuRoot") {
        current = &root;
        cb_menuChange = menuChange;
        cb_menuUse = menuUse;
    }

    MenuItem &getRoot() {
        return root;
    }
    MenuItem &getCurrent() {
        return *current;
    }

    void moveBack() {
        setCurrent(current->getBack());
    }

    void moveUp() {
        setCurrent(current->moveUp());
    }

    void moveDown() {
        setCurrent(current->moveDown());
    }

    void moveLeft() {
        setCurrent(current->moveLeft());
    }

    void moveRight() {
        setCurrent(current->moveRight());
    }

    void use(char shortkey)
    {
        recursiveSearch(shortkey,&root);
        use();
    }

    void use() {
        //current->use();
        if (cb_menuUse) {
            MenuUseEvent mue = { *current };
            cb_menuUse(mue);
        }
    }
      void toRoot() {
            setCurrent( &getRoot() );
      }

private:
    void setCurrent( MenuItem *next ) {
        if (next) {
            if (cb_menuChange) {
                MenuChangeEvent mce = { *current, *next };
                (*cb_menuChange)(mce);
            }
            current = next;
        }
    }
    void foundShortkeyItem(MenuItem *mi) {
        mi->setBack(current);
        current = mi;
    }
    char canSearch(const char shortkey, MenuItem *m) {
        if (m==0) { return 0; }
        else  {
            if (m->getShortkey()==shortkey) {
                foundShortkeyItem(m);
                return 1;
            }
            return -1;
        }
    }
    void rSAfter(const char shortkey, MenuItem *m) {
        if (canSearch(shortkey,m)!=1) {
            rSAfter(shortkey, m->getAfter());
            rSRight(shortkey, m->getRight());
            rSLeft(shortkey, m->getLeft());
        }
    }
    void rSRight(const char shortkey, MenuItem *m) {
        if (canSearch(shortkey,m)!=1) {
            rSAfter(shortkey, m->getAfter());
            rSRight(shortkey, m->getRight());
            rSBefore(shortkey, m->getBefore());
        }
    }
    void rSLeft(const char shortkey, MenuItem *m) {
        if (canSearch(shortkey,m)!=1) {
            rSAfter(shortkey, m->getAfter());
            rSLeft(shortkey, m->getLeft());
            rSBefore(shortkey, m->getBefore());
        }
    }
    void rSBefore(const char shortkey, MenuItem *m) {
        if (canSearch(shortkey,m)!=1) {
            rSRight(shortkey, m->getRight());
            rSLeft(shortkey, m->getLeft());
            rSBefore(shortkey, m->getBefore());
        }
    }
    void recursiveSearch(const char shortkey, MenuItem *m) {
        if (canSearch(shortkey,m)!=1) {
            rSAfter(shortkey, m->getAfter());
            rSRight(shortkey, m->getRight());
            rSLeft(shortkey, m->getLeft());
            rSBefore(shortkey, m->getBefore());
        }
    }

    MenuItem root;
    MenuItem *current;

    cb_change cb_menuChange;
    cb_use cb_menuUse;
};

#endif

And here's the function called when using a menu with no children, I'd like to reach the parent menu from the objectEvent sent to the function :

void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0);
  lcd.print("You used        ");
  lcd.setCursor(0,1); 
  lcd.print(used.item.getName());
  delay(500);  //delay to allow message reading
  menu.toRoot();  //back to Main
}

Here's aswell I want to reach it, from a menu object :

void navigateMenus() {
  MenuItem currentMenu=menu.getCurrent();
  
  switch (lastButtonPushed){
    case buttonPinEnter:
      if(!(currentMenu.moveRight())){  // if menu has no child and has been pressed enter the current menu is used
        menu.use();
      }else{  //otherwise, if the current menu has a child and has been pressed enter then menu navigate to item below
        menu.moveRight();
       } 
      break;
    case buttonPinEsc:
      if(currentMenu.getName()==menu.getRoot()){
        lcd.setCursor(0,1);
        ready = true;
        break;
      }
//      if(lastMenu.getName()=="menuContrast")
//        analogWrite(LCD_CONTRAST_PIN, contrastValues[lastContrast]);
      menu.toRoot();  //back to main
      
      break;
    case buttonPinRight:
      menu.moveDown();
      break;
    case buttonPinLeft:
      menu.moveUp();
      break;
  }
  
  lastButtonPushed=0; //reset the lastButtonPushed variable
}

My project is to do a resistor-sorter, that will put the resistors in a different tub depending on their values. So I have a main loop, where I will run the motors, that will treat a resistor each time it loops through, but I want a menu too, on a lcd, where you could change the resistor values, among other options. So it loops through the main code (to sort resistors) when ready is set to true, and I want the program to put ready to false when a button is pressed during resistors treatment, so after the end of the current resistor treatment it goes to the menu loop that will allow interracting with the menu. Ok, I didn't know that interrupts would stop everything, all I have to do is using detachInterrupt() when entering the menu loop I guess, I don't see how to do it another way, it's pretty easy with interrupts.

And sorry if I offended you, I didn't mean to be rude at all.

PS: I allow myself to up this post, I really need some help using this library. And concerning the interruptions, It's now working, but with only 1 out of the 2 buttons, I don't have the code right now with me, I'll post it tomorrow.