Sub Menu's Nokia 3310

Hi Guys,

I am relatively new to arduino and have got a 3310 wired up and am looking to do some menu and sub menus but am struggling to achieve multiple layers.

I have got the first layer but then am unable to scroll through the second, if you could take a look at the included code and let me know your thoughts it would be much appreciated.

Many thanks,

Menu_1.pde (5.41 KB)

JMinchin:
Hi Guys,

I am relatively new to arduino and have got a 3310 wired up and am looking to do some menu and sub menus but am struggling to achieve multiple layers.

I have got the first layer but then am unable to scroll through the second, if you could take a look at the included code and let me know your thoughts it would be much appreciated.

Many thanks,

I can refer you to

http://www.bytecraft.com/apps/cop8capp.c

Which is a example code for a LCD menu system. I used it as a basis when i needed to do something similar. Hope it helps.

Thanks for your post, I have had a look through the code and get a rough idea of how you have achieved it but still can't quite get my head around the nesting menu....
Many thanks,

I´ve made some Menu structure for anHous domtic system here some coding:

#include <nokia_3310_lcd.h>

int Wert=0;
int runs=0;
boolean clock=false;
boolean lastclock=false;
boolean ls1=false;
boolean ls2=false;
boolean ls3=false;
boolean ls4=false;
boolean cbut=false;
boolean L1=true;
boolean L2=true;
boolean L3=true;
unsigned long pm1;
unsigned long pm2;
int ref1=100;
int ref2=33;
int State=0;
int page=0;
int line=0;



Nokia_3310_lcd lcd=Nokia_3310_lcd();

void setup (){
  lcd.LCD_3310_init();  //Display Intialiseiern
  lcd.LCD_3310_clear();  // Display löschen
}

void loop(){
  if (millis()-pm2 > ref2){
    pm2=millis();
    lcd.LCD_3310_clear();  // Display löschen
  }
  if (millis()-pm1 > ref1){
    pm1=millis();
    clock = !clock;
    /*else{
     clock=false;
     lastclock=false;
     }*/
  }
  if (clock==true){
    key_in();
    //lastclock=true;
  }
  //lastclock=false;
  key();

  if(ls3==true && page==0){
    page=line+1;
  }

  if (ls1==true){
    page=0;
  }
  switch (page){
  case 0:
    Menu();
    break;
  case 1:
    Seite1();
    break;
  case 2:
    Seite2();
    line=0;
    break;
  case 3:
    Seite3();
    break;  
  case 4:
    Seite4();
    break;  
  case 5:
    Seite5();
    break;
  case 6:
    Seite6();
    break;
  }

  if (line <=0){
    line=0;
  }
  if (line >=5){
    line=5;
  }
  digitalWrite(7,L1);
}


void key(){
  if (State==1 && ls1==false){                    //left
    line=0;
    ls1=true;
  }
  if (State==3 && ls3==false){                    //right
    ls3=true;
  }
  if (State==2 && ls2==false){                    // up
    line=line--;
    ls2=true;
  }
  if (State==4 && ls4==false){                    // down
    line=line++;
    ls4=true;
  }
  if (State==5 && cbut==false){
    if (page==2){
      if (line==0)
        L1=!L1;
      if (line==1)
        L2=!L2;
      if (line==2)
        L3=!L3;
    }
    cbut=true;
  }
  if (State==0){
    ls1=false;
    ls2=false;
    ls3=false;
    ls4=false;
    cbut=false;
  }
}

void key_in(){
  Wert=analogRead(A0);
  if (Wert<20)
    State=1;                            //left                                                          
  if (Wert<550 && Wert>475)
    State=2;                            //up                             
  if (Wert<780 && Wert>650)
    State=3;                            //right                           
  if (Wert<370 && Wert>300)
    State=4;                            //down
  if (Wert>980)
    State=0;                            // nichts                                  
  if (Wert<200 && Wert>100)
    State=5;                            // pressed
}

void Menu(){
  lcd.LCD_3310_write_string(0,line,">",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,0,"Wohnzimmer",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,1,"Lampen",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,2,"Seite 3",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,3,"Seite 4",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,4,"Seite 5",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,5,"Seite 6",MENU_NORMAL);
}


void Seite1(){
  lcd.LCD_3310_write_string(0,0,"Im Wohnzimmer",MENU_NORMAL);
  lcd.LCD_3310_write_string(0,1,"sind es ",MENU_NORMAL);
  lcd.LCD_3310_write_string_big(0,2,"+19.3",MENU_NORMAL);
}

void Seite2(){
  lcd.LCD_3310_write_string(0,line,">",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,0,"Lampe1",MENU_NORMAL);
  if (L1==true)
    lcd.LCD_3310_write_string(50,0,"Ein",MENU_HIGHLIGHT);
  else
    lcd.LCD_3310_write_string(50,0,"Aus",MENU_NORMAL); 
  lcd.LCD_3310_write_string(0,line,">",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,1,"Lampe2",MENU_NORMAL);
  if (L2==true)
    lcd.LCD_3310_write_string(50,1,"Ein",MENU_HIGHLIGHT);
  else
    lcd.LCD_3310_write_string(50,1,"Aus",MENU_NORMAL);  
  lcd.LCD_3310_write_string(0,line,">",MENU_NORMAL);
  lcd.LCD_3310_write_string(6,2,"Lampe3",MENU_NORMAL);
  if (L3==true)
    lcd.LCD_3310_write_string(50,2,"Ein",MENU_HIGHLIGHT);
  else
    lcd.LCD_3310_write_string(50,2,"Aus",MENU_NORMAL);   
}

void Seite3(){
  lcd.LCD_3310_write_string(0,0,"Das ist die",MENU_NORMAL);
  lcd.LCD_3310_write_string(0,1,"dritte Seite",MENU_NORMAL);
}

void Seite4(){
  lcd.LCD_3310_write_string(0,0,"Das ist die",MENU_NORMAL);
  lcd.LCD_3310_write_string(0,1,"vierte Seite",MENU_NORMAL);
}

void Seite5(){
  lcd.LCD_3310_write_string(0,0,"Das ist die",MENU_NORMAL);
  lcd.LCD_3310_write_string(0,1,"fuenfte Seite",MENU_NORMAL);
}

void Seite6(){
  lcd.LCD_3310_write_string(0,0,"Das ist die",MENU_NORMAL);
  lcd.LCD_3310_write_string(0,1,"sechste Seite",MENU_NORMAL);
}

Sorry i´m german, so some Codeing is written in german. For Questions you can sent a personal message.

I managed to pull this off with my Nokia 3310. I only nested one of the menu options as that was all I needed, I’ve been wanting to rewrite this and use some multidimensional arrays to make it more extensible and allow more levels but I haven’t had the chance yet. Had to strip some stuff out as it exceeded the post max size, but anything you don’t see in here is just the same as the example code that comes with the library.

#include "nokia_3310_lcd.h"
#include "avr_bmp.h"

//keypad debounce parameter
#define DEBOUNCE_MAX 15
#define DEBOUNCE_ON  10
#define DEBOUNCE_OFF 3 

#define NUM_KEYS 5
#define NUM_MENU_ITEM	4
#define NUM_MENU_ITEM_PROG	3

// joystick number
#define UP_KEY 3
#define LEFT_KEY 0
#define CENTER_KEY 1
#define DOWN_KEY 2
#define RIGHT_KEY 4

// menu starting points
#define MENU_X	10		// 0-83
#define MENU_Y	1		// 0-5

// adc preset value, represent top value,incl. noise & margin,that the adc reads, when a key is pressed
// set noise & margin = 30 (0.15V@5V)
int adc_key_val[5] ={30, 150, 360, 535, 760 };
int menu_level;
byte button_count[NUM_KEYS]; // debounce counters
byte button_status[NUM_KEYS]; // button status - pressed/released
byte button_flag[NUM_KEYS]; // button on flags for user program 

// menu definition
char menu_items[NUM_MENU_ITEM][12]={
	"PROGRAM",
	"TEMPERATURE",
	"TIME",
	"ABOUT"	
};
void (*menu_funcs[NUM_MENU_ITEM])(void) = {
	menu_program,
	menu_temperature,
	menu_time,
	menu_about
};

// submenu defs
char menu_items_program[NUM_MENU_ITEM_PROG][12]={
	"YOGURT",
	"SOUS-VIDE",
	"INCUBATE"
};
void (*menu_funcs_program[NUM_MENU_ITEM_PROG])(void) = {
	menu_yogurt,
	menu_sousvide,
	menu_incubate
};

char current_menu_item;

Nokia_3310_lcd lcd=Nokia_3310_lcd();

void setup() {
   // setup interrupt-driven keypad arrays  
   // reset button arrays
   for(byte i=0; i<NUM_KEYS; i++){
     button_count[i]=0;
     button_status[i]=0;
     button_flag[i]=0;
   } //for
  
  // Setup timer2 -- Prescaler/256
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);
  TCCR2B = (1<<CS22)|(1<<CS21);      
  
  ASSR |=(0<<AS2);

   // Use normal mode  
  TCCR2A =0;  
   
  //Timer2 Overflow Interrupt Enable  
  TIMSK2 |= (0<<OCIE2A);
  TCNT2=0x6;  // counting starts from 6;  
  TIMSK2 = (1<<TOIE2);    
  
  SREG|=1<<SREG_I;
  
  // INITIALIZE SCREEN
  lcd.LCD_3310_init();
  lcd.LCD_3310_clear();
  
  // INITIALIEZE MENU
  menu_level = 1;
  init_MENU();
  current_menu_item = 0;	
}


/* LOOP */
void loop() {
  byte i;
  for(i=0; i<NUM_KEYS; i++){
    if(button_flag[i] != 0) {
      button_flag[i]=0;  // reset button flag
      
      switch(i){
      case UP_KEY:
        // Main Menu
        switch(menu_level) {
        case 1:
          // Unhighlight the old selected option
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_NORMAL );
	  current_menu_item -= 1;

          // If we were already at the top, jump to the bottom
	  if(current_menu_item < 0) {
            current_menu_item = NUM_MENU_ITEM - 1;
          }         

          // Highlight the new selected item
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_HIGHLIGHT );
          break;

        // Program Submenu
        case 2:
          // Unhighlight the old selected option
          lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items_program[current_menu_item], MENU_NORMAL );
	  current_menu_item -= 1;

          // If we were already at the top, jump to the bottom
	  if(current_menu_item < 0) {
            current_menu_item = NUM_MENU_ITEM_PROG - 1;
          }

          // Highlight the new selected item
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items_program[current_menu_item], MENU_HIGHLIGHT );
          break;

        default: // Default to main menu
          // Unhighlight the old selected option
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_NORMAL );
	  current_menu_item -= 1;

          // If we were already at the top, jump to the bottom
	  if(current_menu_item < 0) { 
            current_menu_item = NUM_MENU_ITEM -1;
          }
          
          // Highlight the new selected item
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_HIGHLIGHT );
        }
  	break;
  
      case DOWN_KEY:
        switch(menu_level) {
	// Main Menu
        case 1:
          // Unhighlight the old selected option
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_NORMAL );
	  current_menu_item +=1;

          // If at the top, loop around to the bottom
	  if(current_menu_item > (NUM_MENU_ITEM-1) ) {
            current_menu_item = 0;
          }
          
          // Highlight the new selected item
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_HIGHLIGHT );

          break;

        // Program Submenu
        case 2:
          // Unhighlight the old selected option
          lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items_program[current_menu_item], MENU_NORMAL );
	  current_menu_item +=1;

          // If at the top, loop around to the bottom
	  if(current_menu_item > (NUM_MENU_ITEM_PROG-1 )) {
            current_menu_item = 0;
          }
          
          // Highlight the new selected option
	  lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items_program[current_menu_item], MENU_HIGHLIGHT );

          break;
        }
	
	break;

      case LEFT_KEY:
        switch(menu_level) {
        case 1: // Main Menu
          init_MENU();
          menu_level = 1;
          current_menu_item = 0;
  	  break;   
  
        case 2: // Program Menu
          init_MENU();
          menu_level = 1;
          current_menu_item = 0;
  	  break;
        break;

      case RIGHT_KEY:
  	lcd.LCD_3310_clear();
        switch(menu_level) {
        case 1: // Main Menu
	  (*menu_funcs[current_menu_item])();
          break;
          
        case 2: // Program Menu
          (*menu_funcs_program[current_menu_item])();
          break;
        }
        
        lcd.LCD_3310_clear();       
        switch(menu_level) {
        case 1: // Main Menu
	  init_MENU();
          break;
          
        case 2: // Program Menu
          init_MENU_program();
          break;
        }

	current_menu_item = 0;           
	break;	
      } //switch
    } //if
  } //for
}

/* menu functions */
void init_MENU(void){
  byte i;
 
  lcd.LCD_3310_clear();
  lcd.LCD_3310_write_string(MENU_X, MENU_Y, menu_items[0], MENU_HIGHLIGHT );
	
  for (i=1; i<NUM_MENU_ITEM; i++){
    lcd.LCD_3310_write_string(MENU_X, MENU_Y+i, menu_items[i], MENU_NORMAL);
  }//for
}

void init_MENU_program(void){
  byte i;
 
  lcd.LCD_3310_clear();
  lcd.LCD_3310_write_string(MENU_X, MENU_Y, menu_items_program[0], MENU_HIGHLIGHT );
	
  for (i=1; i<NUM_MENU_ITEM_PROG; i++){
    lcd.LCD_3310_write_string(MENU_X, MENU_Y+i, menu_items_program[i], MENU_NORMAL);
  }//for
}


void menu_program(){
  menu_level = 2;
  init_MENU_program();
  //waitfor_OKkey();
}


// Program Submenu
void menu_yogurt() {
  lcd.LCD_3310_write_string(10, 1, "Start", MENU_NORMAL);
  lcd.LCD_3310_write_string(10, 2, "Schedule", MENU_NORMAL);
  lcd.LCD_3310_write_string(38, 5, "[Cancel]", MENU_HIGHLIGHT );
  waitfor_OKkey();
}
void menu_sousvide() {
  lcd.LCD_3310_write_string(10, 1, "Start", MENU_NORMAL);
  lcd.LCD_3310_write_string(10, 2, "Schedule", MENU_NORMAL);
  lcd.LCD_3310_write_string(38, 5, "[Cancel]", MENU_HIGHLIGHT );
  waitfor_OKkey();
}
void menu_incubate() {
  lcd.LCD_3310_write_string(10, 1, "Start", MENU_NORMAL);
  lcd.LCD_3310_write_string(10, 2, "Schedule", MENU_NORMAL);
  lcd.LCD_3310_write_string(38, 5, "[Cancel]", MENU_HIGHLIGHT );
  waitfor_OKkey();
}